batisto4ka
Apr 18 2012, 11:40
Помогите, пожалуйста, поставить точки над i. Насколько мне понятно, в stm32 bootloader может быть использован вместо программатора. Для того, чтоб залить прошивку в контроллер, необходимо подсоединить плату с МК к компу через ком порт( по USART1 МК), подать на вход бут0 1, на бут 1 -0, загрузить бинарник, используя специальную утилиту Flash Loader Demonstrator.Это весь алгоритм?
Второй вопрос. Часто встречается в сети такое выражение, как "написать загрузчик". Что имеется в виду под этим? В каком случае нужно писать свой загрузчик и как это сделать?
lead_seller
Apr 18 2012, 11:52
Бутлоадер (термин "загрузчик" имеет несколько значений, например, есть еще загрузчик ОС) - это код который позволяет прошить МК не используя стандартные средства МК (для STM32 таким средством является JTAG). Контроллеры STM32 уже с завода имеют такой бутлоадер, работающий по USART (это как раз то, что Вы описали - с управлением ножками BOOT0 и BOOT1).
В общем же случае, "написать бутлоадер" означает написать такой код, который будет менять прошивку контроллера без применения JTAG по какому-либо протоколу (например, на плате есть возможность установки SD-карты, пользователь кидает на карту hex-файл, и Ваше устройство обнаружим такой файл заливает его содержимое в память программ МК).
KnightIgor
Apr 18 2012, 11:53
Цитата(batisto4ka @ Apr 18 2012, 12:40)

Поомгите, пожалуйста, поставить точки над i. Насколько мне понятно, в stm32 bootloader может быть использован вместо программатора...
Второй вопрос. часто втсречается в сети такое выражение, как "написать загрузчик". Что имеется в виду под этим? В каком случае нужно писать свой загрузчик и как это сделать?
1. Со встроенным загрузчиком (USART0, Flash Loader) все верно.
2. Написать свой загрузчик означает использовать для обновления программы микроконтроллера иные способы коммуникации нежели те, что уже в данном микроконтроллере встроены. Например, через USB, или I2C, или Ethernet или чтение с SD-карты. В этом случае необходимо написать часть кода основной программы (которая ИЗНАЧАЛЬНО попадает в микроконтроллер исключительно либо через JTAG, либо как Ваш первый вопрос) так, чтобы он обеспечил обновление программы. Это весьма нетривиальная задача.
batisto4ka
Apr 18 2012, 11:57
Спасибо всем, кто откликнулся. Подскажите, где можно найти подробную информацию о том, как написать свой загрузчик
nicks80
Apr 18 2012, 13:12
Цитата(batisto4ka @ Apr 18 2012, 15:57)

Спасибо всем, кто откликнулся. Подскажите, где можно найти подробную информацию о том, как написать свой загрузчик
Сейчас имею проект с W5100 и stm32 + SD с fatfs.
Надо написать обновление прошивки по Ethernet.
Код с рабочим изернетом занимает 12килобайт + 30байт рам.
Как думаю делать.
Загрузчик (1 подпрограмма) при команде обновления по изернету принимает прошивку и шьет ее допустим с адресса на 20 кило больше чем основная программа.
При перезагрузке(1 подпрограмма) проверяет crc осноновной прошивки и если совпадает то запускает программу по адресу на 20 кило больше.
Еще как вариант. написать 1 функцию прошивальщика и все переменные для работы с изернетом будут в стэке этой функции. Загрузит ее в рам. и запустить.
а потом как в 1м варианте.
вот еще
http://we.easyelectronics.ru/STM32/stm32-i...h-programm.html
batisto4ka
Apr 18 2012, 13:16
И еще хотелось бы уточнить, есть отладочная плата sk-mstmf107. В нее залита некая программа. Отключаю питание, ставлю пеермычку на J5. Запускаю Flash Loader Demonstrator. Выбираю порт, бодрэйт 9600 (пробовала и все остальные варианты скоростей), паритет -четный, эхо-дизэйблт, ттаймаут 5. Включаю плату, пытаюсь соединиться, вылазит "No response from target, the Boot loader cannot be started. Please, verify the boot mode configuration and the flash protection status, Reset tour device then try again".
Что не так? Я что-то пропустила? Если с "verify the boot mode configuration" понятно (boot 0 =1, boot 1 =0), то что имеется в виду под "flash protection status"? Может в этом причина? Еще в документе AN2606 Application note STM32™ microcontroller system memory boot mode нашла следующее: Connectivity line
USART1 / USART2 (remapped) / CAN2 (remapped) / DFU (USB Device). А на самой отладочной плате сам ком-порт запаян на USART2. Может в этом причина?
И все же, еще раз хотелось бы уточнить.
1. Если, допустим, есть доступ к USART1 (соединение по ком-порту между USART1 МК и ПК), можно залить прошивку, используя утилиту Flash Loader Demonstrator, предварительно посадив ногу бут0 на 1, а бут 1 на 0?
2. Если, например, нет возможности подсоединиться к USART1, нужно писать свой загрузчик. При этом переход в ситем бут лоадер осуществляется ИСКЛЮЧИТЕЛЬНО ПРОГРАММНО? Никаких махинаций с ногами бут 1 и бут 0 проводить не нужно?
3. Что будет с МК при включении, если сконфигурировать boot0=1, boot1=0? Будет спокойно выполняться старая прошивка пока по юсарту не прийдет комбинация спец символов для перехода в систем бут лоадер? Или МК просто повиснет пока не снять сигнал с бут0 и не перегрузить МК?
lead_seller
Apr 18 2012, 20:22
Собственно ответы:
1. да
2. нет. Заводской бутлоадер активируется только подачей соответствующих сигналов на соответствующие ноги. Если Вы хотите написать собственный бутлоадер, то должны будете полностью реализовать всю логику прошивки контроллера - получение прошивки с ПК (или иного носителя прошивки), временное хранение в контроллере, верификацию этой прошивки (проверки правильности полученных кодов), запись полученной прошивки в Flash-память контроллера, передачи управления залитой прошивке. По поводу логики работы бутлоадеров можете почитать апнот от STMй AN2557 (http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/APPLICATION_NOTE/CD00161640.pdf). В нем описывается логика работы бутлоадера с передачей прошивки по USART (не путать с заводским).
3. МК будет ожидать прошивку, пользовательская программа выполнятся не будет. Ноги BOOT0 и BOOT1 определяют из какой области памяти будет грузится контроллер. Подробнее об этих ногах расписано в AN2606 (http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/APPLICATION_NOTE/CD00167594.pdf)
А от себя добавлю (строго мое мнение, без намерения кого-либо оскорбить), написание бутлоадеров не самая тривиальная задача, которая требует достаточно хорошего знания периферии микроконтроллера, ядра Cortex-M3, и особенностей работы компиляторов.
Цитата(lead_seller @ Apr 19 2012, 00:22)

А от себя добавлю (строго мое мнение, без намерения кого-либо оскорбить), написание бутлоадеров не самая тривиальная задача, которая требует достаточно хорошего знания периферии микроконтроллера, ядра Cortex-M3, и особенностей работы компиляторов.
+1.
Планирование раскладки памяти, настройка линкера под эту раскладку, разработка и реализация способа загрузки и проверки целостности прошивки, способы передачи управления от загрузчика к основной прошивке и обратно - всё это не для начинающих.
Цитата(scifi @ Apr 19 2012, 00:45)

+1.
Планирование раскладки памяти, настройка линкера под эту раскладку, разработка и реализация способа загрузки и проверки целостности прошивки, способы передачи управления от загрузчика к основной прошивке и обратно - всё это не для начинающих.
+1. Таблицу векторов прерываний тоже переносить надо.
От себя добавлю, я имел опыт написания своего загрузчика на PIC18, PIC24, там куда сложнее чем на STM32, поэтому после ознакомления с последним, написание загрузчика составило не больше 1-й недели. Тут, по сути, Вам надо разобраться, как с flash работать, как работать с контроллером прерываний, как работать с желаемым коммуникационным интерфейсом, уметь писать для ПК простые ”утилитки”, на уровне работы с COM портом. По поводу верификации поищите по форуму, я как то создавал тему по модулю CRC на STM32, вещь ‘железная’ и простая, там и ”исходники” выложил. Вообще свои загрузчик нужен там, где его нет заводского, либо там где нет пригодного коммуникационного интерфейса в заводском загрузчике, но есть на борту МК, либо нужно защититься от плагиата, т.е. использовать шифрованный загрузчик. Среди STM32 я писал шифрованный USB загрузчик для STM32F1 и для STM32F2 семейства, там разница не так уж большая, разве, что размер секторов в семействе F2/F4 немного удручает.
Кстати, свой загрузчик бывает нужен те только для загрузки памяти программ firmware, но и памяти данных, размещенных, например, во flash микроконтроллера.
batisto4ka
Apr 19 2012, 05:44
Цитата(lead_seller @ Apr 19 2012, 00:22)

