首先介绍一些背景。当固件由于任何原因崩溃(例如堆栈溢出,功能指针损坏...)时,它可能会跳到某个地方并开始执行一些代码。这迟早会导致看门狗复位。 MCU将重置,我们回到正轨。除非...

当我们有写入闪存的代码(例如引导加载程序)时该怎么办?现在可能发生的是,我们将不小心直接跳入Flash编写代码-跳过所有检查。在看门狗吠叫之前,您将得到损坏的固件。这正是我正在发生的事情。

现在有人可能会说-修复导致我们甚至跳入编写代码的根本错误。好吧,当您进行开发时,您将不断更改代码。即使目前没有这种错误,也可能有明天。此外,没有代码没有错误-或至少不是我的。

所以现在我正在做某种交叉检查。我有一个名为'wen'的变量,在常规检查之前将其设置为0xa5(例如,进行检查以确保目标有效)。然后在进行实际擦除或写入之前,我检查'wen'是否真的设置为0xa5。否则,这意味着我们无意中跳入了编写代码。成功写入后,将清除“wen”。我已经用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"
);

还没有尝试过代码,明天再做。你有什么问题吗?您如何/将如何解决此类问题?

最佳答案

我见过的一种技术是确保紧接Flash写入例程之前的字节将触发某种看门狗超时或重置处理器。这样,不可能执行导致闪存写入功能并“落入”该功能的随机数据。

重置之前,您可能需要准备一些NOP,以确保正确理解说明。

假设您在完成写操作后清除了wen变量,那么您从一开始就验证该函数已运行的技术看起来很不错。

关于assembly - 避免意外覆盖固件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9320652/

10-11 16:44