嵌入式软件永远不会结束,该软件总是需要一些调整,增加功能或修复错误。嵌入式开发人员可以将产品退回给制造商进行更新,或者可以向产品派遣技术人员。无论哪种方式都很贵!有些产品的构造方式使得访问微控制器的编程端口需要完全拆除系统。引导加载程序是这两种情况的完美解决方案。
引导加载程序已经成为几乎每个嵌入式系统的必需品,但不幸的是,它们很少受到关注。对于大多数开发人员来说,更新固件的能力是事后才想到的,而不是事先想到的,这种疏忽的结果是在最后一刻放弃将任何更新功能构建到系统中。错误悄悄进入系统,并且由于缺乏测试,毫无疑问地进入了领域。有7个技巧可以遵循,以确保引导加载程序不仅更新固件,而且每次都正确。
技巧1——尽早添加引导加载程序
在设计的早期就开始启动引导加载程序,最好是在项目得到正式资助的概念验证阶段之后。嵌入式开发人员尽早将引导加载加载程序集成到系统中,不仅可以进行彻底的测试,还可以限制在集成过程中可能需要对应用程序进行的更改。
技巧2——检查复位向量
引导加载程序的目的之一是让系统进入一个已知的状态,并决定是跳到应用程序还是等待编程指令。在引导加载程序决定应该启动应用程序的情况下,到应用程序向量的跳转不应该是盲目的。系统闪存可能之前已被擦除,从而使复位向量的唯一位置为0xFFFFFFFF。如果执行这个重置向量,系统会发生什么?
在启动应用程序之前,可以对其执行的最简单的检查是确保复位向量已被编程为一个值,即未被擦除。一个被编程的重置向量给出了一个最低程度的信心,即程序不会跳到杂草中。下面的图1给出了一个例子。嵌入式开发人员甚至想变得更好,对可能的有效复位向量进行边界检查。边界检查将有助于确保复位向量不仅被编程,而且被指向有效的位置。
技巧3——执行CRC校验
重置向量检查是验证应用程序存在的良好开端,但重置向量本身并不能说明全部情况。如果固件更新中途中止会发生什么?复位向量可能已写入闪存,但应用程序本身已损坏。向应用程序添加CRC校验是验证应用程序的一个很好的方法。引导加载程序可以在启动时对应用程序空间执行快速CRC检查,如果检查成功,引导加载程序可以假定应用程序空间是完整的。
技巧4——锁定引导加载程序
在现场更新引导加载程序是一项极其危险的工作。电源故障、杂散的宇宙射线或脏兮兮的外观都可能导致内存的引导加载程序部分损坏和无法使用。结果是一个嵌入式系统被阻塞了,直到被更复杂的编程工具所拯救。引导装载程序应该是一个小的、简单的和健壮的应用程序,不需要功能升级或错误修复。嵌入式开发人员应该将引导加载程序放在受保护的内存部分,以确保它不会以任何方式、形状或形式被意外删除或覆盖。
技巧5——将闪存分成多个应用插槽
嵌入式系统有时会有复杂的需求,例如在应用程序仍在运行时更新固件,或者在更新失败时能够恢复到以前的版本。如果不将闪存空间分成多个应用程序段,这些要求将很难实现。例如,闪存空间可以被分割以包括受保护存储器中的引导加载程序和原始固件,然后是用于更新固件的两个备用应用部分。引导加载程序将对备用插槽之一进行编程,如果成功,则可以切换到使用该应用程序。在失败的情况下,引导装载程序可以总是退回到原始的或者存储在备份插槽中的应用程序。
技巧6——使用握手协议
编译器将生成应用程序的表示,该表示被分解成记录。这些记录可以以多种格式生成,但一个共同的特征是每个记录代表应用程序的一个较小的块,并且包含校验和。开发人员可以创建一个协议,一次发送一条记录,验证记录,将其写入闪存,然后用确认响应更新工具。一旦工具收到确认,就可以发送下一条记录。使用握手将刷新过程分成可管理的块,并且在出现错误时,系统可以立即处理它,而不是在更新周期结束时。
技巧7——使用Delta发生器
传统的微控制器引导程序会在更新过程中完全擦除应用闪存空间。如果仅对软件进行微小的更改,更新固件可能会浪费时间。在大型计算机系统中经常采用的方法是确定应用文件之间的增量或差异,并且仅更新那些已经改变的文件或存储器部分。嵌入式开发人员使用Delta发生器还可以用来最大限度地缩短更新微控制器应用所需的时间。