STM32H7 的 D-Cache 与 DMA 数据一致性:按行清理/无效化为何仍偶发丢帧

· 3 浏览

回答(4)

最稳做法是把 DMA 缓冲区用 MPU 配成 non-cacheable,彻底绕开维护;性能敏感再考虑手动 clean/invalidate。
H7调参侠 · 2026-09-13
DMA 完成中断里先 invalidate 再读,且要确认传输完成标志已置位;在 DMA 还在写时 invalidate 等于主动丢数据。
CortexM7玩家 · 2026-09-13
检查缓冲区是否 32 字节对齐,长度是否向上取整到行边界;不对齐时 clean/invalidate 会波及相邻数据,造成随机丢帧。
嵌入式老张 · 2026-09-13
STM32H7 上按 cache line 做 clean/invalidate 仍丢帧,最常见原因是操作粒度与顺序不对。首先,Cortex-M7 的 D-Cache line 是 32 字节,而 DMA 传输长度往往不是 32 的整数倍,若只对“数据长度”做 clean/invalidate,会漏掉尾部不足一行的部分,导致相邻变量被误清或脏数据未写回。其次,invalidate 必须放在 DMA 接收完成之后、CPU 读取之前,且要确保 DMA 已停止或传输完成标志已置位;若在 DMA 仍写内存时 invalidate,会把 DMA 刚写入但尚未被 cache 感知的数据直接丢弃。第三,发送方向应在启动 DMA 前 clean,接收方向应在 DMA 完成后 invalidate,顺序反了就会读到旧数据。实操建议:把 DMA 缓冲区按 32 字节对齐并向上取整到行边界,用 SCB_CleanDCache_by_Addr / SCB_InvalidateDCache_by_Addr 对整段地址范围操作;若条件允许,将 DMA 缓冲区放到 MPU 配置为 non-cacheable 的区段,或使用带 cache 维护的 HAL 回调,能显著降低偶发丢帧。
mcuku 阿沐 · 2026-09-13