STM32H7 的 D-Cache 与 DMA 一致性:Clean/Invalidate 的时机选择与踩坑复盘

· 2 浏览

回答(4)

最稳还是 MPU 配 Non-Cacheable,性能损失可接受,省去所有 Clean/Invalidate 调用,代码也简单,不容易漏。
阿杰 · 2026-09-18
实测 H7 上如果缓冲区跨 Cache 行且未对齐,Invalidate 会把相邻变量清掉,表现为随机死机。建议用 __attribute__((aligned(32))) 强制对齐。
夜风 · 2026-09-18
补充一个踩坑:DMA 描述符本身若放在 Cacheable 区,改完描述符也要 Clean,否则 DMA 读到旧描述符,现象是传输长度或地址不对。
嵌入式老兵 · 2026-09-18
STM32H7 的 D-Cache 与 DMA 一致性核心是:DMA 访问的是物理内存,CPU 可能读到 Cache 中的旧数据。正确做法:发送方向(CPU 写内存,DMA 读)在启动 DMA 前对缓冲区执行 Clean(写回),确保内存数据最新;接收方向(DMA 写内存,CPU 读)在 DMA 完成中断后先 Invalidate(无效化)再读,避免读到 Cache 旧值。关键坑点:1) 缓冲区必须按 Cache 行大小(32 字节)对齐,否则 Clean/Invalidate 会误伤相邻数据;2) Invalidate 前必须确保 CPU 没有未写回的数据,否则会丢失;3) 不要用全局 Invalidate,会清掉栈等关键数据;4) 推荐用 MPU 将 DMA 缓冲区配置为 Write-Through 或 Non-Cacheable,从根上避免一致性问题。实操建议:优先 MPU 方案,若用 Cache 维护,务必用 SCB_CleanDCache_by_Addr 和 SCB_InvalidateDCache_by_Addr 按地址范围操作。
mcuku 阿沐 · 2026-09-18