姜晓道,赵紫君

(华东光电集成器件研究所,安徽蚌埠,233000)

0 引言

在产品开发过程中,对微处理器的调试通常使用专用的仿真调试工具,如ARM系列芯片通常使用J-Link,DSP芯片使用XDS工具,这都需要将调试工具通过线缆连接到产品单板上,通过JTAG接口对微处理器进行仿真和程序下载[1]。此种调试方法在开发阶段非常适合于软件工程师调试产品,然而当软硬件定型且产品大批量生产之后,这种程序更新方法就显得效率低下,每次产品升级都需要维保人员现场更新程序,会导致企业维护成本增加。另外,一个企业的产品往往多种多样,特别是目前芯片垄断的大背景下,各个厂家都在寻求国产化替代方案,不同产品应用的微处理器可能多种多样。针对上述产品开发背景,本文提出了一种新型的在线升级方案,基于在线应用编程技术原理,设计一个独立的引导加载软件,可利用产品的现有通信端口,对产品的软件程序进行更新。此方案不仅能够实现程序代码的在线更新,还能做到在不同型号微处理器之间进行快捷移植,实现跨平台应用。

1 在线应用编程(IAP)原理

IAP(In Application Programming)即在线应用编程,指的是用户自己设计的程序在运行过程中可实现对芯片应用程序部分的Flash区域的擦除和烧写[2]。在后续维护升级时,尤其是产品发布后,IAP可复用现有的通信端口对产品的应用程序进行更新,实现产品软件版本的升级。因为IAP仅仅使用产品的一组通信接口,所以IAP从技术理论上可实现产品的不拆封调试和远程调试。

在一款芯片中应用IAP技术中可以实现程序A对程序B的在线更新,意味着芯片存储程序的Flash至少需要映射为两个存储单元[3],分别存储程序A和B。程序A命名为引导加载(Bootloader)软件,程序B命名为应用程序(Application)软件。Bootloader软件主要实现的功能:

(1)判断程序执行在线升级功能还是跳转应用程序执行;(2)通过某种通信方式(USB、CAN、UART、SPI、MODBUS等)接收上位机发送的数据;(3)擦除“应用程序”区的Flash并将接收到的数据写入“应用程序”区Flash;(4)从引导加载软件跳转到应用程序处并执行。

Bootloader软件必须在出厂前通过JTAG或ISP等方式烧写到芯片中,并且每台产品的bootloader软件仅需在出厂时烧写一次即可,后续应用程序则可以由Bootloader软件进行烧写和更新。

2 Bootloader软件设计

一个完整的产品bootloader功能需要包含的软件有三部分:bootloader软件、PC上位机软件和应用程序软件。Bootloader软件和应用程序软件使用C语言编程,非常方便移植和后续升级;PC上位机软件采用当前主流的C#语言编程,实现指令下发和通信数据帧的显示。

本次Bootloader软件设计背景是基于STM32F407芯片的电机控制器,产品默认配置启动方式为从内部Flash启动,产品本身设有的RS232接口,Bootloader软件可复用RS232端口实现在线升级功能。

2.1 Flash地址分配

对于bootloader软件,要求上电后立即进入boot区域执行,即系统上电复位后,bootloader软件从地址为0x8000000处执行,因此Flash起始地址需设置为0x0800000。根据对bootloader软件的规划和对应用程序大小的分析评估,应用程序规模不超过400K字节大小,所以bootloader软件所占用flash大小设置为16K字节,即flash地址从0x8000000处开始,前16k字节存储bootloader软件,其余496K字节全部作为应用程序存储使用,如图1所示。

图1 Flash内部区域划分示意图

STM32F407芯片编程使用的工具为Keil,Flash区域划分方法如下:

(1)keil软件“魔术棒工具”菜单下“Target”页面中起始地址设置为0x8000000,大小设置为0x3E80。

(2)修改工程文件中的SCT文件,将SCT文件中起始地址和程序大小设置为0x0800000和0x3E80。