А от себя добавлю (строго мое мнение, без намерения кого-либо оскорбить), написание бутлоадеров не самая тривиальная задача, которая требует достаточно хорошего знания периферии микроконтроллера, ядра Cortex-M3, и особенностей работы компиляторов.
Всем спасибо за советы и ответы. Мне приходилось как-то писать свой компилятор и интерпретатор на базе pic24, писать/читать флеш-память вроде как умеем, мелкие улититки по передачи через ком порт для ПК писать приходилось. В проекте, дя которого нужно написать свой бутлоадер, как раз такая ситуация " либо там где нет пригодного коммуникационного интерфейса в заводском загрузчике", то есть сам юсарт1 занят под другие нужды (в проекте используется камень stm32f103vet).
То есть вроде как все махинации с флешкой понятны, но, поскольку еще не начинала "колупать" остаются вопросы:
1. Не понятно, зачем пеерносить таблицу векторов прерываний.
2. Сейчас пок а вголове созрела идея такая: первую страницу ПЗУ использовать для хранения своего загрузчика. Ее защитить от записи. В эту область будет попадать программный счетчик либо при старте системы, либо когда нужно будет перепрошивать МК. Условие попадание будет проверяться по какому-то флагу. Если это обычный режим работы, то бутлоадер отправляет программный счетчик на начало программы. А программа сама будет записываться со второй страницы. Таким образом, сам загрузчик может быть стерт только при перепрошивке с помощью программатора, либо иным способом, предусморенным программой загрузчика. И тогда, если теоретически, так сделать можно, то остается вопрос, как с помощью стандартной улититы (стмовского флэш лоадер демонсттратор) зашить бинарник, как понять сигналы утилиты и т.д. Это думаю найти в AN2557, который посоветовал load_seller.
lead_seller
Apr 19 2012, 06:41
Вектора прерываний переносятся потому, что и бутлоадеру и основной прошивке как правило требуется работа с прерываниями, и необходимо выбирать какой код обработчика прерывания мы выполняем - код бутлоадера или код основной прошивки. Для этой цели у STMовского контроллера прерываний есть функция переноса таблицы векторов прерываний. При этом появляется возможность иметь отдельные наборы обработчиков прерываний для бутлоадера и для основной прошивки.
Конечно возможен вариант с одной таблицей векторов, и программным выбором какой обработчик использовать (устанавливаем флаг работает бутлоадер или основная прошивка, и по этому флагу делаем if в ветках которого расположены разные обработчики) - бутлоадера или основной прошивки (в зависимости от того что активно), но такой вариант замедляет реакцию системы на прерывания.
Вариант с переносом таблицы векторов удобней тем, что в памяти программ мы можем хранить несколько разных прошивок (естественно скомпилированных и линкованных для использования разных стартовых адресов), и на старте системы можем выбирать какой из прошивок отдавать управление. Сейчас как раз занимаюсь такой развлекухой)). Требуется шиться по CAN с оооочень низкой скоростью (порядок байтов в секунду), причем с огромной вероятностью разрывов на линии. При этом вероятность того, что устройство продолжит функционировать после неудачной перепрошивки, должна стремится к 100%.
batisto4ka
Apr 19 2012, 06:49
Правильно ли я понимаю, что под переносом таблицы векторов понимается копирование . То есть старая таблица векторов прерываний рапсоложенная по адресу 0x0000_0000 согласно RM0008 Table 63. Vector table for other STM32F10xxx devices остается на том же месте, и еще дополнительно копируется для своего бутлоадера? Как тогда контроллер при срабатывании прерываний будет понимать,какая обработчик ему нужно вызвать? и как описываютсся обработчики прерываний, перенесеннной таблицы веткоров прерываний?
Цитата(batisto4ka @ Apr 19 2012, 08:44)

1. Не понятно, зачем пеерносить таблицу векторов прерываний.
Вероятно, можно и не переносить, но мне пока в голову не приходит, как организовать тогда взаимодействие загрузчика и основной программы.
У меня два проекта отдельных:
Первый – загрузчик, начинается с начала flash микроконтроллера (0x08000000), таблица векторов с адреса 0х08000004, соответственно свои обработчики прерываний, которые к загружаемой прошивке не имеют никакого отношения.
Второй – прошивка (firmware), готовиться и отлаживается отдельно от загрузчика (так же начиная с адреса 0x08000000), после ее разработки и отладки, переносите таблицу векторов (ну соответственно и адрес начала программы во flash) на несколько килобайт вперед (в зависимости от размере загрузчика и размера страницы памяти микроконтроллера), компилируйте с выходом простого «бинарника».
Так Вы гарантируете /перенос таблицы и начало программы/ отсутствие наложения проектов при их объединении в один «кусок». Объединение в один проект очень просто, зашиваете загрузчик, зашиваете прошивку, по средствам своего загрузчика, считываете всю память.
Так сделано у меня, и я не выдаю это за лучший вариант организации.
Цитата(batisto4ka @ Apr 19 2012, 09:49)

Правильно ли я понимаю, что под переносом таблицы векторов понимается копирование . То есть старая таблица векторов прерываний рапсоложенная по адресу 0x0000_0000 согласно RM0008 Table 63. Vector table for other STM32F10xxx devices остается на том же месте, и еще дополнительно копируется для своего бутлоадера? Как тогда контроллер при срабатывании прерываний будет понимать,какая обработчик ему нужно вызвать? и как описываютсся обработчики прерываний, перенесеннной таблицы веткоров прерываний?
Нет.
NVIC - Контроллер вложенных векторизированных прерываний STM32, позволяет гибко располагать таблицу во флэш или ОЗУ.
Как раз при его конфигурации и указывается адрес начала этой таблицы.
Цитата(batisto4ka @ Apr 19 2012, 09:49)

и как описываютсся обработчики прерываний, перенесеннной таблицы веткоров прерываний?
прерываний?
Обработчики прерываний описываютсся одинаково везде.
Цитата(Danis @ Apr 19 2012, 10:57)

таблица векторов с адреса 0х08000004
у cortex-m3 таблица векторов не может с такого адреса начинаться!
зачем куда то копировать/перносить таблицу? У cortex-m3 в контроллере прерываний есть регистр который указывает где таблица находится!
в IAR например можно так стартовать программу
Код
VTOR = (unsigned) адрес приложения (в начале таблица прерываний)
asm ("ldm r1, {r0,r1}\n"
"mov r13, r0\n"
"mov r15, r1");
while(1);
Цитата(lead_seller @ Apr 19 2012, 12:41)

