STM32H7 的 D-Cache 与 DMA 一致性:Clean/Invalidate 的正确顺序与踩坑案例

· 3 浏览

回答(4)

注意 SCB_InvalidateDCache_by_Addr 的地址必须 32 字节对齐,长度也要按 cache line 对齐,否则会误伤相邻变量,这是最隐蔽的坑。
Cortex小马 · 2026-10-05
MPU 把 DMA 区设为 Non-Cacheable 最省心,代价是 CPU 访问变慢。数据量大时可用 Write-Through,兼顾性能与一致性。
H7搬砖工 · 2026-10-05
补充一个细节:Invalidate 前若 CPU 刚写过该缓冲区,脏数据会被丢弃。所以接收缓冲区在读完后、交给 DMA 前,最好先 Clean 一次再启动下一轮。
嵌入式老张 · 2026-10-05
STM32H7 的 D-Cache 与 DMA 一致性核心原则:CPU 写、DMA 读(发送方向)→ 先 Clean 再启动 DMA;DMA 写、CPU 读(接收方向)→ DMA 完成后先 Invalidate 再读。顺序不能反:接收方向若先 Invalidate 再等 DMA 完成,会把 DMA 期间写入的数据连同脏行一起丢弃;发送方向若只 Invalidate 不 Clean,DMA 可能读到旧内存。实操建议:1) 缓冲区按 32 字节对齐,长度向上取整到 cache line,避免相邻数据被误 invalidate;2) 用 SCB_CleanDCache_by_Addr / SCB_InvalidateDCache_by_Addr 按地址范围操作,不要整片 Clean/Invalidate;3) 接收完成中断里先 Invalidates 再读数据,且读之前不要再写该缓冲区;4) 最稳妥是把 DMA 缓冲区放到 MPU 配置为 Write-Through 或 Non-Cacheable 的 RAM 区,从根上免维护。踩坑案例:常见现象是串口/以太网偶发丢包或数据错位,调试时单步正常、全速跑就错,往往就是漏了 Clean 或 Invalidate 顺序颠倒。
mcuku 阿沐 · 2026-10-05