Jump to content

    
Sign in to follow this  
=Zap=

После софтварной перезагрузки не работает прерывание SysTick

Recommended Posts

Выполняю перезагрузку с помощью прыжка по адресу ResetISR, хранящемуся во флэше 0x4:

((void (*)(void))HWREG(0x00000004))();

Всё перезагружается нормально, проходит __iar_program_start, main, вообще всё работает кроме прерываний SysTick. При этом SysTick работает, считает его счётчик, он ставит бит пендинг прерывания, если бит снять, то SysTick его опять ставит. Другие прерывания происходят. Да и вообще ошибки в коде инициализации нет, так как при аппаратном ресете всё работает. А при софтварном ресете вот такое чудо.

Такое ощущение, что я чего-то не знаю про инициализацию Cortex-M3 ядра.

Есть советы куда копать?

Share this post


Link to post
Share on other sites
Выполняю перезагрузку с помощью прыжка по адресу ResetISR, хранящемуся во флэше 0x4:

При такой "перезагрузке" не будет сброшена периферия и NVIC. Почему не хотите выполнить её штатными средствами?

Share this post


Link to post
Share on other sites
Выполняю перезагрузку с помощью прыжка по адресу ResetISR, хранящемуся во флэше 0x4:

((void (*)(void))HWREG(0x00000004))();

Всё перезагружается нормально, проходит __iar_program_start, main, вообще всё работает кроме прерываний SysTick. При этом SysTick работает, считает его счётчик, он ставит бит пендинг прерывания, если бит снять, то SysTick его опять ставит. Другие прерывания происходят.

Странный способ...

А SP загружаете?

 

сброс через запрос:

NVIC_SystemReset();

Share this post


Link to post
Share on other sites

Спасибо за рекомендации. Перезагружал таким способом так как по-быстрому это когда-то работало и с тех пор не трогал. А потом вдруг сломалось и было непонятно почему.

Тем не менее, разгадку я, видимо, нашёл. Поделюсь опытом: в перезагрузку я ухожу из прерывания SysTick (использовал его для счёта задержки времени перед перезагрузкой), таким образом NVIC не чувствует возврата из SysTick и новые прерывания больше не вызывает. Вызывает только более высокоприоритетные.

С SP (stack pointer) проблем нет: его нормально переинициализирует стартовый код IAR.

Кроме перезагрузки мы используем переход из бутлоадера в основную прошивку, что NVIC_SystemReset() или SYSRESETREQ уже не помогает сделать. Там были те же проблемы и придётся использовать прыжок на адрес. Теперь понятно, что его надо сделать не из прерывания.

Watchdog timer хорошая мысль. Как раз подойдёт для отсчёта той задержки, которая нужна перед перезагрузкой.

Share this post


Link to post
Share on other sites
Кроме перезагрузки мы используем переход из бутлоадера в основную прошивку, что NVIC_SystemReset() или SYSRESETREQ уже не помогает сделать. Там были те же проблемы и придётся использовать прыжок на адрес. Теперь понятно, что его надо сделать не из прерывания.

Для перехода на основную прошивку из загрузчика делаю следующее:

- Выставляю флаг "запуск основной прошивки" (переменная в ОЗУ, записываю туда сигнатуру типа 0xCAFEBABE).

- Делаю software reset.

- Загрузчик в самом начале (low_level_init()) проверяет регистр причины сброса. Если "software reset", то проверяем сигнатуру, и если есть совпадение, то затираем сигнатуру нулями и прыгаем на основную прошивку. В противном случае продолжаем исполнять код загрузчика.

Таким образом основная прошивка запускается до того, как началась инициализация загрузчика.

Share this post


Link to post
Share on other sites
// Программный RESET - Эквивалент дерганья лапы RESET.

*(u32*)(0xE000ED0C)=0x05FA0004;

Дергаем откуда угодно и когда угодно :)

Т.е. Вы предлагаете сделать ресет через регистр "AIRCR".

 

Автор не написал, что у него за МК. К сожалению, у NXP семейства LPC175x, LPC176x не поддерживают данный способ (см. UM10360, "34.4.3.6 Application Interrupt and Reset Control Register"). Поэтому приходится делать ресет через Watchdog Timer.

 

Как обстоят дела с этим регистром у других МК - я не знаю.

Share this post


Link to post
Share on other sites

Проверил свою гипотезу про прыжок изнутри прерывания. Она-то подтвердилась, но после прыжка извне прерываний таблицу векторов стартовый код IAR из флэша уже не копирует в оперативку. Видимо он видит, что таблица уже в оперативке... Так как обработчики я ставлю динамически, то всё заработало.

Для перехода на основную прошивку из загрузчика делаю следующее:

- Выставляю флаг "запуск основной прошивки" (переменная в ОЗУ, записываю туда сигнатуру типа 0xCAFEBABE).

- Делаю software reset.

- Загрузчик в самом начале (low_level_init()) проверяет регистр причины сброса. Если "software reset", то проверяем сигнатуру, и если есть совпадение, то затираем сигнатуру нулями и прыгаем на основную прошивку. В противном случае продолжаем исполнять код загрузчика.

Таким образом основная прошивка запускается до того, как началась инициализация загрузчика.

Я делаю почти так же: сигнатура в памяти, перезагрузка и проверка и затирание сигнатуры. Еще проверяю CRC прошивки перед тем как на неё перейти, а то мало ли что. low_level_init() происходит до копирования таблицы векторов прерываний в RAM. Это значит, что стартовый код основной прошивки скопирует таблицу сам, взяв её из стартового сектора. Не достанется ли ему в таком случае таблица от бутлоадера?

Автор не написал, что у него за МК. К сожалению, у NXP семейства LPC175x, LPC176x не поддерживают данный способ (см. UM10360, "34.4.3.6 Application Interrupt and Reset Control Register"). Поэтому приходится делать ресет через Watchdog Timer.

У меня Texas Instruments контроллер семейства Stellaris LM3S5Rхх. Довольно глючная штука.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this