Перейти к содержанию
    

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

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

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

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

 

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

NVIC_SystemReset();

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как вариант сбрасывать через Watchdog Timer. Завели его на несколько миллисекунд и дальше while(1);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гость MALLOY2

Если это Cortex-M3, надо использовать встроенную возможность софтвеерной перегрузки, в регистре SCB_AIRCR установить бит SYSRESETREQ.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

- Делаю software reset.

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

// Программный RESET - Эквивалент дерганья лапы RESET.

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

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

// Программный RESET - Эквивалент дерганья лапы RESET.

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

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

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

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проверил свою гипотезу про прыжок изнутри прерывания. Она-то подтвердилась, но после прыжка извне прерываний таблицу векторов стартовый код 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хх. Довольно глючная штука.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...