IAP程序升级(全网最全)
一、什么是IAP,为什么要IAP
IAP即为In Application Programming(在应用中编程),一般情况下,以STM32F10x系列芯片为主控制器的设备在出厂时就已经使用J-Link仿真器将应用代码烧录了,如果在设备使用过程中需要进行应用代码的更换、升级等操作的话,则可能需要将设备返回原厂并拆解出来再使用J-Link重新烧录代码,这就增加了很多不必要的麻烦。站在用户的角度来说,就是能让用户自己来更换设备里边的代码程序而厂家这边只需要提供给用户一个代码文件即可。
而IAP却能很好的解决掉这个难题,一片STM32芯片的Code(代码)区内一般只有一个用户程序。而IAP方案则是将代码区划分为两部分,两部分区域各存放一个程序,一个叫bootloader(引导加载程序),另一个较user application(用户应用程序)。bootloader在出厂时就固定下来了,在需要变更user application时只需要通过触发bootloader对userapplication的擦除和重新写入即可完成用户应用的更换。如图所示
在程序执行初始进入bootloader,在bootloader里面检测条件是否被触发(可通过按键是否被按下、串口是否接收到特定的数据、U盘是否插入等等),如果有则进行对user application进行擦除和重新写入操作,如果没有则直接跳转到user application执行应用;如果有则进行擦除用户代码并重新写入新的用户代码。
二、STM32F103ZET6硬件条件
STM32F103ZET6的启动方式有三种:内置FLASH启动、内置SRAM启动、系统存储器ROM启动,通过BOOT0和BOOT1引脚的设置可以选择从哪中方式启动,这里选择内置的FLASH启动。其FLASH的地址为0x08000000—0x0807 FFFF,共512KB,这些都能从芯片数据手册中直接得到。而这里首要的一个问题是中断的问题。正常情况下发生中断的过程为:发生中断(中断请求)到中断向量表查找中断函数入口地址跳转到中断函数执行中断函数中断返回。也就是说在STM32的内置的Flash中有一个中断向量表来存放各个中断服务函数的入口地址,内置Flash的分配情况大致如下图。
在只有一个程序的情况下,程序执行的走向应该如图所示(借用网友的原图)。
STM32F10x有一个中断向量表,这个中断向量表存放在代码开始部分的后4个字节处(即0x0800 0004),代码开始的4个字节存放的是堆栈栈顶的地址,当发生中断后程序通过查找该表得到相应的中断服务程序入口地址,然后再跳到相应的中断服务程序中执行。上电后从0x08000004处取出复位中断向量的地址,然后跳转到复位中断程序的入口(标号①所示),执行结束后跳转到main函数中(标号②所示)。在执行main函数的过程中发生中断,则STM32强制将PC指针指回中断向量表处(标号③所示),从中断向量表中找到相应的中断函数入口地址,跳转到相应的中断服务函数(标号④所示),执行完中断函数后再返回到main函数中来(标号⑤所示)。
若在STM32F103x中使用IAP方案,则内置的Flash分配情况大致如下图。
在内置的Flash里面添加一个BootLoader程序,BootLoader程序和user application各有一个中断向量表,假设BootLoader程序占用的空间为N+M字节,则程序的走向应该如下图所示(借用网友的原图并做改动,其中虚线部分为原图步骤④⑤的走向,本人改为指向灰色部分)。
上电初始程序依然从0x08000004处取出复位中断向量地址,执行复位中断函数后跳转到IAP的main(标号①所示),在IAP的main函数执行完成后强制跳转到0x08000004+N+M处(标号②所示),最后跳转到新的main函数中来(标号③所示),当发生中断请求后,程序跳转到新的中断向量表中取出新的中断函数入口地址,再跳转到新的中断服务函数中执行(标号④⑤所示),执行完中断函数后再返回到main函数中来(标号⑥所示)。
对于步骤④⑤,网友认为是:“在main执行的过程中,如果CPU得到一个中断请求,PC指针仍强制跳转到地址0x08000004中断向量表处,而不是新的中断向量表,如图标号④所示,程序再根据我们设置的中断向量表偏移量,跳转到对应中断源新的中断服务程序中,如图标号⑤所示”。我对此的理解是:“当发生中断后,程序从0x08000004(旧)处的中断向量表中得到相应的中断服务函数入口地址,继而跳转到相应的中断服务程序”。但是旧的中断向量列表里边存放的是IAP程序中断函数的入口地址,它是如何得到user程序中断函数的入口地址呢?所以我觉得此种说法是错误的。“当发生中断时PC指针强制会跳转到0x08000004处”这种说法并没有错,只是忽略了后续的一些知识要点而导致这个说法出现矛盾。
对于步骤④⑤我认为的是,在main函数的执行过程中,如果CPU得到一个中断请求,PC指针本来应该跳转到0x08000004处的中断向量表,由于我们设置了中断向量表偏移量为N+M,因此PC指针被强制跳转到0x08000004+N+M处的中断向量表中得到相应的中断函数地址(待求证),再跳转到相应新的中断服务函数,执行结束后返回到main函数中来。
三、实现过程
STM32F103ZET6的Flash地址为0x08000000—0x0807 FFFF共512KB,把这512KB的空间分为两块,第一块大小为32KB存放BootLoader程序,剩余的空间存放用户程序(根据实际情况分配这两块空间的大小,BootLoader程序占用的空间越小越好,则BootLoader地址为0x08000000—0x08007fff,用户程序地址为0x08008000—0x0807ffff。BootLoader流程图大致应该如下:
1、初始化时钟。
2、初始化中断向量表地址。
3、初始化按键。 (使用按键触发方式,上电时如果按键被按下则进行用户程序更新操作)
4、初始化串口。
5、检测按键是否被按下,是则执行步骤6,否则执行步骤10。
6、擦除用户程序(擦除0x08008000—0x0807ffff地址空间Flash)。
7、从串口读取新的用户代码数据,把代码写入用户程序空间。
8、检测串口数据接收完毕?是则执行步骤9,否则跳回步骤7。
9、用户程序更新完毕,等待重新上电或硬件复位。
10、跳转到用户程序(强制将PC指针跳转到0x08008000+4处)。
到这里首先要解决的问题就有:
1、如何进行对STM32的Flash进行擦除和写入操作。
2、中断向量表偏移如何设置。
3、如何改变代码存放的地址空间(因为BootLoader要存放在0x08000000处,用户程序要存放在0x08008000处,而默认的代码存放的地址空间为0x08000000)。
4、怎么进行PC指针的强制跳转,跳转时需要做些什么。
5、串口接收的用户代码数据是什么样的代码数据,是一种什么样的文件。
问题的解决:
1、使用STM32的固件库函数,只需调用几个库函数即可轻松解决,使用的固件库为stm32f10x_flash.c文件,对Flash的操作过程简要为:Flash解锁àFlash擦除àFlash写入àFlash上锁。(对Flash编程的更详细操作参考STM32F10xxx闪存编程手册)
①解锁:
FLASH_Unlock(); //解锁Flash
FLASH_SetLatency(FLASH_Latency_2); //因为系统时钟为72M所以要设置两个时钟周期的延时
②擦除:
for(i=0;i<240;i++)
{if(FLASH_ErasePage(FLASH_ADDR+i*2048) != FLASH_COMPLETE) //一定要判断是否擦除成功return ERROR;
}
说明:FLASH_ErasePage(uint32_t Page_Address)即为Flash擦除操作,按页擦除,每页2KB,Page_Address为页的起始地址,如0x08000000是第一页起始地址,0x08000800为第二页起始地址,这里的操作擦除了0x08008000—0x0807ffff地址空间的Flash。
③写入:
unsigned char buf[1024]; //假设待写入的代码数据
unsigned short temp; //临时数据
for(i=0;i<512;i++)
{temp = (buf[2*i+1]<<8) | buf[2*i]; //2个字节整合为1个半字if(FLASH_ProgramHalfWord(ADDR,temp) != FLASH_COMPLETE) //判断是否写入成功{Return ERROR;}
ADDR +=2; //地址要加2,因为每次写入的是2个字节(1个半字)
}
说明:因为STM32的Flash写入为双字节(1个半字)写入,FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)函数即为对地址为Address写入1个半字的Data,每次写入完成后地址要加2。
④上锁:
FLASH_Lock(); //Flash 上锁,一个固件库函数即可实现。
2、关于中断向量表的偏移设置,对于BootLoader程序只需设置中断向量表的指向在0x08000000处,对于用户程序需要设置中断向量表的指向在0x08008000处即可。
①在BootLoader程序的中断向量表指向设置中应有这么一句:
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); //设置中断向量表指向
其中NVIC_VectTab_FLASH是个宏定义,的值为0x08000000。
②在用户程序的中断向量表指向设置用应有这么一句:
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x8000); //设置中断向量表指向
四、结束语
总的来说STM32的IAP方案实现需要在进行用户程序之前加一段Bootloader程序,BootLoader程序的作用就是:
①什么都不做,直接跳转到用户程序。
②删除原有的用户程序,读取*.bin文件数据并将数据重新写入新的用户程序。
对于用户程序相比普通的编程只需要做三步改动即可
①改变中断向量表。
②改变代码存放的地址空间
③修改生成*.bin文件
使用通过UART的IAP方案并不是很好的选择,这只是IAP方案的一个机制,因为能使用PC机通过串口升级程序,同样能通过Jlink烧写程序,并且自定义的串口通讯协议在没有校CRC校验的情况下不能及时发现数据传输过程发生的错误。这里推荐使用SD卡(或U盘)进行用户程序更新,将*.bin文件复制到SD卡(或U盘)中,STM32再通过读取SD卡(或U盘)的*.bin文件进行用户程序更新,这也避免了STM32与PC笨重的通讯,只需插一个SD卡(或U盘)更显得人性化一些,但需要去弄懂STM32如何与SD卡(或U盘)的通讯。
参考文章:https://www.cnblogs.com/birdBull/p/11776749.html
IAP程序升级(全网最全)相关推荐
- STM32 IAP 在线升级原理全解析
点击左上角的"关注",定期更新 STM32 最新资讯,总有你想要的信息! STM32 IAP 在线升级原理全解析 1. 什么是 IAP? IAP(In-Application ...
- 电子产品如何使用IAP方式升级程序
目录 1.ICP.ISP和IAP的概念 2.IAP升级程序的原理 3.IAP升级程序的流程 4.IAR环境下IAP的实现 4.1.BootLoader程序设计 4.2.User Application ...
- CRC校验原理及STM32 IAP在线升级程序
CRC校验原理: 什么是CRC校验? CRC即循环冗余校验码:是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定.循环冗余检查(CRC)是一种数据传输检错功能,对数据 ...
- 瑞萨单片机iap串口升级boot程序与app程序合并的工程构建-学习记录
MCU型号: R7F0C004 编辑软件:CS+ for CC boot区程序地址分配:0x0000-0x1ffff app区程序地址分配: 0x2000-0xfffff 复制一份常规的app程序,然 ...
- 全云端万能小程序_百搜全云端万能门店小程序v4.0.13五端独家2次开发升级独立版...
百搜全云端五端万能小程序独立版简介: 包含:百度小程序,支付宝小程序,微信小程序,头条小程序,QQ小程序,H5,PC商城. 功能:支持小程序一键上传极速审核,对接微信开放平台发布使用,也可以单独使用开 ...
- 基于IAP和USB技术的嵌入式系统应用程序升级
对于内含IAP功能的嵌入式微控制器提出基于IAP和USB技术的系统应用程序升级的新方法.U盘被用作程序代码的存储设备,将微控制器的存储器Flash和SRAM进行有效的区间分配,经外部扩展接口USB,微 ...
- 前端程序升级linux方案,开源:AspNetCore 应用程序热更新升级工具(全网第一份公开的解决方案)...
1:下载.开源.使用教程 使用教程: 解压AspNetCoreUpdater.rar,得到两个压缩包,分别对应用Window和Linux. A.使用教程:For Window IIS 1.解压AspN ...
- 全网最全安全加固指南
干货 | 全网最全安全加固指南 安全加固相关概念阐述 安全加固定义 安全加固和优化是实现信息系统安全的关键环节.通过安全加固,将在信息系统的网络层.主机层.软件层.应用层等层次建立符合安全需求的安全状 ...
- LPC2478(22)IAP在线升级
目录 1.开发环境 2.特性 3.IAR编译器的相关文件 3.1.icf文件 3.2.IcfEditorFile文件内容 3.3.ddf文件 3.4.board文件 4.IAP相关 4.1.软件复位 ...
- 冰河连夜复现了Log4j最新史诗级重大漏洞,含视频和完整案例代码,全网最全,赶快收藏吧
大家好,我是冰河~~ 周末与一些小伙伴交流的过程当中,发现一些小伙伴公司的项目中使用的Log4j版本还是2.14.0,我一听就有点震惊了:你们还在使用Log4j的2.14.0版本,这个版本存在重大漏洞 ...
最新文章
- 网页(Webpage)粒度分析算法
- python读取配置文件
- eclipse中启动tomcat,不能访问localhost解决办法
- Spring MVC 使用拦截器 HiddenHttpMethodFilter配置Rest风格的URL
- 你的“苦劳”,真的不值钱!
- oracle和mysql查询_Oracle和MySQL分组查询GROUP BY
- boost::geometry::tuples用法的测试程序
- java 集合类简单的分析1
- maven项目pom中scope类型
- ansible 常用命令
- 企业数字化转型需注意什么
- MFC学习笔记(一)MFC基本知识介绍、建立MFC应用程序
- Perl语言必看书籍推荐
- 攻击者视角对AntiSpam工作的分析
- win7 计算机不显示u盘启动不了,Win7系统下bios中找不到U盘启动项如何解决
- antdesign——select搜索
- 计算机d盘可以格式化吗,d盘怎么格式化
- MySql重装出错, Staring the server出错,日志3306 with user root with no password...
- 【正点原子FPGA连载】第一章 ZYNQ简介 -摘自【正点原子】领航者ZYNQ之FPGA开发指南_V2.0
- 如何科学增长邮件订阅用户?
热门文章
- Verilog基本语法之wire和reg
- java 实心圆_java JFrame窗口中画一个实心圆并设置背景颜色,但背景不显示,级求解!!...
- wordpress插件_顶级WordPress反垃圾邮件插件
- 张家港、张家口、张家界、张家川
- 腾讯和360之争所折射出的下作
- 迈开职场充电第一步,让我们在这个冬天邂逅社科院杜兰金融管理硕士项目
- 装完虚拟机后键盘无法使用
- C++中---结构体变量的默认值以及构造函数的应用
- mysql-bin文件删除与产生的原因
- Django之全局配置-ALLOWED_HOSTS、LOGGING及多个子应用管理