STM32H7 的 D-Cache 与 DMA 双缓冲冲突:从 MPU 配置到 clean/invalidate 时序的完整排查路径

· 行业用户 · 9 浏览

回答(4)

调试时先关 D-Cache 复现,再逐段打开,配合 SCB_GetCacheLine 思路定位是哪条 cache line 被污染。
硬件小刘 · 2026-11-04
双缓冲切换时最容易漏的是对“即将发送”的 buffer 做 clean,顺序错了 DMA 会发旧数据。
Cortex_M7 · 2026-11-04
优先用 MPU 把 DMA 区设为 Non-cacheable,能省掉大部分 clean/invalidate 时序坑,性能损失通常可接受。
嵌入式老张 · 2026-11-04
先确认冲突根因:D-Cache 行回写覆盖 DMA 新数据,或 CPU 读到 DMA 未写入的旧缓存行。排查顺序:1) MPU 配置:把 DMA 缓冲区所在区域设为 Non-cacheable 或 Write-through,并确保 region 基址/大小按 32 字节对齐、优先级高于默认背景区;若用 Write-back,必须显式维护。2) 缓冲区地址与长度按 32 字节(Cortex-M7 cache line)对齐,避免 clean/invalidate 波及相邻变量。3) 时序:发送前对缓冲区执行 SCB_CleanDCache_by_Addr,再启动 DMA;接收时在 DMA 完成中断里先 SCB_InvalidateDCache_by_Addr 再读数据,且 invalidate 前确保 CPU 未访问该区域。4) 双缓冲切换时,对“刚被 DMA 写入”的 buffer 做 invalidate,对“即将交给 DMA 发送”的 buffer 做 clean,顺序不能颠倒。5) 用 __DSB()/__DMB() 保证维护操作与 DMA 启动的顺序,必要时关闭中断窗口。6) 验证:临时将区域设为 non-cacheable 对比现象,用调试器观察 cache 行状态与内存差异。注意 invalidate 会丢弃未回写数据,只对纯 DMA 写入区使用。
mcuku 阿沐 · 2026-11-04