|
|
  |
Помогите выгрузить ОС и перейти в Bootloader, STM32, ChibiOS |
|
|
|
Jan 8 2015, 16:58
|

В поисках истины
  
Группа: Свой
Сообщений: 431
Регистрация: 7-01-06
Из: Россия
Пользователь №: 12 923

|
Всем првиеТ!
Экспериментирую с bootloader и пока сделал так: в самое начало Flash располагаю Bootloader, а с 0x0800400 первый попавшийся пример с USART из набора ChibiOS (ессестно с измененным .ld скриптом, чтобы начиналось всё с 0x0800400). Бутлоадер проверяет не нажата ли кнопочка при подаче питания на протяжении там 500ms и если нет, то перекидывает таблицу указателей и стек "на основное приложение", ежеле нажата кнопочка, то загружается сам и делает своё грязное дело. Ну всё примитивно просто и как обычно. Теперь захотелось странного - загрузить бутлоадер из приложения. Самое простое сделать SoftReset, но надо держать кнопочку. тогда я сделал ячейку в памяти куда пишу флаг и снова переношу таблицу векторов и вызываю ResetHandler бутлоадера. Но вот беда, всё падает и зависает. Нет, переходить то оно переходит, но вызываются какие-то прерывания, видать которые были настроены в примере. Я пошёл в ЛОБ - перечислил перед переносом таблицы прерывания все регистры переферии, где можно было бы разрешить прерывание и запретил их наверняка. Отключил SysTick. Но ВСЁ РАВНО что-то происходит и bootloader зависает в Assert вызванный из заглушки на прерывание. Есть способ выяснить что его вызывает? Дебагер не видит какое прерывание прыгнуло в этот указатель - back trace тупо начинается сразу с Assert(). Сижу вот и описываю все вектора в пустышки, дабы понять какая именно пустышка вызывается.
|
|
|
|
|
Jan 8 2015, 20:46
|

Знающий
   
Группа: Участник
Сообщений: 974
Регистрация: 4-04-08
Из: далека
Пользователь №: 36 467

|
Цитата(Alexey Belyaev @ Jan 8 2015, 11:58)  Всем првиеТ!
Экспериментирую с bootloader и пока сделал так: в самое начало Flash располагаю Bootloader, а с 0x0800400 первый попавшийся пример с USART из набора ChibiOS (ессестно с измененным .ld скриптом, чтобы начиналось всё с 0x0800400). Бутлоадер проверяет не нажата ли кнопочка при подаче питания на протяжении там 500ms и если нет, то перекидывает таблицу указателей и стек "на основное приложение", ежеле нажата кнопочка, то загружается сам и делает своё грязное дело. Ну всё примитивно просто и как обычно. Теперь захотелось странного - загрузить бутлоадер из приложения. Самое простое сделать SoftReset, но надо держать кнопочку. тогда я сделал ячейку в памяти куда пишу флаг и снова переношу таблицу векторов и вызываю ResetHandler бутлоадера. Но вот беда, всё падает и зависает. Нет, переходить то оно переходит, но вызываются какие-то прерывания, видать которые были настроены в примере. Я пошёл в ЛОБ - перечислил перед переносом таблицы прерывания все регистры переферии, где можно было бы разрешить прерывание и запретил их наверняка. Отключил SysTick. Но ВСЁ РАВНО что-то происходит и bootloader зависает в Assert вызванный из заглушки на прерывание. Есть способ выяснить что его вызывает? Дебагер не видит какое прерывание прыгнуло в этот указатель - back trace тупо начинается сразу с Assert(). Сижу вот и описываю все вектора в пустышки, дабы понять какая именно пустышка вызывается. Чтото не так сделано, наверное. В HardFaultHandlere можно поймать откуда что пришло. Но: какая микросхема хоть?. А! СТМ32 А таблицу векторов зачем переносить? Просто SoftReset. Код void NVIC_GenerateSystemReset(void) { SCB->AIRCR = AIRCR_VECTKEY_MASK | (u32)0x04; }
Сообщение отредактировал A. Fig Lee - Jan 8 2015, 20:48
--------------------
Верить нельзя никому, даже себе. Мне - можно.
|
|
|
|
|
Jan 9 2015, 18:09
|

Знающий
   
Группа: Участник
Сообщений: 974
Регистрация: 4-04-08
Из: далека
Пользователь №: 36 467

