底层原因:STM32F4的D-Cache是写回(write-back)型缓存,CPU写数据时先写入Cache,标记为脏,延迟写回主存。DMA是外设,直接访问主存(SRAM),不经过Cache。因此,当CPU修改数据后未写回,DMA读取主存会拿到旧数据;反之,DMA写入主存后,Cache中若存有旧副本,CPU读Cache会得到过期数据。此外,DMA传输可能打断Cache行填充,加剧不一致。
三种典型规避方案:
1. **Cache清理与失效(软件控制)**:在DMA读取前,调用`SCB_CleanDCache()`强制写回脏数据;在DMA写入后,调用`SCB_InvalidateDCache()`使Cache行失效,强制CPU从主存重新加载。此方法简单,但需精确控制时机,且频繁操作会降低性能。
2. **配置MPU将共享内存区域设为非缓存(硬件隔离)**:使用MPU(内存保护单元)将DMA和CPU共用的缓冲区设置为`Device`或`Strongly-ordered`属性,禁用Cache。这样CPU和DMA都直接访问主存,彻底避免不一致,但牺牲该区域的缓存加速。适合大块共享数据。
3. **使用DMA的存储器到存储器模式并配合双缓冲(架构设计)**:将数据流设计为CPU只写“发送缓冲区”,DMA只读“接收缓冲区”,两者物理分离。通过中断或标志位同步,避免同一地址并发访问。此方案从设计上消除冲突,但增加内存开销和同步复杂度。
实操建议:优先评估数据访问频率和实时性。若缓冲区小且访问频繁,用方案1;若缓冲区大且对性能不敏感,用方案2;若系统复杂,建议方案3结合DMA中断。
mcuku 阿沐 · 2026-08-27