- 空间分布
将flash空间分为自举程序区和应用程序区。
应用程序区存放用户应用程序。
自举程序负责获取用户应用程序数据,并写入应用程序区,实现程序升级。
- 程序跳转
自举程序需要可以跳转到应用程序区,当然应用程序也可以根据需要设计成可以跳转到自举程序区。
如果程序不是在默认的起始地址,则需要复制向量,并映射到相应的空间。
#define VECTORNUM 108
__IO uint32_t VectorTable[VECTORNUM] __attribute__((at(0x20000000)));
#define BOOTAREA_ADDRESS (uint32_t)0x080FC000
#define APPLICATION_ADDRESS (uint32_t)0x08000000
for(i = 0; i < VECTORNUM; i++)
{
VectorTable[i] = *(__IO uint32_t*)(BOOTAREA_ADDRESS + (i<<2));
}
__HAL_RCC_SYSCFG_CLK_ENABLE(); // 使能 SYSCFG 外设
__HAL_SYSCFG_REMAPMEMORY_SRAM(); // 将内部sram映射到0X00000000地址
而如果从非默认起始地址的空间跳转到默认起始地址空间的程序,则需要恢复向量表
__HAL_SYSCFG_REMAPMEMORY_FLASH(); // 将0地址重新映射回内部FLASH空间
程序跳转:
if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000) // 语句为判断地址处存放的是否为SP堆栈指针,判断栈顶指针是否合法
{
JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
JumpToApplication = (pFunction) JumpAddress;
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS); // 设置堆栈指针SP,指向用户代码首地址
JumpToApplication();
}
- 其他
上面的宏定义VECTORNUM 的值根据不同芯片有所不同,可以查看启动文件或芯片资料。启动文件里的向量表数量+1.
KEIL工程设置
1区是程序空间的起始地址以及空间大小。这里是将自举程序放在0X80FC00起始的0X400(即16K)大小的空间。
2为全局变量分布的起始地址即大小,起始地址以前的用做向量表重映射,需要留足空间,否则编译会出错(提示:Execution region RW_IRAM1 with Execution range [0x20000100,0x20000518) overlaps with Execution region ER$$.ARM.__AT_0x20000000 with Execution range [0x20000000,0x200001b0))。这里是留了256字节给向量重映射。