|
Цитата(Alexey Belyaev @ Jan 9 2015, 12:41)  А как поймать? Яж написал, что не хочу ресет, ибо придётся деражать кнопочку. Хочется перейти в бутлоадер, да так, чтобы дать ему понять, что это произошло не по ресету, а именно его вызвали "на сцену". 1.Я в JLink/IAR ставлю брейкпоинт на HardFaultHandler. 2. Легче использовать ресет, но передавать флаг. Флаг может быть разный. У меня есть внешняя EEPROM, там флаг. Работает так: На ресет (в том числе и ресет/принудительный переход в бутлоадер) или питание: а) проверяется состояние кнопки, если она нажата, стоим в бутлоадере б) если она не нажата, читаем флаг, если он 0xFF, значит программы нет или она недействительна (или был принудительный переход в бутлоадер), стоим в бутлоадере в) если там 0хFE, значит мы записали правильную программу, и прыгаем туда д) если мы все еще в бутлоадере, ждем команды. В гланую программу прыгаем по определенной команде В программе: а) делаем какуюто инициализацию б) проверяем наш флажок, если там 0xFF, пишем туда 0xFE, чтобы бутлоадер нас загружал в) если поступила команда в бутлоадер, пишем в флажок 0хFF, делаем ресет В качестве флажка можно использовать: а) внешнюю EEPROM  внутренюю flash c) battery backed RAM (RTC) d) обычную RAM память. Только надо одну ячейку в определенном для бутлоадера и программе месте назначить __no_init в IAR и проверять ее на каой нибудь ключ, типа 0х3FDEADEB..
--------------------
Верить нельзя никому, даже себе. Мне - можно.
|
|
|
|
|
Jan 9 2015, 19:04
|

Знающий
   
Группа: Участник
Сообщений: 974
Регистрация: 4-04-08
Из: далека
Пользователь №: 36 467

|
Цитата(Alexey Belyaev @ Jan 9 2015, 13:17)  а RAM проца после SoftReset в каком состоянии? Как после хард ресета, все в 0. он же переходит на начальный аддресс, там обнуление глобальной памяти, поэтому и надо __no_init для какойто ячейки, чтоб ЕЕ не обнуляли никогда
--------------------
Верить нельзя никому, даже себе. Мне - можно.
|
|
|
|
|
Jan 10 2015, 08:03
|

В поисках истины
  
Группа: Свой
Сообщений: 431
Регистрация: 7-01-06
Из: Россия
Пользователь №: 12 923

|
Цитата(Сергей Борщ @ Jan 9 2015, 22:53)  Такой флажок у вас уже есть, он называется RCC_CSR_SFTRSTF и лежит в RCC->CSR. Просто делайте программный сброс и проверяйте его в загрузчике. После проверки сбрасывайте битом RCC_CSR_RMVF. После окончания загрузки сбрасывайте процессор собакой, это позволит не попасть снова в загрузку после сброса. Думал об этом. Но в программу у меня хорошо получается переходить переносом прерывайний и всего такого. Цитата(A. Fig Lee @ Jan 9 2015, 22:04)  Как после хард ресета, все в 0. он же переходит на начальный аддресс, там обнуление глобальной памяти, поэтому и надо __no_init для какойто ячейки, чтоб ЕЕ не обнуляли никогда Просто интересно было, если не учитывать действия "софта" содержимое RAM после софтового сброса сохраняется...
|
|
|
|
|
Jan 10 2015, 12:28
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Alexey Belyaev @ Jan 10 2015, 10:03)  Думал об этом. Но в программу у меня хорошо получается переходить переносом прерывайний и всего такого. Пока получается. Усложните загрузчик - начнется цирк. После того, как ваша программа или загрузчик запустит кучу прерываний, что будет вызываться после подмены таблицы векторов? А если программа или загрузчик еще и ПДП запустит - будет вообще весело, когда ПДП начнет складывать данные поверх данных загрузчика/программы. Сброс гарантирует, что все последствия работы предыдущей программы будут устранены. И достигается это минимальными усилиями - одной командой сброса. Приводить периферию в исходное состояние вручную гораздо сложнее. То есть при переходе в программу вам нужно будет переносить прерывания и все такое, но делать это желательно сразу после сброса, пока периферия находится в нетронутом состоянии.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|