最近,我一直在清理一些在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。我还没有考虑过吗?
答案 0 :(得分:8)
实现“硬复位”的最佳解决方案,就是简单地跳过复位向量,是强制看门狗定时器重置 - 如果你有一个,那就是。< / p>
由于你的头衔是“最干净的重置”,这是我的建议。如果您只是执行“跳转到复位向量”,系统可能处于任意数量的状态(外设仍处于活动状态,ADC转换正在进行中等等)
答案 1 :(得分: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。
这可能实际上与什么&#34; Judge Maygarden&#34;发布,但他的帖子中使用的标识符似乎是Atmel特定的,而AIRCR寄存器&amp; SYSRESETREQ位由底层ARMv7-M架构定义,而不是由Atmel定义。
答案 2 :(得分: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);
}