STM32H7 的 D-Cache 与 DMA 一致性:Clean/Invalidate 操作顺序写错会怎样翻车

· 7 浏览

回答(4)

调试时若开了 Cache 又用 DMA,串口/ADC 数据偶发错乱,先怀疑一致性;可临时关 D-Cache 验证,定位后再按方向加维护操作。
夜跑的程序猿 · 2026-09-23
注意 SCB_InvalidateDCache_by_Addr 是按行操作的,地址和长度必须 32 字节对齐,否则会把相邻变量的脏数据一起丢掉,出现玄学 bug。
Cortex小王子 · 2026-09-23
最稳的做法是用 MPU 把 DMA 缓冲区配成 Non-cacheable,彻底绕开 Clean/Invalidate,代价是 CPU 访问该区变慢,适合大数据量搬运。
嵌入式老张 · 2026-09-23
STM32H7 的 D-Cache 是 write-back 的,DMA 与 CPU 看到的内存可能不一致。正确顺序要分方向:CPU 写数据后启动 DMA 发送(内存→外设),必须先 SCB_CleanDCache_by_Addr 把脏行写回,再启动 DMA,否则 DMA 读到旧数据。DMA 接收(外设→内存)完成后,CPU 读之前必须先 SCB_InvalidateDCache_by_Addr 丢弃缓存中的旧行,否则读到旧值。常见翻车:先 Invalidate 再 Clean 会把 DMA 刚写入的数据清掉;在 DMA 传输进行中 Invalidate 会丢数据;地址未按 32 字节对齐、长度未覆盖整行,会误伤相邻变量。实操建议:DMA 缓冲区用 __attribute__((aligned(32))) 且大小取 32 字节整数倍,放在非缓存区或用 MPU 配置为 Device/Non-cacheable 最省心;若用 Cache 维护,发送前 Clean、接收后 Invalidate,且不要在传输中操作。
mcuku 阿沐 · 2026-09-23