Вектора прерываний переносятся потому, что и бутлоадеру и основной прошивке как правило требуется работа с прерываниями, и необходимо выбирать какой код обработчика прерывания мы выполняем - код бутлоадера или код основной прошивки. Для этой цели у STMовского контроллера прерываний есть функция переноса таблицы векторов прерываний. При этом появляется возможность иметь отдельные наборы обработчиков прерываний для бутлоадера и для основной прошивки.
Конечно возможен вариант с одной таблицей векторов, и программным выбором какой обработчик использовать (устанавливаем флаг работает бутлоадер или основная прошивка, и по этому флагу делаем if в ветках которого расположены разные обработчики) - бутлоадера или основной прошивки (в зависимости от того что активно), но такой вариант замедляет реакцию системы на прерывания.
Вариант с переносом таблицы векторов удобней тем, что в памяти программ мы можем хранить несколько разных прошивок (естественно скомпилированных и линкованных для использования разных стартовых адресов), и на старте системы можем выбирать какой из прошивок отдавать управление. Сейчас как раз занимаюсь такой развлекухой)). Требуется шиться по CAN с оооочень низкой скоростью (порядок байтов в секунду), причем с огромной вероятностью разрывов на линии. При этом вероятность того, что устройство продолжит функционировать после неудачной перепрошивки, должна стремится к 100%.
У нас работают тысячи устройств имеющих загрузчик (правда на LPC). Обновление прошивки - по любому интерфейсу по рабочему протоколу, при внезапной перезагрузке ничего не слетит 100%, загрузка нового ПО может быть продолжена с точки разрыва. Сбой питания возможен в любой момент хоть при загрузке прошивки хоть при обновлении её во флеш. Никакие таблицы векторов переносить не надо - на время работы загрузчика прерывания запрещены, рабочее ПО при старте само настраивает таблицу прерываний.
ПО состоит из:
1. неизменяемой части (загрузчика) в первом секторе флеш, который прошивается изначально на заводе и при удалённой прошивке не может быть перешит;
2. собственно рабочего ПО (во флеш после загрузчика).
Вся флеш (за исключением первого сектора) делится на две половины: первая - область исполняемого рабочего ПО; вторая - область хранения нового ПО, которое надо прошить.
Рабочее ПО по любому интерфейсу (или по всем включая CAN и беспроводные) принимает прошивку по рабочему протоколу устройства среди прочего обмена данными не мешая основной работе устройства.
Приём идёт в ОЗУ (так как если шить сразу во вторую половину флеши контроллера, то надо запрещать прерывания надолго, а это помешает работе основной программы).
По завершении приёма и проверки валидности прошивки, новая прошивка переписывается во вторую половину флеш контроллера и во флеш выставляется флаг требования обновления прошивки,
после чего делается RESET процу.
Стартует загрузчик, который обнаружив флаг и проверив CRC прошивки во второй половине, перешивает прошивку из второй половины флеш в первую, далее - удаляет флаг и стартует рабочее ПО из первой
половины флеш. Если загрузчик флаг не обнаруживает - значит не надо обновлять прошивку и просто передаёт управление рабочему ПО в первую половину прошивки.
Вот такой алгоритм обеспечивает 100%-надёжное удалённое обновление прошивки в устройстве по рабочему протоколу, не боящееся неожиданных сбоев питания и с возможностью широковещательного
обновления ПО.
Если в устройстве есть внешняя энергонезависимая память (SPI-флеш к примеру), то можно обойтись без хранения принимаемой прошивки во второй половине флеш контроллера и хранить её в этой памяти.
Цитата(Danis @ Apr 19 2012, 13:04)

Вероятно, можно и не переносить, но мне пока в голову не приходит, как организовать тогда взаимодействие загрузчика и основной программы.
Расположите с помощью компоновщика команду перехода на _c_int00 (точку входа в С-программу) с самого начала образа прошивки и передавайте управление на первый адрес прошивки.
Цитата(Danis @ Apr 19 2012, 13:04)

Обработчики прерываний описываютсся одинаково везде.
Неправда
batisto4ka
Apr 19 2012, 07:26
Цитата(jcxz @ Apr 19 2012, 11:22)

1. неизменяемой части (загрузчика) в первом секторе флеш, который прошивается изначально на заводе и при удалённой прошивке не может быть перешит;
2. собственно рабочего ПО (во флеш после загрузчика).
Ну где-то так я себе это и предсатвляю. У меня еще вот вопросы:
1. Как можно определить программно размер записанной программы в МК.
2. Как программно перегрузить МК?
Цитата(jcxz @ Apr 19 2012, 10:22)

Неправда

Критика – это хорошо, разъясните еще как это сделать для ТС, будет вообще здорово

.
lead_seller
Apr 19 2012, 07:27
Делаю примерно так же, но помимо текущей версии ПО, храню в памяти программ и дефолтную заводскую прошивку, чтобы можно было одной простой командой откатить версию прошивки на гарантировано рабочую. Просто специфика в том, что прошивку подгоняют под нужды заказчиков прямо на объекте, а при проблемах с новыми версиями необходимо максимально быстро восстановить работоспособность устройства.
Вот для возможности запуска обоих прошивок и переношу таблицу прерываний в область нужной мне прошивки.
По программной перезагрузке:
функция NVIC_SystemReset(); в StdPeriph Lib от STM.
Цитата(batisto4ka @ Apr 19 2012, 10:26)

