STM32H7 的 D-Cache 与 DMA 双缓冲冲突:Clean/Invalidate 顺序写错导致偶发数据错位的排查实录

· 9 浏览

回答(4)

别忘了 __DSB() 和内存屏障,Clean/Invalidate 之后加 DSB 确保操作完成再启动 DMA,很多偶发就是缺屏障。
硬件小兵 · 2026-10-21
H7 的 AXI SRAM 和 DTCM 行为不同,DTCM 不经过 Cache,DMA 能访问的话优先放 DTCM,省掉所有维护操作。
CortexM7笔记 · 2026-10-21
建议把 DMA 缓冲区放到 MPU 配置为 Non-Cacheable 的区段,彻底绕开一致性问题,代价是访问稍慢但最稳。
老张嵌入式 · 2026-10-21
这类偶发错位几乎都源于把 Clean 和 Invalidate 当成了可互换操作。正确原则:CPU 写缓冲区后交给 DMA 发送,只需 Clean(把脏行写回内存),绝不能 Invalidate,否则会丢弃尚未回写的 CPU 数据;DMA 接收完成后交给 CPU 读取,必须先 Invalidate 再读,且 Invalidate 前要确保 DMA 已停止或已通过中断/标志确认传输完成,否则会把 DMA 刚写入但未命中的行清掉。排查时先确认缓冲区按 32 字节对齐(H7 Cache 行 32B),长度向上取整到行边界,避免相邻变量被误清。再用 SCB_CleanDCache_by_Addr / SCB_InvalidateDCache_by_Addr 替代整片 Clean/Invalidate,缩小影响范围。双缓冲切换时在 DMA 完成中断里先 Invalidated 当前读缓冲,再切换;发送侧在启动 DMA 前 Clean。最后用 DWT 或 GPIO 翻转配合逻辑分析仪抓 DMA 请求与 Cache 操作时序,定位错位发生在哪一帧。
mcuku 阿沐 · 2026-10-21