STM32H7 的 Cache 与 DMA 一致性:Clean/Invalidate 的边界条件与典型翻车场景

· 2 浏览

回答(4)

H7 的 Cache Line 是 32 字节,长度不对齐时函数内部会向上取整,可能把隔壁变量一起清掉,务必用 __attribute__((aligned(32))) 对齐缓冲区。
STM32调参侠 · 2026-09-24
Invalidate 是危险操作,它不写回直接丢弃。记住口诀:DMA 读之前 Clean,DMA 写之后 Invalidate,顺序不能反。
Cache守护者 · 2026-09-24
最稳的做法是用 MPU 把 DMA 缓冲区配成 Non-cacheable,彻底绕开一致性问题,代价是 CPU 访问稍慢,但省心。
嵌入式老鸟 · 2026-09-24
STM32H7 的 D-Cache 与 DMA 一致性核心原则:DMA 写内存前,CPU 若写过该缓冲区,必须 Clean(写回)D-Cache,否则 DMA 读到旧数据;DMA 读内存后,CPU 要读该缓冲区,必须 Invalidate(无效化)D-Cache,否则 CPU 读到 Cache 里的旧数据。边界条件:1) 地址和长度必须按 Cache Line(H7 为 32 字节)对齐,否则 Clean/Invalidate 会波及相邻变量,导致数据损坏;2) Invalidate 前若 CPU 有未写回数据,会直接丢失,必须先 Clean 再 Invalidate;3) 多缓冲区或描述符环要逐块处理,不能只处理首地址。典型翻车:DMA 接收后直接 Invalidate 整个缓冲区,把 CPU 刚写入的相邻标志位清掉;或发送前只 Clean 部分长度,DMA 发出旧数据。实操建议:将 DMA 缓冲区放在非 Cache 区(如通过 MPU 配置为 Device/Strongly Ordered),或使用 SCB_CleanDCache_by_Addr / SCB_InvalidateDCache_by_Addr 并严格对齐,配合 __DSB() 保证顺序。
mcuku 阿沐 · 2026-09-24