Ну где-то так я себе это и предсатвляю. У меня еще вот вопросы:
1. Как можно определить программно размер записанной программы в МК.
2. Как программно перегрузить МК?
Вот для Вас полезная ссылочка будет
тыц
Цитата(batisto4ka @ Apr 19 2012, 13:26)

1. Как можно определить программно размер записанной программы в МК.
В общем случае - никак.
Если вам нужно определять размер, то можно зафиксировать его постоянным (равным макс. доступной памяти программ).
Возможно в каких-то конкретных компоновщиках есть возможность определить максимальный адрес размещения прошивки и
поместить его в заранее определенное место памяти - тогда можно воспользоваться этим.
Не забывайте, что программа в общем случае может занимать ряд несоседних участков памяти программ с дырками между ними.
Цитата(batisto4ka @ Apr 19 2012, 13:26)

2. Как программно перегрузить МК?
Например - с помощью внутреннего сторожевика.
Цитата(lead_seller @ Apr 19 2012, 12:41)

....с огромной вероятностью разрывов на линии. При этом вероятность того, что устройство продолжит функционировать после неудачной перепрошивки, должна стремится к 100%.
позвольте встрять в вашу беседу.
с СТМ я пока еще только теоретик, и у меня возник вопрос:
если имеются во флеш firmware1 и firmware2.
допустим firmware1 - битый, тогда как стартанут с firmware2 без использования ассэмблерной комманды по переходу на точку входа firmware2?
Цитата(lead_seller @ Apr 19 2012, 13:27)

Делаю примерно так же, но помимо текущей версии ПО, храню в памяти программ и дефолтную заводскую прошивку, чтобы можно было одной простой командой откатить версию прошивки на гарантировано рабочую. Просто специфика в том, что прошивку подгоняют под нужды заказчиков прямо на объекте, а при проблемах с новыми версиями необходимо максимально быстро восстановить работоспособность устройства.
Вот для возможности запуска обоих прошивок и переношу таблицу прерываний в область нужной мне прошивки.
Проблема будет при таком даунгрейде если у вас есть некая область в энергонезависимой памяти данных для хранения текущей конфигурации и например каких-то рабочих данных.
Если в новой версии ПО меняется формат этой области, то новая версия как правило знает как переконвертить старый формат в новый, а вот старая прошивка не может знать формат данных новой прошивки.
lead_seller
Apr 19 2012, 07:44
При каждом старте бутлоадер проверяет целостность прошивки по CRC. Если CRC совпало то стартуем custom прошивку, если прошивка битая - проверяем целостность default прошивки и стартуем ее, если и default окажется битым, то бутлоадер будет ждать процесса прошивки.
А запуск прошивки реализуется переносом таблицы векторов и банальным переходом по стартовым адресам прошивок (они жестко заданы).
По данным - области константных данных в Flash контроллера для каждой из прошивок свои, данные во внешней SPI flash (там хранятся настройки и архив) при подгрузке их любой прошивкой проверяются (тем же CRC) и если они не подходят для работающей прошивки изменяются на настройки по умолчанию. Так что никаких проблем с несовместимостью данных не возникает
Цитата(lead_seller @ Apr 19 2012, 13:44)

При каждом старте бутлоадер проверяет целостность прошивки по CRC. Если CRC совпало то стартуем custom прошивку, если прошивка битая - проверяем целостность default прошивки и стартуем ее, если и default окажется битым, то бутлоадер будет ждать процесса прошивки.
А запуск прошивки реализуется переносом таблицы векторов и банальным переходом по стартовым адресам прошивок (они жестко заданы).
По моему алгоритму у вас НЕ МОЖЕТ оказаться случая, что обе прошивки битые (при условии что начальная прошивку на заводе прошла нормально).
lead_seller
Apr 19 2012, 07:56
Не спорю. Вообще и при моем алгоритме тоже. Но лучше перестраховаться, чем телепать в шахту, и в полузатопленном штреке, при свете коногонки, перепрошивать устройство по JTAG). У меня задача, обеспечить максимальную вероятность того, что устройство запустится с хоть какой-то прошивкой, и 100% вероятность того, что при работающей связи и питании, его можно будет прошить удаленно.
Цитата(lead_seller @ Apr 19 2012, 13:44)

