2012-02-16 69 views
5

首先一些背景。当出于任何原因的固件崩溃(例如堆栈溢出,损坏的函数指针...)时,它可能发生,它跳到某处并开始执行一些代码。这迟早会导致看门狗复位。 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" 
); 

还没有试过的代码呢,明天就会那样做。你有没有看到任何问题?你如何解决这个问题?

回答

3

一种技术我所看到的是,以确保立即字节之前你的闪存写入程序会引发某种看门狗超时,或者复位处理器。这样,就不可能执行导致闪存写入功能的随机数据,而只是“陷入”该功能。

您可能需要重置,以确保指令正确解释前,有一些NOP指令。

您的验证功能已经从开始运行的技术,看起来像一个很好的,假设你清除wen变量一旦你做到了写。

+0

是的,成功写入后会清除wen。 这个对__assert的调用实际上触发了看门狗复位(加上它记录了关于触发它的一些信息)。 很高兴听到人们实际上使用这种方法:) – Stefan 2012-02-17 07:01:47

2

我不确定为什么你需要有能力在你的引导程序中写入闪存。我们的引导加载程序可以,因为它可以通过串口更新应用程序。因此,我们通过确保加载程序不包含任何写入闪存的代码,消除了无意写入的可能性。下载的代码是包含要写入的图像的相同包中的头文件。板载图像具有存储的编程算法的校验和,并在运行之前对其进行验证。

如果你正在写内部生成的东西,那么我会看看硬件相关的联锁。如果先前已将特定离散输出引脚设置为ON,则只允许写入。要回答“IP跳过检查怎么办”的问题?你可以分两部分来完成。首先为算法设置一些关键变量。 (要写入的地址 - 将初始化的内容保存到无效的内存中,并且只在写入之前的独立调用中正确设置,然后让写入功能检查您的硬件互锁。在中断中执行其中一个启用步骤,或者对计时器作出响应,如果你有恶意IP,那么这些东西不可能以正确的顺序被击中。

如果您的IP真的可以跳到任何地方,可能无法防止无意的写入。你所希望的最好的就是你确保到达那里的唯一途径也设置了成功写作所需的一切。

+0

我正在做同样的事情(通过UART更新)。在应用程序和引导程序中都有写入代码。所以他们可以交叉更新对方,并且我还在闪存中存储了一些配置。 我不知道你有什么样的uC,但是我拥有的不能从RAM执行代码,所以上传写入代码不是一种选择。 其实我正在使用类似的程序,你说的与HW联锁。这是我在设置问题时试图解释的问题......看起来我做得不好:) – Stefan 2012-02-17 18:09:43

+0

@Stefan:小心从应用程序更新引导加载程序。擦除和写入之间的功率损耗会发生什么?糟糕,您的引导程序已经消失,并且您已经堵塞了您的设备。作为飞思卡尔HCS08项目,引导加载程序实际上设置了CPU寄存器以防止其被覆盖,并且应用程序无法写入闪存中的这些页面。注意安全。 – tomlogic 2012-02-17 18:49:54

+0

@tomlogic:我有2个编写代码 - 在应用程序和引导程序中 - 他们可以交叉更新对方。 uC默认为应用程序代码。如果我无法更新bootloader,我仍然会唤醒应用程序并可以重试。 引导程序使用一个技巧。它将应用程序代码从最高页面写入最低页面。在写入第一个页面(实际上是最高页面)之前,它会将'跳转到引导加载程序'写入页面0.现在唯一的问题是它不应该写入最后一页(页面0)。所以机会非常小,最终导致不可恢复的闪光。 – Stefan 2012-02-18 00:21:15