[STM32H7] STM32H7 上 D-Cache 与 DMA 数据一致性问题的排查与解决思路

[复制链接]
2|0
LOVEEVER 发表于 2026-9-18 13:20 | 显示全部楼层 |阅读模式
【前言】
STM32H7 主频高、带 L1 Cache,性能提升明显,但也带来一个经典问题:DMA 搬运的数据和 CPU 看到的对不上。这类问题不会编译报错、也不会每次必现,排查起来很耗时间。本文按实际工程顺序把处理思路讲清楚。

一、问题现象
1. 以太网 DMA 收到的数据,CPU 读出来是旧值或半新半旧。
2. ADC 用 DMA 采样,偶尔出现连续几个点数值相同。
3. 用 DMA 发串口数据,发出去的内容比预期短或内容错位。

二、根本原因
Cortex-M7 带 D-Cache,CPU 读写内存会先经过 Cache。DMA 直接访问物理内存,不经过 Cache,两边看到的可能不是同一份数据,这就是一致性问题。

三、解决方式
1. 把 DMA 缓冲区放在 MPU 配置为 Device 或 Strongly-ordered 的内存区,绕开 Cache,配置简单、最不容易出错。
2. 或者把该区域配置成 Write-through,避免脏数据滞留。
3. 在 Cache 使能的情况下必须按方向维护:发送方向,也就是 CPU 写、DMA 读,发送前对缓冲区执行 Clean;接收方向,也就是 DMA 写、CPU 读,DMA 完成后先 Invalidate 再读数据。注意 Invalidate 必须在 DMA 关闭或确认写完后再做,否则会把刚写入的数据丢掉。
4. 注意 Cache 行大小是 32 字节,缓冲区地址和长度都要按行对齐,否则一次失效会波及邻近数据。

四、几种典型错误的写法
1. 只在初始化时做一次 Clean 或 Invalidate,运行中不做维护。
2. 用 Invalidate 代替 Clean,方向搞反。
3. 缓冲区放在普通 SRAM 却没配 MPU,靠运气运行。
4. 中断里做 Cache 维护,但缓冲区跨越了 Cache 行边界。

五、调试手段
1. 先用 MPU 把缓冲区设成 Non-cacheable,如果问题消失,基本可以确认是一致性问题。
2. 用汇编或 CMSIS 的 SCB 接口做精确维护,不要用整片失效操作。
3. 结合 DWT 计数和断点观察,确认 DMA 完成中断与数据读取的先后顺序。

以上是 STM32H7 上比较典型的一致性处理思路,实际项目中建议优先选 MPU Non-cacheable 方案,减少维护代码出错的机会。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

423

主题

3520

帖子

8

粉丝
快速回复 在线客服 返回列表 返回顶部
0