По данным - области константных данных в Flash контроллера для каждой из прошивок свои, данные во внешней SPI flash (там хранятся настройки и архив) при подгрузке их любой прошивкой проверяются (тем же CRC) и если они не подходят для работающей прошивки изменяются на настройки по умолчанию. Так что никаких проблем с несовместимостью данных не возникает
Да, так не возникнет, но при этом будут потеряны текущие настройки связи к примеру, а с дефолтными связь может не работать.
У нас по этой причине запрещены даунгрейды ПО.
lead_seller
Apr 19 2012, 12:36
У нас проблемы с настройками связи не возникают. По всей сети одна, жестко заданная скорость CAN. Максимум что может случится - изменится идентификатор устройства (номер) на линии, на номер по умолчанию. При этом он все равно останется уникальным (при монтаже номер по умолчанию не используется), а потом его поменяют командой сверху. Все остальные данные генерятся непосредственно прошивкой на этапе самотестирования.
Мы даунгрейды тоже не любим, но не все протестируешь наверху, и приходится заливать в работающие устройства экспериментальные прошивки. Вот и надо иметь возможность быстрого отката.
EugenyAM
Apr 19 2012, 18:37
Хочу привести несколько рекомендаций, основываясь на собственном опыте, как не наступить на грабли при написании связки бутлоадер-приложение.
1. Перед переходом на приложение запретите прерывания.
2. Если разрешен Watchdog, задайте его период "с запасом" и перед переходом на приложение
вызовите IWDG_ReloadCounter();
3. Если бутлоадер использует USB, не забудьте выполнить USB_Cable_Config(DISABLE);
4. Отключите устройства, которые не используются приложением, если такие есть.
5. В приложении первым действием задайте новый адрес таблицы векторов, затем проинициализируйте WatchDog и только потом разрешайте прерывания. После Reset, инициированного Watchdog'ом или после прошивки по JTAG, STM32 стартует с текущей таблицей векторов, т.е с начала приложения. Поэтому приложение в общем случае не должно знать о существовании бутлоадера и о том, какая периферия уже была включена и настроена. В приложении лучше сделать все заново.
6. STM32 XL-Density имеют два банка Flash по 512К, расположенные с одного и того же адреса.
Какой банк будет подключен после Reset, задается в Option Byte. Этот механизм можно использовать
для хранения двух версий прошивки, скомпилированных с одного начального адреса. При этом, бутлоадер нужно продублировать в каждом банке.
batisto4ka
Apr 22 2012, 17:02
Подскажите, как сделать безусловный переход по адресу. Бутлоадер записал прогу например по адресу 0х08010000. Находила примеры типа
Код
void (*FuncPtr)(void);
FuncPtr=(void(*)(void))0x08010000; //адресс куда переходим
FuncPtr();
Но при выполнении последней строчки (вызов функции) FuncPtr() стшка вылетает в хард фолт. В чем может быть проблемма и как организовать прыжек из бутлоадера в основную программу? Может, можно сделать ассемблерную ставку типа goto или jump?
Цитата(batisto4ka @ Apr 22 2012, 21:02)

Но при выполнении последней строчки (вызов функции) FuncPtr() стшка вылетает в хард фолт.
Нужно к адресу прибавить единицу. Это особенность режима Thumb. На досуге почитайте систему команд кортексов, посмотрите листинг дизассемблера.
Код
((void(*)(void))0x08010001)();
EugenyAM
Apr 23 2012, 03:44
Цитата(batisto4ka @ Apr 23 2012, 00:02)

Подскажите, как сделать безусловный переход по адресу. Бутлоадер записал прогу например по адресу 0х08010000.
как организовать прыжек из бутлоадера в основную программу?
Если приложение скомпилировано для загрузки с адреса 0x8010000, по этому адресу будет размещаться таблица векторов.
Вектор Reset находится по смещению +4, но это не точка входа, а указатель на нее. Поэтому нужно достать адрес из таблицы векторов и уже его присвоить указателю на функцию.
Смотрим проверенный пример от ST:
Код
#define ApplicationAddress 0x08010000 //Начало нашего приложения
typedef void (*pFunction)(void);
pFunction Jump_To_Application;
uint32_t JumpAddress;
if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000) //Проверяем, есть ли что-нибудь по адресу (там должно лежать значение SP для приложения, его кладет линкер)
{
JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4); //Адрес перехода из вектора Reset
Jump_To_Application = (pFunction) JumpAddress; //Указатель на функцию перехода
__set_MSP(*(__IO uint32_t*) ApplicationAddress); //Устанавливаем SP приложения
Jump_To_Application(); //Запускаем приложение
}
while(1); // Если приложение не записано, Watchdog вернеет нас на начало бутлоадера
В приложении переносим таблицу векторов, ведь мы приходим сюда с активной таблицей векторов бутлоадера и первое же прерывание выкинет нас в обработчик бутлоадера, если он определен, а если не определен, то возможен переход неизвестно куда и его следствие - HardFault.
Код
void main(void)
{
__disable_interrupt(); // Запрещаем прерывания
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x10000); //Адрес таблицы относительно начала Flash
...
}
Ответы на все вопросы лежат в примерах из AN2557
batisto4ka
Apr 23 2012, 07:03
Цитата(EugenyAM @ Apr 23 2012, 07:44)

Ответы на все вопросы лежат в примерах из AN2557
Где найти эти примеры?
EugenyAM
Apr 23 2012, 09:29
Цитата(batisto4ka @ Apr 23 2012, 14:03)

Где найти эти примеры?
Все лежит на сайте ST
Описание AN2557Примеры AN2557
batisto4ka
Apr 23 2012, 13:34
Цитата(EugenyAM @ Apr 23 2012, 07:44)

//Указатель на функцию перехода
__set_MSP(*(__IO uint32_t*) ApplicationAddress); //Устанавливаем SP приложения
__disable_interrupt();
}[/code]
что то ругается компилятр на эи строчки, хотя путь к CoreM3 прописан.
Цитата(batisto4ka @ Apr 23 2012, 17:34)

что то ругается компилятр на эи строчки, хотя путь к CoreM3 прописан.
Мне вот такой способ больше нравится:
Код
#define APP_ADDR 0х08010000
void
start_app(void)
{
static const uint16_t code[] =
{
0xF850, 0xDB04, /* LDR.W SP, [R0], #4 */
0x6800, /* LDR.W R0, [R0] */
0x4700, /* BX R0 */
};
((void (*)(uint32_t))(1 + (int)code))(APP_ADDR);
}
EugenyAM
Apr 23 2012, 19:32
Цитата(batisto4ka @ Apr 23 2012, 20:34)

