STM32H7 的 Cache 与 DMA 数据一致性:Clean/Invalidate 的时机与踩坑复盘

· 8 浏览

回答(4)

实测发现:DMA 传输长度不是 32 字节整数倍时,Invalidate 会多无效化相邻数据,导致其他变量被意外丢弃,务必按行对齐。
踩坑小王子 · 2026-09-29
注意 SCB_CleanInvalidateDCache_by_Addr 与 SCB_InvalidateDCache_by_Addr 的区别:前者先写回再无效,适合 CPU 和 DMA 都可能写同一区域的情况。
H7玩家 · 2026-09-29
补充一个实用技巧:用 MPU 把 DMA 缓冲区设为 Non-Cacheable,虽然牺牲一点性能,但彻底避免一致性问题,适合新手或对性能不敏感的场景。
嵌入式老鸟 · 2026-09-29
STM32H7 的 L1 Cache 与 DMA 数据一致性核心在于:DMA 看到的是物理内存,CPU 看到的是 Cache 副本。发送方向(内存→外设):CPU 写数据后,必须对数据区域执行 Clean(写回),确保物理内存最新,再启动 DMA。接收方向(外设→内存):启动 DMA 前先 Invalidate(无效化)对应 Cache 行,防止 CPU 读旧数据;DMA 完成后,若 CPU 要读,需再次 Invalidate(注意:若 CPU 在 DMA 期间访问过该区域,需先 Clean 再 Invalidate,否则可能丢失 CPU 写入)。常见坑:1) 缓冲区未按 Cache 行(32 字节)对齐,导致误伤相邻数据;2) 使用 DTCM RAM 可绕过 Cache,但需确认 DMA 能否访问(DMA1/2 不能访问 DTCM,MDMA 可以);3) 多缓冲区时未逐块处理;4) 中断中调用 HAL 的 Cache 操作可能耗时。建议:缓冲区用 __attribute__((aligned(32))) 对齐,长度向上取整到 32 字节;优先用 MPU 将 DMA 缓冲区配置为 Write-Through 或 Non-Cacheable,可省去手动维护。
mcuku 阿沐 · 2026-09-29