STM32在复杂系统中实现固件自动升级的方法
2017-11-24
(沈阳新松机器人自动化股份有限公司,沈阳 110168)
STM32在复杂系统中实现固件自动升级的方法
宋宇宁
(沈阳新松机器人自动化股份有限公司,沈阳 110168)
提供了一种应用STM32微控制器实现在复杂的硬件系统中完成固件自动升级的方法。通过以太网和SPI接口实现了ARM架构STM32微控制器固件的传输、存储和自动升级;通过JTAG接口协议实现了STM32微控制器对Xilinx公司Spartan-6系列FPGA固件的下载和升级。文中详细介绍了固件自动升级方法的实现原理和开发流程,并提供了部分源码及程序流程图。经实际产品验证,该方法极大提升了现场升级维护硬件的效率,节约了服务成本,提高了产品的稳定性。
固件自动升级;STM32;微控制器;以太网;FPGA
引 言
伴随着市场上工业自动化及大型医疗器械产品的竞争加剧,产品的毛利润不断压缩,降低产品的服务成本、提升产品的服务收益已经成为企业利润成长的重要形式。作为硬件升级与维护不可或缺的环节,板卡的固件升级在工程设计及调试阶段通常是应用仿真器连接板卡来进行。但在产品发布及售出之后,应用该方法会带来很多问题:有些产品需要拆装外壳,有些则需要在复杂的系统中手动连接下载电缆,除了延长设备维护的时间,提升服务成本外还会带来额外的安全风险。因此,实现固件的自动升级成为每个大型的工业及医疗产品都必须考虑的服务功能。
实现产品固件的自动升级需要依赖系统中的控制器,本文提出了一种基于ARM微控制器实现自身的固件以及为FPGA固件自动升级的方法,通过上位机及以太网传输固件,通过JTAG协议将FPGA固件下载到FPGA外扩的PROM中,整个过程不需要拆装外壳及连接硬件仿真器,操作简单且提升了效率。
1 硬件方案概述
大型的工业及医疗器械硬件系统实现的功能较多,结构比较复杂,通常会采用x86、ARM以及FPGA多种硬件平台实现系统功能,典型的系统硬件框图如图1所示。
图1 系统硬件框图
其中,基于x86平台的PC104工控机通过有线以太网或者WiFi连接的方式与控制台计算机连接,并通过集成的无线路由器与控制台计算机及各ARM控制器板组成内部局域网。PC104用于控制台控制命令的转发、各板卡状态的反馈以及升级固件的传输等功能。ARM控制器板卡采用STM32F407微控制器,主要用于实现板卡间协议通信,复杂算法的实现及固件自动升级功能。FPGA板卡采用Xilinx公司Spartan-6系列XC6SLX45T。由于FPGA内部没有大容量Flash存储器,需要外扩PROM存储固件程序。在设置配置方案后,板卡上电时将PROM中的固件读出并加载到FPGA的SRAM中运行,配套PROM的型号为Xilinx XCF16P。FPGA板卡主要用于实现高速信号数据传输及控制命令的并发执行。ARM控制器外扩的Flash用于存放ARM控制器和FPGA板卡的固件。ARM控制器和FPGA板卡之间通过串行及并行接口进行数据通信,并通过JTAG接口将FPGA外接的PROM以菊花链的方式连接,按照JTAG的协议规范将固件依次下载到菊花链上的各PROM中。
2 STM32系列MCU与FPGA固件文件解析
2.1 STM32系列MCU的固件文件介绍
STM32系列的MCU(微控制器单元)可应用IAR for EWARM V6.40编译环境进行开发设计,程序编译后默认生成的固件格式后缀为.out,可通过JTAG仿真器及修改编译环境的配置选项,直接将程序下载到MCU的内部Flash中运行,也可下载到内部SRAM中进行在线调试。
如果采用自动升级方式,建议通过开发编译环境的配置选项输出一个*.bin文件,即二进制格式的固件文件。该文件不仅支持STM32固件的传输和自动升级,还可通过ST公司提供的STM32系列固件下载工装软件ST-link utility及ST-Link V2仿真器,将固件下载到STM32 MCU的内部Flash中运行。
图3 菊花链的连接及FPGA配置方式
ISE软件是Xilinx公司推出的FPGA及CPLD集成开发环境,该软件环境下编译生成的FPGA固件格式通常包括.bit和.mcs格式两种。编译器默认生成.bit格式的固件文件,可通过JTAG仿真器将文件下载到内部SRAM中,也可应用该文件实现FPGA固件的自动升级。BIT文件的组织格式通常为15字节的文件开始标记、文件名记录、文件创建时间、配置数据开始标记及配置数据,该文件可通过UltraEdit软件查看。在通过网络传输FPGA固件的过程中,通常只需要传递配置数据,配置数据的起始部分固定为FF FF FF FF AA 99 55 66,所以在传输数据过程中只需要检索关键字,识别到配置数据起始关键字后将前面的数据剔除即可。
MCS格式文件为ASCII格式文件,文件内容可通过文本编辑器查看。该文件格式是在ISE软件中通过BIT文件经位转换及添加校验信息等过程转换生成。该文件格式可用于通过JTAG下载电缆对PROM的配置,也可用于固件自动升级后对固件文件的回读校验。
3 硬件结构简化及FPGA固件配置方案
如果只考虑实现ARM及FPGA固件的自动升级功能,可将系统的硬件方案进行简化,因为STM32F407微控制器提供以太网MAC层接口,也可通过上位机直接与该控制器通过网络接口连接,简化的硬件框图如图2所示。
图2 简化的系统硬件框图
通常,FPGA固件的下载方式是通过板卡上预留的JTAG接口来实现的。应用ISE软件及JTAG仿真器将由BIT文件转换生成的MCS文件下载到FPGA配置的PROM中,系统重新启动后FPGA控制器读取外部PROM的文件,并将配置文件自动下载到FPGA的SARM中运行。
FPGA固件自动升级的配置方案及硬件连接如图3所示,STM32控制器要为3个FPGA控制器传递升级固件,而实现过程是将STM32及3个PROM以菊花链的方式连接,按照JTAG软件协议依次将固件下载到3个PROM中。系统重新启动后,FPGA从PROM中分别读取各自的配置文件,并加载到SRAM中实现各自的功能。
4 固件升级实现方案及关键代码
固件升级的功能在IAR for EWARM V6.4集成开发环境中完成,STM32和FPGA固件升级代码都通过STM32平台实现,STM32通过网络接收上位机传递的固件升级代码。FPGA固件升级的过程更加复杂,需要 STM32控制器按照JTAG协议将固件下载到FPGA外扩的PROM中。
4.1 STM32自动升级方案
STM32系统中除了要实现固件升级功能,还要完成板卡间通信、系统状态监控等多项功能。为了实现多任务调度及网络传输功能,需要在STM32系统中移植μC/OS-II系统及LwIP以太网协议栈。μC/OS-II是Micrium(现被Silicon Labs收购)公司的一款可裁剪、可移植、抢占式多任务嵌入式实时内核,广泛应用于微控制器中。LwIP是瑞典计算机科学院开发的一个小型开源的TCP/IP协议栈,由于它能在保持TCP协议主要功能的前提下减少对RAM和存储空间的占用,特别适合于硬件资源比较有限的MCU。操作系统的移植过程可以参考Micrium公司网站上基于STM32控制器的移植范例。
图4 .bin固件文件的存储映射方案
为了实现STM32固件自升级功能并提高系统的稳定性,需要将STM32的固件分成3个部分,分别为引导代码、备份代码及应用代码。3部分代码分别建立3个工程开发,最后将3个编译生成的.bin文件通过VC++软件合并为一个大小为256 KB的固件文件。如图4所示,引导代码存放的地址区间为0x00000~0x28000,是一个未移植操作系统的单循环任务,主要用于加载BSP文件并判断系统的固件状态,如果有新固件存放在外部Flash中,则从外部Flash将固件读取到内部Flash中。
当引导程序通过读取内部Flash标志位确认没有新固件需要更新时,引导代码将重映射的起始地址设置为应用代码的起始地址,初始化用户应用程序的堆栈指针后进行程序的重映射,程序会自动跳转到应用程序中运行,重映射部分的代码如下:
//判断用户固件起始地址是否映射到内部Flash地址
if (((*(_ _IO uint32_t*)App_base_address) & 0x2FFE0000 ) == 0x20000000){
JumpAddress = *(_ _IO uint32_t*) (App_base_address + 4);//App_base_address为应用代码起始地址
Jump_To_Application = (pFunction) JumpAddress;
//初始化用户应用代码堆栈
_ _set_MSP(*(_ _IO uint32_t*) App_base_address);
Jump_To_Application(); //跳转到应用程序
}
备份代码存放在固件中的地址区间为0x28000~0x16800,它作为应用代码的备份,只保留最基本的功能,当引导代码检测到上次固件升级失败时,将加载备份代码起始地址为重映射地址,并跳转到备份代码中运行,确保系统的基本功能能够实现,防止因固件升级失败导致板卡功能失效。
应用程序代码存放的位置为0x16800~0x3FFFF,共166 KB,用于实现全部的用户自定义应用程序,包括STM32和FPGA的固件自动升级任务。μC/OS-II系统提供了任务调度、任务管理、内存管理、任务间通信等基本功能,固件升级功能通过5个任务相互协调完成。这5个任务包括IP层任务、TCP层任务、网络服务任务、FPGA升级任务、外部Flash读写驱动任务。
(1)IP层任务和TCP层任务
这两个任务为TCP/IP协议栈的任务,负责Ethernet网络数据传输,是以太网应用层和物理层之间衔接的桥梁。代码主要来源于LwIP以太网协议栈,在此不进行详细的设计说明,只给出协议栈工作流程图。此协议栈对外的接口为标准的Socket接口函数,图5为TCP/IP协议栈的流程示意图。
图5 TCP/IP协议栈流程图
图6为TCP/IP协议栈在应用中的层次关系图。网络协议栈允许多任务通信。应用程序和协议栈的通信通过消息邮箱完成。对于每一个通信任务都有一个专用结构体变量记录任务中的信号量和消息队列。在通信时,应用进程将消息放入到邮箱中,等待TCP进程来提取消息,TCP进程根据消息的类别进行不同的处理,处理完成后TCP进程发送消息到应用进程。
图6 TCP/IP协议栈在应用中的层次关系图
(2)网络服务任务
该任务主要用于与上位机之间建立连接并实现数据传输。此任务建立网络服务器,接收来自于上位机的连接、服务请求,并接收升级固件。升级固件包括STM32和FPGA固件两种,当接收到升级STM32的请求后启动外部Flash读写驱动任务,将接收到的升级数据保存到外部Flash中,当收到完整的升级数据后将升级标志置为1并存储到特定的Flash地址。重新上电之后,引导代码优先启动,并检查该标志位,如果为1,启动升级流程,清空标志位。应用DMA将外部Flash中的固件读出并拷贝到内部Flash中然后进行重映射,程序将跳转到应用程序入口运行。此任务对外的接口为接收消息队列和网络层接口队列(通过标准的Socket接口与TCP/IP进行通信)。图7为网络服务任务的流程图。
图7 网络服务任务流程图
(3)外部Flash读写驱动任务
图8 Flash读写驱动任务流程图
外部数据Flash读写任务主要负责将从网络接收到的FPGA和STM32的升级文件通过SPI接口存储到外扩的数据Flash中,并进行数据校验。如果校验失败则上电后运行备份代码,实现系统的基本功能。在任务中采用定时查询的方式进行外部Flash的读写。任务启动后首先初始化控制I/O,并检测外部Flash状态,如果状态正常则进入等待接收数据状态,否则发送错误信息。当通过接收消息队列收到消息后,分别完成向外部Flash写入数据和从Flash回读校验的工作,完成后将数据写入成功信号发送给网络服务任务。此任务对外的接口为接收消息队列(用于接收其他任务的消息)和控制外部串行Flash的接口队列。图8为外部Flash读写任务的流程图。
4.2 FPGA自动升级方案
图9 FPGA升级任务流程图
FPGA的固件是通过网络服务任务接收而来的。网络服务任务传递消息给外部Flash读写驱动任务,调用写外部Flash函数将数据按页写入到外部Flash中并进行回读校验,随后启动FPGA升级任务。将按页读取的数据通过JTAG协议写入到FPGA外接的PROM存储器中。重新上电后,经过配置的FPGA会自动读取PROM中的固件并运行。FPGA升级任务首先初始化I/O及JTAG接口,并申请用于保存外部Flash数据的缓存区,顺序地读取固件数据,通过异或校验码确定读取数据的正确性,然后调用JTAG下载函数执行程序下载。JTAG函数中每次读取指定字节的数据并按照JTAG协议下载到FPGA的存储器中,通过写入之后的回读校验来验证写入固件数据的正确性。当所有固件数据都正确写入后向网络服务任务返回升级成功信号,否则返回错误信息。FPGA升级任务再次进入等待状态,等待任务启动信号量的唤醒,图9为FPGA升级任务流程图。
在FPGA升级任务中,JTAGRun_for_16P()函数通过JTAG下载时序将读出的固件升级数据下载到FPGA的PROM中,PROM的型号为XCF16P,函数中的关键子函数及实现方法如下:
(1)Detect( )
由图3可知,STM32微控制器的JTAG与PROM是按照菊花链方式连接的,操作PROM之前需要先通过指令探测菊花链中PROM的数量,确定后续读写PROM的指令格式。JTAG TAP状态机有6个稳定的状态,其中Shift-IR和Shift-DR为两个主要的稳态,分别用于传递指令和数据。探测器件数量应进入Shift-DR状态,将32位的0xFFFF FFFF数据通过TDI接口传递给PROM1,随后按时钟周期循环发送数据到TDI端口,直到TDO接口中收到该数据,则PROM器件的数量为循环的次数减1。在循环了4次后,TDO端口收到0xFFFF FFFF数据,所以PROM数量为3个。
(2)Ispen( )
向有效器件发送ISPEN命令,设置器件进入ISP状态,并进行Unlock操作,只有进入ISP状态后,器件才可以进行擦除和写入等其他操作。XSIR函数中的两个参数分别表示指令编号及输入指令后的等待时间;XSDR函数的4个参数分别表示要移入数据的长度、移入数据的起始地址、保存移出数据的地址及延时时间。
{
unsigned int command;
unsigned int ucTdo = 1;
GotoTapState( XTAPSTATE_RESET );
XSIR( SVF_ISPEN, 0 );
//ISPEN命令 command = 0xd0;
XSDR( 8, &command, &ucTdo, 100 );
XSIR( SVF_UNLOCK, 0 ); //解锁
command = 0x3f;
XSDR( 24, &command, &ucTdo, 100 );
}
(3)Erase( )
器件进入ISP状态后进行擦除操作,依次输入擦除指令和地址,并通过调用Check_STATUS函数周期性查询寄存器的状态,判断擦除是否结束。
{
unsigned int ucTdo;
unsigned int command = 0;
unsigned long int RunTimeTest;
RunTimeTest = 0;
XSIR( SVF_ERASER, 0 ); //擦除命令
command = 0x3f;
XSDR( 24, &command, &ucTdo, RunTimeTest );
}
(4)Write_row( )和Fvfy( )
写入和回读校验是通过Write_row( )和Fvfy( )函数完成的,Flash读取函数按行将STM32外部Flash中的数据读取到缓存中,每行512字节。因为MCS文件是BIT文件经过位转换而得到的,而实际PROM中的配置文件应该是MCS格式,所以从Flash读取的数据需要将每个字节按位颠倒顺序,再依次写入PROM中。写入和回读的过程同样按照先指令后数据的顺序,循环将数据下载到PROM中存储,如果回读校验失败,则将升级失败的结果传递给网络服务任务,并通过网络通信方式反馈给上位机。操作人员可以决定重新执行升级流程或检查软硬件故障。
结 语
[1] 高世皓.利用HEX文件实现TMS320F28335的程序升级方法[J].单片机与嵌入式系统应用,2017(7):13-18.
[2] 杨旭.基于微处理器的螺旋CT固件远程升级的设计与实现[D].沈阳:东北大学,2009.
[3] 刘火良,杨森. STM32库开发实战指南[M].北京:机械工业出版社,2013.
[4] 徐文波,田耕.Xilinx FPGA开发实用教程[M].北京:清华大学出版社,2012.
[5] 程小艳.嵌入式STM32F107VCT6微处理器接口模块开发及应用研究[D].合肥:合肥工业大学,2012.
宋宇宁(工程师),主要从事基于ARM架构的嵌入式系统软硬件开发与设计工作。
RealizationofFirmwareAutomaticUpdatinginComplexSystemBasedonSTM32
SongYuning
(SIASUN Robot&Automation Co.,Ltd.,Shenyang 110168,China)
In the paper,a method of firmware automatic updating in complicated hardware system through STM32 microcontroller is proposed.The ARM architecture STM32 microcontroller firmware transmission,storage and automatic upgrade are achieved through Ethernet and SPI interface.Spartan-6 series FPGA of Xilinx firmware download and upgrade are achieved through the STM32 microcontroller and JTAG protocol.In the paper,the realization principle and development flow of the firmware automatic upgrade method are introduced in detail.Some source codes and program flow chart are also provided.By the actual product verification,the method greatly enhances the efficiency of on-site hardware updating and maintenance,saves the service costs,and improves the stability of the product effectively.
firmware automatic updating;STM32;microcontroller;Ethernet;FPGA
TP368.1
A
2017-08-21)