几乎每个嵌入式系统都需要能够在字段中更新固件以添加新特性或修复bug。但是,作为开发人员,固件领域的更新是很有挑战性的,因为开发人员必须从第三方组件供应商中规划自己的引导加载程序或获取引导加载程序。
有一条更容易的路线。这篇文章将展示如何使用设备固件更新(DFU)功能,它内置在许多微控制器中,但却常常被忽视。
固件更新选项
从头开始开发一个引导程序并不是一件简单的事情。开发人员需要解析他们的flash空间,以便多个应用程序能够共存。然后,他们需要开发一种方法,在不使用编程工具的情况下将编译后的二进制文件传输到微控制器上。这就要求他们要么开发他们的通信协议,要么通过增加外部存储器来存储新的图像来增加系统的复杂性。他们还可以增加他们在微控制器上的内部记忆量。
此外,软件本身也可能变得复杂,因为引导加载程序需要设置系统状态,并确定是否可以安全地跳转到应用程序代码。
使用自定义引导程序可以为开发人员提供非常需要的灵活性,但是有一个固件更新标准,可以在许多不需要开发人员工作的应用程序中工作:USB标准的内置设备固件更新(DFU)类。这可用于通过USB端口更新微控制器在该领域的应用程序代码,从而大大减少固件更新过程和开发周期。
DFU已经变得如此普遍,以至于一些微控制器供应商,例如STMicroelectronics甚至包括了需要将更新硬编码到ROM中的软件,而那些不需要的软件,通常提供了如何支持DFU的示例代码。
选择一个DFU-capable单片机
支持DFU最简单的方法是选择一个已经包含DFU的微控制器,如STMicroelectronics的stm32微控制器。在这些设备中,对于开发人员来说最有趣的设备是STM32 IoT发现节点和STM32F429发现组件。
STMicroelectronics STM32 IoT发现节点的图像。
图1:意法半导体STM32发现物联网节点是基于一个手臂®皮层®m4核心运行STM32L475单片机固件更新包括DFU模式功能。这个特殊的设备被设计用作一个物联网节点。(图片来源:凯利讯半导体)
STM32 IoT发现节点是一个低成本开发板,设计用于作为一个IoT传感器节点。该板包括几个不同的接口连接板,如Wi-Fi和蓝牙。有趣的是,板载STM32L475为开发人员提供了测试和使用DFU功能的能力,该设备设计用于连接互联网。
对于只想测试DFU在正常设备上的开发人员来说,STM32F429发现工具包是一个众所周知的低成本开发工具包,用于STM32F4系列的微控制器。让我们讨论一下开发人员是如何在这些微控制器上测试DFU的。
STMicroelectronics STM32F429 Discovery Kit的图像。
图2:意法半导体STM32F429发现工具包是基于一个手臂®皮层®m4核心。这个低成本开发委员会的单片机也包含了固件升级的dfumode功能。(图片来源:凯利讯半导体)
一个简单的DFU示例
DFU在每个微控制器上的访问方式不同。作为一个简单的例子,看看开发人员如何在运行STM32L475 MCU的设备上更新他们的固件。
正如前面提到的,STM32微控制器包括一个内置到他们ROM中的DFU引导加载程序,为了访问这个引导加载程序,开发人员需要在MCU启动时将一个引导脚拖到地上。引导引脚控制MCU启动的模式,比如从flash、RAM或我们的首选案例DFU USB模式启动。
准备使用DFU下载的应用程序不需要开发人员的任何额外工作。GNU编译器集合(GCC)和许多其他工具链一起支持在编译应用程序时生成DFU文件。对于开发人员来说,惟一的诀窍是确定该文件存储在何处:就像任何典型应用程序一样,调试或对象文件夹就是其中的位置。可以找到dfu文件。
DFU文件非常类似于其他应用程序记录格式,如二进制、s-record和十六进制文件。文件格式包含了通过USB传输的地址和数据信息,经过处理后写入flash中指定的位置。这个过程是如此的无缝,以至于开发人员甚至很少需要检查正在使用的协议。这些都是在幕后进行抽象的,这有助于使固件更新过程和开发工作变得不那么复杂。
有几种不同的工具,开发人员可以使用DFU将他们的应用程序转移到他们的微控制器上。可以使用的通用命令行工具是dfu-util。它可以在Linux和Windows®作为开源软件包。如果开发人员使用STM工具链,他们可以利用STMicroelectronics应用程序DfuSe(图3)。
STMicroelectronics DfuSe工具图像。
图3:STMicroelectronics DfuSe工具可用于编写由编译器(如GCC)生成的DFU文件,并将其加载到DFU的微控制器中。(图片来源:Beningo嵌入式组)
DfuSe是一种Windows GUI实用工具,它可以检测任何在DFU模式下启动的STM32设备,并通过USB连接到计算机。开发人员可以检索诸如编程供应商和产品id之类的信息。如果flash空间没有得到适当的保护,它们甚至可以复制MCU的内存内容,并使用Upload操作框将它们存储在计算机上。
在使用DfuSe时,开发人员通常只使用升级或验证操作部分。在这个区域,开发人员可以选择他们的DFU应用程序文件,然后选择升级按钮。然后,DfuSe将自动协调固件更新过程,直到整个文件被成功加载到MCU上。然后,开发人员可以选择验证映像是否被成功接收。一旦验证完毕,引导引脚可以被设置回它们的默认配置,如BOOT到flash,然后选择“Leave DFU”模式来加载和执行更新后的固件。
在没有DFU支持的设备上使用DFU
仅仅因为一个微控制器在ROM中不包含DFU引导加载程序,并不意味着开发人员不能继续使用DFU功能。DFU是一个USB类,在许多USB栈中支持。这意味着开发人员可以轻松地将DFU功能添加到他们的应用程序框架中,并且仍然执行DFU更新。
例如,微芯片技术的AT32UC3A3,没有内置的DFU模式(图4)。开发人员可以遵循一个简单的应用程序说明,描述DFU的工作原理,以及开发人员应该如何配置他们的微控制器来正确支持DFU。
爱特梅尔公司的形象AT32UC3A3 UC3-A3 XPLD AVR®32 32位单片机AVR嵌入式评估板
图4:AT32UC3A3 UC3-A3 XPLD AVR®32 32位单片机AVR嵌入式评估板不包括DFU片上但是可以添加框架USB代码,使得DFU固件更新功能。(图片来源:凯利讯半导体)
用于执行固件更新的提示和技巧。
在字段中更新固件并不一定只能来自DFU的微控制器。开发人员可能会决定更新固件的另一种方法是必要的或更实用的。在这种情况下,开发人员应该记住一些关于他们的固件更新过程的提示。这些包括:
使用校验和或散列来验证将写入微控制器内存的应用程序。
选择一个具有足够内存的微控制器来存储固件的备份拷贝,以便在出现问题时可以回滚固件版本。
验证微控制器是否有内置的flashloader,最终用户不能意外触发它。
确保已经编译并优化了任何软件引导加载程序。
锁定flash外围设备,以便应用程序不能被读取内存和反向工程。
始终确保堆栈指针、矢量表和程序计数器寄存器都设置为适当的应用程序值。
考虑使用其他的更新方法,比如使用USB MSD来使用USB MSD进行更新,就像在KL46Z自由板上演示的那样(图5)。
NXP半导体的KL46Z自由板图像。
图5:NXP半导体的KL46Z自由板是一个低成本开发板,默认情况下不支持DFU。开发人员可以使用其他的更新方法,如USB MSD,其中一个新的固件镜像被拖放到内存中。(图片来源:凯利讯半导体)
结论
几乎每个嵌入式系统都需要一种方法来更新字段中的应用程序代码,以避免被召回。从头创建或修改现有的引导程序可以将复杂性和集成问题引入到开发周期中。
相反,开发人员可以利用已经被证实的DFU能力,它被内置在USB标准中,以非常快的速度和有效地进行现场升级,几乎不需要任何努力。为了使其顺利进行,开发人员需要仔细检查他们的微控制器,并确定DFU是否内置到他们的微控制器中,或者是否需要包含支持DFU功能的软件栈。