|
Самозагрузчик |
|
|
|
Apr 7 2016, 06:51
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555

|
Цитата(inventor @ Apr 7 2016, 09:34)  после того, как бинарник записан по адресу 0x08001000 как мне LOADER - ом передать ему управление? Самый лучший способ IMHO - сделать хардварный reset с помощью watchdog! лоадер уже не обнаружит прошивку и передаст управление... Но есть еще нюанс - для того что бы лоадеру обнаружить файл на SD, необходимо частично проинитить периферию..., а передавать управление основной программе после этого не хорошо! Я ставлю метку в озу по определенному адресу (типа 0x55AAAA55) и если лоадер ее обнаруживает, то стирает и передает управление основной программе (установив адрес таблицы прерываний кончено)
|
|
|
|
|
Apr 7 2016, 07:05
|
Знающий
   
Группа: Свой
Сообщений: 524
Регистрация: 25-12-08
Из: Москва
Пользователь №: 42 748

|
Цитата(KRS @ Apr 7 2016, 10:51)  Самый лучший способ IMHO - сделать хардварный reset с помощью watchdog! лоадер уже не обнаружит прошивку и передаст управление...
Но есть еще нюанс - для того что бы лоадеру обнаружить файл на SD, необходимо частично проинитить периферию..., а передавать управление основной программе после этого не хорошо! Я ставлю метку в озу по определенному адресу (типа 0x55AAAA55) и если лоадер ее обнаруживает, то стирает и передает управление основной программе (установив адрес таблицы прерываний кончено) у меня вот такие вопросы, вектора должны находится по адресу 80000000 как мне сделать так чтобы у прошики эти вектора были переопределены и не накладывались на адреса векторов у лоадера.
|
|
|
|
|
Apr 7 2016, 07:11
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
Цитата(inventor @ Apr 7 2016, 10:05)  у меня вот такие вопросы, вектора должны находится по адресу 80000000 как мне сделать так чтобы у прошики эти вектора были переопределены и не накладывались на адреса векторов у лоадера. Вся прошивка в целом линкуется с таким скриптом линкера, чтобы осталось пустое место под загрузчик. При этом вектора прошивки будут сдвинуты. Скажем на 0x8001000 - это зависит от размера загрузчика. Есть такой регистр - VTOR, который задает положение таблицы векторов Соответственно в загрузчике перед стартом прошивки его надо скорректировать, выставить стек и перейти по адресу сброса Код #define PO_START 0x8001000 SCB->VTOR = PO_START; __set_MSP(*(uint32_t*)PO_START); __DMB();
typedef void (* pf)(); (*((pf*)(PO_START+4)))();
|
|
|
|
|
Apr 7 2016, 07:46
|
Знающий
   
Группа: Свой
Сообщений: 524
Регистрация: 25-12-08
Из: Москва
Пользователь №: 42 748

|
то есть я делаю в файле линкера для прошивки исправления: define symbol __ICFEDIT_intvec_start__ = 0x08001000; define symbol __ICFEDIT_region_ROM_start__ = 0x08001000; про компиляции программы моя программа и векторы должны начинаться с адреса 0x08001000 теперь в лоадере я должен передать управление по новому адресу вектора сброса: 0x08001000 правильно я понял? вернее вектор старта + 4, там вроде в начале адрес стека идет
Сообщение отредактировал IgorKossak - Apr 7 2016, 18:33
Причина редактирования: бездумное цитирование
|
|
|
|
|
Apr 7 2016, 08:07
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(inventor @ Apr 7 2016, 12:34)  саму программу Loader я хочу разместить по адресу Flash 0x08000000 а рабочая прошивка, предположим, будет работать с адреса 0x08001000 после того, как бинарник записан по адресу 0x08001000 как мне LOADER - ом передать ему управление? В 0x1000 байт не впихнёте работу с файловой системой однозначно. Чтобы загрузчик был маленький, нужно работу с ФС вынести в основное ПО. Например: основное ПО обнаружив файл с новой прошивкой, формирует в ОЗУ информацию о цепочке кластеров файла прошивки и ставит флаг наличия. Дальше - перегружается (WDT). Дальше - загрузчик видит флаг, считывает прошивку из цепочки кластеров и шьёт её во флеш программ. Стартует новое ПО. Новое ПО, видя что обновилось, стирает исходный файл прошивки. Всё. Если нужно чтобы операция обновления ПО была устойчива к сбоям питания, то флаг и инфу о цепочку кластеров нужно сохранять в энергонезависимой памяти. Как передать управление из загрузчика в основное ПО тут уже 100500 раз обсуждалось и не ранее чем позавчера очередной раз. Учитесь искать.
|
|
|
|
|
Apr 7 2016, 08:09
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555

