IAP_Bootloader固件升级实现方法
2024年9月 · 预计阅读时间: 5 分钟
#
1. 升级方案#
1.1 基本概念IAP
是“In Application Programming”
的简写,就是用户程序运行时对 Flash 的某些区域进行烧写,可以写入新版本的软件、用户数据等。
IAP
主要包括 BootLoader
和应用程序
两部分:在升级时运行的是 Bootloader,它接收新版本的应用程序,烧写在 Flash 上。
而OTA
是 Over-the-Air
的简写,即空中下载技术
,通过移动通信网络(2G/3G/4G 或 Wifi)对设备终端上固件、数据及应用进行远程管理的技术。简单来说 OTA 技术实现分三步:首先将更新软件上传到 OTA 中心,然后 OTA 中心无线传输更新软件到设备端,最后设备端自动更新软件。
因此,OTA 技术的基础是 IAP 技术,需要基于 IAP 实现程序的自动下载。
OTA 流程如下:
Bootloader
完整功能包括:
- 初始化硬件:比如设置时钟、初始化内存
- 启动内核:从 Flash 读出内核、存入内存、给内核设置参数、启动内核
- 调试作用:在开发产品时需要经常调试内核,使用 BootLoader 可以方便地更新内核
在单片机中,我们可以简单一点,因为不涉及内核,我只是借助它实现 IAP 功能。
#
1.2 Flash 规划STM32H563RIV 内置 2MB Flash,划分如下:
- Bootloader 占据 256KB 空间
- APP 占据 1784KB 空间
- 配置信息占据最后一个扇区 8KB 空间:用来保存 APP 版本、大小、校验码等信息。
#
1.3 Bootloader 程序流程#
2. Bootloader 实现启动功能(跳转)#
2.1 必备知识地址 0 就是默认的异常向量表基地址,使用 Flash 启动时 0 地址被映射到 Flash 基地址 0x08000000。
CPU 读取异常向量表第 1 个 word(4 字节),写入 SP 寄存器
CPU 读取异常向量表第 2 个 word(4 字节),跳转执行:这就是 CPU 运行的第 1 个指令
发生各类异常、中断时,硬件会从异常向量表中,根据异常号、中断号找到一项,这项里保存的是“处理函数的地址”
能正确使用中断的前提是:
- 把异常向量表的基地址告诉 CPU:这可以设置 SCB 里的
VTOR
寄存器(寄存器地址为0xE000ED08
) - 在异常向量表里,填充中断处理函数
#
2.2 APP在 APP 中我们需要设置 ROM 的地址为 0x08040000,因为在 1.2 中我们把这里起始的 1784KB 分给 APP 了。
同时,需要注意,后面 system 函数中又重置了 VTOR 寄存器
#
2.3 Bootloader(jump.S)为了保证中断和异常的使用,先设置 VTOR
寄存器为新的异常向量表,如果不设置的话,默认就会使用 Bootloader 的异常向量表。
- 设置
VTOR
寄存器为新的异常向量表
Bootloader 要启动 APP,需要模仿硬件上电后做的事情:
读取异常向量表的第 1 个 word,设置进 SP 寄存器
读取异常向量表的第 2 个 word,跳转执行
编写jump.S
#
3. Bootloader 实现下载功能#
3.1 下载协议下载协议可以自己定义,根据使用流程定义如下:
Bootloader 发出获取固件信息的请求:发出“1”字符给上位机
上位机发送固件信息:先发出 5 个“0x5a”数据给下位机,用于同步,再发送固件信息。
固件信息如下定义:
注意:为了方便在串口里操作,上位机发送 uint32_t 的整数时,先发送高字节(大字节序)。
- Bootloader 发出获取固件的请求:发出“2”字符给上位机
- 上位机发送 bin 文件
- Bootloader 在烧写过程中,可以发送进度:
“$1%”
、“$2%”
、“$100%“
。以字符“$”
开头、字符“%”
结束。
Bootloader 基本流程在 1.3 中已经展现。这里展示细节。
#
3.2 GetLocalFirmwareInfo获取本地固件信息,只需要到最后一个扇区读取就可以,即地址 CFG_OFFSET (0x081FE000)处。
#
3.3 GetServerFirmwareInfo获取上位机(服务器)的固件信息:先发送‘1’字符给上位机,然后等待上位机发送固件信息的头部标志0x5a
,最后读取sizeof(FirmwareInfo)
个字节的数据,完成后存入ptFirmwareInfo
返回。(注意字节流是大端的,需要转换为小端)。
#
3.4 GetServerFirmware如果需要更新固件,就需要获得固件文件:
先发送’2‘
字符过去,循环读取 len 个字节就可以了。
#
4. Bootloader 实现烧录功能获得完服务器的固件,进行 CRC 校验成功后,就要进行烧录了。首先就需要了解 STM32H5 的 Flash 分区。
#
4.1 Flash 分区内部 Flash 有 2M 字节的空间,分为两个 Bank,每个 Bank 有 128 个分区(sector),每个分区为 8KB。(8KB 128 2 = 2MB)
#
4.2 烧录对于烧录,要先擦除(使用“HAL_FLASHEx_Erase”函数),再烧写(使用“HAL_FLASH_Program”函数)。
基本原理就是需要分 Bank 分 Sector 烧录。
烧录固件 APP:
烧录固件信息:
#
5. Bootloader 实现启动功能(软复位)在启动 APP 之前,应该让系统“尽量”处于初始状态。比如:关闭各类中断、让各类设备处于初始状态。有一个办法可以轻松实现这点:软件复位。
所以,Bootloader 启动 APP 时,可以这样改进:
- 触发软件复位
- 会再次运行 Bootloader
- Bootloader 在初始各类硬件之前判断复位原因,发现是软件服务时,启动 APP
#
5.1 main 函数在 main.c 开头添加:
start_app 就是之前在第 2 小节实现的汇编函数。
isSoftReset 用于判断是否是软件复位;get_app_vector 获取需要跳转过去的地址。
#
5.2 Bootloaderstart_app_c();
使用 hal 库函数HAL_NVIC_SystemReset