STM32单片机实现Bootloader跳转的关键步骤(转载)
STM32单片机实现Bootloader跳转的关键步骤 - 知乎 (zhihu.com)
STM32单片机实现Bootloader跳转的关键步骤 (qq.com)
现在越来越多的嵌入式设备支持远程自动升级,不需要再借助下载器。这样对于设备的维护非常方便。
当然若使设备支持远程升级,需要编写支持升级的程序代码,可以称之为 BootLoader。
也就是说,将设备的程序代码分为两部分:BootLoader 和 APP。
BootLoader 负责升级 APP 以及引导APP运行。APP 负责实现设备的业务处理功能,也就是设备的核心功能代码。
对于Cortex-M 系列的单片机来说,若要实现 BootLoader 安全跳转到 APP,需要进行一些配置。
本文就以 STM32 单片机为例,来聊一聊实现 BootLoader 跳转的关键配置步骤。
聊一聊
在程序开发设计阶段,要根据具体应用情况,对程序存储的 Flash 进行分区。
即,BootLoader 存储的位置以及需要分配的空间大小,以及 APP 的存储的位置和大小。这个存储位置直接关系到程序的执行和跳转。
最简单的一种升级方案是:一个 BootLoader 和 一个 APP ,BootLoader 实现跳转和升级APP 的功能。本文以这个升级方案为例进行介绍。
对于 STM32 单片机来说,程序启动的映射地址为 0x8000000。
可以将 BootLoader 存储在 0x8000000 地址,分配的空间可以根据芯片具体的Flash大小进行调整。比如 0x10000,64K 字节。
APP 存储的地址,安排在 BootLoader 后边,即存储地址为 0x8010000,Flash 剩余的空间都可以分配给APP。
BootLoader 工程配置
BootLoader 的工程需要进行一些配置,以MDK为例,如下图所示,BootLoader 程序存放的 FLASH 地址为 0x8000000,大小为 0x10000。
![](https://pic4.zhimg.com/80/v2-7929c198dba157690ceac694f984b30b_720w.webp)
在跳转APP的程序代码需要注意以下几点:
- 检查栈顶地址是否合法,也就是 APP 存放的起始地址是否合法,
if(((*(__IO uint32_t *)APP_FLASH_ADDR) & 0x2FFE0000) == 0x20000000)
- 屏蔽总中断,防止在程序跳转过程中,中断干扰出现异常
- 获取APP程序起始地址,代码区第二个字(起始地址+4 Flash 位置存储的数据)
- 初始化堆栈指针(用户代码区的第一个字用于存放栈顶地址)
- 利用 APP 起始地址,转化为函数指针类型,执行跳转
其具体的跳转代码如下:
/* 定义类型 */
typedef void (*pFunction)(void);
/* APP flash address */
#define APP_FLASH_ADDR (0x8010000)
void jump_to_app(void)
{
uint32_t JumpAddress;
pFunction Jump_To_Application;
/* 检查栈顶地址是否合法 */
if(((*(__IO uint32_t *)APP_FLASH_ADDR) & 0x2FFE0000) == 0x20000000)
{
/* 屏蔽所有中断,防止在跳转过程中,中断干扰出现异常 */
__disable_irq();
/* 用户代码区第二个 字 为程序开始地址(复位地址) */
JumpAddress = *(__IO uint32_t *) (APP_FLASH_ADDR + 4);
/* Initialize user application's Stack Pointer */
/* 初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址) */
__set_MSP(*(__IO uint32_t *) APP_FLASH_ADDR);
/* 类型转换 */
Jump_To_Application = (pFunction) JumpAddress;
/* 跳转到 APP */
Jump_To_Application();
}
}
APP 工程配置
APP 的工程需要进行一些配置,以MDK为例,如下图所示,APP 程序存放的 FLASH 地址为 0x8010000,大小为 0x30000。
![](https://pic4.zhimg.com/80/v2-47c125b151b4bfe091aac7f19eee2863_720w.webp)
APP程序代码需要进行如下配置:
- 修改APP 内部 Flash 向量表重定位
SCB->VTOR
- APP运行后,初始化函数中,开启中断,否则程序会运行异常
正常来说,在启动文件中执行调用 SystemInit()
函数,这个函数会配置 Flash 的接口信息。 SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET
。
![](https://pic4.zhimg.com/80/v2-620caceb449ffdfebfc411a3de3c909b_720w.webp)
修改宏定义 VECT_TAB_OFFSET
的值为 0x10000。
![](https://pic2.zhimg.com/80/v2-a5e6f619dc9d0295ac9ce31a4f86d9a1_720w.webp)
APP程序启动之后,需要先使能全局中断,可将下边的代码放在初始化的地方:
/* 使能中断 */
__enable_irq();
最后
设备运行期间,APP 在运行处理业务功能。如果要升级 APP ,需要从 APP 切换到 BootLoader 中。
那么如何实现 APP 跳转到 BootLoader 呢?有两种方法:
- 硬件方式,设备断电重启或复位按键
- 软件方式,通过软件控制复位MCU
软件方式,可以在APP代码中添加控制指令,当APP接收到跳转指令(或者升级指令)后,复位 MCU。如下代码可以复位MCU:
/* 复位芯片 */
HAL_NVIC_SystemReset();
好了,就这些内容。欢迎探讨交流。