2.2 Bootloader上位机软件功能设计分析

Bootloader在线烧录系统包含上位机控制端软件和嵌入式终端设备两部分,上位机控制软件主要功能是将编译器编译完成的应用程序烧写文件进行处理打包,然后发送至嵌入式设备,嵌入式设备接收后更新应用程序区的Flash,Flash更新完成后,嵌入式设备给上位机发送结束帧命令,并将写入Flash的数据校验码返回给上位机,上位机收到校验码并校验无误后,结束与嵌入式设备的通信[4]。上位机软件运行流程如图2所示。

图2 上位机软件运行流程示意图

2.3 Bootloader软件引导加载流程分析

要实现在线加载功能,最关键部分为bootloader软件的引导加载设计。对引导加载软件的功能进行分析,将引导加载软件整个执行过程分为三大状态:升级态、跳转态和空闲态。三种状态的转换条件如图3所示。

图3 Bootloader软件状态迁移图

其中“空闲态”为系统上电时的状态,此时bootl oader软件处于待命状态,接收上位机的指令。“升级态”主要完成对应用程序区flash擦除和烧写任务,并重新读取应用程序区Flash数据,计算出校验值。“跳转态”需要完成任务是完成bootloader到应用程序软件的跳转。通过对bootloader软件功能的分析,由升级态到空闲态,跳转态到空闲态,跳转态到升级态三种状态转换不适应bootloader软件。最终只保留空闲态转升级态,空闲态转跳转态,升级态转跳转态三种状态转换。三种状态转换的条件如下:

条件①:(1)上位机软件与Bootloader软件握手成功;(2)Bootloader 软件接收到正确的升级命令。

条件②:(1)Bootloader软件接收到的帧校验与从应用程序Flash中读取到的数据计算出的校验码一致;(2)Bootloader软件接收到上位机发送的帧结束命令。

条件③:Bootloader软件运行后,五秒内没有收到上位机发送的握手指令。

2.4 中断向量表映射

STM32F407内部划分为两个区域,如图4所示。

图4 在线烧录功能系统中断向量表

STM32的Flash的两个存储区分别存储两个独立的程序,同时也包含两个中断向量表。程序从起始地址0x08000000处开始运行,运行至地址0x08000004处时取此地址的复位中断向量,然后跳转到对应的中断服务函数中,中断服务函数运行结束后,跳转到bootloader软件的main函数中执行。当Bootloader软件对应用程序区Flash的擦除和烧写任务执行完成后,跳转到应用程序区的复位中断向量(应用程序的起始地址)处执行,从复位中断向量中取出新程序的复位中断向量地址,然后跳转到新程序的中断服务函数开始执行,执行完中断服务函数后跳转到应用程序区的main函数中执行。

由于STM32芯片硬件的设计,在main函数执行过程中,若CPU得到一个中断请求,系统的PC指针仍然会跳转至地址为0x08000004的中断向量表处,而非应用程序中新的中断向量表处。因此应用程序中所有的中断向量地址都需要根据Flash区域的划分而相应的调整,本系统中应用程序中断向量表的偏移地址为bootloader软件占用的Flash大小,即应用程序中断向量表偏移量需设置为0x3E80。在工程文件中全局搜索:

SCB->VTOR=FLASH_BASE|VECT_TAB_OFFSET

“VECT_TAB_OFFSET”宏定义中定义的是系统的中断偏移量,将其设置为0x3E80即可完成应用程序中断向量偏移量的设置。

2.5 bootloader通用通信协议

为了实现bootloader软件在不同平台之间的通用性,从通信协议上制定一套完整的与上位机主机的交互协议[5]。上位机向bootloader发送数据帧的协议格式如表1所示。

表1 bootloader软件接收协议格式

其中,数据类型Type有3种指令格式格式,如表2所示。

表2 数据类型(Type)格式定义

Bootloader解析上位机指令帧后,返回给上位机应答帧格式如表3所示。

