STM32H7 的 D-Cache 与 DMA 数据一致性:Clean/Invalidate 顺序错误引发的偶发数据错乱排查

· 1 浏览

回答(4)

H7 的 Cache Line 是 32 字节,地址和长度都要按 32 对齐并向上取整,否则会误伤相邻变量,这是偶发错乱的高发原因。
码农小何 · 2026-09-11
注意 SCB_InvalidateDCache_by_Addr 会丢弃未写回数据,调用前必须确保该区域没有 CPU 脏数据,否则就是丢数据。
CortexM7玩家 · 2026-09-11
最稳做法:把 DMA 缓冲区放到 MPU 配置的 Non-Cacheable 区域,彻底绕开 Clean/Invalidate,代价是访问稍慢,但省心。
嵌入式老张 · 2026-09-11
STM32H7 的 D-Cache 与 DMA 一致性问题,核心是区分“谁写、谁读”。CPU 写内存后交给 DMA 发送:必须先 SCB_CleanDCache_by_Addr,把 CPU 脏数据写回 SRAM,再启动 DMA,否则 DMA 读到旧数据。DMA 接收数据后由 CPU 读取:应先等 DMA 完成,再 SCB_InvalidateDCache_by_Addr,丢弃 Cache 中的旧行,让 CPU 从 SRAM 重新加载。常见错误是顺序颠倒:发送前先 Invalidate,会把 CPU 刚写的数据丢掉;接收后先 Clean,会把 Cache 旧数据写回覆盖 DMA 新数据。更隐蔽的是对同一缓冲区先 Invalidate 再 Clean,或 Clean/Invalidate 地址未按 32 字节 Cache Line 对齐、长度未向上取整,导致相邻变量被误伤。排查建议:1) 用 SCB_InvalidateDCache_by_Addr 前确保 DMA 已停止且无 CPU 访问;2) 缓冲区用 __attribute__((aligned(32))) 并放在非 Cache 区或 MPU 配置为 Write-Through/Non-Cacheable;3) 在 DMA 完成中断里只做 Invalidate,发送前只做 Clean;4) 用 DWT 或 GPIO 翻转配合逻辑分析仪观察时序。若仍偶发,检查是否在中断中访问了同一 Cache Line 的其他变量。
mcuku 阿沐 · 2026-09-11