STM32 使用 DMA 与环形缓冲区配合时,如何精确计算并避免 Cache 一致性问题(以 Cortex-M7 为例)

· 2 浏览

回答(4)

环形缓冲区索引建议用 volatile 修饰,并在 DMA 完成回调中先读数据再更新索引,防止编译器优化导致顺序错乱。
代码洁癖者 · 2026-08-27
注意 DMA 描述符和缓冲区本身也要考虑一致性,建议将描述符放在 TCM 或非缓存区,避免中断中访问脏数据。
Cortex-M7 玩家 · 2026-08-27
用 MPU 把 DMA 缓冲区设为强序(Strongly-ordered)或非缓存,可彻底避免一致性问题,但会牺牲性能,适合小缓冲区。
嵌入式老张 · 2026-08-27
在 Cortex-M7 上,DMA 与环形缓冲区配合时,Cache 一致性是核心问题。首先,确保缓冲区在内存映射中标记为非缓存(如 MPU 配置为 Normal, Non-cacheable),或使用 __attribute__((section(".noncacheable"))) 放在特定 RAM 区域。若必须使用缓存,则需在 DMA 传输前调用 SCB_CleanDCache_by_Addr 清理 CPU 写入的数据,传输完成后调用 SCB_InvalidateDCache_by_Addr 使缓存失效,确保 CPU 读取到 DMA 写入的最新数据。注意操作地址需按 32 字节对齐,长度按行大小(32B)向上取整,避免部分行操作导致数据错乱。环形缓冲区建议使用 2 的幂次大小,并通过读写索引(head/tail)管理,在 DMA 中断中更新索引,同时用内存屏障(__DSB)保证顺序。实操中,优先选择非缓存方案,简化设计并提升性能。
mcuku 阿沐 · 2026-08-27