简体   繁体   English

ARM 处理器的最干净重置

[英]The Cleanest Reset for an ARM Processor

Lately, I've been cleaning up some some C code that runs on an ARM7 controller. In some situations (upgrade, fatal error, etc...) the program will perform a reset.最近,我一直在清理一些在 ARM7 controller 上运行的 C 代码。在某些情况下(升级、致命错误等),程序将执行重置。 Presently it just jumps to 0 and assumes that the start-up code will reinitialize everything correctly.目前它只是跳转到 0 并假定启动代码将正确地重新初始化所有内容。 It got me to thinking about what would be the best procedure a la "Leave No Trace" for an ARM reset.这让我开始思考什么是 ARM 重置的最佳程序,如“不留痕迹”。 Here is my first crack at it:这是我的第一个尝试:

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)();
}

This code assumes the IAR ARM compiler and the At91Lib.此代码假定 IAR ARM 编译器和 At91Lib。 Anything I haven't considered?有什么我没有考虑到的吗?

The very best solution to accomplish a "hard reset", as opposed to simply jumping through the reset vector, is to force a watchdog timer reset -- if you have one, that is. 实现“硬复位”的最佳解决方案,就是简单地跳过复位向量,是强制看门狗定时器复位 - 如果你有一个,那就是。

Since your title is "cleanest reset", that's my advice. 由于你的头衔是“最干净的重置”,这是我的建议。 If you simply do a "jump to reset vector", the system could be in any number of states (peripherals still active, ADC conversions in progress, etc...) 如果您只是“跳转到复位向量”,系统可能处于任意数量的状态(外设仍处于活动状态,正在进行ADC转换等...)

I agree with @Dan that if your system has a watchdog timer available, that should provide the cleanest whole-board reset. 我同意@Dan,如果您的系统有可用的看门狗定时器,那应该提供最干净的全板复位。 BUT... If your processor is an ARMv7-M architecture (eg Cortex-M3, etc), you may be able to do the following even if you do NOT have a watchdog timer available, depending on your particular implementation: 但是......如果您的处理器是ARM​​v7-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);

See the ARMv7-M Architecture Reference Manual, search for AIRCR and SYSRESETREQ. 请参阅“ARMv7-M体系结构参考手册”,搜索AIRCR和SYSRESETREQ。

This may be effectively the same solution as what "Judge Maygarden" posted, but the identifiers used in his post appear to be Atmel-specific, while the AIRCR register & SYSRESETREQ bits are defined by the underlying ARMv7-M architecture, not by Atmel. 这可能与“Judgar Maygarden”发布的解决方案实际上是相同的,但是他的帖子中使用的标识符似乎是Atmel特定的,而AIRCR寄存器和SYSRESETREQ位是由底层ARMv7-M架构定义的,而不是由Atmel定义的。

That should do the trick. 这应该够了吧。 I use a similar function with an Atmel SAM3U. 我使用与Atmel SAM3U类似的功能。 I never bothered to poll the status register, but that's a good idea and I'm going to go add that right now! 我从不打扰轮询状态寄存器,但这是一个好主意,我现在就去添加它!

However, you should never get to the reset vector line since the processor will have already reset. 但是,由于处理器已经重置,因此您永远不应该进入复位向量线。 IAR has an __noreturn attribute for use in these cases to allow further compiler optimization. IAR具有__noreturn属性,可用于这些情况以进一步优化编译器。 I also load my reset function into ram (see __ramfunc ) since I use at the end of firmware updates where the microcontroller can't run from flash. 我还将我的重置功能加载到ram中(参见__ramfunc ),因为我在固件更新结束时使用,其中微控制器无法从闪存运行。

Also, you shouldn't need AT91C_RSTC_EXTRST flag unless you are controlling the reset of external devices with that line. 此外,除非您使用该线路控制外部设备的复位,否则不应使用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);
}

These days, wouldn't using CMSIS __NVIC_SystemReset(void) be cleanest?现在,使用 CMSIS __NVIC_SystemReset(void) 不是最干净的吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM