реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Самозагрузчик
inventor
сообщение Apr 7 2016, 06:34
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 524
Регистрация: 25-12-08
Из: Москва
Пользователь №: 42 748



Подскажите как правильно сделать вот что:

имеется какой то прибор с SD картой на проце STM32
я хочу сделать для пользователя возможность самому менять прошивку.
делал такие вещи для других процов,
с ST возникли некоторые вопросы.

предположим - нужно поменять прошивку прибора,
саму прошивку - бинарник заливаю в корень SD карты.
при включении питания маленькая программа, loader смотрит:
есть ли файл с определенным именем на SD и если есть, то
записывает его в определенный раздел внутренней flash памяти
далее после того как успешно записал бинарник на flash,
стирает его на SD карте. - передает ему управление.
если файла bin нет - то loader просто передает управление программе.

саму программу Loader я хочу разместить
по адресу Flash 0x08000000
а рабочая прошивка, предположим, будет работать с адреса 0x08001000
после того, как бинарник записан по адресу 0x08001000
как мне LOADER - ом передать ему управление?
Go to the top of the page
 
+Quote Post
KRS
сообщение Apr 7 2016, 06:51
Сообщение #2


Профессионал
*****

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



Цитата(inventor @ Apr 7 2016, 09:34) *
после того, как бинарник записан по адресу 0x08001000
как мне LOADER - ом передать ему управление?


Самый лучший способ IMHO - сделать хардварный reset с помощью watchdog!
лоадер уже не обнаружит прошивку и передаст управление...

Но есть еще нюанс - для того что бы лоадеру обнаружить файл на SD, необходимо частично проинитить периферию..., а передавать управление основной программе после этого не хорошо!
Я ставлю метку в озу по определенному адресу (типа 0x55AAAA55) и если лоадер ее обнаруживает, то стирает и передает управление основной программе (установив адрес таблицы прерываний кончено)
Go to the top of the page
 
+Quote Post
inventor
сообщение Apr 7 2016, 07:05
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 524
Регистрация: 25-12-08
Из: Москва
Пользователь №: 42 748



Цитата(KRS @ Apr 7 2016, 10:51) *
Самый лучший способ IMHO - сделать хардварный reset с помощью watchdog!
лоадер уже не обнаружит прошивку и передаст управление...

Но есть еще нюанс - для того что бы лоадеру обнаружить файл на SD, необходимо частично проинитить периферию..., а передавать управление основной программе после этого не хорошо!
Я ставлю метку в озу по определенному адресу (типа 0x55AAAA55) и если лоадер ее обнаруживает, то стирает и передает управление основной программе (установив адрес таблицы прерываний кончено)


у меня вот такие вопросы, вектора должны находится по адресу 80000000
как мне сделать так чтобы у прошики эти вектора были переопределены и не накладывались
на адреса векторов у лоадера.
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Apr 7 2016, 07:11
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 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)))();
Go to the top of the page
 
+Quote Post
inventor
сообщение Apr 7 2016, 07:46
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 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
Причина редактирования: бездумное цитирование
Go to the top of the page
 
+Quote Post
jcxz
сообщение Apr 7 2016, 08:07
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(inventor @ Apr 7 2016, 12:34) *
саму программу Loader я хочу разместить
по адресу Flash 0x08000000
а рабочая прошивка, предположим, будет работать с адреса 0x08001000
после того, как бинарник записан по адресу 0x08001000
как мне LOADER - ом передать ему управление?

В 0x1000 байт не впихнёте работу с файловой системой однозначно. Чтобы загрузчик был маленький, нужно работу с ФС вынести в основное ПО.
Например: основное ПО обнаружив файл с новой прошивкой, формирует в ОЗУ информацию о цепочке кластеров файла прошивки и ставит флаг наличия. Дальше - перегружается (WDT). Дальше - загрузчик видит флаг, считывает прошивку из цепочки кластеров и шьёт её во флеш программ. Стартует новое ПО. Новое ПО, видя что обновилось, стирает исходный файл прошивки. Всё.
Если нужно чтобы операция обновления ПО была устойчива к сбоям питания, то флаг и инфу о цепочку кластеров нужно сохранять в энергонезависимой памяти.
Как передать управление из загрузчика в основное ПО тут уже 100500 раз обсуждалось и не ранее чем позавчера очередной раз. Учитесь искать.
Go to the top of the page
 
+Quote Post
KRS
сообщение Apr 7 2016, 08:09
Сообщение #7


