如何使用STM32F4的BootLoader和APP程序
一.概念扫盲
1.IAP
IAP是In Application Programming的首字母缩写,IAP是用户自己的程序在运行过程中对User Flash的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。
通常在用户需要实现IAP功能时,即用户程序运行中作自身的更新操作,需要在设计固件程序时编写两个项目代码,第一个项目程序不执行正常的功能操作,而只是通过某种通信管道(如USB、USART)接收程序或数据,执行对第二部分代码的更新;第二个项目代码才是真正的功能代码。
2.Bootloader
在上述IAP的概念中,bootloader就是其第一个项目程序。bootloader主要实现的功能:从串口、USB等媒介接收数据;存储和搬运数据;程序跳转等功能。
3.App程序
对IAP概念中,对第二个项目代码的一种称呼
Stm32的bootloader和App的编写注意事项
1、 怎么分配bootloader和app的地址空间
2、 怎么得到升级软件数据并写入flash
3、 怎么从bootloader跳转到app
4、 怎么设置App的中断向量
5、 App中怎么生成bin文件
6、程序执行的流程
1、怎么分配bootloader和app的地址空间
图1 STM32 Flash分区情况
(1)分配地址
我使用的是STM32F407,它的Flash的大小是512K,所以我把它分成如下所示:
0x08000000 ---0x08010000分配给bootloader使用,大小是64k
0x08010000----0x0801F000分配给第一个APP的使用,大小是124k
0x0801FC00----0x0801FFFF 分配给user_flag和其它标志使用
(2)在keil中设置ROM的大小
A、BootLoader中ROM大小的设置
B、App中设置ROM的大小
2、怎么得到升级软件数据并写入flash
在我的程序是通过串口接收数据,然后调用iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 appsize)将接收到的APP程序存放到STM32F4的FLASH中,其中appxaddr为应用程序的起始地址,appbuf是应用程序CODE,appsize是应用程序大小(字节),代码如下:
- #define FLASH_APP1_ADDR 0x08010000 //第一个应用程序起始地址
- if(applenth)//串口接收数据长度
- {
- printf("开始更新固件...\r\n");
- LCD_ShowString(30,210,200,16,16,"Copying APP2FLASH...");
- if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
- {
- iap_write_appbin(FLASH_APP1_ADDR,USART_RX_BUF,applenth);//更新FLASH代码
- LCD_ShowString(30,210,200,16,16,"Copy APP Successed!!");
- printf("固件更新完成!\r\n");
- }else
- {
- LCD_ShowString(30,210,200,16,16,"Illegal FLASH APP! ");
- printf("非FLASH应用程序!\r\n");
- }
- }else
- {
- printf("没有可以更新的固件!\r\n");
- LCD_ShowString(30,210,200,16,16,"No APP!");
- }
- clearflag=7;//标志更新了显示,并且设置7*300ms后清除显示
- void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 appsize)
- {
- u32 t;
- u16 i=0;
- u32 temp;
- u32 fwaddr=appxaddr;//当前写入的地址
- u8 *dfu=appbuf;
- for(t=0;t<appsize;t+=4)
- {
- temp=(u32)dfu[3]<<24;
- temp|=(u32)dfu[2]<<16;
- temp|=(u32)dfu[1]<<8;
- temp|=(u32)dfu[0];
- dfu+=4;//偏移4个字节
- iapbuf[i++]=temp;
- if(i==512)
- {
- i=0;
- STMFLASH_Write(fwaddr,iapbuf,512);
- fwaddr+=2048;//偏移2048 512*4=2048
- }
- }
- if(i)STMFLASH_Write(fwaddr,iapbuf,i);//将最后的一些内容字节写进去.
- }
3、怎么从bootloader跳转到app
- //跳转到应用程序段
- //appxaddr:用户代码起始地址.
- void iap_load_app(u32 appxaddr)
- {
- if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000) //检查栈顶地址是否合法.
- {
- jump2app=(iapfun)*(vu32*)(appxaddr+4); //用户代码区第二个字为程序开始地址(复位地址)
- MSR_MSP(*(vu32*)appxaddr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
- jump2app(); //跳转到APP.
- }
- }
SCB->VTOR = FLASH_BASE | 0x10000;/*中断向量表定位在FLASH_BASE(0X08000000)+0x10000处*/
因为APP的起始地址为(0X08000000)+0x10000
5、 App中怎么生成bin文件
我们通过在 MDK 点击 Options for TargetUser
选项卡,在 After Build/Rebuild 栏,勾选 Run #1,并写入:D:\tools\mdk5.14\ARM\ARMCC\bin\fromelf.exe --bin -o ..\OBJ\RTC.bin..\OBJ\RTC.axf ,如图所示:
总结:
Bootloader里面主要是
1、设置bootloader和app的空间
2、接收编译好的app的bin文件,写入flash
3、实现跳转
App里面主要修改的地方是
1、 ROM起始地址和分配的空间大小
2、 重定向中断向量
3、 生成bin文件