["STM32H7 的 D-Cache 开启后 DMA 收发数据出现随机错误:地址对齐与 clean/invalidate 时序怎么排"]

· 1 浏览

回答(4)

发送前 clean,接收前 invalidate,接收后 invalidate;如果收发共用缓冲区,中间必须加 __DSB() 确保操作顺序。
H7调参侠 · 2026-09-11
注意 SCB_InvalidateDCache_by_Addr 的地址必须 32 字节对齐,长度也要是 32 的倍数,否则会误无效化相邻缓存行导致随机错误。
CortexM7玩家 · 2026-09-11
最稳做法:把 DMA 缓冲区放到 MPU 配置的 Non-Cacheable 区域,彻底避开 clean/invalidate,代价是 CPU 访问稍慢,但省心。
嵌入式老鸟 · 2026-09-11
STM32H7 的 D-Cache 与 DMA 协同问题,核心是保证 CPU 访问与 DMA 访问的缓存一致性。首先,DMA 缓冲区必须按 32 字节对齐(Cortex-M7 缓存行大小),推荐使用 __attribute__((aligned(32))) 或 ALIGN_32 宏,且大小设为 32 的整数倍,避免同一缓存行内混有非 DMA 数据。其次,时序要分方向处理:DMA 发送(内存到外设)前,必须对缓冲区执行 SCB_CleanDCache_by_Addr,将 CPU 写的数据刷到 SRAM;DMA 接收(外设到内存)前,先 SCB_InvalidateDCache_by_Addr 无效化对应区域,防止 CPU 预取旧数据,接收完成后再无效化一次。注意:invalidate 会丢弃未回写的脏数据,因此接收缓冲区在 DMA 期间 CPU 不应写入。若使用 MPU 将 DMA 缓冲区配置为 Write-Through 或 Non-Cacheable 可简化操作,但会牺牲性能。推荐用 HAL 的 SCB_* 函数并确保地址 32 字节对齐,否则函数内部会按行操作导致误伤相邻数据。
mcuku 阿沐 · 2026-09-11