归志宁无五亩园,读书本意在元元。这篇文章主要讲述基于STM32的IAP升级程序相关的知识,希望能为你提供帮助。
基于STM32的IAP升级程序
- ??IAP介绍??
- ??功能设计??
- ??硬件设计??
- ??软件设计??
- ??软件设计流程如下??
- ??完整程序??
- ??具体实现??
- ??设计功能程序??
- ??IAP实现程序??
- ??主程序??
- ??后续??
简单来说,就是程序首先运行在boot升级区,检测是否有升级程序,当有升级程序的时候,用户将升级的固件通过某种通信接口(如串口)传输到开发板的某个位置中,之后放在APP的位置。当没有升级程序,直接运行APP中的程序。
功能设计将最新的产品固件通过串口上传到开发板中,按下按键1,开发板将固件更新到设置的功能程序存放地址,按下按键2,执行功能程序。
【基于STM32的IAP升级程序】
Created with Rapha?l 2.3.0开始是否有升级程序将升级固件暂存在RAM中是否按下按键1将RAM中的固件更新到Flash功能程序位置是否按下按键2跳转到执行产品功能程序yesnoyesnoyesno
硬件设计使用的MCU为STM32F103
使用元器件为两个按键和两个LED灯
软件设计 软件设计流程如下
- 编写需要升级的产品功能程序
- 设置产品功能程序在keil 5中Target的程序的Flash起始地址和大小,并且程序中设置中断向量表的偏移量
- 生成产品功能程序的固件bin文件
- 设置IAP升级程序存放的起始地址和大小
- 串口接收产品功能程序
- 将最新的升级程序放入到功能程序的Flash位置
- 跳转到功能程序的Flash地址处
具体实现 设计功能程序主要为两处:
- 在main()函数中最开始处,添加
SCB-> VTOR = FLASH_BASE|0x9C00;
- 在keil 5中Target的程序的Flash起始地址和大小
文章图片
生成bin文件:我们通过在 MDK 点击 Options for Target→User 选项卡,在 After Build/Rebuild 栏,
勾选 Run #1,并写入:D:\\32\\Keil 5\\ARM\\ARMCC\\bin\\fromelf.exe --bin -o …\\OBJ\\LED.bin …\\OBJ\\LED.axf
文章图片
编译后,就会生成.bin文件了。
IAP实现程序
- IAP写入程序
将暂存在RAM中的程序存放到Flash的对应地址中
appxaddr:应用程序的起始地址
appbuf:应用程序CODE.
appsize:应用程序大小(字节).
void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 appsize)
u16 t;
u16 i=0;
u16 temp;
u32 fwaddr=appxaddr; //当前写入的地址
u8 *dfu=appbuf;
for(t=0; t
temp=(u16)dfu[1]< < 8;
temp+=(u16)dfu[0];
dfu+=2; //偏移2个字节
iapbuf[i++]=temp;
if(i==1024)
i=0;
STMFLASH_Write(fwaddr,iapbuf,1024);
fwaddr+=2048; //偏移204816=2*8.所以要乘以2.
if(i)STMFLASH_Write(fwaddr,iapbuf,i); //将最后的一些内容字节写进去.
- 运行地址偏移程序
程序转移到指定地址运行
跳转到应用程序段
appxaddr:用户代码起始地址.
void iap_load_app(u32 appxaddr)
if(((*(vu32*)appxaddr)& 0x2FFE0000)==0x20000000) //检查栈顶地址是否合法.
jump2app=(iapfun)*(vu32*)(appxaddr+4); //用户代码区第二个字为程序开始地址(复位地址)
MSR_MSP(*(vu32*)appxaddr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
jump2app(); //跳转到APP.
主程序通过按键对接收到的升级程序进行更新,或者直接转入到功能程序地址。
while(1)
if(USART_RX_CNT)
if(oldcount==USART_RX_CNT)
applenth=USART_RX_CNT;
oldcount=0;
USART_RX_CNT=0;
printf("代码长度:%dBytes\\r\\n",applenth);
else oldcount=USART_RX_CNT;
if(key==WKUP_PRES)
if(applenth)
printf("开始更新固件...\\r\\n");
if(((*(vu32*)(0X20001000+4))& 0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
iap_write_appbin(FLASH_APP2_ADDR,USART_RX_BUF,applenth); //更新FLASH代码
printf("固件更新完成!\\r\\n");
else
printf("固件更新失败!\\r\\n");
else
printf("没有可以更新的固件!\\r\\n");
if(key==KEY1_PRES)
printf("开始执行FLASH用户代码!!\\r\\n");
if(((*(vu32*)(FLASH_APP2_ADDR+4))& 0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
iap_load_app(FLASH_APP2_ADDR); //执行FLASH APP代码
else
printf("非FLASH应用程序,无法执行!\\r\\n");
后续如果想了解更多物联网、智能家居项目知识,可以关注我的项目实战?专栏。
或者关注公众号观看更多。
文章图片
编写不易,感谢支持。
推荐阅读
- Zabbix latest.php SQL注入漏洞(CVE-2016-10134)
- 路由基础之RIP的水平分割及触发更新
- Oracle Data Guard系列(单机环境基于拷贝文件方式搭建DG)
- python之uWSGI和WSGI
- PDManer [元数建模]-v4.0 (一款简单好用的数据库建模平台)
- Docker下RabbitMQ四部曲之三(细说java开发)
- 高级程序员与初级程序员差别在哪里()
- Docker下RabbitMQ四部曲之四(高可用实战)
- #导入Word文档图片#值得收藏:当向数据库导入大量数据时,mysql主键唯一键重复插入,如何丝滑操作并不导入重复数据呢