Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Обновление ПО с удаленного сервера.
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Atridies
Доброго времени суток, армоводы!

Есть железка на Cortex-M0, в которой хотелось бы иметь возможность обновления ПО с фирменного FTP-сервера. Все части загрузчика: скачивание файла в SPI Flash, собственно запись в MCU Flash - готово. Но пока не могу всё это взаимоувязать, чтобы получился надежный загрузчик (чтобы из-за провалов питания и кривых рук персонала - не умирал насовсем).

На msp430 делал следующим образом (обновление по rs485): все обработчики прерывания - были расположены по жестким адресам и обслуживали основное ПО. Сам загрузчик не использовал вообще прерывания - вся обработка была через контроль соответствующих флагов (кроме reset-а). Соответственно как бы чего не происходило - всегда после перевключения стартовал загрузчик и в этот момент его можно было перехватить (нужным пакетом на rs485) и обновить ПО. Если перехвата нет - уходим в основное ПО.

Ровно сделать также на кортексе - не получается: почему-то uart-ы периодически подвисают.

Вообще мне видится несколько решений задачи загрузчика:
1. Сделать работу загрузчика чисто по флагам и оставить прерывания для основного ПО. Хорошо, но пока - не получается.
2. Сделать загрузчик как часть основной программы, но тогда - все вызовы между ними надо будет делать по жестким адресам. Муторно писАть и отлаживать.
3. Сделать работу загрузчика по прерываниям, но внутри сделать ветвление: в функцию загрузчика или в функцию основного ПО. Убиваем скорость реакции. Не айс.


Вопросы, которые хотелось бы прояснить для себя:
1. Какой вариант загрузчика все-таки лучше ?
2. Нет ли каких-то подводных камней при работе с флагами прерывания, но без самих прерываний ? Возможно ли это в принципе на кортексе ?

Заранее спасибо.
A. Fig Lee
А там что,
NVIC_SetVectorTable()
не присутствует?

Можно и с векторами.
У нас на Кортексе М3 и сам бутлоадер можно апдейтить.
Состоит из 2х независимых программ, бутлоадер стартует с ресета, дальше
по условию или комманде может перейти в главную программу.
Было несколько граблей, но решаемо.
KRS
Цитата(A. Fig Lee @ Dec 19 2013, 00:37) *
А там что,
NVIC_SetVectorTable()
не присутствует?

Нет, у M0 VTOR нету!
Но легко эмулируется! Так что с прерываниями проблем нет!
Я эмулировал - так
http://electronix.ru/forum/index.php?s=&am...t&p=1095595
kolobok0
Цитата(Atridies @ Dec 19 2013, 00:10) *
..хотелось бы ..обновления ПО..чтобы получился надежный загрузчик..
1. Какой вариант загрузчика все-таки лучше ?..


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


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

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


минусы
а) отладка релизной версии модулей(не ядра) - на уровне азма(боевой вариант). дебажный так-же существует, (отдельно только данный модуль с
эмуляцией окружения) - и в таком варианте уже полная поддержка студией дебаг фич.
б) для модулей нельзя использовать статик адреса на память (хотя тут можно и зарезервировать бла-бла-бла, но сделал универсально).
в) при некоторых операциях взятия адреса в релиз версии, требуется привести адрес к базовому адресу загруженного
модуля(флэша), а не адреса компиляции.
jcxz
Цитата(A. Fig Lee @ Dec 19 2013, 02:37) *
У нас на Кортексе М3 и сам бутлоадер можно апдейтить.

При провале питания, во время такого обновления, потеряете своё устройство.

Цитата(kolobok0 @ Dec 19 2013, 03:14) *
сейчас для себя решил следующее:
...

Во всех наших устройствах на М3 мы давно так и делаем:
1. ПО разделено на 2 независимых: бутлоадер и рабочее. Обновляется только рабочее.
2. Загрузка нового ПО во флешь (внутреннюю флешь программ в нерабочую область или в SPI флешь) в рабочем ПО по рабочему протоколу.
3. По завершении загрузки - выставление флага и ресет.
4. В бутлоадере: проверка наличия флага, проверка валидности ПО во флешь. Если валидно - обновление ПО и снятие флага после.
5. Переход на рабочее ПО из бутлоадера.
Бутлоадер и рабочее ПО никак не связаны - при переходе на рабочее ПО, бутлоадер переходит на начальный (стартовый) адрес.
Проблем с прерываниями в бутлоадере нет если правильно управлять таблицей прерывания и NVIC и инитить всю периферию с нуля.
A. Fig Lee
Цитата(jcxz @ Dec 18 2013, 21:50) *
При провале питания, во время такого обновления, потеряете своё устройство.

Мы минимизировали такую вероятность.
Первый шаг при замене бутлоадера - перезапись вектор тейбл на
апгрейдер, если че случится после этого,
рестарт вылетит в ботлоадер апгрейдер.
Потом перепрошивается весь бутлоадер и последняя стадия -
запись реального вектор тейбл бутлоадера.

Вероятность краша есть, но заказчик предупрежден и согласился
demiurg_spb
Цитата(jcxz @ Dec 19 2013, 06:50) *
При провале питания, во время такого обновления, потеряете своё устройство.


Во всех наших устройствах на М3 мы давно так и делаем:
1. ПО разделено на 2 независимых: бутлоадер и рабочее. Обновляется только рабочее.
2. Загрузка нового ПО во флешь (внутреннюю флешь программ в нерабочую область или в SPI флешь) в рабочем ПО по рабочему протоколу.
3. По завершении загрузки - выставление флага и ресет.
4. В бутлоадере: проверка наличия флага, проверка валидности ПО во флешь. Если валидно - обновление ПО и снятие флага после.
5. Переход на рабочее ПО из бутлоадера.
Бутлоадер и рабочее ПО никак не связаны - при переходе на рабочее ПО, бутлоадер переходит на начальный (стартовый) адрес.
Проблем с прерываниями в бутлоадере нет если правильно управлять таблицей прерывания и NVIC и инитить всю периферию с нуля.

Если залили приложение с косяком в части приёма прошивки или её записи, да мало-ли ещё чего, тоже получаете КИРПИЧ.
scifi
Цитата(demiurg_spb @ Dec 19 2013, 10:33) *
Если залили приложение с косяком в части приёма прошивки или её записи, да мало-ли ещё чего, тоже получаете КИРПИЧ.

Для этого у меня загрузчик имеет аварийный режим: заливка через TFTP. Через этот же режим можно делать и первичную прошивку.
mantech
Цитата(A. Fig Lee @ Dec 19 2013, 00:37) *
У нас на Кортексе М3 и сам бутлоадер можно апдейтить.


Можно глупый вопрос? rolleyes.gif А зачем апдейтить бутлоадер вообще, создавая при этом дополнительные возможности потери прошивки?
scifi
Цитата(mantech @ Dec 19 2013, 13:22) *
Можно глупый вопрос? rolleyes.gif А зачем апдейтить бутлоадер вообще, создавая при этом дополнительные возможности потери прошивки?

Не всегда можно заранее предвидеть и реализовать весь функционал, который может потребоваться от загрузчика. Ну и баг может всплыть, куда ж без этого.
mempfis_
Цитата(scifi @ Dec 19 2013, 15:05) *
Не всегда можно заранее предвидеть и реализовать весь функционал, который может потребоваться от загрузчика. Ну и баг может всплыть, куда ж без этого.


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

Работа загрузчика и обновление ПО организованы приблизительно так:
- загрузчик стартует, проверяет crc32 2х банков внешней загрузочной памяти и crc32 приложения.
- если во внешней загрузочной памяти сбой и приложение в порядке, то запускает его.
- если во внешней загрузочной памяти всё ок, а в приложении сбой, то секция приложения обновляется из того блока загрузочной памяти, прошивка в котором помечена как новая или активная или старая (в порядке убывания приоритета), или из того блока загрузочной памяти, в котором корректное crc32. После успешного обновления запускается приложение, иначе устройство уходит в глубокий сон на 10 минут.
- если во внешней загрузочной памяти всё ок и в приложении всё ок, то проверяется статус загрузочной памяти - ищется в которой из них находится прошивка со статусом новая и выполняется обновление секции приложения. В случае успешного обновления статус прошивки в области загрузочной памяти меняется на активная. В другом банке загрузочной памяти статус меняется на старая, если текущий статус банка активная После успешного обновления запускается приложение, иначе устройство уходит в глубокий сон на 10 минут.
- если во внешней загрузочной памяти сбой и в приложении сбой, то устройство уходит в глубокий сон на 10 минут.