|
Цитата(inventor @ Apr 7 2016, 10:46)  вернее вектор старта + 4, там вроде в начале адрес стека идет да! и стек надо тоже проинитить у меня такой код, но это для LPC и IAR (просто у IAR в r1 = 0x1000 после присваивания VTOR) Код VTOR = (unsigned)0x1000; asm ("ldm r1, {r0,r1}\n" "mov r13, r0\n" "mov r15, r1"); while(1);
|
|
|
|
|
Apr 7 2016, 10:13
|
Знающий
   
Группа: Свой
Сообщений: 524
Регистрация: 25-12-08
Из: Москва
Пользователь №: 42 748

|
Цитата(jcxz @ Apr 7 2016, 11:07)  В 0x1000 байт не впихнёте работу с файловой системой однозначно. а 4 k не влезет но в 22 киболайт вполне влезает. с рюшками, uart для отладки и светодиодами
|
|
|
|
|
Apr 7 2016, 13:54
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(inventor @ Apr 7 2016, 07:34)  имеется какой то прибор с SD картой на проце STM32 я хочу сделать для пользователя возможность самому менять прошивку. У меня есть такой загрузчик. Ему требуется примерно 12K флэша. Я зарезервировал 16К, то есть, приложение компилируется так, чтобы начинаться с 16К. Файловая система на FatFS, с которой выброшено все, кроме чтения (файл прошивки я не удаляю). Есть варианты для SPI и SDIO доступа к карте. Если при старте карта и файл с определенным именем на ней обнаружены, загрузчик считывает версию образа и сравнивает с текущей версией прошивки. Прошивка для этого содержит соответствующие поля, которые как данные расположены непосредственно за таблицей векторов. Загрузчик, конечно, знает, что и как искать. Если на карте новая версия, производится запись образа во флэш и его запуск. Во всех остальных случаях загрузчик запускает имеющуюся прошивку сразу.
|
|
|
|
|
Apr 7 2016, 15:07
|
Участник

Группа: Участник
Сообщений: 63
Регистрация: 25-11-11
Пользователь №: 68 515

