STM32G474内部FLASH数据管理实战:从原理到IAP应用

张开发
2026/4/15 6:10:29 15 分钟阅读

分享文章

STM32G474内部FLASH数据管理实战:从原理到IAP应用
1. STM32G474内部FLASH架构解析STM32G474系列微控制器搭载了512KB容量的内部FLASH存储器采用创新的双Bank设计架构。我第一次拿到芯片手册时发现这个双Bank结构特别有意思——它把512KB空间平均分成两个256KB的Bank每个Bank又细分为128个2KB大小的页。这种设计最大的好处就是支持并行操作比如在Bank1执行应用程序的同时可以对Bank2进行擦写操作。实际项目中我经常利用这个特性来实现无缝固件升级。举个例子当设备需要OTA升级时可以把新固件下载到空闲的Bank中验证通过后再切换执行整个过程用户完全无感知。芯片默认将Bank1映射到0x08000000地址Bank2映射到0x08040000通过SYSCFG_MEMRMP寄存器的FB_MODE位可以动态调整映射关系。除了主存储区还有几个关键区域需要注意系统存储区56KB存放芯片厂商预置的Bootloader这个区域是写保护的OTP区域1KB一次性可编程区域适合存储加密密钥等关键信息选项字节控制读写保护和芯片配置相当于FLASH的控制面板2. FLASH读写操作实战技巧2.1 安全擦除操作指南在给G474的FLASH写入数据前必须先进行擦除操作。这里有个坑我踩过好几次——忘记擦除就直接写入会导致数据异常。擦除的最小单位是2KB的页但也可以通过配置实现多页或整片擦除。标准的擦除流程应该是这样的解锁FLASH调用HAL_FLASH_Unlock()这个函数内部会处理密钥验证清除错误标志用__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS)清空状态寄存器配置擦除参数FLASH_EraseInitTypeDef eraseConfig; eraseConfig.TypeErase FLASH_TYPEERASE_PAGES; eraseConfig.Banks FLASH_BANK_1; // 指定Bank1 eraseConfig.Page 64; // 从第64页开始 eraseConfig.NbPages 2; // 擦除2页(4KB)执行擦除HAL_FLASHEx_Erase(eraseConfig, sectorError)重新上锁操作完成后立即调用HAL_FLASH_Lock()重要提示擦除操作会把目标区域全部置为0xFF务必确认地址范围无误。我有次误擦了正在运行的代码区导致设备直接死机。2.2 高效写入策略STM32G474的FLASH写入有个特殊要求必须按64位(8字节)对齐。这意味着如果你只想保存几个字节的配置参数也需要凑够8字节再写入。我的经验是设计一个环形缓冲结构攒够8字节再统一写入。写入操作示例uint64_t configData 0x1122334455667788; // 示例数据 HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, 0x08010000, // 目标地址 configData);实测发现连续写入时最好在每次写入后加入10ms左右的延时。特别是在高温环境下这个延时能显著提高写入成功率。另外写入前一定要关闭全局中断避免被打断导致数据异常。3. IAP应用开发实战3.1 双Bank固件升级方案基于双Bank架构我设计了一套可靠的IAP方案将FLASH划分为三个区域Bank1运行中的固件256KBBank2新固件存储区256KB最后4页参数存储区8KB升级流程通过通信接口接收新固件写入Bank2计算CRC32校验值与预期值比对验证通过后在参数区写入跳转标志重启后Bootloader检测到标志将执行权交给Bank2关键代码片段// 跳转到新固件 void JumpToApplication(uint32_t appAddress) { typedef void (*pFunction)(void); pFunction Jump_To_Application; uint32_t jumpAddress *(__IO uint32_t*)(appAddress 4); Jump_To_Application (pFunction)jumpAddress; __set_MSP(*(__IO uint32_t*)appAddress); Jump_To_Application(); }3.2 掉电保护机制在开发数据记录仪时我遇到了掉电导致FLASH数据损坏的问题。后来设计了一套三重保护机制影子备份法每个参数保存两份分布在不同的Bank状态标记写入前先设置状态为写入中完成后再改为正常预写入校验先在RAM构建完整数据校验无误后再写入FLASH具体实现时可以结合RTC的备份寄存器来保存状态标记这样即使主电源掉电纽扣电池也能维持状态信息。4. 安全保护配置技巧4.1 读写保护实战STM32G474提供三级读保护级别0完全开放默认级别1禁止调试器读取但代码可以读级别2最高保护连芯片都无法读取配置读保护后如果尝试通过调试器读取会看到全是0x00或0xFF。但要注意提升保护级别会触发整片擦除我有次不小心在代码里设置了级别2结果把辛苦调试的程序全擦没了。写保护配置示例FLASH_OBProgramInitTypeDef OBInit; HAL_FLASHEx_OBGetConfig(OBInit); // 先获取当前配置 OBInit.OptionType OPTIONBYTE_WRP; OBInit.WRPArea OB_WRPAREA_BANK1_AREAA; OBInit.WRPStartOffset 0x00; // 保护前16页(0-15) OBInit.WRPEndOffset 0x0F; HAL_FLASHEx_OBProgram(OBInit);4.2 选项字节的妙用选项字节除了配置保护还能设置一些实用功能BOR级别调整掉电复位阈值硬件看门狗上电自动使能启动延迟解决某些外设上电慢的问题配置选项字节需要特别注意时序解锁FLASH解锁选项字节修改配置触发选项字节加载软复位或重新上电我在电机控制项目中就利用选项字节配置了硬件看门狗解决了软件看门狗可能被意外关闭的问题。

更多文章