STM32H7 的 D-Cache 开启后 DMA 数据错位:如何用 MPU 配置回写策略彻底解决

· 18 浏览

回答(4)

如果 DMA 是双向的,建议每次传输前后都做 Clean+Invalidate,并确保没有其他主设备访问同一缓存行。
Cache不迷路 · 2026-10-08
注意 SCB_InvalidateDCache_by_Addr 的地址必须 32 字节对齐,长度也要是 32 的倍数,否则会清掉其他变量。
STM32小王子 · 2026-10-08
更简单的做法:把 DMA 缓冲区放到非缓存区域(如通过 MPU 配置为 Device 或 Strongly Ordered),但会牺牲 CPU 访问性能。
嵌入式老鸟 · 2026-10-08
STM32H7 开启 D-Cache 后,DMA 直接访问物理内存而 CPU 可能读到缓存中的旧数据,导致数据错位。彻底解决需用 MPU 将 DMA 缓冲区配置为回写(Write-Back)策略,并配合 Cache 维护操作。具体步骤:1) 在链接脚本或代码中定义 DMA 缓冲区,确保地址 32 字节对齐(Cache 行大小)。2) 配置 MPU 区域:基地址为缓冲区起始,大小覆盖整个缓冲区,属性设为 Normal, Write-Back, Read/Write allocate,并设置 TEX=001, C=1, B=1。3) 使能 MPU 和 D-Cache。4) 在 DMA 传输前,若 CPU 写过缓冲区,调用 SCB_CleanDCache_by_Addr() 回写;传输后,若 CPU 要读,调用 SCB_InvalidateDCache_by_Addr() 无效化。注意:Invalidate 前必须确保 DMA 已完成,且缓冲区地址和长度按 32 字节对齐,否则可能误伤相邻数据。推荐使用 ARM 的 CMSIS 函数,并避免在中断中频繁操作 Cache。
mcuku 阿沐 · 2026-10-08