您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 其它行业文档 > 基于IAP的远程升级设计
基于IAP的远程升级设计写在前面:三个周之前,我突然想写一个远程升级的程序。那个时候我只是大概知道IAP的意思是在应用编程,但怎么编,我还一无所知。我给自己定下一个个阶段目标,从最基础的代码一点点写起,解决一个又一个的问题。三个周之后,我用自己设计的方法实验了50多次,无一例升级失败。三个周来,遇到了很多的不解、困惑,甚至是想放弃,但我现在想说的是:很多未知的困难会挡在我们面前,我们会感觉毫无头绪甚至觉得毫无出路忍不住要放弃,但多坚持一下,那些困难不但能烟消云散还能带给我们进步。本设计是基于LPC2114和KeilMDK(V4.10),但所有支持IAP的处理器都可借鉴本方案,重要的是思想,而不是用什么。0引言在应用编程(IAP)技术为系统在线升级和远程升级提供了良好的解决方案,也为数据存储和现场固件的升级都带来了极大的灵活性。通常可利用芯片的串行口接到计算机的RS232口、通过现有的Internet或、无线网络或者其他通信方式很方便地实现在线以及远程升级和维护。本文以NXP的LPC2114ARM微处理器为平台,以KeilMDK为开发工具,阐述IAP的原理、Flash的划分、分散加载机制、中断重映射以及在线升级的实现方案及其优化。本方案使用多种校验技术,最大限度的保障传输数据的正确性;使用bootloader机制,即使因意外事件(断电,编程Flash失败等)造成升级失败后,程序也能返回到升级前的状态。1LPC2114的Flash规划1.1扇区描述LPC2114共有128KB片内Flash,共分为16个扇区,分别为0扇区~15扇区,每个扇区为8KB存储空间。其中第15扇区出厂时被固化为BootBlock区,控制复位后的初始化操作,并提供实现Flash编程的方法。所以用户可用的Flash空间只有120KB。IAP程序固化于BootBlock中,IAP操作是以扇区为单位,并占用片内RAM的高32字节。下表列出LPC2114器件所包含的扇区数和存储器地址.表1.1LPC2114Flash器件中的扇区1.2Flash的扇区划分本设计将Flash划分为四个区,扇区0存放跳转程序和升级引导程序(Bootloader)。分站上电后执行跳转程序,跳转到用户程序处。用户程序运行过程中,如果接收到升级指令,会从用户程序跳转到引导程序区(Bootloader),接收新程序数据包,完成Flash编程并跳转到新程序区执行程序。扇区1~扇区7为程序存储低区;扇区8~扇区13为程序存储高区;扇区14存放当前程序运行区域标志,如果当前程序运行在高区,该标志区的最低四个字节为0x00010000,如果当前程序运行在低区,该标志区的最低四个字节为0x00008000。2IAP的原理与软件设计2.1IAP的原理IAP函数是固化在微处理器内部flash上的一些函数代码,最终的用户程序可以直接通过调用这些函数来对内部flash进行擦除和编程操作。LPC2114微处理器的内部flash有一个块称为BootBlock,位于flash的顶端,可供调用的IAP函数就位于该块中。上电后BootBlock被映射到内部地址空间的顶端,同样IAP函数人口地址也被映射到地址0x7ffffff0处。用户可通过跳转到该地址来调用相应的lAP函数。2.2IAP命令对于在应用编程来说,应当通过寄存器r0中的字指针指向存储器(RAM)包含的命令代码和参数来调用IAP程序。IAP命令的结果返回到寄存器r1所指向的返回表。用户可通过传递寄存器r0和r1中的相同指针重用命令表来得到结果。参数表应当大到足够保存所有的结果以防结果的数目大于参数的数目。参数传递见图2-1。参数和结果的数目根据IAP命令而有所不同。参数的最大数目为5,由“将RAM内容复制到Flash”命令传递。结果的最大数目为2,由“扇区查空”命令返回。命令处理程序在接收到一个未定义的命令时发送状态代码INVALID_COMMAND。IAP程序是thumb代码,位于地址0x7FFFFFF0。图2-1IAP的参数传递表2-1描述了IAP的命令。表2-1IAP命令汇总IAP命令2.3IAP编程函数接口IAP功能可用下面的C代码来调用。定义IAP程序的入口地址。由于IAP地址的第0位是1,因此,当程序计数器转移到该地址时会引起Thumb指令集的变化。#defineIAP_LOCATION0x7ffffff1定义数据结构或指针,将IAP命令表和结果表传递给IAP函数unsignedlongcommand[5];unsignedlongresult[2];定义函数类型指针,函数包含2个参数,无返回值。注意:IAP将函数结果和R1中的表格基址一同返回。typedefvoid(*IAP)(unsignedint[],unsignedint[]);IAPiap_entry;设置函数指针iap_entry=(IAP)IAP_LOCATION;使用下面的语句来调用IAP。iap_entry(command,result);Flash存储器在写或擦除操作过程中不可被访问。执行Flash写/擦除操作的IAP命令使用片内RAM顶端的32个字节空间。如果应用程序中允许IAP编程,那么用户程序不应使用该空间。3LPC2114升级实现过程由于在升级程序软件设计中,分散加载机制、中断向量的重映射、软中断等的实现还与所使用的编译器紧密相关,因此,本文结合KeilMDK(V4.10)编译工具,来详细阐述升级程序的实现过程。3.1总体思路分站上电后,首先运行位于Flash0x000~0x3FF中的跳转程序。跳转程序会读取位于14扇区的当前程序运行标志,如果该扇区的最低四个字节为0x00010000,表示当前程序运行在高区,跳转程序会跳转到Flash的0x00010000处执行用户程序;如果该标志区的最低四个字节为0x00008000,表示当前程序运行在低区,跳转程序会跳转到Flash的0x00002000处执行用户程序。用户程序正常执行后,会按照设计进行正常的程序采集、数据处理传送。当接收到升级命令后,用户程序会跳转到Flash的0x00000400处的Bootloader处进行升级的一些操作。当升级成功后,Bootloader程序更新当前程序运行区标志,程序跳转到新程序处运行,如果升级不成功,返回升级前的程序。流程图如下所示:3.2跳转程序的设计跳转程序是分站上电后最先运行的程序,根据当前程序运行区标志,跳转到相应的用户程序区执行。本段程序占用Flash的最低1K字节空间,与Bootloader同在第0扇区。跳转程序的启动代码仅初始化堆栈,不使用PLL和存储加速功能。代码1描述了跳转程序的主要启动代码。;EnterUserModeandsetitsStackPointerMSRCPSR_c,#Mode_USRMOVSP,R0SUBSL,SP,#USR_Stack_Size;EntertheCcodeIMPORT__mainLDRR0,=__mainBXR0代码1:跳转程序启动代码当跳转程序确定要跳转到高区用户程序或者低区用户程序后,使用函数指针跳转到0x00010000处(高区用户函数入口地址)或0x00002000处(低区用户函数入口地址)。定义函数指针:void(*UserProgram)();指定入口地址:UserProgram=(void(*)())(0x00010000);UserProgram=(void(*)())(0x00002000);实现跳转:(*UserProgram)();要将用户代码精确定位到Flash的0x00010000处(高区用户函数入口地址)或0x00002000处(低区用户函数入口地址),需要使用编译器的分散加载机制,将在Bootloader中详细描述实现过程。另外,跳转程序还在烧录代码的同时初始化当前程序运行区标志,即对Flash的0x0001C000地址处写入0x00008000,表示当前用户程序在低区。主要使用了编译器的__at关键字:精确定位变量。需要注意的是,使用该关键字必须包含头文件absacc.h。constuint32x__at(0x0001C000)=0x00008000;//初始化用户程序标志区,默认运行低区3.3升级程序Bootloader的设计升级程序的好坏,在很大程度上取决于Bootloader设计的好坏。一个优秀的IAP升级Bootloader,必须做好升级中出现故障等异常的处理。保证系统不会崩溃,即使升级失败,也能返回升级前的程序。Ø有升级指令,进行初始化工作(串口、定时器、看门狗)Ø接收升级数据包,检测帧头、长度、帧号、数据区校验,最大程度的保证升级数据的完整性、正确性。Ø实时检测接收状态,10S内没有接收到数据或接收到的数据包都是错的,则退出升级,返回原程序。Ø接收的数据按照512字节一组写入Flash,写入后再读出与原数据进行对比校验,校验成功后,本次编程Flash成功。允许连续3次编程Flash,三次都不成功,退出升级程序,执行原程序。Ø升级成功后,更新当前程序运行区标志,跳转到新程序,同时原程序保存。本设计的Bootload位于Flash的0x400开始的扇区0存储区内,使用分散加载机制,将程序的入口地址定位到0x00000400处。当用户程序接收到升级指令后,就会使用函数指针跳转到这个入口处。3.3.1使用IAP图3-1描述了使用IAP编程Flash所必须的步骤。3.3.1.1定义系统参数在使用IAP前,需要定义一些系统参数,比如系统时钟、IAP中断入口、输入输出缓存。#defineIAP_CLK11059200UL#defineIAP_LOCATION0x7FFFFFF1typedefvoid(*IAP)(uint32[],uint32[]);//定义函数类型指针IAPiap_entry=(IAP)IAP_LOCATION;//设置函数指针unsignedlongcommand[5]={0,0,0,0,0};unsignedlongresult[2]={0,0};代码3-1:定义系统参数3.3.1.2选择扇区在任何擦除和编程Flash之前,必须选中扇区,可以选中一个或多个。/*******************************************************************名称:SelSector()*功能:IAP操作扇区选择,命令代码50。*入口参数:sec1起始扇区*sec2终止扇区*出口参数:IAP返回值(paramout缓冲区)CMD_SUCCESS,BUSY,INVALID_SECTOR*********************************************************************/voidSelSector(uint8sec1,uint8sec2){paramin[0]=IAP_SELSECTOR;//设置命令字paramin[1]=sec1;//设置参数paramin[2]=sec2;iap_entry(paramin,paramout);//调用IAP服务程序}代码3-2选择扇区3.3.1.3擦除扇区在编程Flash前必须执行擦除操作,如果某个扇区已经擦除,就不需要再次擦除。可以一次擦除一个或多个扇区。/*******************************************************************名称:EraseSector()*功能:扇区擦除,命令代码52。*入口参数:sec1起始扇区*sec2终止扇区*出口参数:IAP返回值(paramout缓冲区)CMD_SUCCESS,BUSY,INVALID_SECTOR************************************************************************/voidEraseSector(uint8sec1,uint8sec2){paramin[0]=IA
本文标题:基于IAP的远程升级设计
链接地址:https://www.777doc.com/doc-2569989 .html