3

最近,我一直在清理一些在 ARM7 控制器上运行的 C 代码。在某些情况下(升级、致命错误等),程序将执行重置。目前它只是跳转到 0 并假设启动代码将正确地重新初始化所有内容。这让我开始思考什么是 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。有什么我没有考虑过的吗?

4

3 回答 3

9

与简单地跳过复位向量相反,完成“硬复位”的最佳解决方案是强制看门狗定时器复位——如果你有的话。

由于您的标题是“最干净的重置”,这是我的建议。如果您只是简单地执行“跳转到复位向量”,系统可能处于任意数量的状态(外设仍处于活动状态,ADC 转换正在进行等...)

于 2010-05-14T16:17:02.837 回答
4

我同意@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。

这实际上可能与“Judge Maygarden”发布的解决方案相同,但他的帖子中使用的标识符似乎是 Atmel 特定的,而 AIRCR 寄存器和 SYSRESETREQ 位是由底层 ARMv7-M 架构定义的,而不是由 Atmel 定义的。

于 2014-03-25T23:04:53.420 回答
1

这应该够了吧。我在 Atmel SAM3U 上使用了类似的功能。我从来没有费心去查询状态寄存器,但这是个好主意,我现在就去添加它!

但是,您永远不应该到达复位向量线,因为处理器已经复位。IAR 具有__noreturn在这些情况下使用的属性,以允许进一步的编译器优化。我还将重置功能加载到 ram(请参阅 参考资料__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);
}
于 2010-05-14T13:43:55.260 回答