Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Cortex M3 bootloader MSP/PSP
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
andrewlekar
Уже неделю бьюсь над вот такой задачей.

Есть бутлоадер, внутри ось ucos-III. Нужно стартовать приложение, в котором та же ось.
Если бутлоадер стартует приложение до запуска оси, то всё просто и понятно:
Код
static void inline jump(uint32_t addr)
{
  asm("LDR      SP,[R0]");
  asm("LDR      R0,[R0, #+4]");
  asm("BX       R0");
  
  DROP(addr);
}

Однако если ось уже запущена и стартуем из-под неё, то вылезают какие-то жуткие проблемы со стеками. Вероятно причина в отдельном стеке MSP/PSP. Я смотрю состояние CONTROL и вижу, что при запущенной оси используется стек PSP, при незапущенной MSP. В принципе проблема решается, если использовать из-под запущенной оси следующий код:
Код
static void inline jump(uint32_t addr)
{
  asm("LDR      R1,[R0]");
  asm("MSR      MSP,R1");
  asm("LDR      R0,[R0, #+4]");
  asm("BX       R0");
  
  DROP(addr);
}

Но и в таком случае происходят странности со стеками.
Я так понимаю, что проблема в том, что ось постоянно находится в PendSV Exception и использует стек PSP и при переходе в приложение это влияет на работу пользовательского приложения. Хочется при переходе в приложение выходить из режима Exception и восстанавливать стек MSP, но как покинуть Exception, я так и не вкурил. Пробовал пихать во все места EXC_RETURN, но не помогло. Восстановление стека через CONTROL[1] помогло запускать пользовательское приложение без видимых глюков, однако при возврате в бутлоадер (есть функционал возврата в бутлоадер из приложения) опять сыплются глюки.
Сергей Борщ
QUOTE (andrewlekar @ Jul 31 2013, 09:47) *
Однако если ось уже запущена и стартуем из-под неё, то вылезают какие-то жуткие проблемы со стеками.
А вы не стартуйте из-под оси. Вы можете в самом начале загрузчика (еще до запуска инициализации памяти) проверить, взведен ли флаг программного сброса. Если да - продолжаете запуск загрузчика. Если нет - проверяете целостность приложения и если оно выглядит целым - запускаете его. Если оно выглядит битым (или его нет вообще) - уходите на запуск загрузчика. После выполнения обновления делаете сброс собакой - попадете на начало этого алгоритма и уйдете по ветке проверки приложения. Если приложение получило команду обновления - делаете программный сброс, попадете в загрузчик при проверки первого условия.
При таком подходе при включении питания вы запускаете приложение не тратя кучу времени на запуск ненужного в данный момент загрузчика и приложение получает практически только что сброшенный процессор, без всяких чуждых этому приложению настроек периферии.
andrewlekar
Ну да, сброс на каждый чих решает проблему. Хотелось обойтись более мягким способом...
Сергей Борщ
QUOTE (andrewlekar @ Jul 31 2013, 10:15) *
Ну да, сброс на каждый чих решает проблему.
Он полностью развязывает загрузчик и приложение. И не на каждый чих, а только на передачу управления из приложения загрузчику.
QUOTE (andrewlekar @ Jul 31 2013, 10:15) *
Хотелось обойтись более мягким способом...
Это будет дорога усыпанная граблями. На одни вы уже наступили, некоторые могут вылезти когда будет продано очень много устройств и менять что-то будет уже поздно.
demiurg_spb
Цитата(andrewlekar @ Jul 31 2013, 12:15) *
Ну да, сброс на каждый чих решает проблему. Хотелось обойтись более мягким способом...
ИМХО это классика жанра, а не чих.
andrewlekar
Тем не менее, спасибо за совет. Переделал на сброс и стало гораздо проще.
Хотелось бы у знающих людей всё-таки выяснить, как ось деинициализировать до состояния в начале сброса, чтобы уже честно скакнуть на приложение. Просто любопытно. sm.gif

Да, ещё интересный момент. Я сделал бутлоадер релоцируемым в ОЗУ (при помощи линкера и какой-то матери), чтобы можно было при желании апдейтить и его самого. Однако при попытке разместить CRP секцию не вижу вообще никакого результата. Видимо дело в том, что секция CRP объявлена как readonly, а в линкере требуется всё readonly инициализировать в ОЗУ. Кто-то натыкался на такую проблему? Как можно потребовать, чтобы инициализация (IAR 6.5x) тащила в ОЗУ всё кроме секции CRP?
toweroff
Цитата(Сергей Борщ @ Jul 31 2013, 12:12) *
После выполнения обновления делаете сброс собакой

или через RGU

Цитата(andrewlekar @ Jul 31 2013, 12:31) *
Как можно потребовать, чтобы инициализация (IAR 6.5x) тащила в ОЗУ всё кроме секции CRP?

указать CRP как const unsigned int @ 0xxxxxxxx
andrewlekar
Цитата
или через RGU

Я сделал всё через системный сброс. Но выделил в ОЗУ неинициализированную расшаренную область. В неё пишу magic и boot_request.

Цитата
указать CRP как const unsigned int @ 0xxxxxxxx

Неа, не работает.
toweroff
C IAR не работал, в кейле бы выделил область CRP и в скаттере явно указал в LoadRegion адрес укладки этой области
andrewlekar
Запилил релизную версию на гитхаб. Довольно-таки узкоспециализированная штука получилась, но может кому пригодится при написании своего бутлоадера...

https://github.com/blackyblack/LPC-DfuSe-Bootloader
kolobok0
Цитата(andrewlekar @ Jul 31 2013, 12:31) *
...Хотелось бы у знающих людей всё-таки выяснить, как ось деинициализировать до состояния в начале сброса, чтобы уже честно скакнуть на приложение. Просто любопытно. sm.gif...


Те жи грабли, другой вектор захода и увы - тот же финал(приблизительно в это же время как и у Вас). Суть: юзаю freertos, по задаче надо её тормознуть. торможение сделал с возвратом в точку запуска(с полным восстановлением контенкста). обошёл режимы работы тем, что выход из шедуллера на фазе прерывания. Но грабли как и у Вас - при повторном запуске происходит кривизна. Некоторое время бился, но в последствии взвесив все за и против рещил уходить через ребут, перед необходимостью рестартовать ось(она так-же является обновляемой и версионной) - такая комбинация для изделия более устойчивей.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.