表3 bootloader软件通信发送协议格式

上位机与bootloader之间的通信协议严格按照上述协议格式要求执行,不区分通信方式。

2.6 Bootloader软件架构设计

根据对bootloader软件需求的分析,软件主要需要实现的模块功能有:

(1)RS232通信;(2)Flash读写;(3)Flash绝对地址跳转。

上述功能模块采用前后台设计框架即可实现所有功能,因此无需使用实时操作系统,故bootloader软件采用前后台设计框架,即主函数循环执行为后台,中断服务函数为前台。bootloader软件设计原则为分层架构,即单向逐层调用,针对接口编程。从上到下分为3层,如图5所示。

图5 软件架构分层示意图

硬件驱动层:包括MCU片内资源驱动代码与外部各类IC的底层驱动代码,MCU片内驱动代码与IC驱动代码最好也能各自保持独立。向上提供API接口。

模块功能层:隔离顶层与底层,实现与提供顶层所需的API接口。

业务逻辑层:具体业务逻辑代码,也可以说是应用层。

2.6.1 RS232通信

Bootloader软件与嵌入式设备采用RS232通信,通信收发和解析为前台中断收发,后台循环解析的方式,中断将上位机软件下发的数据帧全部接收,在主循环中寻找软件通信帧中帧头字节,帧头字节确认后,按照字节寻址解析数据内容。待所有的数据帧解析完成后,存放于数据缓存数组中等待Flash读写使用。

Flash读写模块按照数据帧中的flash地址将数据写入flash后,需要对写入的Flash数据进行校验,然后按照bootloader软件通信发送协议将写入flash的结果进行回传。等待上位机所有的数据帧都下发完成后,bootloader软件将写入flash地址的所有数据进行总校验,并将校验结果回传至上位机软件。若bootloader软件的校验和与上位机软件下发的校验和一致,bootloader自动执行跳转函数,跳转至应用软件区域执行。若bootloader对flash的总校验和与app下发的总校验和不一致,则bootloader软件将校验异常结果回传,提示操作者应用软件更新失败,操作者可重新推送应用软件进行更新。

2.6.2 Flash读写

根据bootloader软件需求分析,STM32的Flash读写功能主要包含flash块擦除、读指定地址长度数据功能。因此调用ST官方库函数即可实现Flash读写的全部功能。

2.6.3 跳转函数实现

Bootloader软件对应用程序区Flash擦除和烧写完成并且校验无误之后,即执行Flash跳转,从bootloader区跳转至应用程序区执行,跳转函数设计思路如下:

(1)检查栈顶地址是否合法;(2)初始化栈顶指针;(3)跳转到指定地址执行。

跳转函数代码实现如下:

void PhyIAP_Loadapp(u32 ulAppAddr)

{

if(((*(vu32*) ulAppAddr)&0x2FFE0000)==0x20000000)

{

vJumpApp =(vIapFunc)*(vu32*)(ulAppAddr +4);

_MSP(*(vu32*) ulAppAddr);

vJumpApp();

}

}

3 软件烧录流程

将Bootloader软件通过J-Link烧写到电机控制器中,电机控制器通过USB-232转换器连接电脑,设置上位机波特率为115200,上位机加载应用程序的烧录文件并校验无误后自动开始烧写。应用软件烧录文件为bin文件,大小为482K字节,通过理论计算,每帧传输数据个数为16字节,共需约30125帧字节传输整个烧录文件,每帧数据结合帧头帧尾等指令字后,结合波特率计算,理论烧写时间约为59s。实际测试,bootloader加载482K字节的烧写文件实际花费时间为62s,符合设计要求。

4 结束语

基于IAP技术的通用嵌入式系统在线升级软件,可在复杂工况条件下对设备产品进行维护升级,其操作仅需一台电脑就可实现,大大提高了产品维保升级的效率,同时软件设计时兼顾的可移植性,可在不同产品平台进行功能移植,也降低了企业开发成本。