что то ругается компилятр на эи строчки, хотя путь к CoreM3 прописан.
Пример под IAR, компилировал на 6.21.
__disable_interrupt() объявлена в intrinsics.h
Под другие компиляторы примеры есть в AN2557
batisto4ka
Apr 24 2012, 13:53
Цитата(scifi @ Apr 23 2012, 17:52)

Мне вот такой способ больше нравится:
Вылетает в хард фолт.
Меня интересует этот вопрос только для кейла.
Цитата(batisto4ka @ Apr 24 2012, 17:53)

Вылетает в хард фолт.
Для этого может быть множество причин, не связанных с этим кодом.
Цитата(batisto4ka @ Apr 24 2012, 17:53)

Меня интересует этот вопрос только для кейла.
Прелесть этого кода состоит в том, что он должен работать с любым компилятором.
batisto4ka
Apr 24 2012, 19:17
Цитата(scifi @ Apr 24 2012, 17:59)

Для этого может быть множество причин, не связанных с этим кодом.
Например???
k000858
Apr 26 2012, 06:12
подскажите плиз по переходу из бутлоадера в основную программу:
- можно ли одной простой коммандой деинициализировать всю переферию, которая была инициализирована в бутлоадере??? ну или каким нибудь простым изящным движением руки?
- при переходе в основную программу оперативная память контроллера остается занятой данными из бутлоадера, так? подскажите плиз простой способ подчистить память от всех этих данных?
Цитата(jcxz @ Apr 19 2012, 11:22)

Вот такой алгоритм обеспечивает 100%-надёжное удалённое обновление прошивки в устройстве по рабочему протоколу, не боящееся неожиданных сбоев питания и с возможностью широковещательного
обновления ПО.
У вашего подхода есть минус. Представьте ситуацию - загруженная прошивка в девайс имеет правильную crc, но сама по себе так испорчена, что не позволяет загрузить новую прошивку.
Конечно перед заливкой, надо провести полные испытания новой прошивки.
Ваши предложения как обойти этот минус?
Учтите, что рабочий интерфейс в общем случае у нас может быть сложным - сокет TCP/IP поверх Ethernet или GSM или ZigBee и т.п., т.е. - канал, для которого нельзя задать конфигурационные параметры по умолчанию.
EugenyAM
Apr 26 2012, 08:31
Цитата(k000858 @ Apr 26 2012, 13:12)

- можно ли одной простой коммандой деинициализировать всю переферию, которая была инициализирована в бутлоадере??? ну или каким нибудь простым изящным движением руки?
- при переходе в основную программу оперативная память контроллера остается занятой данными из бутлоадера, так? подскажите плиз простой способ подчистить память от всех этих данных?
В начале бутлоадера проверяем признак его запуска (это может быть состояние Option Byte или бита в регистре Backup Domain, далее, если не надо его запускать, идем на основную программу с неинициализированной периферией, если надо - инициализируем периферию, пишем прошивку, сбрасываем признак запуска и делаем NVIC_SystemReset(), который выкидывает нас снова на старт,
но уже со сброшенным признаком запуска.
Если память надо чистить для конфиденциальности или приложение написано на асме, тогда ничего лучше записи чего-нибудь в цикле не придумать. (Может быть DMA?)
Если приложение на Си самостоятельное, не является частью проекта бутлоадера, то компилятор пропишет в стартовом коде все инициализации переменных.
Глобальные и статические переменные автоматом обнуляются до вызова функции main(), если они явно не инициализированы в программе, поэтому ничего страшного для программы при старте из бутлоадера не должно произойти.
Цитата(jcxz @ Apr 26 2012, 12:07)

Ваши предложения как обойти этот минус?
По-моему обойти это можно только, если неизменяемый загрузчик в первом секторе флеш, зашиваемый вами на заводе, будет иметь возможность "засасывать" прошивку из вне.
lead_seller
Apr 26 2012, 12:52
Раздумывал над таким вариантом. Придумал такой вариант тестирования прошивки: в самой прошивке пишем функцию и располагаем ее по четко указанному адресу памяти программ, задача функции получить какое-нибудь число, выполнить некие действия (например, какие то арифметические действия) и вернуть ответ. Перед загрузкой основной прошивки бутлоадер сделает вызов этой функции с какими-то данными, получит от нее результат, выполнит такие же операции с этим же набором данных сам, сравнит результаты, если результаты совпадут то прошивка будет считаться валидной. Получится эдакий аналог системы пароль-отзыв.
Конечно, от необнаруженных при помощи CRC ошибок в прошивке это может и не спасти (если ошибки в прошивке есть, а сама функция-ключ будет работоспособной), но хотя бы спасет от заливки "левых" прошивок и выполнения устройством непредусмотренных действий.
batisto4ka
Apr 26 2012, 13:00
Прилагаю свой проект с функцией перехода по адресу приложения. Подскажите, почему не хочет линковаться проект?
Цитата(Lotor @ Apr 26 2012, 18:08)

По-моему обойти это можно только, если неизменяемый загрузчик в первом секторе флеш, зашиваемый вами на заводе, будет иметь возможность "засасывать" прошивку из вне.
Каким образом?
Учтите мои требования по интерфейсам, приплюсуйте сюда необходимость реализации некоего рабочего протокола обмена (довольно сложного) в бутлоадере, необходимость определения параметров конфигурации каналов связи (формат этой конфигурации каналов связи может от прошивки к прошивке поменяться и бутлоадер должен заранее знать какой он был в прошлом и будет в будущем

Т.е. - вам придётся еще раз реализовать все те функции, что есть в рабочем ПО + необходимо как-то определить, что основное рабочее ПО функционирует неверно
(а ведь определить это бутлоадеру будет очень сложно, раз на этапе тестирования новой прошивки вы сами не выявили её неработоспособности, значит эту неработоспособность очень сложно даже вам определить не говоря уже о бутлоадере

Таким образом вам придётся написать бутлоадер значительно сложнее самого рабочего ПО! Значит если у нас рабочее ПО перед пуском в серию должно пройти опытную эксплуатацию на объекте как минимум месяц, то и такой бутлоадер тем более надо ставить на опытную эксплуатацию. Только как вы будете его отлаживать, ставить на опытную эксплуатацию на объект и УДАЛЁННО ОБНОВЛЯТЬ???
Таким образом - приходим к абсурдности этой идеи

А если вы о простом интерфейсе для обновления ПО, не подразумевающем использование различных каналов связи с переменной конфигурацией, то по-моему это уже есть в самом проце в ROM изначально - у NXP в её LPC есть ISP через UART.
Цитата(lead_seller @ Apr 26 2012, 18:52)

Раздумывал над таким вариантом. Придумал такой вариант тестирования прошивки: в самой прошивке пишем функцию и располагаем ее по четко указанному адресу памяти программ, задача функции получить какое-нибудь число, выполнить некие действия (например, какие то арифметические действия) и вернуть ответ. Перед загрузкой основной прошивки бутлоадер сделает вызов этой функции с какими-то данными, получит от нее результат, выполнит такие же операции с этим же набором данных сам, сравнит результаты, если результаты совпадут то прошивка будет считаться валидной. Получится эдакий аналог системы пароль-отзыв.
Конечно, от необнаруженных при помощи CRC ошибок в прошивке это может и не спасти (если ошибки в прошивке есть, а сама функция-ключ будет работоспособной), но хотя бы спасет от заливки "левых" прошивок и выполнения устройством непредусмотренных действий.
Всё то же самое, но гораздо лучше реализует обычное CRC всей прошивки. Ведь вы предлагаете контролировать малую часть прошивки (функцию), а я - всю прошивку.
А спасение от заливки левых прошивок в моём способе делает бутлоадер, проверяя эту самую CRC перед обновлением поверх рабочей. Считать CRC генерируемой прошивки должен линковщик, благо к примеру в IAR-е это есть. Либо сторонее ПО - автоматом следующим шагом после линковки.
spasbyspas
Apr 26 2012, 17:06
Цитата(batisto4ka @ Apr 26 2012, 16:00)

Прилагаю свой проект с функцией перехода по адресу приложения. Подскажите, почему не хочет линковаться проект?
После компиляции выдает сообщение:
"
.\Listings\MSU_KDM-3322.axf: Warning: L6310W: Unable to find ARM libraries.
.\Listings\MSU_KDM-3322.axf: Error: L6411E: No compatible library exists with a definition of startup symbol __main.
"
А у вас?
Цитата(jcxz @ Apr 26 2012, 17:59)

Таким образом вам придётся написать бутлоадер значительно сложнее самого рабочего ПО! Значит если у нас рабочее ПО перед пуском в серию должно пройти опытную эксплуатацию на объекте как минимум месяц, то и такой бутлоадер тем более надо ставить на опытную эксплуатацию. Только как вы будете его отлаживать, ставить на опытную эксплуатацию на объект и УДАЛЁННО ОБНОВЛЯТЬ???
Таким образом - приходим к абсурдности этой идеи

Абсурдные идеи говорите? Представьте, что кто-то хочет сделать диверсию на вашем приборе и выставить фирму в неприглядном свете, он просто зальет 3 левых байта с правильной crc. И как удаленно вы почините такое при вашей "100% надежной" реализации?)
Цитата(Lotor @ Apr 27 2012, 10:23)

Абсурдные идеи говорите? Представьте, что кто-то хочет сделать диверсию на вашем приборе и выставить фирму в неприглядном свете, он просто зальет 3 левых байта с правильной crc. И как удаленно вы почините такое при вашей "100% надежной" реализации?)
Интересно - откуда этот злодей знает где должна храниться эта CRC и по какому алгоритму она должна быть посчитана? А если он это узнал из неких источников, то из них же он и узнает всё про вашу функцию контроля и добавит и её.
Защита от таких злодеев реализуется защитой канала связи.
В нашем ПО этому злодею сначала надо узнать пароль доступа ДЛЯ ОБНОВЛЕНИЯ ПО, а также ключ шифрования для доступа к каналу С ПРАВАМИ ОБНОВЛЕНИЯ ПО.
Или Вы в ваших устройствах позволяете обновлять ПО кому попало без защиты канала связи???