读取 STM32H5 Data Flash 触发 NMI 的问题解析 LAT1544 - 实践

关键字:STM32H5, data flash, high-cycle data, NMI

问题描述

客户反馈,启用 STM32H563 的 data flash(high-cycle data flash),在还没有写入任何数据之前去读取 data flash, 会触发 hardfault 异常。

1. 问题分析

我们尝试在 NUCLEO-H563ZI 板上重现难题,直接运用 CubeH5 包内的示例工程 :
STM32Cube_FW_H5_V1.4.0\Projects\NUCLEO-H563ZI\Examples\FLASH\FLASH_EDATA_EraseProgram
此示例代码的大体流程如下 :

1> 系统启动后,初始化系统时钟。

2> 调整 OB, 将 FLASH bank1 的最末尾的 8 个 sector 安装为 high-cycle flash.如下红框所示 :

图1. 配置末尾 8 个 sector 为 data flash

3> 擦除所有 8 个 high-cycle data flash 扇区

4> 往 8 个 data flash 扇区写入数据 0xAA55(半字).

5> 最后读出 8 个 data flash 扇区的数据进行检查

这里有一个细节,每次编程只写半字数据,为什么是半字呢?那是因为 data flash 区域每16bit 对应一个 6 位的 ECC 校验。当然你要是写一个 32bit 的字也是可以的。

为了模拟客户的困难,我们将第 4>步骤跳过,即在擦除扇区后,直接读取扇区内数据。最终重现了问题 :

图2. 触发了 NMI 异常

此时查看 FLASH 的 FLASH_ECCDETR 寄存器 :

图3. FLASH_ECCDETR 寄存器

从寄存器内容可看出,此时触发了 EDATA_ECC double error 错误。刚擦除了 data flash不能立即读取吗?于是在参考手册上找到如下对应内容:

如上图参考手册内容所描述,当 data flash 为 virgin word 时(比如刚擦除完,还未写入任何素材), 此时若去访问它,当触发 ECC 错误,只有编程后(no more virgin), ECC 错误才会消失。

至于读取 data flash 时,触发 ECC 错误时,寄存器中显示的内容为什么是 0xf000? 这个在参考手册中也能找到对应内容:

可见,FLASH_ECCDETR 寄存器的 ADDR_ECC 中显示的地址并不是简单地将 flash 地址直接显示,而是有一定的规则。代码中访问的是 0x09000000U 位置就触发了 data flash ECCD 错误,它对应的是 Data area sector 7 的起始位置,如上表所示,对应 0xF000, 此扇区对ECC 错误记录范围为 0xF000~0xF1FF.

2. 应对办法

知道了原因,再去解决就比较容易了。克服方法有两个:

1> 确保代码中每次读取 data flash 之前必须先写入信息。

2> 屏蔽 ECC 错误

在读取 data flash 之前,执行如下代码:
__HAL_RCC_SBS_CLK_ENABLE();
HAL_SBS_FLASH_DisableECCNMI();

如此一来,虽 ECC 错误仍然存在(已忽略),但不再触发 NMI 中断。

3. 其它

与 data flash 具体类似特性的还有 OTP, 它也是若写任何数据前就去读取其内容也会触发 ECCD 错误,从而导致 NMI 异常。

另外,对于 data flash,访问它要关闭其对应的缓存属性。该在示例中也有相关代码,比如:

若不如此做,则当访问 data flash 时,将触发 hardfault 中断。

图4. 若不关闭缓存属性,访问 data flash 将触发 hardfault

与这个类似的还有 OTP, 和 readonly data(比如芯片 UID). 若对应地址没关闭缓存直接读取也会触发 hardfault.

posted @ 2025-09-06 21:33  yfceshi  阅读(58)  评论(0)    收藏  举报