STM32H7 的 D-Cache 与 DMA 一致性坑:地址对齐、Clean/Invalidate 顺序到底怎么排

· 5 浏览

回答(4)

对齐检查可用 `((uint32_t)buf % 32) == 0`,长度用 `(len + 31) & ~31` 补齐。调试时先关 D-Cache 验证逻辑,再开 Cache 排查一致性问题。
码农小张 · 2026-10-13
实际项目更推荐 MPU 把 DMA 缓冲区设为 Non-Cacheable,省去手动维护,性能损失可接受。若必须用 Cache,务必用带地址范围的 Clean/Invalidate 函数,别用全局版。
H7实战派 · 2026-10-13
补充一个易错点:接收时若缓冲区在 Invalidate 前已被 CPU 读过,Cache 行是脏的,Invalidate 会直接丢弃未写回数据。建议接收缓冲区只由 DMA 写、CPU 读,且读前不做写操作。
嵌入式老鸟 · 2026-10-13
STM32H7 的 D-Cache 与 DMA 一致性核心是:DMA 访问的是物理内存,CPU 可能读到 Cache 里的旧数据。正确顺序取决于数据流向。 发送(CPU 写 → DMA 读):先 Clean(写回)D-Cache 中对应区域,再启动 DMA。若顺序反了,DMA 可能读到未写回的旧数据。 接收(DMA 写 → CPU 读):先 Invalidate(无效化)D-Cache 对应区域,再启动 DMA。注意:Invalidate 必须放在 DMA 启动前,否则 DMA 写入期间 CPU 可能预取脏数据,导致 Cache 行被错误覆盖。 地址对齐:DMA 缓冲区必须按 Cache 行大小(H7 为 32 字节)对齐,且长度补齐到 32 字节整数倍。否则 Clean/Invalidate 会波及相邻数据,造成数据损坏。推荐用 `__attribute__((aligned(32)))` 定义缓冲区。 更稳妥方案:将 DMA 缓冲区放在 MPU 配置为 Non-Cacheable 的内存区,或使用 `SCB_CleanDCache_by_Addr` / `SCB_InvalidateDCache_by_Addr` 按地址操作,避免全局 Cache 操作。
mcuku 阿沐 · 2026-10-13