STM32H7 的 D-Cache 开启后 DMA 数据错乱:地址对齐与 Clean/Invalidate 时序的实测分析

· 6 浏览

回答(4)

注意 Clean 和 Invalidate 的顺序:发送前 Clean,接收后 Invalidate。若接收后先 Invalidate 再 Clean,会丢失数据。另外,Invalidate 前需确保 DMA 传输完成标志已置位。
Cache小王子 · 2026-10-11
更稳妥的方案:将 DMA 描述符和缓冲区放在 DTCM 或 AXI SRAM 的 Non-Cacheable 区域,通过 MPU 配置,省去手动维护,但注意 DTCM 不支持 DMA。
STM32调参侠 · 2026-10-11
实测发现,若缓冲区跨越两个缓存行,Clean 操作会多写相邻行,导致其他变量被意外刷回。建议缓冲区大小按 32 字节对齐,且首地址对齐。
嵌入式老鸟 · 2026-10-11
STM32H7 的 D-Cache 与 DMA 冲突核心是缓存一致性。实测发现:若 DMA 缓冲区未按 32 字节对齐(Cortex-M7 缓存行大小),Clean/Invalidate 会误伤相邻数据。正确做法:1) 缓冲区用 __attribute__((aligned(32))) 强制对齐;2) DMA 发送前对缓冲区执行 SCB_CleanDCache_by_Addr,确保数据写入内存;3) DMA 接收后先 SCB_InvalidateDCache_by_Addr 再读数据,避免读到旧缓存。注意:Invalidate 前必须确保 DMA 已完成传输,否则会丢弃未写入的数据。若使用 MPU 将 DMA 区域配置为 Write-Through 或 Non-Cacheable,可彻底避免一致性问题,但会牺牲性能。推荐对高频小数据用 Non-Cacheable 区域,大数据用对齐+Clean/Invalidate 组合。
mcuku 阿沐 · 2026-10-11