STM32H7 的 D-Cache 与 DMA 一致性:Clean/Invalidate 的精确调用时机与踩坑复盘

· 9 浏览

回答(4)

注意:SCB_InvalidateDCache_by_Addr 会丢弃指定地址范围的 Cache 内容,如果缓冲区未按 32 字节对齐,可能误伤相邻变量。建议用 __attribute__((aligned(32))) 对齐缓冲区。
Cache小王子 · 2026-09-12
踩坑:Invalidate 前一定要先 Clean,否则 Cache 里的脏数据会被直接丢弃,导致 DMA 写入的数据被旧值覆盖。我调试三天才发现这个问题。
H7调参侠 · 2026-09-12
补充:如果 DMA 缓冲区在 DTCM 或 AXI SRAM 的 Non-Cacheable 区域,则无需 Clean/Invalidate,但性能会下降。建议用 MPU 将 DMA 缓冲区设为 Non-Cacheable,省去维护操作。
嵌入式老鸟 · 2026-09-12
STM32H7 的 D-Cache 与 DMA 一致性核心原则:DMA 写内存(外设→内存)前,必须对目标缓冲区做 Clean(写回)或 Invalidate(无效化),但更安全的是先 Clean 再 Invalidate,避免脏数据覆盖。DMA 读内存(内存→外设)前,必须对源缓冲区做 Clean。DMA 传输完成后,若 CPU 要读 DMA 写入的数据,必须 Invalidate 对应缓冲区。踩坑复盘:常见错误是只 Invalidate 不 Clean,导致 Cache 中脏数据在 Invalidate 时被丢弃,但实际内存未更新,DMA 写入的数据被旧数据覆盖。正确做法:DMA 写内存前,先 Clean 再 Invalidate;DMA 读内存前,只 Clean。注意缓冲区地址和长度必须按 Cache Line(32 字节)对齐,否则会误伤相邻数据。推荐使用 SCB_CleanDCache_by_Addr 和 SCB_InvalidateDCache_by_Addr,并确保操作前后有内存屏障(__DSB())。若使用 MPU 配置 Write-Through 或 Non-Cacheable 区域,可简化操作。
mcuku 阿沐 · 2026-09-12