首先一些背景。当出于任何原因的固件崩溃(例如堆栈溢出,损坏的函数指针...)时,它可能发生,它跳到某处并开始执行一些代码。这迟早会导致看门狗复位。 MCU将重置,我们回到正轨。除非......避免意外的固件覆盖
什么,当我们有一个写入闪存(例如引导程序)代码?现在可能会发生我们不小心直接跳入闪存编写代码 - 跳过所有检查。在监督人员咆哮之前,最终会损坏固件。这正是我发生的事情。
现在,有些人可能会说 - 解决导致我们甚至跳进写代码的根本错误。那么,当你正在开发时,你会不断地改变代码。即使目前在那里没有这样的错误,明天可能会有。此外,没有代码是无bug的 - 或者至少不是我的。
所以现在我正在做一些交叉检查。我有一个名为'wen'的变量,我在通常的检查之前将其设置为0xa5(例如,检查以确保目标有效)。然后在做实际的擦除或写之前,我检查'wen'是否真的被设置为0xa5。否则这意味着我们不小心跳进了写作代码。成功写入'文'后清除。我已经在C中完成了它,并且它运行良好。但是,仍然存在轻微的理论上的机会腐败将会发生,因为从'wen'这个最终检查的指示很少,直到写入SPMCR寄存器。
现在我想通过把这个检查到组装,在写SPMCR和SPM指令之间,以改善这一点。
__asm__ __volatile__
(
"lds __zero_reg__, %0\n\t"
"out %1, %2\n\t"
"ldi r25, %3\n\t"
"add __zero_reg__, r25\n\t"
"brne spm_fail\n\t"
"spm\n\t"
"rjmp spm_done\n\t"
"spm_fail: clr __zero_reg__\n\t"
"call __assert\n\t"
"spm_done:"
:
: "i" ((uint16_t)(&wen)),
"I" (_SFR_IO_ADDR(__SPM_REG)),
"r" ((uint8_t)(__BOOT_PAGE_ERASE)),
"M" ((uint8_t)(-ACK)),
"z" ((uint16_t)(adr))
: "r25"
);
还没有试过的代码呢,明天就会那样做。你有没有看到任何问题?你如何解决这个问题?
是的,成功写入后会清除wen。 这个对__assert的调用实际上触发了看门狗复位(加上它记录了关于触发它的一些信息)。 很高兴听到人们实际上使用这种方法:) – Stefan 2012-02-17 07:01:47