Самый чистый сброс для процессора ARM - PullRequest
3 голосов
/ 14 мая 2010

В последнее время я очищаю некоторый код C, который работает на контроллере ARM7. В некоторых ситуациях (обновление, фатальная ошибка и т. Д.) Программа выполнит сброс. В настоящее время он просто переходит на 0 и предполагает, что код запуска будет правильно все заново инициализировать. Это заставило меня задуматься о том, что будет лучшей процедурой а-ля "Leave No Trace" для сброса ARM. Вот мой первый треск на это:

void Reset(void)
{
   /* Disable interrupts */
   __disable_interrupts();

/* Reset peripherals, externals and processor */
AT91C_BASE_RSTC->RSTC_RCR = AT91C_RSTC_KEY | AT91C_RSTC_PERRST | AT91C_RSTC_EXTRST| AT91C_RSTC_PROCRST;

while(AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_SRCMP);

/* Jump to the reset vector */
(*(void(*)())0)();
}

Этот код предполагает использование компилятора IAR ARM и At91Lib. Что-то, что я не учел?

Ответы [ 3 ]

8 голосов
/ 14 мая 2010

Самое лучшее решение для «жесткого сброса», в отличие от простого перехода через вектор сброса, - это принудительный сброс сторожевого таймера - если он у вас есть, то есть.

Так как ваш заголовок "чистый сброс", это мой совет. Если вы просто выполните «переход к сбросу вектора», система может находиться в любом количестве состояний (периферийные устройства все еще активны, выполняется преобразование АЦП и т. Д.)

4 голосов
/ 26 марта 2014

Я согласен с @Dan, что если в вашей системе имеется сторожевой таймер, это должно обеспечить самый чистый сброс всей платы.НО ... Если ваш процессор имеет архитектуру ARMv7-M (например, Cortex-M3 и т. Д.), Вы можете сделать следующее, даже если у вас нет сторожевого таймера, в зависимости от вашей конкретной реализации:

#define SYSRESETREQ    (1<<2)
#define VECTKEY        (0x05fa0000UL)
#define VECTKEY_MASK   (0x0000ffffUL)
#define AIRCR          (*(uint32_t*)0xe000ed0cUL) // fixed arch-defined address
#define REQUEST_EXTERNAL_RESET (AIRCR=(AIRCR&VECTKEY_MASK)|VECTKEY|SYSRESETREQ)

printf("\nRequesting an external reset...\n");
fflush(stdout);
REQUEST_EXTERNAL_RESET;
printf("\nIt doesn't seem to have worked.\n");
fflush(stdout);

См. Справочное руководство по архитектуре ARMv7-M, выполните поиск AIRCR и SYSRESETREQ.

Это может фактически быть тем же решением, что и сообщение, опубликованное «Судьей Мейгарден», но появляются идентификаторы, использованные в его сообщении.быть специфичными для Atmel, в то время как регистр AIRCR и биты SYSRESETREQ определяются базовой архитектурой ARMv7-M, а не Atmel.

1 голос
/ 14 мая 2010

Это должно сработать. Я использую аналогичную функцию с Atmel SAM3U. Я никогда не удосужился опросить регистр статуса, но это хорошая идея, и я собираюсь добавить это прямо сейчас!

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

Кроме того, вам не нужен флаг AT91C_RSTC_EXTRST, если вы не управляете сбросом внешних устройств с этой линией.

__noreturn void Reset(void)
{
    __disable_interrupts();

    AT91C_BASE_RSTC->RSTC_RCR = AT91C_RSTC_KEY |
                                AT91C_RSTC_PERRST |
                                AT91C_RSTC_EXTRST |
                                AT91C_RSTC_PROCRST;

    while (AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_SRCMP);
}
...