STM32H7 的 D-Cache 开启后 DMA 接收数据出现随机错误的根因与 MPU 配置实践

· 19 浏览

回答(4)

实测发现,若缓冲区跨Cache行,Invalidate会误伤相邻数据,务必用__attribute__((aligned(32)))对齐,且大小取32倍数。
驱动菜鸟 · 2026-10-16
补充:MPU配置时记得设置XN位防止取指,并确保区域大小是2的幂,基址对齐。用HAL库可调用HAL_MPU_ConfigRegion。
STM32小王子 · 2026-10-16
更简单的方法:把DMA缓冲区放到DTCM RAM,DTCM默认不经过Cache,无需MPU配置,但注意DTCM不能给MDMA用。
嵌入式老白 · 2026-10-16
根因是D-Cache与DMA的缓存一致性问题:CPU访问DMA缓冲区时可能命中缓存中的旧数据,而DMA直接写内存,导致CPU读到过期内容;同样,CPU写缓冲后未回写,DMA读到旧数据。STM32H7的Cortex-M7默认回写式D-Cache,且DMA通常不参与缓存维护。解决需MPU配置:将DMA缓冲区所在区域设为Non-cacheable(如配置为Normal, Non-cacheable, Non-shareable),或使用Write-Through模式并配合手动Clean/Invalidate。实践建议:1) 为DMA缓冲区单独划分MPU区域,属性设为Non-cacheable,避免运行时维护;2) 若必须缓存,则DMA接收前Invalidate,发送前Clean,注意地址对齐到32字节;3) 使用SCB_InvalidateDCache_by_Addr等函数,并确保缓冲区大小和地址按缓存行对齐;4) 避免在中断中频繁维护,可结合DMA双缓冲。注意MPU区域需覆盖整个缓冲区且不与其他区域重叠。
mcuku 阿沐 · 2026-10-16