|
Цитата(inventor @ Apr 7 2016, 09:34)  Подскажите как правильно сделать вот что: ......... саму программу Loader я хочу разместить по адресу Flash 0x08000000 а рабочая прошивка, предположим, будет работать с адреса 0x08001000 после того, как бинарник записан по адресу 0x08001000 как мне LOADER - ом передать ему управление? 1) делаете 2 отдельных проекта-загрузчика и основной программы. В каждом проекте задаете свой стартовый адрес (меню keil project->options for target->IROM1),чтобы компилятор генерировал код с данного адреса 2) в код загрузчика добавляете функцию Код __asm void run_main_programm() { mov32 r0,#MY_PROGRAMM_START_ADRESS ldr r1,[r0] mov sp,r1 ldr pc,[r0,#4] } 3) прошили, выход из загрузчика Код VTOR=MY_PROGRAM_START_ADRESS; run_main_programm(); перед присваиванием VTOR запрещаем прерывания всей используемой в загрузчике периферии+еще запрещаем их в контролеере NVIC Ну вот собственно и все...не забудьте закоментировать в функции system_init() в коде основной программы строку типа VTOR=FLASH_BASE_ADDRESS, потому как вы уже ему присвоили свою таблицу в коде загрузчика
|
|
|
|
|
Apr 7 2016, 20:01
|

Профессионал
    
Группа: Свой
Сообщений: 1 333
Регистрация: 27-10-08
Из: Планета Земля
Пользователь №: 41 226

|
Цитата(KnightIgor @ Apr 7 2016, 16:54)  У меня есть такой загрузчик. Ему требуется примерно 12K флэша. Я зарезервировал 16К, то есть, приложение компилируется так, чтобы начинаться с 16К. Файловая система на FatFS, с которой выброшено все, кроме чтения (файл прошивки я не удаляю). Есть варианты для SPI и SDIO доступа к карте. Если при старте карта и файл с определенным именем на ней обнаружены, загрузчик считывает версию образа и сравнивает с текущей версией прошивки. Прошивка для этого содержит соответствующие поля, которые как данные расположены непосредственно за таблицей векторов. Загрузчик, конечно, знает, что и как искать. Если на карте новая версия, производится запись образа во флэш и его запуск. Во всех остальных случаях загрузчик запускает имеющуюся прошивку сразу. Вот бы его на github'е увидеть !
|
|
|
|
|
Apr 7 2016, 21:06
|
практикующий тех. волшебник
    
Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417

|
Цитата(KnightIgor @ Apr 7 2016, 16:54)  У меня есть такой загрузчик... в своё время сделал немного по другому. прошивка сама себя меняет. есть понятие версия фулл, инкрементальная, модуля. каждый модуль может существовать во флэше несколько экземпляров. загрузчик подымает последнюю устойчивую версию и все модули которые в него входят. собирает статистику, и содержит маленький проверенный код записи во флэш. каналы апдэйтов - куча = микроСД, изернет, модбас, вайфай. благо флэша - как у дурака махорки  как то так (круглый)
Сообщение отредактировал kolobok0 - Apr 7 2016, 21:07
|
|
|
|
|
Apr 8 2016, 05:37
|
Знающий
   
Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153

|
Цитата(kolobok0 @ Apr 8 2016, 00:06)  в своё время сделал немного по другому. прошивка сама себя меняет. есть понятие версия фулл, инкрементальная, модуля. каждый модуль может существовать во флэше несколько экземпляров. загрузчик подымает последнюю устойчивую версию и все модули которые в него входят. собирает статистику, и содержит маленький проверенный код записи во флэш. каналы апдэйтов - куча = микроСД, изернет, модбас, вайфай. благо флэша - как у дурака махорки  Гм, т.е. вы сделали dll на МК. Главный вопрос - зачем  ? И еще кучка вопросов по реализации, интересно  * как тестировали? По идее надо проверять каждую версию с каждым набором версий других модулей * как линковали? Каждый модуль - как отдельный проект? * у вас код запускался из flash? Тогда как разруливались несколько экземпляров модулей (адреса же фиксированные на этапе линковки)? Или вы копировали в ОЗУ? Или не применяли команды, которые работают с фиксированными адресами, только по смещению? * где жила системная библиотека (общая для всех модулей)? * что происходит с глобальными и статическими переменными? У каждого модуля фиксированный регион RAM? Или все хранится в куче? * межмодульное взаимодействие как было организовано? Т.е. как позвать функцию из другого модуля?
|
|
|
|
|
Apr 8 2016, 09:55
|
Частый гость
 
Группа: Участник
Сообщений: 123
Регистрация: 12-06-15
Из: Земля
Пользователь №: 87 133

|
Вот мой скелет бутлоадераю Выделено под него 16К флеш. В любом случае прийдется выделить целое количество секторов, тк стереть часть сектора невозможно. CODE #define APP_ADDRESS (uint32_t)0x08004000
typedef void (*pFunction)(void); pFunction Jump_To_App; uint32_t JumpAddr;
int main(void) { init_hw(); // Hardware init
upgrade_firmware();
if(check_firmware()) { // Jump to application JumpAddr = *(__IO uint32_t*) (APP_ADDRESS + 4); Jump_To_App = (pFunction) JumpAddr; // Initialize application's Stack Pointer __set_MSP(*(__IO uint32_t*) APP_ADDRESS); Jump_To_App(); } else Fault();
return 0; } APP_ADDRESS - адрес, с которого начинается основное приложение. upgrade_firmware() - процедура записи приложения в флеш - ищем на SD, если находим, сверяем версию (чтоб не перезписывать одно и то же), обновляем. check_firmware() - проверяем наличие / валидность приложения. Я, например, считаю CRC, Вы можете изобрести другой метод (напимер ЭЦП). Fault() - говорит сам за себя - приложения нет / повреждено - "моргаем красным светодиодом". Основное приложение пишется как обычно, только адрес заггрузки указывается равный APP_ADDRESS. В Keil это делается в опциях проекта. Project -> Options for target -> Target поле IROM1 = 0x08004000 Кроме этого нужно указать адрес таблицы векторов прерываний равный APP_ADDRESS. Делается это правкой файла system_*.c. Ищем строку #define VECT_TAB_OFFSET 0x0 и заменяем на свой оффсет #define VECT_TAB_OFFSET 0x4000
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|