Как стать автором
Обновить

Bootloader. Part 1. Нюансы Cortex-M, устройство памяти stm32 и преднастройка

Время на прочтение8 мин
Количество просмотров20K
Всего голосов 29: ↑29 и ↓0+29
Комментарии33

Комментарии 33

Это файл ликер-скрипта

Долго думал... Захотел выпить. Потом догадался, что скорее всего имелось ввиду лиНкер-скрипта. )

Да, разумеется линкер) Спасибо

Пара тонких моментов:

  1. __set_MSP() - зло. Сразу после её вызова все стековые переменные превращаются в тыкву, а никто не гарантирует, что, к примеру, Jump_To_Application не в стеке хранится. Корректнее будет установку MSP и переход в App завернуть во что-нибудь такое: asm("msr msp, %0 \n bx %1" :: "r" (msp), "r" (reset_vector));

  2. Если на 100% придерживаться идеи «на входе в app состояние - как после сброса, только всё смещено на размер bootloader», то bootloader должен оставить прерывания разрешёнными (но деактивировать все их источники, а так же все DMA итд). С этим бывают сложности - забыли что-то деинициализировать итд, и некоторые люди поступают радикально - из boot в app оставляют единственный, максимально короткий путь сброс->проверка на необходимость входа в loader->иначе сразу в app (и ничего особо деинициализировать здесь не надо, не успели наинициализировать), а если таки вошли в loader - выходим из него перезагрузкой (таким образом деинициализируя всё и вся). Впрочем, мы - сами себе хозяева, никто не заставляет следовать именно таким правилам, на железе с ограниченной памятью бывает выгодно вообще сознательно унаследовать инициализированное состояние (попадалась даже загрузка по USB с наследованием состояний toggle и «бесшовным» продолжением общения уже из app).

  1. Все почему-то выбирают темную сторону)) Но замечание понимаю. Дело в том, что я разрабатываю общий подход, который буду использовать сабмодулем для проектов, и там все будет унифицировано. Хотя замечание очень интересное, учту;

  2. Да, это имеет смысл. Я как-то об этом даже не думал. Возможно это лучшее решение. Спасибо за комментарий!

Далеко не все STM32 всегда стартуют с адреса 0x00000000 - во многих STM32 адрес старта прошивается в специальном регистре.

Как загрузчик может обмениваться данными с приложением?

Я сразу хочу отметить, что большую часть ваших вопросов я хочу осветить в будущих статьях. Если вас действительно интересует этот или многие другие вопросы из тех что вы задали, обратитесь в личку. Мне бы не хотелось спойлерить и на скорую руку отвечать на них. Отвечая на этот вопрос, можно разметить общую область, определив ее в линкер скриптах, например. Задача тривиальна для всех кто задавался вопросом о разработке бутлоадера. Еще раз... Развернутый ответ хотелось бы оставить на будущее и действовать по собственному плану.

Как загрузчику понять, что загрузчик принял в самом деле прошивку, а не набор случайных циферок с правильной CRC?

Простой ответ: SHA. Может, есть что-то более. Но, на мой взгляд, все остальное избыточно. Для одного CRC32 нужно более 1 миллиона файлов разного размера для того, чтобы хотя бы у двух из них совпало CRC.

Можно ли сделать так, чтобы загрузчик стартовал не с адреса начала Main Flash 0x0800_0000, а например с адреса 0x0806_0000?

Можно! А нужно? Для какой задачи это может пригодиться? Кажется это что-то специфичное.

 Для какой задачи это может пригодиться? 

Например, хочу чтобы при подаче питания generic прошивка быстрее стартовала минуя загрузчик без нужды.

Да, это может быть полезно в устройствах с батарейным питанием для энергосбережения, в случае, если они используют для экономии энергии режим Standby, и быстро обрабатывают события после выхода из него, работая от внутреннего RC-генератора тактовой частоты. Исключение лишних действий может немного сократить время обработки события, а значит и количество энергии на его обработку.

Например, чтобы исключить передачу управления не до конца прошитому загрузчику в случае сбоя при его обновлении, например при пропадании питания.

Вам прислали прошивки в *.bin файле. Как загрузить и запустить эту прошивку по произвольному отступу в on-chip Nor Flash памяти?

Думаю я бы смог найти решение, если я правильно понял вопрос. Но меня, в таком случае, интересовал бы вопрос отладки.

Можно. Но если это делать без специальных ухищрений - это вызовет проблемы с обновлением самого загрузчика.

А если функция в загрузчике использует глобальные переменные?
В теории тогда в приложении случайная RAM память тихо изменитя никто об этом не узнает...

А потом прошивка внезапно возьмёт и упадет.

Это вообще повседневная ситуация, к примеру, во всяких Bluetooth контроллерах, где коммуникационный стек выполнен в виде отдельного бинарного модуля (нередко и в ROM хранящегося), из которого пользовательская часть вызывает различные функции, имеющие внутренние состояния в переменных в RAM. В таких случаях просто в «контракт» между модулями включается ограничение «диапазон RAM от сих до сих зарезервирован за ROM», в пользовательском .ld файле исключаем его, да и всё.

Можно. У st есть видео инструкция. Кажется вы знаете ответ на этот вопрос, но могу прислать ссылку, если правда интересно.

Почему в микроконтроллерах STM32 секторы NOR Flash(а) разных размеров?

К сожалению, не во всех - в некоторых все сектора размером в четверть всего флэша. Чтобы выделить при этом на загрузчик меньше нужно изворачиваться.

В STM32F4XX все сектора не одинакового размера. Есть 16k 64k 128k. Почету так?

Для одновременно быстрого стирания NOR Flash и возможности стирать только небольшие блоки в рамках подхода, когда за раз стирается только один сектор.

Да, но когда это надо в реальных приложениях на MCU?

Быстрая запись большими блоками нужна для обновления ПО в устройствах, которые должны работать постоянно, например телефонных коммутаторах, для того, чтобы уменьшить время недоступности при обновлении ПО.

А малый размер блока стирания нужен для экономии памяти, при её выделении под загрузчик и данные, которые должны стираться независимо, для уменьшения числа перезаписей каждого блока при хранении небольших данных в NOR Flash контроллера, для уменьшения потребления энергии в мобильных устройствах при этом. Также это нужно для уменьшения времени стирания при записи данных во время работы.

Было бы лучше, если бы все блоки были небольшими, но можно было бы стирать сразу много блоков. Но это сложнее схемотехнически.

Каким образом кнопочные телефоны Siemens/Motorola/Nokia могли в run-time до устанавливать игры без пере прошивки микроконтроллера внутри?

Я родился с Сони Эриксон в руках, а в сознательном возрасте был уже Андроид, так что мне нечего на это ответить, кроме "я никогда не думал над этим."

Есть открытый проект микроконтроллерного загрузчика OpenBLT.
https://www.feaser.com/en/openblt.php
Написан на Си. Собирается из CMake скриптов.

Обновляет прошивку по XCP/Modbus RTU.

Есть также прошивка Host утилитой c GUI(MicroBoot) и c CLI( BootCommander).

Учитывает шифрование Aes256.

Круто! Я перед тем как писать статью исследовал Хабр на подобную тему, но вашу не видел. Спасибо!

В таблице BOOT mode перепутаны местами boot0 и boot1. А то я загоняться стал, верно ли схему развел.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории