简介
许多现代嵌入式系统需要通过现场固件更新来修复错误或改进功能。通常,此类更新功能通过自举程序来实现。自举程序是一个独立于主应用程序的特殊应用程序,能够更新主应用程序。本文档介绍了设计稳健的自举程序时必须考虑的一些细节。
1、自举程序的类型和固件更新选项
单片机自举程序可以多种不同方式工作,具体取决于硬件的复杂度和用户外部通信接口的可用性。
最基本的自举程序可以通过通信接口接收映像,并在通过完整性验证后写入接收的映像。大多数情况下,自举程序不可更新,并且仅限用于简单的接口,如UART、SPI或I2C。最终产品的用户通常无法访问这类接口,因此这类接口比较适合用于已经与主控制器建立通信接口的从MCU。
高级自举程序将实现用户可访问的接口,例如USB、SD卡或以太网。这会增大自举程序的大小,并且要求自举程序自行更新,以修复协议实现中的缺陷或者适应外部设备的变化。例如,原版本产品最高仅支持2 GB容量的SD卡,而随着时间的推移,应用经过不断更新后可支持更高容量的SD卡,但旧版自举程序仍将要求使用2 GB SD卡(届时相对来说可能很难购买到)。
如果需要高级更新,则要评估主应用程序是否可以接收和存储低级格式的映像,以便确保可供简单自举程序使用。凭借这种方法,可以实现高级更新接口,同时能够让实际自举程序依然保持简单而紧凑。
当无线系统需要更新时,将无法在自举程序中复制无线协议栈。因此,通过无线方式更新无线系统的惟一选择是在应用程序运行时接收新映像,然后让简单的自举程序执行更新。映像可以存储在主闪存阵列的可用空间中,或存储在外部存储器中。当存储在外部存储器中时,映像必须保持加密状态;而当存储在内部存储器中时,则可以对映像进行解密和验证,从而简化自举程序的设计。
2、进入方法
与主机控制器搭配使用的简单自举程序可以使用以下任一进入方法:
•专用引脚(在复位时必须置为有效)
• 重复使用其中一个接口引脚
• 应用程序请求
• 没有有效的应用程序
专用引脚是最稳健的方法,但它需要在主机和从MCU上分配额外的引脚,这并不总是可行的。
许多接口包括处于已知空闲状态的引脚,例如,SPI或I2C中SCL和SDA线上的片选。这些引脚通常使用外部上拉电阻保持空闲状态,因此从器件可以在复位时检测到置为有效的状态并保持在自举程序模式。
这两种方法都需要访问从MCU的复位引脚。但其优势在于可完全确保稳健性。即使主应用程序已损坏且主通信接口无法正常工作,主机也始终可以请求执行自举程序。
应用程序请求不需要任何附加引脚,并且通过正常的主机到从器件通信接口即可发出自举程序的运行请求。此方法需要正常工作的应用程序来处理请求。
即使应用程序区域为空或已损坏,自举程序也依然可以执行。检测算法既可能简单到仅仅查找闪存存储单元的非擦除状态,也可能复杂到对整个应用程序映像进行CRC或哈希计算。必须针对每个应用程序评估错误检测的速度和稳健性之间的权衡结果。
更高级的自举程序可能会检测到U盘或SD卡上存在更新文件,并以这种方式启动更新。
3、应用程序和自举程序之间的通信
在某些情况下,应用程序和自举程序之间需要交换更多信息,例如新映像通知、更新状态或一些附加请求。
一些MCU具有一组专门为此类用途分配的通用寄存器。这些寄存器可保证在上电时复位为0,但在复位周期内保持不变。这样即创建了一个稳健的通信通道。
如果没有特殊寄存器,则可以使用系统RAM。虽然RAM在复位周期内的状态通常保持不变,但在上电后的状态并不确定。为避免发生错误通信,建议使用多个命令副本。如果所有副本包含相同的值,则命令一定是有效的。副本数量是误报概率和存储器消耗之间权衡后的结果。至少应使用4个副本,对于单字节命令,通常使用16个副本就足够了。
如果认为RAM不可靠,或者MCU的复位过程擦除了RAM(在一些面向安全的器件上可能出现),则可以转为使用EEPROM或闪存。但缺点是许多现代MCU上暂无法提供真正的EEPROM,并且闪存具有擦除和写入粒度要求,这将导致浪费大量的闪存空间。
…………未完待续…………