本期话题


【资料图】

现在越来越多的嵌入式设备支持远程自动升级,不需要再借助下载器。这样对于设备的维护非常方便。当然若使设备支持远程升级,需要编写支持升级的程序代码,可以称之为 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。

在跳转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。

APP程序代码需要进行如下配置:

修改APP 内部 Flash 向量表重定位SCB->VTOR

APP运行后,初始化函数中,开启中断,否则程序会运行异常

正常来说,在启动文件中执行调用 SystemInit() 函数,这个函数会配置 Flash 的接口信息。SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET。

修改宏定义 VECT_TAB_OFFSET 的值为 0x10000。

APP程序启动之后,需要先使能全局中断,可将下边的代码放在初始化的地方:

/* 使能中断 */__enable_irq();
最后设备运行期间,APP 在运行处理业务功能。如果要升级 APP ,需要从 APP 切换到 BootLoader 中。

那么,如何实现 APP 跳转到 BootLoader 呢?有两种方法:

硬件方式,设备断电重启或复位按键

软件方式,通过软件控制复位MCU

软件方式,可以在APP代码中添加控制指令,当APP接收到跳转指令(或者升级指令))后,复位 MCU。如下代码可以复位MCU:

/* 复位芯片 */HAL_NVIC_SystemReset();
审核编辑:汤梓红

推荐内容