STM32H7 双Bank Flash在线升级失败后自动回滚的硬件级保障机制
👁 2 阅读 · 2026-08-27 · 嵌入式
在嵌入式设备OTA升级中,固件损坏或升级中断可能导致设备变砖。STM32H7系列凭借其双Bank Flash架构和硬件级回滚机制,为开发者提供了强大的安全保障。本文深入剖析双Bank Flash的工作原理,详解如何利用硬件特性实现升级失败后的自动回滚,并给出完整的配置步骤与代码示例,帮助开发者构建高可靠的在线升级方案。
# 引言
在嵌入式设备OTA升级中,固件损坏或升级中断可能导致设备变砖。STM32H7系列凭借其双Bank Flash架构和硬件级回滚机制,为开发者提供了强大的安全保障。本文深入剖析双Bank Flash的工作原理,详解如何利用硬件特性实现升级失败后的自动回滚,并给出完整的配置步骤与代码示例,帮助开发者构建高可靠的在线升级方案。
# 双Bank Flash架构原理
STM32H7系列(如STM32H743、H750)内置的Flash存储器被划分为两个独立的Bank:Bank1和Bank2,每个Bank的容量通常为1MB(或根据型号不同)。这种物理隔离的设计允许系统在运行时从一个Bank执行代码,同时对另一个Bank进行擦除和编程操作,从而实现无缝的固件更新。
关键特性包括:
- **独立擦写**:每个Bank可独立擦除和编程,互不干扰。
- **硬件切换**:通过设置选项字节或系统控制寄存器,可以切换系统从哪个Bank启动。
- **自动回滚**:当新固件校验失败时,硬件可自动回退到旧Bank执行,无需软件干预。
# 硬件级回滚机制
STM32H7的硬件回滚机制依赖于以下两个核心功能:
1. **启动配置**:通过BOOT0引脚和选项字节(nBOOT1、nBOOT0)决定系统从Bank1还是Bank2启动。
2. **固件有效性标志**:在每次启动时,硬件检查当前Bank的启动标志(如`FLASH_OPTR`中的`B_BFB2`位),若发现新固件未正确设置有效标志,则自动从另一个Bank启动。
具体流程:
- 升级时,将新固件写入非活动Bank(如Bank2),并设置其有效性标志。
- 重启后,硬件检查Bank2的标志,若有效则从Bank2启动;若无效(如校验失败),则自动回滚到Bank1。
# 配置步骤
## 1. 内存布局规划
将固件分为两个版本,分别放置在Bank1和Bank2的起始地址。例如:
- Bank1:0x08000000(默认启动)
- Bank2:0x08100000(升级目标)
## 2. 设置选项字节
使用STM32CubeProgrammer或代码配置选项字节,确保系统支持双Bank启动。关键设置:
- `nBOOT1=1`,`nBOOT0=0`(从Flash启动)
- `B_BFB2=1`(允许从Bank2启动)
## 3. 编写固件升级与回滚逻辑
在应用代码中实现以下功能:
- 接收新固件并写入Bank2。
- 写入完成后,设置Bank2的有效性标志(如写入特定魔数到固定地址)。
- 重启系统。
# 完整代码示例
以下示例基于STM32H743,使用HAL库实现固件写入和回滚标志设置。
```c
#include "stm32h7xx_hal.h"
#define BANK2_BASE_ADDR 0x08100000
#define VALID_MAGIC 0xA5A5A5A5
#define MAGIC_ADDR (BANK2_BASE_ADDR + 0x1FF000) // 预留区域
// 擦除Bank2扇区
void Erase_Bank2(void) {
FLASH_EraseInitTypeDef eraseConfig;
uint32_t sectorError = 0;
eraseConfig.TypeErase = FLASH_TYPEERASE_SECTORS;
eraseConfig.Banks = FLASH_BANK_2;
eraseConfig.Sector = 0;
eraseConfig.NbSectors = 8; // 根据实际扇区数调整
eraseConfig.VoltageRange = FLASH_VOLTAGE_RANGE_3;
HAL_FLASHEx_Erase(&eraseConfig, §orError);
}
// 写入固件数据到Bank2
void Write_Firmware(uint32_t *data, uint32_t size) {
uint32_t address = BANK2_BASE_ADDR;
for (uint32_t i = 0; i < size; i += 8) {
HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, address, (uint64_t*)&data[i]);
address += 8;
}
}
// 设置有效标志
void Set_ValidFlag(void) {
HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, MAGIC_ADDR, (uint64_t)VALID_MAGIC);
}
// 升级主函数
void OTA_Update(void) {
HAL_FLASH_Unlock();
Erase_Bank2();
// 假设firmware_data和firmware_size已从外部获取
Write_Firmware(firmware_data, firmware_size);
Set_ValidFlag();
HAL_FLASH_Lock();
NVIC_SystemReset(); // 重启
}
// 启动时检查回滚标志
void Check_Rollback(void) {
uint32_t magic = *(__IO uint32_t*)MAGIC_ADDR;
if (magic != VALID_MAGIC) {
// 新固件无效,硬件将自动从Bank1启动,这里可添加日志
printf("Firmware invalid, rolling back\n");
}
}
```
# 注意事项
- **地址对齐**:写入数据必须按8字节对齐,否则HAL_FLASH_Program会报错。
- **扇区大小**:STM32H7的Flash扇区大小因型号而异,需查阅数据手册。
- **有效标志位置**:建议将标志放在Bank2的末尾区域,避免与代码冲突。
- **硬件回滚依赖**:确保选项字节配置正确,否则硬件不会自动切换Bank。
- **测试验证**:在实际设备上模拟升级失败(如写入错误数据),确认回滚功能正常。
# 总结
STM32H7的双Bank Flash硬件级回滚机制为OTA升级提供了强大的可靠性保障。通过合理配置选项字节和设置有效性标志,开发者可以轻松实现升级失败后的自动回滚,避免设备变砖。本文的代码示例和配置步骤可直接应用于实际项目,帮助提升嵌入式系统的健壮性。