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

STM32 · 潘东芯片应用 · 63 浏览

回答(4)

发送前 clean,接收前 invalidate,接收后 invalidate;如果收发共用缓冲区,中间必须加 __DSB() 确保操作顺序。
H7调参侠 · 2026-09-11
嵌入式老鸟:我们也是这么处理的,串口打印关键变量一发,问题基本就定位了。
注意 SCB_InvalidateDCache_by_Addr 的地址必须 32 字节对齐,长度也要是 32 的倍数,否则会误无效化相邻缓存行导致随机错误。
CortexM7玩家 · 2026-09-11
H7调参侠:我们试过类似的,最后发现是上拉电阻阻值不对,换 4.7K 就好了。
最稳做法:把 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 字节对齐,否则函数内部会按行操作导致误伤相邻数据。
崔健物联网 · 2026-09-11