Обновление загрузочной памяти осуществляется только в приложении (прошивка загружается через GPRS). В процессе загрузки прошивки контролируется принадлежность прошивки данному устройству, после завершения загрузки проверяется crc32 прошивки, и если всё ок, то устанавливается статус прошивки в банке загрузочной памяти - новая. После чего устройство перезагружается.

Есть устройства с одним банком загрузочной памяти.
Там вместо статусов прошивка из секции приложения сравнивается с прошивкой из загрузочной памяти (естественно если все crc32 верны).
A. Fig Lee
Цитата(mantech @ Dec 19 2013, 04:22) *
Можно глупый вопрос? rolleyes.gif А зачем апдейтить бутлоадер вообще, создавая при этом дополнительные возможности потери прошивки?

В общем это было требование начальства.
Они в курсе рисков.
Разработка на довольно начальной стадии, поэтому бутлоадер тоже может немного менятся.
mantech
Цитата(A. Fig Lee @ Dec 19 2013, 15:55) *
В общем это было требование начальства.
Они в курсе рисков.


Ооо, ну с этим конечно, не поспоришь.. biggrin.gif
Golikov A.
надо 2 загрузчика делать
1. примитивный, на 1 путь загрузки данных, не убиваемый никогда и ничем, в который схема валиться во всех критических ситуациях. Вернее она начинает работу всегда с него и если все хорошо уходит дальше.
2. уже с наваротами, изменяемый, и прочее прочее...

правда что-то до 2 никогда не доходил, обычно уже шла рабочая прошивка, так как канала смены от 1 базового загрузчика всегда хватало....
mantech
Цитата(Golikov A. @ Dec 20 2013, 01:18) *
надо 2 загрузчика делать
1. примитивный, на 1 путь загрузки данных, не убиваемый никогда и ничем, в который схема валиться во всех критических ситуациях. Вернее она начинает работу всегда с него и если все хорошо уходит дальше.
2. уже с наваротами, изменяемый, и прочее прочее...

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


В принципе так и есть. Мне тоже хватало первого, причем загрузчик - это не ахти какая сложная прога, чтоб при тестировании не выявить принципиальные баги...
Atridies
Спасибо за ответы!

Проблема несколько модифицировалась, но не буду создавать отдельной темы.
Итак: перенес основное ПО в верхние адреса, перенес туда же вектора прерываний (временно убрав полностью использование прерываний: только ResetVector и начальное значение SP). Если в начальных адресах ставлю такие же значения для ResetVector и SP, как в векторах прерываний - все отлично работает.
Но если - в ResetVector - указать адрес функции, где стоит тупо
Код
asm("B ххх")
(где xxx - тот же адрес, что и в ResetVector) - ничего не работает.


Скажу по-другому:
Изначально ПО и вектора прерываний - лежат в 0x0800'0000. Переношу ПО и вектора в 0x0800'8000, а в 0x0800'0000 - ставлю константами те же значения, что и в 0x0800'8000 - 8 байт (SP и указатель Reset-а = 0x0800'8E41). Все работает.
Добавляю функцию в 0x0800'0100, которая состоит из одной команды "
Код
B 0x0800'8E41
". Заменяю указатель Reset-а - на 0x0800'0100. Ничего не работает.

В чем дело? Я ведь добавил-то только безусловный переход...


P.S. Да, оказывается у меня Cortex-M3 и соответственно VTOR - есть. Только от этого пока не легче.
Atridies
Проблема решена.

"указатель Reset-а - на 0x0800'0100." - должно быть 0x0800'0101. У кортекса все адреса почему-то сдвинуты на один байт вперед.
alx125
Цитата(Atridies @ Jan 7 2014, 01:40) *
Проблема решена.

"указатель Reset-а - на 0x0800'0100." - должно быть 0x0800'0101. У кортекса все адреса почему-то сдвинуты на один байт вперед.


Это не сдвижка, а признак системы команд Thumb. Для Cortex M3 он всегда "1"
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.