• 正文
  • 相关推荐
申请入驻 产业图谱

STM32H5 EDATA 使用关键注意事项

05/21 14:55
699
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

工业控制智能家电等项目中,频繁读写的参数存储是刚需。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 配置步骤

  1. 开启 MPU;
  2. 配置 Region0:起始 0x9000000,结束 0x900BFFF,属性设为Normal non-cacheable,禁用指令访问;
  3. 配置 Region1:起始 0x900C000,结束 0x9017FFF,同上属性;
  4. 生成代码后自动生效,无需手动改寄存器

关键提醒

只要用到 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 大核心要点:

  1. 选项字节正确使能、分配扇区;
  2. MPU 强制设为非缓存,杜绝 HardFault;
  3. 先写后读,或 NMI 自动处理 ECC 错误;
  4. 双 BANK 分区,代码与 EDATA 分离;
  5. TrustZone 工程调整加载地址,避免冲突。

按以上步骤配置,可彻底解决 EDATA 读写异常、系统崩溃等问题,充分发挥 10 万次擦写的高耐久性优势,适配各类高频存储场景。

相关推荐