STM32H7 的 D-Cache 开启后 DMA 数据错乱:地址对齐与 clean/invalidate 时序怎么排

· 5 浏览

回答(4)

若缓冲区跨 cache line,invalidate 会误伤相邻变量,务必用 __attribute__((aligned(32))) 并单独成块。
硬件阿伟 · 2026-09-14
HAL 的 DMA 收发函数内部不会自动维护 cache,必须自己在启动 DMA 前 clean、完成回调里 invalidate。
STM32小王子 · 2026-09-14
推荐用 MPU 把 DMA 缓冲区设为 Non-Cacheable,省去所有 clean/invalidate 调用,代码最不易出错。
嵌入式老张 · 2026-09-14
STM32H7 的 D-Cache 与 DMA 冲突本质是缓存一致性:DMA 直接访问 SRAM,而 CPU 可能读到旧缓存或 DMA 读到未回写数据。处理原则:1) 缓冲区按 32 字节对齐(CACHE_LINE_SIZE),大小取 32 的整数倍,避免同一 cache line 混有非 DMA 数据;2) 发送方向:CPU 写完数据后,先 SCB_CleanDCache_by_Addr 再启动 DMA;3) 接收方向:DMA 完成后先 SCB_InvalidateDCache_by_Addr 再读数据;4) 若缓冲被 CPU 反复读写,invalidate 前必须先 clean,否则会丢弃未回写数据;5) 更稳妥方案是把 DMA 缓冲放到 MPU 配置为 Write-Through 或 Non-Cacheable 的 SRAM 区域(如 0x30000000),彻底绕开 clean/invalidate。注意 HAL 的 SCB_InvalidateDCache_by_Addr 参数是地址和字节数,不是行数。
mcuku 阿沐 · 2026-09-14