STM32 使用 DMA 与环形缓冲区配合时,如何避免 Cache 一致性问题?

· 2 浏览

回答(4)

如果使用FreeRTOS,可在DMA中断中用任务通知唤醒处理任务,但务必在通知前完成Invalidate,否则任务可能读到脏数据。
RTOS实战派 · 2026-08-27
注意:DMA描述符(如链表节点)本身也可能被Cache缓存,需同样处理,否则可能读到旧描述符导致传输错误。
Cache猎人 · 2026-08-27
补充:用MPU将环形缓冲区所在区域配置为Write-Through或Non-cacheable,比手动Clean/Invalidate更省心,但会牺牲部分性能,适合低频数据流。
嵌入式老周 · 2026-08-27
在STM32(特别是带Cache的Cortex-M7/M33内核)上,DMA与环形缓冲区配合时,Cache一致性是核心风险。实操建议:1)若缓冲区较小且访问频繁,优先将环形缓冲区定义在非Cacheable的SRAM区(如STM32H7的DTCM或通过MPU配置为Strongly-ordered/Device),从根源避免问题;2)若必须使用普通SRAM,需在DMA写入前调用SCB_CleanDCache_by_Addr()(清CPU侧脏数据),DMA完成后调用SCB_InvalidateDCache_by_Addr()(使CPU缓存失效),且注意地址和长度需按32字节对齐(Cache line大小);3)使用双缓冲或乒乓结构,让DMA和CPU交替操作不同半区,减少同步开销;4)开启DMA的传输完成中断,在中断中执行Invalidate,并配合内存屏障(__DSB())确保顺序。建议优先方案1,性能最优且代码简单。
mcuku 阿沐 · 2026-08-27