STM32H7 的 D-Cache 开启后 DMA 数据错位:地址对齐与 clean/invalidate 顺序怎么处理

· 6 浏览

回答(4)

发送前 clean,接收后 invalidate,接收前也要 invalidate 一次防止预取。顺序错了数据必错。
DMA调试员 · 2026-10-15
注意 SCB_InvalidateDCache_by_Addr 的地址参数必须是 32 字节对齐,长度也要向上取整到缓存行,否则会误伤其他变量。
CortexM7玩家 · 2026-10-15
最省心的办法是用 MPU 把 DMA 缓冲区配成 Non-Cacheable,这样完全不用 clean/invalidate,性能损失可接受。
嵌入式老鸟 · 2026-10-15
STM32H7 开启 D-Cache 后,DMA 与 CPU 数据不一致的根因是缓存一致性。首先,DMA 缓冲区必须按缓存行(Cortex-M7 通常 32 字节)对齐,且大小是缓存行整数倍,否则 clean/invalidate 会波及相邻数据。其次,操作顺序至关重要:DMA 发送(内存到外设)前,CPU 写数据后必须执行 SCB_CleanDCache_by_Addr,将脏数据写回 SRAM,再启动 DMA;DMA 接收(外设到内存)时,启动 DMA 前先 SCB_InvalidateDCache_by_Addr 无效化对应区域,防止 CPU 预取旧数据,DMA 完成后再 invalidate 一次,确保 CPU 读到最新数据。注意:invalidate 会丢弃未写回的脏数据,因此接收缓冲区在 invalidate 前不能有 CPU 未 clean 的写入。推荐将 DMA 缓冲区放在非缓存区域(如通过 MPU 配置为 Write-Through 或 Non-Cacheable),或使用 __attribute__((section(".dma_buffer"))) 并配合 MPU,可彻底避免手动维护。若必须用缓存,务必用 SCB_ 系列函数并保证对齐。
mcuku 阿沐 · 2026-10-15