最近在面试的时候遇到一个关于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中

STM32f103x IAP远程升级小结-LMLPHP

STM32f103x IAP远程升级小结-LMLPHP

MDK5中魔术棒设置

STM32f103x IAP远程升级小结-LMLPHP

USER APP部分:

(1)   
从FLASH启动

a.设置向量表起始地址(0x0800 0000+iap app size),如果此处设置的不正确,会造成中断不能正常使用,需特别注意。

STM32f103x IAP远程升级小结-LMLPHP

b.设置MDK5代码存放地址(程序中设定IAP APP
SIZE=0X8000 32Kbyte,所以USER APP起始地址为0x0800 8000,大小为256k-32k = 224k = 0x38000)

STM32f103x IAP远程升级小结-LMLPHP

c.使用MDK5软件生成USER APP的bin文件D:\MDK5.14\ARM\ARMCC\bin\fromelf.exe
--bin -o  ..\OBJ\TEST.bin ..\OBJ\TEST.axf

STM32f103x IAP远程升级小结-LMLPHP

(2)从SRAM启动

a.设置向量表起始地址(0x0200 0000+iap app size)

STM32f103x IAP远程升级小结-LMLPHP

b. 设置MDK5代码存放地址

SRAM分配:0x20001000开始的40K(0XA000)用做ROM,0X2000B000开始的4K(0X1000)用作RAM.

STM32f103x IAP远程升级小结-LMLPHP

c.使用MDK5软件生成USER APP的bin文件D:\MDK5.14\ARM\ARMCC\bin\fromelf.exe
--bin -o  ..\OBJ\TEST.bin ..\OBJ\TEST.axf

STM32f103x IAP远程升级小结-LMLPHP

利用串口工具进行远程升级演示

程序中并未对代码段数据进行安全校验,所以串口比特率不要设定太高,通过串口工具将USER APP的BIN文件发送给下位机即可,具体操作可以根据窗口界面提示信息进入交互界面。

STM32f103x IAP远程升级小结-LMLPHP

STM32f103x IAP远程升级小结-LMLPHP

到此我的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

04-25 13:56