STM32H7 的 Cache 与 DMA 一致性:Clean/Invalidate 时机怎么放才不踩内存错乱

· 2 浏览

回答(4)

对齐是隐形杀手,长度不是 32 倍数时 Invalidate 会清掉相邻变量,建议缓冲区单独放一个段并加 __attribute__((aligned(32)))。
硬件阿飞 · 2026-10-03
记住口诀:DMA 读之前 Clean,DMA 写之后 Invalidate。中断里做 Invalidate 时先关中断或确保没有其他 CPU 访问该缓冲区。
码农小陈 · 2026-10-03
最稳的做法是把 DMA 缓冲区用 MPU 配成 Non-Cacheable,直接绕开一致性问题,代价是访问稍慢,但省心且不会踩坑。
嵌入式老张 · 2026-10-03
核心原则:DMA 读内存(外设→内存)前,CPU 必须对缓冲区做 Clean(把 Cache 里脏数据写回 SRAM),否则 DMA 读到旧数据;DMA 写内存(内存→外设)完成后,CPU 必须对缓冲区做 Invalidate(丢弃 Cache 中旧副本),否则 CPU 读到旧数据。顺序不能反:先 Clean 再启动 DMA,DMA 传输完成中断里再 Invalidate。注意 Invalidate 前要确保 CPU 没有未写回的脏数据,否则会丢数据。实操建议:1) 缓冲区按 32 字节对齐(Cortex-M7 Cache line 大小),长度补齐到 32 字节整数倍,避免相邻数据被误清;2) 用 SCB_CleanDCache_by_Addr / SCB_InvalidateDCache_by_Addr,地址必须 32 字节对齐;3) 若缓冲区与 CPU 频繁交互,建议放在 MPU 配置为 Non-Cacheable 的区,省去维护;4) 双缓冲时每块独立维护,别对整块大缓冲区反复 Invalidate。
mcuku 阿沐 · 2026-10-03