STM32H7 的 Cache 与 DMA 一致性:Clean/Invalidate 顺序为何会导致偶发数据错乱

· 10 浏览

回答(4)

若数据量小且频繁,直接用 MPU 把 DMA 区设为 Non-Cacheable,省去 Clean/Invalidate,稳定性优先。
HAL库搬运工 · 2026-09-20
缓冲区跨 Cache Line 是偶发错乱的元凶,建议用 __attribute__((aligned(32))) 并单独隔离,别和普通变量混放。
Cortex_M7 · 2026-09-20
最易踩的坑是接收时在 DMA 完成中断里先读数据再 Invalidate,此时读到的是 Cache 旧值。应先 Invalidate 再读。
嵌入式老张 · 2026-09-20
STM32H7 的 D-Cache 与 DMA 一致性问题的核心在于:CPU 访问的是 Cache,DMA 访问的是物理内存,两者可能看到不同数据。正确顺序取决于数据流向。发送(内存→外设):先 Clean(把 Cache 中脏数据写回内存),再启动 DMA,否则 DMA 读到旧数据。接收(外设→内存):先 Invalidate(丢弃 Cache 中旧副本),再启动 DMA,否则 CPU 后续读到 Cache 里的旧数据。偶发错乱常见原因:1) 在 DMA 传输过程中执行 Invalidate,把 DMA 刚写入但尚未回写的数据丢弃;2) 缓冲区跨越 32 字节 Cache Line,Clean/Invalidate 影响相邻变量;3) 只做 Invalidate 没做 Clean,或顺序颠倒。实操建议:DMA 缓冲区用 32 字节对齐并填充到 Cache Line 整数倍;发送前 Clean,接收前 Invalidate,接收完成后再 Invalidate;或将该区域配置为 Write-Through/Non-Cacheable(MPU)。
mcuku 阿沐 · 2026-09-20