在工业控制、智能家电等项目中,频繁读写的参数存储是刚需。STM32H5 独有的EDATA 高寿命数据区,可模拟 EEPROM 功能,支持 10 万次擦写周期,完美替代传统 Flash 模拟方案。但 EDATA 配置门槛高,90% 的异常(HardFault、NMI 中断、读写失败)都源于配置疏漏。本文基于 ST 官方 LAT1571 文档,从选项字节、MPU 配置、ECC 处理、分区规划、TrustZone 兼容 5 大核心维度,拆解实操要点与避坑技巧,帮你快速上手 EDATA 开发。
资料获取:经验分享 | LAT1571 STM32H5使用EDATA时的注意事项
1. EDATA 核心认知:高寿命模拟 EEPROM
EDATA 是 STM32H5 专属的高耐久性 Flash 区域,专为频繁读写场景设计:
- 擦写寿命:10 万次(远超普通 Flash 的 1 万次);
- 容量分配:双 BANK 架构,每 BANK 最多 8 个扇区(6KB / 扇区,共 48KB);
- 核心用途:模拟 EEPROM,存储频繁更新的校准参数、状态数据;
- 硬件特性:自带 6 位 ECC 校验,保障数据可靠性。
EDATA 默认关闭,需通过选项字节启用,且必须匹配 MPU、ECC 等配置,否则极易触发系统异常。
2. 要点 1:选项字节(OB)正确配置
EDATA 的启用与容量分配,完全依赖EDATA1/2_EN(使能位)和EDATA1/2_STRT(扇区位)两个选项字节,配置错误会导致区域无法识别或容量异常。
2.1 配置参数说明
- EDATA1_EN/EDATA2_EN:BANK1/BANK2 使能位,1 = 启用,0 = 禁用;
- EDATA1_STRT/EDATA2_STRT:扇区数量(0-7),0 = 最后 1 个扇区,7 = 最后 8 个扇区;
- 地址映射:BANK1 EDATA(8 扇区)=0x9000000~0x900BFFF;BANK2=0x900C000~0x9017FFF。
2.2 两种配置方式
方式 1:STM32CubeProgrammer 可视化配置
直接在工具中勾选 EDATA1_EN,设置 STRT=7(8 扇区),一键写入选项字节,适合快速配置。
方式 2:代码动态配置
通过 HAL 库解锁选项字节,检查并配置 EDATA 容量,适配动态开启场景:
FLASH_OBInitStruct.OptionType = OPTIONBYTE_EDATA;
FLASH_OBInitStruct.Banks = FLASH_BANK_1; // 配置BANK1
HAL_FLASHEx_OBGetConfig(&FLASH_OBInitStruct);
if(FLASH_OBInitStruct.EDATASize != 8) { // 未配置8扇区
FLASH_OBInitStruct.EDATASize = 8;
HAL_FLASHEx_OBProgram(&FLASH_OBInitStruct);
HAL_FLASH_OB_Launch(); // 生效配置
}
3. 要点 2:MPU 必须设为非缓存(致命坑)
EDATA 通过 AHB 总线访问,默认所有 AHB 区域都是缓存属性,而 EDATA、OTP 等特殊区域禁止缓存,否则访问时直接触发 HardFault。
3.1 CubeMX 配置步骤
- 开启 MPU;
- 配置 Region0:起始 0x9000000,结束 0x900BFFF,属性设为Normal non-cacheable,禁用指令访问;
- 配置 Region1:起始 0x900C000,结束 0x9017FFF,同上属性;
- 生成代码后自动生效,无需手动改寄存器。
关键提醒
只要用到 EDATA,MPU 非缓存配置必做,这是 90% HardFault 的根源。
4. 要点 3:ECC 错误处理(高频 NMI 元凶)
EDATA 自带 6 位 ECC 校验,未初始化( Virgin)的区域直接读取,会触发 ECC 双错误,进而引发 NMI 不可屏蔽中断,这是最常见的异常场景。
4.1 错误原因
EDATA 擦除后未写入数据时,ECC 校验位为空,读取时校验失败,触发 NMI;只有写入数据后,ECC 位自动生成,错误才会消失。
4.2 解决方案
方案 1:严格遵循 “先写后读”
首次使用 EDATA 前,先擦写初始化,避免空读。
方案 2:NMI 中断自动修复
在 NMI 服务函数中,通过 HAL 库 API 获取错误地址,判断是否为 EDATA 未初始化区域,自动擦写初始化:
void NMI_Handler(void) {
HAL_FLASHEx_Eccd_IRQHandler(); // ECC中断处理
if(EccInfo.Address == EDATA_START_ADDR && EccInfo.Data == 0xFFFF) {
// 未初始化,擦写初始化
HAL_FLASH_Unlock();
FLASH_EraseInitTypeDef EraseInitStruct = {.TypeErase = FLASH_TYPEERASE_SECTORS};
HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD_EDATA, EDATA_START_ADDR, 0xA55A);
HAL_FLASH_Lock();
}
}
5. 要点 4:BANK 分区规划(性能优化)
STM32H5 双 BANK Flash 支持RWW(边读边写),合理分区可大幅提升 EDATA 访问效率:
- 推荐配置:BANK1 跑应用代码,BANK2 分配 EDATA;
- 优势:代码运行与 EDATA 读写分属不同 BANK,互不干扰,实现并行操作;
- 避坑:禁止同一 BANK 混用代码和 EDATA,会导致总线竞争,降低读写速度。
6. 要点 5:TrustZone 工程地址冲突
启用 TrustZone 的工程中,安全 / 非安全区跳转函数默认存放在 Flash 最后扇区,而 EDATA 恰好占用 Flash 尾部区域,会导致地址重叠、编译失败。
解决方法
修改工程分散加载文件(.ld),将 TrustZone 跳转函数移至非 EDATA 区域,避开 0x9000000~0x9017FFF 地址范围,解决冲突。
STM32H5 的 EDATA 是高频参数存储的最优解,但配置需严格遵循 5 大核心要点:
- 选项字节正确使能、分配扇区;
- MPU 强制设为非缓存,杜绝 HardFault;
- 先写后读,或 NMI 自动处理 ECC 错误;
- 双 BANK 分区,代码与 EDATA 分离;
- TrustZone 工程调整加载地址,避免冲突。
按以上步骤配置,可彻底解决 EDATA 读写异常、系统崩溃等问题,充分发挥 10 万次擦写的高耐久性优势,适配各类高频存储场景。
699