最近在面试的时候遇到一个关于IAP远程程序升级的问题,由于之前所做的项目没有涉及到远程升级需求,当时一脸懵呆,不过回答的还是不错的,今天针对STM32F103系列调试了IAP的程序,这里做一下小结,如有不妥的地方,欢迎大家及时 提出宝贵建议。
之前网上有很多关于IAP远程升级的讲解,个人觉得有一篇帖子写的非常好,
http://m.blog.csdn.net/u013165704/article/details/72828249大家可以先看一下这篇帖子,这里就不在重复,正所谓“站在巨人的肩膀上,才能看的更远”,所以本帖主要讨论如何编写IAP Bootload以及关键点。
根据STM32芯片的启动过程可以知道,bootload即IAP APP)应该放在0X800 000(从FLASH启动)或者0x2000 0000(在SRAM启动),代码空间大小根据具体情况设定(可以从编辑信息里获取代码大小),在IAP APP的main函数中主要完成的任务就是接收用户的更新命令,然后根据指定的启动方式接收user app,我写的程序是在进入更新界面后,把接收到的USER APP的bin文件放在sram中,地址为0x2000 0000 ,当启动方式为SRAM启动时,就可以使PC指向0X2000 0000 的位置直接启动用户程序。对于从FLASH启动时稍微麻烦一些,牵扯到芯片片上FLASH的操作知识,不过借鉴官方的内部FLASH读写例程,很容易就能懂。言归正传,我们只需要从SRAM上拷贝接收到的USER APP到指定的FLASH位置(0x800 0000 + IAP APP SIAE),然后跳转PC指针就可以执行用户程序了,用户程序中添加相关信号,触发软件复位中断就可以重新进入IAP远程升级用户交互界面了,下面讲一下所用到的几个关键的函数。
IAP APP部分:
重新加载代码的程序
为了实现Boot和App程序之间跳转,则必须在升级完成之后重新加载新的程序文件,其中涉及到在C语言里内嵌汇编语言,代码如下:
__asm void MSR_MSP(u32 addr)
{
MSR MSP, r0 //set Main Stack value将主堆栈地址保存到MSP寄存器(R13)中
BX r14 //跳转到lr中存放的地址处。bx是强制跳转指令 lr是连接寄存器,是STM32单片机的R14
}
typedef void (*IapFun)(void);
//定义一个函数类型的参数
IapFun JumpToApp;
//跳转到应用程序 AppAddr:用户代码起始地址.
void Iap_Load_App(u32 AppAddr)
{
if(((*(vu32*)AppAddr)&0x2FFE0000)==0x20000000)
//检查栈顶地址是否合法.
{
JumpToApp =
(IapFun)*(vu32*)(AppAddr+4); //用户代码区第二个字为程序开始地址(新程序复位地址)
MSR_MSP(*(vu32*)AppAddr);
//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
JumpToApp(); //设置PC指针为新程序复位中断函数的地址,往下执行
}
}
首先 if(((*(vu32*)AppAddr)&0x2FFE0000)==0x20000000) 的作用是检查栈顶地址是否合法,(*(vu32*)AppAddr)是去除用户程序首地
址里面的数据,而这个数据就是用户代码的堆栈地址,而堆栈地址指向RAM,RAM的起始地址是0x20000000,因此可以用上免得语句判断用
户的堆栈地址是否合法。
当判断栈顶地址合法之后取出新的复位中断函数的地址即(vu32*)(AppAddr+4),并把它赋值给函数指针JumpToApp,然后调用
MSR_MSP()函数把主堆栈指针赋值给MSP寄存器,最后调用JumpToApp();来执行新的程序。
(这里涉及到函数指针的知识,一定要理解函数名本身就是该函数的入口地址,它的实质是一个地址。)
上面涉及到嵌入汇编的知识,可能讲解不是很透彻感兴趣的朋友可以参考《Cortex-M3 权威指南》获取更多的了解。
中断向量表起始地址及MDK5软件参数设置:
System_stm32f10x.c中
MDK5中魔术棒设置
USER APP部分:
(1)
从FLASH启动
a.设置向量表起始地址(0x0800 0000+iap app size),如果此处设置的不正确,会造成中断不能正常使用,需特别注意。
b.设置MDK5代码存放地址(程序中设定IAP APP
SIZE=0X8000 32Kbyte,所以USER APP起始地址为0x0800 8000,大小为256k-32k = 224k = 0x38000)
c.使用MDK5软件生成USER APP的bin文件D:\MDK5.14\ARM\ARMCC\bin\fromelf.exe
--bin -o ..\OBJ\TEST.bin ..\OBJ\TEST.axf
(2)从SRAM启动
a.设置向量表起始地址(0x0200 0000+iap app size)
b. 设置MDK5代码存放地址
SRAM分配:0x20001000开始的40K(0XA000)用做ROM,0X2000B000开始的4K(0X1000)用作RAM.
c.使用MDK5软件生成USER APP的bin文件D:\MDK5.14\ARM\ARMCC\bin\fromelf.exe
--bin -o ..\OBJ\TEST.bin ..\OBJ\TEST.axf
利用串口工具进行远程升级演示
程序中并未对代码段数据进行安全校验,所以串口比特率不要设定太高,通过串口工具将USER APP的BIN文件发送给下位机即可,具体操作可以根据窗口界面提示信息进入交互界面。
到此我的IAP实现介绍完成,如果大家有什么问题或者我的程序中大家发现了什么bug可以提出来一起探讨,希望以上内容会对大家学习STM32有所帮助。
工程附件:
https://files.cnblogs.com/files/rain123/IAP_Bootload_V2.2%28M3%E5%AF%84%E5%AD%98%E5%99%A8%E7%89%88%E6%9C%AC_MDK%29.rar