STM32H7 的 D-Cache 与 DMA 一致性:从 MPU 配置到 Clean/Invalidate 的完整避坑路径

· 2 浏览

回答(4)

注意 SCB_InvalidateDCache_by_Addr 会丢弃未写回的数据,若缓冲区有 CPU 刚写入但未 Clean 的内容,会丢失。接收前确保无脏数据。
Cache小王子 · 2026-09-23
实际项目中,我常把 DMA 缓冲区放在 MPU 配置为 Non-Cacheable 的 SRAM 区域,这样完全不用 Clean/Invalidate,代码更简单可靠。
H7实战派 · 2026-09-23
补充:若使用 DTCM 内存,它不经过 Cache,DMA 无法访问,所以 DMA 缓冲区不能放 DTCM。AXI SRAM 和 SDRAM 才是常用选择。
嵌入式老鸟 · 2026-09-23
STM32H7 的 D-Cache 与 DMA 一致性核心在于:DMA 直接访问物理内存,而 CPU 可能从 Cache 读写,导致数据不一致。避坑路径分四步:1) MPU 配置:将 DMA 缓冲区所在内存区域(如 SRAM1/2/3、SDRAM)配置为 Write-Through 或 Non-Cacheable,避免 Write-Back 带来的隐式脏数据。若必须用 Write-Back,则需手动维护。2) 发送方向(CPU→DMA):先写数据,再调用 SCB_CleanDCache_by_Addr() 将 Cache 内容写回内存,然后启动 DMA。3) 接收方向(DMA→CPU):DMA 完成中断后,先 SCB_InvalidateDCache_by_Addr() 丢弃 Cache 中旧数据,再读取。4) 地址对齐:Clean/Invalidate 操作要求地址 32 字节对齐,长度向上取整到 32 字节倍数,否则可能误伤相邻数据。注意:Invalidate 前必须确保 CPU 未访问该区域,且 DMA 已停止。推荐使用 CMSIS 的 SCB_* 函数,并考虑使用 MPU 将 DMA 缓冲区设为 Non-Cacheable 以简化设计。
mcuku 阿沐 · 2026-09-23