STM32H7 的 DCache 与 DMA 一致性:地址对齐、Clean/Invalidate 时序与常见踩坑

· 5 浏览

回答(4)

DMA 完成中断里做 Invalidate 前最好先 __DSB(),确保 DMA 写入对总线可见,再清 cache,顺序反了会读到旧数据。
H7调参侠 · 2026-10-09
注意 SCB_InvalidateDCache_by_Addr 的地址和长度都要 32 字节对齐,长度不是 32 倍数时向上取整,否则会清掉别的变量。
Cortex小王子 · 2026-10-09
最稳做法:把 DMA 缓冲区用 MPU 配成 Non-cacheable,彻底绕开一致性问题,代价是 CPU 访问稍慢,但省心。
嵌入式老张 · 2026-10-09
STM32H7 的 Cortex-M7 带 D-Cache,DMA 与 CPU 共享内存时必须显式维护一致性。核心原则:DMA 写内存前,CPU 若写过该缓冲区,先 SCB_CleanDCache_by_Addr 把脏数据写回;DMA 读内存后,CPU 再访问前,先 SCB_InvalidateDCache_by_Addr 丢弃缓存旧数据。地址必须按 cache line(32 字节)对齐,长度也要向上取整到 32 字节,否则 Invalidate 会误伤相邻变量。推荐把 DMA 缓冲区放到非缓存区(MPU 配置为 Device/Strongly Ordered 或 Write-Through),或使用 __attribute__((aligned(32))) 并手动维护。常见坑:1) 只 Invalidate 不 Clean,导致 CPU 新数据未写回;2) 在 DMA 传输中途 Invalidate,破坏正在写的数据;3) 缓冲区跨 cache line 未对齐,Invalidate 丢数据;4) 中断里调用维护函数但未关中断,时序错乱。建议封装统一接口,传输前 Clean、传输完成中断里 Invalidate,并保证缓冲区独占 cache line。
mcuku 阿沐 · 2026-10-09