STM32F4 系列在开启 D-Cache 后,DMA 与 CPU 访问同一内存区域时出现数据不一致,如何通过 MPU 配置和内存屏障指令正确解决?

· 2 浏览

回答(4)

补充:如果性能允许,建议使用“无缓存”属性(TEX=0,C=0,B=0)并配合`__NOP()`延迟,但更推荐用“写透”模式(TEX=1,C=0,B=1),兼顾一致性和速度。
芯片调试员 · 2026-08-27
补充:内存屏障指令`__DSB()`用于等待所有存储完成,`__DMB()`保证访问顺序。在DMA传输完成后,务必先执行`SCB_InvalidateDCache`再读取数据,否则可能读到旧缓存。
码农小刘 · 2026-08-27
补充:MPU配置时,将DMA缓冲区设为“非缓存”最简单,但注意MPU区域优先级,确保覆盖正确。若缓冲区较小,可考虑使用DMA的“内存到内存”模式时关闭Cache。
嵌入式老张 · 2026-08-27
在STM32F4上开启D-Cache后,DMA与CPU共享内存时,数据不一致的根本原因是DMA不经过Cache,直接访问物理内存,而CPU可能读写Cache中的旧数据。解决方案分两步:首先,通过MPU将共享内存区域配置为“非缓存(或写透)”属性,例如设置MPU_RASR_TEX=1、C=0、B=1(写透,不分配写缓存),或使用TEX=0、C=0、B=0(强序,完全非缓存),确保DMA和CPU都直接访问内存。其次,在关键操作前后使用内存屏障指令:CPU写数据给DMA前,执行`__DSB()`和`__DMB()`确保写操作完成并刷新到内存;DMA写数据给CPU前,执行`__DMB()`使CPU读取前看到最新数据。实操建议:优先使用MPU将DMA缓冲区配置为“非缓存”区域,避免频繁使用屏障指令影响性能;若必须使用缓存,则采用“缓存清理+失效”流程(如`SCB_CleanDCache`和`SCB_InvalidateDCache`),并确保在DMA启动前清理,DMA完成后失效。注意,MPU配置需在使能D-Cache前设置,且区域大小对齐到32字节。
mcuku 阿沐 · 2026-08-27