前言:
对于单片机内部Flash的读写操作,其中用于存放带代码空间的大小为:
0x08000000-0x0807FFFF 512K
IAP:本地升级--串口,U盘,SD卡升级
使用方式:
U盘 SD卡:里面直接存放升级文件
串口:通过电脑中的串口助手发送升级文件
OTA:空中下载技术--通过联网模块下载程序,更新本地运行的程序。
- 连接FTP服务器--本质上是一个服务器,我们的目的是从上面获取可执行程序。获取的过程也是建立在TCP/IP之上的FTP协议。 --- 这个协议可以集成在联网模块中(4G)
- 公司内部自己定协议,一帧一帧的下发程序数据,直到下发完成。-- 校验
-
HEX文件:包含地址信息
BIN文件:不包含地址信息
HEX文件比BIN文件大,HEX文件有地址信息,BIN文件没有地址信息
HEX文件和BIN文件都可以是程序文件,但是HEX文件放的信息比BIN多,所以代码会比较大。一般远程升级用bin文件。
-
HEX文件生:
-
Bin文件生成
自己电脑keil路径下的这个绝对路径加上自己的用户名
D:\Keil_v5\ARM\ARMCC\bin\fromelf.exe + o .\Objects\Demo.bin .\Objects\Demo.axf
1 IAP介绍
IAP(In Application Programming)即在应用编程, IAP 是用户自己的程序在运行过程中对User Flash 的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信接口对产品中的固件程序进行更新升级。通常实现 IAP 功能时,即用户程序运行中作自身的更新操作,需要在设计固件程序时编写两个项目代码,第一个项目程序不执行正常的功能操作,而只是通过某种通信方式(如 USB、 USART)接收程序或数据,执行对第二部分代码的更新;第二个项目代码才是真正的功能代码。这两部分项目代码都同时烧录在 User Flash 中,当芯片上电后,首先是第一个项目代码开始运行,它作如下操作:
1)检查是否需要对第二部分代码进行更新;
2)如果不需要更新则转到 4);
3)执行更新操作;
4)跳转到第二部分代码执行;
第一部分代码必须通过其它手段,如 SWD,JTAG 或 ISP 烧入;第二部分代码可以使用第一部分代码 IAP 功能烧入,也可以和第一部分代码一起烧入,以后需要程序更新时再通过第一部分 IAP代码更新。
我们将第一个项目代码称之为 Bootloader 程序(引导加载程序),第二个项目代码称之为 APP 程序,他们存放在 STM32 FLASH 的不同地址范围,一般从最低地址区开始存放 Bootloader,紧跟其后的就是 APP 程序(注意,如果 FLASH 容量足够,是可以设计很多 APP 程序的,我们按最常用的两个 APP 程序的情况来学习IAP)。这样我们就是要实现 3 个程序:Bootloader 和 APP1和APP2。
执行流程图:
STM32正常的程序运行流程:
STM32 的内部闪存(FLASH)地址起始于 0x08000000,一般情况下,程序文件就从此地址开始写入。此外 STM32 是基于 Cortex-M3 内核的微控制器,其内部通过一张“中断向量表”来响应中断,程序启动后,将首先从“中断向量表”取出复位中断向量执行复位中断程序完成启动,而这张“中断向量表”的起始地址是 0x08000004,当中断来临,STM32 的内部硬件机制亦会自动将 PC 指针定位到“中断向量表”处,并根据中断源取出对应的中断向量执行中断服务程序。
STM32 在复位后,先从 0X08000004 地址取出复位中断向量的地址,并跳转到复位中断服务程序,如图标号①所示;在复位中断服务程序执行完之后,会跳转到我们的main 函数,如图标号②所示;而我们的 main 函数一般都是一个死循环,在 main 函数执行过程中,如果收到中断请求(发生重中断),此时 STM32 强制将 PC 指针指回中断向量表处,如图标号③所示;然后,根据中断源进入相应的中断服务程序,如图标号④所示;在执行完中断服务程序以后,程序再次返回 main 函数执行,如图标号⑤所示。
当加入 IAP 程序之后,程序运行流程如图:
加入 IAP 之后程序运行流程图中,STM32 复位后,还是从 0X08000004 地址取出复位中断向量的地址,并跳转到复位中断服务程序,在运行完复位中断服务程序之后跳转到 IAP 的 main 函数,如图标号①所示,在执行完 IAP 以后(即将新的 APP 代码写入 STM32的 FLASH,灰底部分。新程序的复位中断向量起始地址为 0X08000004+N+M),跳转至新写入程序的复位向量表,取出新程序的复位中断向量的地址,并跳转执行新程序的复位中断服务程序,随后跳转至新程序的 main 函数,如图标号②和③所示,同样 main 函数为一个死循环,并且注意到此时 STM32 的 FLASH,在不同位置上,共有两个中断向量表。
在 main 函数执行过程中,如果 CPU 得到一个中断请求,PC 指针仍强制跳转到地址0X08000004 中断向量表处,而不是新程序的中断向量表,如图标号④所示;程序再根据我们设置的中断向量表偏移量,跳转到对应中断源新的中断服务程序中,如图标号⑤所示;在执行完中断服务程序后,程序返回 main 函数继续运行,如图标号⑥所示。
通过以上两个过程的分析,我们知道 IAP 程序必须满足两个要求:
1) 新程序必须在 IAP 程序之后的某个偏移量为 x 的地址开始;
2) 必须将新程序的中断向量表相应的移动,移动的偏移量为 x;
2 内存分区
我们写的代码最终都会被编译成二进制文件并保存在Flash中,那么我们就可以进一步对我们程序进行分区。STM32的闪存模块由:主存储器、信息块和闪存存储器接口寄存器等 3 部分组成。
1)主存储器,该部分用来存放代码和数据常数(如 const 类型的数据)。对于大容量产品,其被划分为 256 页,每页 2K 字节。注意,小容量和中容量产品则每页只有 1K 字节。从上图可以看出主存储器的起始地址就是0X08000000, B0、B1 都接 GND 的时候,就是从 0X08000000开始运行代码的。
2)信息块,该部分分为 2 个小部分,其中启动程序代码,是用来存储 ST 自带的启动程序,用于串口下载代码,当 B0 接 V3.3,B1 接 GND 的时候,运行的就是这部分代码。
3)闪存存储器接口寄存器,该部分用于控制闪存读写等,是整个闪存模块的控制机构。对主存储器和信息块的写入由内嵌的闪存编程/擦除控制器(FPEC)管理;编程与擦除的高电压由内部产生。
那么我们分区就是主要对FLASH的主存储器进行分区,STM32F103ZE共512K的Flash大小,我们将它分成三个区,BootLoader区、App1区、App2区(备份区)具体划分如下表:
BootLoader区存放启动代码 升级的代码限制在250K以内
App1区存放应用代码
App2区存放暂存的升级代码
区域 | 大小 | 地址范围 |
BootLoader | 12K 0x3000 | 0x08000000-0x08002FFF |
APP1 | 250K 0x3E800 | 0x08003000-0x080417FF |
APP2(备份区域) | 250K 0x3E800 | 0x08041800-0x0807FFFF |
3 整体设计流程图
先执行BootLoader程序, 先去检查APP2区有没有程序,
如果有程序就将App2区(备份区)的程序拷贝到App1区, 然后再跳转去执行App1的程序。 -- 查询标志位确定
如果APP2区域没有程序,跳转到APPI1区域去执行; -- 检查跳转地址是否合法,合法跳转,不合法不跳转
如果APP1区域也没有程序,那就执行Bootloader -- 跟上面一样
然后执行App1程序, 因为BootLoader和App1这两个程序的向量表不一样, 所以跳转到App1之后第一步是先去更改程序的向量表,然后再去执行其他的应用程序。
在应用程序里面会加入程序升级的部分,这部分主要工作是拿到升级程序,然后将他们放到App2区(备份区),以便下次启动的时候通过BootLoader更新App1的程序。
流程图如下图所示:
4 Boot Loader 的代码编写
在BootLoader程序中,我们主要实现对APP2区域的中的标志检查,读取APP2内部的程序,写入APP1地址程序,代码执行跳转程序。
具体的代码执行过程,我们参考示例代码来掌握,整个执行流程如下图所示:
5 APP1代码编写
在整个APP代码的编写上,我们首先修改向量表, 因为本程序是由BootLoader跳转过来的, 不修改向量表后面会出现问题;需要在APP的基本功能上加入串口接收数据并保存到APP2(备份区)的功能代码。
具体的代码执行过程,我们参考示例代码来掌握,整个执行流程如下图所示:
在APP程序的编译时,我们需要修改地址属性,具体如下图所示:
6 APP2 代码编写
APP2的代码跟APP1的代码功能基本一致,只是细微处修改BUG。
通过这一步设置,我们就可以在 MDK 编译成功之后,调用 Demo.exe(注意,我的 MDK 是安装在 D盘文件夹下,如果你是安装在其他目录,请根据你自己的目录修改Demo.exe 的路径),根据当前工程的 Demo.axf(如果是其他的名字,请记住修改,这个文件存放在 Objects 目录下面,格式为 xxx.axf),生成一个 RTC.bin 的文件。并存放在 axf 文件相同的目录下,即工程的 Objects 文件夹里面。在得到.bin 文件之后,我们只需要将这个 bin 文件传送给单片机,即可执行 IAP 升级。(我们也可以将bin文件无线发送,存放在SD卡内,存放在外部FLASH内等等方式进行代码升级,其中无线发送的形式叫OTA)。
我们把APP2生成的bin文件,通过串口,发送到APP1的运行设备上,就会自动的保存APP2的代码数据到对应的Flash地址下,那么按下复位按键后(也可以软件复位),再次运行bootloader代码,就会加载APP2的数据到APP1的地址下,并运行新的程序。
实现程序重启:
本地升级:可以选择按下复位键或者断电重启
远程升级:通过看门狗复位或者程序直接调用复位函数
Bootloader:引导加载程序,程序先运行它,
APP1:用户程序1,出厂用的APP1
APP2:用户程序2,当设备需要升级时,远程或者本地将APP2程序传送给设备,设备校验程序没有问题,跳转执行APP2
大家一定要能够表达过程。