杭万里,张荣
(中国电子科技集团公司第五十八研究所,江苏无锡214035)
随着社会发展,各行各业大量使用嵌入式电子设备,如道路上的高清数字监控摄像头、远程水文监控设备等。这些设备的软件升级维护又是常态,而设备一旦安装,拆卸十分繁琐,这就要求其必须能够远程在线升级。嵌入式设备一般是基于单片机/DSP/ARM开发的,远程在线升级实际是对其程序进行远程升级。多数已发表的论文是针对某个特定芯片远程升级的研究,不具备普遍性[1-2]。文中从远程升级的原理,将其分为五个功能环节,每个环节给出一个或多个实现策略,并且某些核心功能代码可以复用,从而简化开发。实际应用中只需根据使用芯片,在各环节选择实现策略,分别实现,最后集成并调试即可。本文最后章节对单片机/DSP/ARM各举一个实际应用范例。
注:不包含可以运行linux/andriod操作系统ARM,因其自身已具备远程升级功能。
远程在线升级包含5个环节:程序数据准备、程序数据传输、烧写环节、程序更新方式、用户程序跳转方式。
嵌入式设备在线升级的前提,是要准备好待烧写程序,这些程序本质上也是数据。编译生成的程序一般为HEX格式,里面包含程序数据、长度、地址、校验等信息。实际烧写只用到程序数据本身,其他信息如长度、地址、校验等信息均不需要。去掉冗余信息后的程序数据为BIN格式的文件。HEX格式文件转BIN格式文件是一步必不可少的环节。但可以选择在上位机预先处理,还是在嵌入式设备中处理。
程序升级必须将待更新的程序数据传输到嵌入式设备中。传输的物理层有串口、SPI、CAN、IIC、网络等,协议层有CAN通讯协议、串口通讯协议、TCP/UPD通讯协议、TFTP通讯协议等。这些协议有些已带有校验和数据重发功能,有些没有。可通过定义通用的数据帧协议[3],从而确保这些数据的校验和完整性,而不是依赖于原有的通讯协议。
程序升级必须将BIN格式的程序数据烧写到指定存储空间去。所以程序须内嵌烧写功能。程序数据的烧写可以一次性烧写,也可以分批次进行,相应的烧写程序可以一次性准备好,也可以分批次准备。
程序更新方式分为两种。第一种是程序整体更新,即擦除,再写入新的程序。就是擦除整个程序所占空间,再写入新的程序数据,较为简单。但中途断电无法启动。第二种是将存储空间上的程序分为两段,第一段启动程序功能为接收并更新第二段程序即用户程序,其始终保持不变,中途掉电不会影响启动。第二段程序为用户程序实现具体功能,可被擦除更新。本节着重分析分析第二种方式,即二级启动及更新原理和更新模式。
1.4.1 基本原理
将程序分为两部分:启动程序和用户程序部分[4-5]。启动程序(Bootloader)是固定的,包含了数据接收、校验、擦除、烧写等功能。用户程序则是实现嵌入式设备功能的代码。如图1所示。
图1 二级启动模式
嵌入式设备上电启动后,开始运行启动程序,到结束时跳转到用户程序,这两段程序可以物理相邻,也可以不相邻。这两段程序实际是分别编写编译生成,彼此独立,只是通过跳转语句进行关联。
如果用户程序中,不涉及中断,可忽略。但一般嵌入式设备程序都会涉及中断。在启动代码跳转到用户程序之前,将系统的中断向量地址转移到用户程序中的中断向量表[6-7],即NVIC2。否则用户程序发生中断后会从启动代码的中断向量表NVIC1查找中断地址,从而产生错误中断响应。
如图1所示的缓冲(Buffer)是启动程序中使用的缓冲空间,在运行用户代码时,可认为没有使用。
1.4.2 擦除/烧写/标志位
用户程序更新涉及两个基本功能:程序和数据空间的擦除和写入。启动代码本身是固定不变的,但又需要判别当前状态,所以一般会设一个的标志位,如图1中的标志位FLAG。标志位中含有多种状态:升级态、擦除态、烧写态、用户程序就绪态(有些包含多个,如用户程序1就绪态、用户程序2就绪态等)。
1.4.3 用户程序策略
如嵌入式设备程序代码过大或存储空间较小,建议擦除原有用户空间,再烧写进新的用户程序。如图1所示,先擦除用户程序空间,再烧写入新的用户程序。在升级过程中,一旦擦除之后,发生错误或掉电情况,嵌入式设备的基本功能将无法实现。但升级功能依然可用。
所以存储空间足够时,建议使用多用户程序策略,如图2所示。假设当前使用用户程序1,升级时擦除用户程序2空间,再将新程序烧写到用户程序2空间,最后修改标志位,即跳转改到用户程序2空间。
图2 接用户程序策略
这种方法是在烧写入用户程序2空间,并完成校验后再修改标志位。如果在升级过程中发生错误或掉电等意外情况,系统依然可以继续运行用户程序1。由此衍生,可以存储多个用户程序,只需更改标志位,从而可以快速切换用户程序。
第一种程序更新方式,程序不存在跳转方式的问题。第二种更新方式启动程序需要跳转到用户程序。根据标志位跳转到最新的用户程序的首地址。
远程升级方案在上面五个环节中,有3个环节有多种实现策略,需要根据实际情况选择合适的方式实现方式。
HEX文件转换为BIN文件可选择在上位机或嵌入式设备中实现[8]。由于上位机实现该功能更为容易、简便。建议在上位机对HEX进行预处理,生成所需的BIN文件。
2.2.1 数据通讯方式
程序数据通过远程方式传输给嵌入式设备。常规模式过多关注物理层和协议层,如串口、SPI、网口、TCP、UPD、TFPT协议。对数据协议帧很少关注,定义时随意性大、通用性差,不利于跨平台使用。制定统一的协议帧,可以做到跨硬件跨平台使用,即便单片机/DSP/ARM不能直接与外界交互,也可通过其他设备对协议帧进行转发,从而实现数据通讯,如图3所示。
图3 远程通讯模式
下面给出一个简化版的通信数据帧[9]。
实际举例,待烧写程序为131 K字节,则程序数据存储在Body[512]中,一共需要后台服务器向单片机/DSP/ARM发送262+1个分包,最后一个为程序校验包,即总分包数BlockTotalNum为263。详细说明不在这里展开。
通过通讯数据帧可以将程序数据分包发送给待升级的嵌入式设备,从而无需关注物理层和协议层是哪种方式。
2.2.2 程序数据接收策略
如果用户程序较小或者缓冲空间很大,可以采用一次性接收待烧写程序。接收完成后,经过完整性校验,再进行烧写。如图4所示。
图4 整体接收程序策略
如果用户程序较大,一次性无法全部缓冲存储,可以采取每接收完一个分包就立刻进行烧写的策略。如图5所示,如果存储空间足够,建议使用整体接收的方式。
图5 分包接收烧写程序策略
烧写程序根据不同的芯片有着固定的烧写方式。
这里分为整体更新和二级启动及更新模式。在1.4中已详细叙述。这里需要注意以下两点
2.4.1 启动代码准备
启动代码正常编译,并使用JTAG等常规方式烧写进存储空间。
2.4.2 用户代码准备
因为用户代码烧写到的是指定地址,所以在编译时,必须设定到相同的地址空间上。编译生成的HEX文件,可以通过PC程序转换成BIN文件,并进行分包和加入校验包。
仅仅在二级启动模式下有用。
本节中将举3个实际应用范例,由于篇幅关系,仅涉及部分核心代码。
这是一颗以8051为核的单片机升级方案[10-12],与外界通讯是通过SPI端口。程序数据准备在上位机完成,程序数据传输通过数据协议帧方式,烧写代码内嵌在程序中。更新模式采用二级启动模式,不含多用户程序。
在KEIL的内存分配框中对启动代码和用户代码的进行空间分配:
第一条是关中断,因为一旦发生中断将会跳转到用户程序的中断响应,从而发生不可知错误。第二条是烧写。第三条跳转到绝对地址。由于8051的中断向量地址固定不可变,所以用户程序必须通过二次跳转的方式实现中断。增加一个JUMP.ASM文件,下面是部分代码:
其中0x03为外部中断0地址,0x0B为定时器0溢出地址,当发生外部中断0时,跳转到地址0x03,然后再跳转到0x801003。即用户程序发生中断时,增加了一次中断向量地址的跳转,从效果上看是和正常的中断没有区别。定时器0中断和其他中断地址依次类推。
这是 TI的 TMS320DM642 的升级方案[13,14]。与外界通讯是通过网络口。该DSP芯片启动后由系统自动将NOR FLASH上的1K字节搬移到SDRAM当中,然后运行。通过这1K字节程序将NOR FLASH上的其余内容搬移到SDRAM当中。
该芯片使用较为复杂。程序数据在上位机使用TI的HEX6X软件进行数据转换。程序数据的传输通过网络采用数据协议帧的方式传输到DSP的SDRAM当中。程序的更新模式采用整体擦除,然后整体烧写的模式。这种方式一旦发生错误或中途掉电,程序不可恢复。采用方式的部分代码:
由于整个系统的NOR FLASH整体为4M字节,而SDRAM空间较大,可直接更新整个NOR FLASH。该方案存在一定的风险,但由于其主频为600MHz,速度较快,实际使用中尚未发生错误。
这是ST的STM32F207VCT6的升级方案[15-20]。程序数据同样在上位机处理完成。程序数据通过SPI采用数据协议帧方式进行传输。程序更新采用二级启动模式,单用户程序模式。在KEIL的内存分配框中对启动代码和用户代码的进行空间分配:
本文归纳了单片机/DSP/ARM远程升级基本原理,针对程序数据准备、程序数据传输、程序数据烧写、程序更新方式、用户程序跳转方式提出了不同的实现方案,并详细分析了这些方案的原理和优缺点。各环节方案相对独立,易于实现。在实际应用中,根据需求选择各环节的方案组合成最终远程方案。最后给出了实际项目中基于单片机、DSP、ARM3个范例,并列出了部分核心代码。
单片机/DSP/ARM远程升级是嵌入式设备必不可少的功能。本文对远程升级开发具有很强的指导意义。