一、分区
首先要对flash进行分区,模拟固件升级的场景。一般来说分为bootloader区、A区、B区,我又加了一个更新标志位的区。
我使用的是stm32f103c8t6,flash是64k,sram是20k。查询数据手册可以看到flash和sram的起始地址分别为:0x08000000、0x0x20000000。(该图flash为128k,我的是64k)
明确起始地址后,还要知道容量是怎么转换为十六进制的。如flash大小是64k个字节,如何转换成十六进制呢?单片机的地址是按字节编址的,也就是说flash大小为64*1024=65536字节,十进制的65536转换成十六进制就是0x10000,因此,flash的大小就是0x10000,即从0x08000000-0x0800FFFF。
二、bootloader区
这个区主要就是用来进行上电检测的,读取更新标志区的标志位,来判断程序从A区还是B区启动。我将这个区大小设置为19k,随便设置的,可自行调整。转换成十六进制是0x4C00。需要注意的是每个区的sram均使用全部容量即可,即20k。下图是bootloader程序的keil对应设置。
除此之外还要注意,keil的下载设置,要设置为部分擦除,防止下载程序时影响其他分区,如下图。
下面为bootloader区的核心代码,主要就是初始化串口1、跳转程序。
#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "flash.h"
#define A 1U
#define B 0U
/*
bootloader地址: 0x8000000 - 0x8004BFF
更新标志位地址: 0x8004C00 - 0x8004FFF
A区地址: 0x8005000 - 0x800A7FF
B区地址: 0x800A800 - 0x800FFFF
*/
void SystemClock_Config(void);
typedef __IO uint32_t vu32;
//声明指针函数
void (*jump2app)();
//跳转到应用程序段
//appxaddr:用户代码起始地址.
void iap_load_app(uint