升级嵌入式设备软件时常常会出现“变砖”的可能性,例如在写入FLASH时发生了电源故障。两个问题:
- 实施升级机制的最佳实践是什么,以最小化设备“变砖”的概率?
- 使升级过程具有失效安全性的最佳实践是什么,以便可以从安装软件到FLASH期间发生的断电等事件中恢复?
升级嵌入式设备软件时常常会出现“变砖”的可能性,例如在写入FLASH时发生了电源故障。两个问题:
这完全取决于应用的重要性。有两种基本方法(备份和引导程序),有时也会将它们结合起来。
许多系统具有只读引导程序(例如redboot),然后是两个闪存存储器块(通常在同一芯片上)。然后,引导程序有一个标志来选择从哪个存储器块启动。该标志会根据升级(失败或成功)等事件而更改。
因此,在升级时,运行版本会将新负载复制到备份存储器块中,检查校验和,切换引导标志,然后重新启动设备。设备将在新存储器块上重新启动,使用新的负载。重新启动后,新的负载可以将自己复制到备份存储器块中。
通常还有一个硬件复位的看门狗定时器。这样,如果固件失控,则无法启动看门狗,硬件复位将重新启动设备,引导程序将寻找一个稳定的负载。
Open Mesh项目是此方法的一个很好的例子。
在内部闪存上使用校验和,如果CRC/校验和无法正常工作,则默认备份。这样,如果设备出现错误的校验和,它就知道升级未完成,并可以重置到另一设备上存储的默认/先前的固件。
这需要一些预启动(可能在引导加载程序中)来检查校验和。一个静态的代码位。
编辑:进一步评论。如果您想检查错误的固件,而不仅仅是损坏的固件,则您的校验和/检查数据也可以封装版本信息(以及该标头的检查)。我认为Linksys路由器就是这样做的,这可能使它们难以使用自定义固件重新刷写。
校验和很好,但只能保护您免受闪存损坏的数据。如果您闪存了一个具有有效校验和但适用于不同产品型号的图像文件呢?在紧急情况下可以访问的只读默认引导加载程序是我见过的最好的东西。
确保在运行任何应用程序代码之前(在启动时或下载完成后),引导加载程序对应用程序进行CRC检查。如果不合法,则引导加载程序不会运行该代码。
如果引导加载程序决定无法运行应用程序代码,则必须具有向用户发出信号并重新开始下载的能力。
如果处理器的闪存不足以存储备份应用程序,或者RAM不足以存储新应用程序直到下载完成,则这些显然变得更加重要。
在这些情况下,下载的文件最好具有一个小标题,使得引导加载程序可以确定该文件是否适用于该系统。此标题也可以具有CRC。如果此系统的标题有效且CRC正确,则引导加载程序可以擦除闪存(但不包括自身!)并继续下载。否则,它将中止而不触及现有的应用程序代码。
我知道这个问题已经有答案了,但有些人需要更可靠的解决方案。如果你的项目确实是使命关键的,你可以选择这种方法。
基本计划是始终拥有一个不能失败的备份计划。
使用 PIC 或其他可以编程真正处理器闪存的微控制器。您可以让它在一块数据上使用校验和,并通过串行、USB 甚至以太网接口进行交互(不要笑,这并不难)。这个设备在现场(甚至可能永远)无法重新编程,因此您始终有一个备份计划。PIC 可以在 PPP/SLIP 或以太网上运行 Web 服务器,因此与它的接口并不一定很麻烦。搜索 TCP-Lean。尽量不要嘲笑。(该网站适合工作场所)。将编程端口放在其他地方。安全性不能得到保证。
程序在主 CPU 上运行,并运行自己的引导加载程序。您有三个程序:引导加载程序、维护程序和真正的程序。
这允许升级引导加载程序过程以及程序。您可以在一些额外的闪存中运行备份引导加载程序,带有看门狗来重置您并使用备份,如果您无法启动。
所以你有可升级的嵌入式应用程序、可升级的引导加载程序和可升级的维护模式。还有一个备份模式,不能失败。
希望没有人需要发现这很有用。
在一些实验室设备(而不是消费者设备)上,我看到了使用程序员电路构建的板子。在最糟糕的情况下,您可以打开外壳,插入程序员并重新加载默认软件 - 或将其送回供您执行相同操作。当然,这需要真正的金钱。
在我的一些项目中使用的一些自定义板上有可替换的ROM。这更便宜,但不太方便。