Профессионал
*****

Группа: Модераторы
Сообщений: 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);



Go to the top of the page
 
+Quote Post
inventor
сообщение Apr 7 2016, 10:13
Сообщение #8


Знающий
****

Группа: Свой
Сообщений: 524
Регистрация: 25-12-08
Из: Москва
Пользователь №: 42 748



Цитата(jcxz @ Apr 7 2016, 11:07) *
В 0x1000 байт не впихнёте работу с файловой системой однозначно.


а 4 k не влезет но
в 22 киболайт вполне влезает.
с рюшками, uart для отладки и светодиодами
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Apr 7 2016, 13:54
Сообщение #9


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(inventor @ Apr 7 2016, 07:34) *
имеется какой то прибор с SD картой на проце STM32
я хочу сделать для пользователя возможность самому менять прошивку.

У меня есть такой загрузчик. Ему требуется примерно 12K флэша. Я зарезервировал 16К, то есть, приложение компилируется так, чтобы начинаться с 16К.
Файловая система на FatFS, с которой выброшено все, кроме чтения (файл прошивки я не удаляю). Есть варианты для SPI и SDIO доступа к карте.
Если при старте карта и файл с определенным именем на ней обнаружены, загрузчик считывает версию образа и сравнивает с текущей версией прошивки. Прошивка для этого содержит соответствующие поля, которые как данные расположены непосредственно за таблицей векторов. Загрузчик, конечно, знает, что и как искать. Если на карте новая версия, производится запись образа во флэш и его запуск. Во всех остальных случаях загрузчик запускает имеющуюся прошивку сразу.
Go to the top of the page
 
+Quote Post
romas2010
сообщение Apr 7 2016, 15:07
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 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, потому как вы уже ему присвоили свою таблицу в коде загрузчика
Go to the top of the page
 
+Quote Post
x893
сообщение Apr 7 2016, 20:01
Сообщение #11


Профессионал
*****

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



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

Вот бы его на github'е увидеть !
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Apr 7 2016, 21:06
Сообщение #12


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(KnightIgor @ Apr 7 2016, 16:54) *
У меня есть такой загрузчик...


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

благо флэша - как у дурака махорки sm.gif

как то так
(круглый)

Сообщение отредактировал kolobok0 - Apr 7 2016, 21:07
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Apr 8 2016, 05:37
Сообщение #13


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Цитата(kolobok0 @ Apr 8 2016, 00:06) *
в своё время сделал немного по другому.
прошивка сама себя меняет. есть понятие версия фулл, инкрементальная, модуля. каждый модуль может существовать во флэше несколько экземпляров.
загрузчик подымает последнюю устойчивую версию и все модули которые в него входят. собирает статистику, и содержит маленький проверенный код
записи во флэш. каналы апдэйтов - куча = микроСД, изернет, модбас, вайфай.

благо флэша - как у дурака махорки sm.gif


Гм, т.е. вы сделали dll на МК. Главный вопрос - зачем cranky.gif ?

И еще кучка вопросов по реализации, интересно sm.gif
* как тестировали? По идее надо проверять каждую версию с каждым набором версий других модулей
* как линковали? Каждый модуль - как отдельный проект?
* у вас код запускался из flash? Тогда как разруливались несколько экземпляров модулей (адреса же фиксированные на этапе линковки)? Или вы копировали в ОЗУ? Или не применяли команды, которые работают с фиксированными адресами, только по смещению?
* где жила системная библиотека (общая для всех модулей)?
* что происходит с глобальными и статическими переменными? У каждого модуля фиксированный регион RAM? Или все хранится в куче?
* межмодульное взаимодействие как было организовано? Т.е. как позвать функцию из другого модуля?
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Apr 8 2016, 09:26
Сообщение #14


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(x893 @ Apr 7 2016, 21:01) *
Вот бы его на github'е увидеть !

Не ставил себе такую задачу. Да и там наверняка уже куча такого добра. Для меня выложить проект будет сложно, т.к. его придется вычленить из моей, как модно говорить, экосистемы. Другими словами, мой загрузчик ссылается на много чего из наработаного кода, а этот код частично организован в общие библиотеки, и т.п.
Go to the top of the page
 
+Quote Post
bugdesigner
сообщение Apr 8 2016, 09:55
Сообщение #15


Частый гость
**

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 12:50
Рейтинг@Mail.ru


Страница сгенерированна за 0.01483 секунд с 7
ELECTRONIX ©2004-2016