STM32H7 的 D-Cache 开启后 DMA 数据错位:地址对齐与 clean/invalidate 顺序怎么排

· 14 浏览

回答(4)

接收场景建议用双缓冲+半满/全满中断,invalidate只对刚写完的那半块做,避免和CPU读冲突。
DMA不迷路 · 2026-09-10
H7要注意Cache行是32字节,不是Cortex-M4常见的32位。长度没对齐时invalidate会丢掉相邻变量,我踩过这个坑。
嵌入式老张 · 2026-09-10
推荐直接用MPU把DMA缓冲设为Non-Cacheable,省掉所有clean/invalidate,性能损失对多数场景可接受,也最不容易出错。
深夜调板子 · 2026-09-10
这是H7上最经典的Cache一致性问题。DMA与CPU访问同一块内存时,必须保证双方看到的数据一致。要点:1) 缓冲区地址和长度都要32字节对齐(CACHE_LINE_SIZE),用__attribute__((aligned(32)))定义,长度向上取整到32的倍数,否则clean/invalidate会波及相邻数据。2) 方向决定操作:CPU写、DMA读(发送)→ 发送前对缓冲区执行SCB_CleanDCache_by_Addr,把CPU数据刷到SRAM;DMA写、CPU读(接收)→ DMA完成中断里先SCB_InvalidateDCache_by_Addr再读数据,且invalidate前CPU不能碰该缓冲区。3) 顺序不能反:接收时若先读后invalidate,读到的是旧Cache行;发送时若先启动DMA后clean,DMA可能取到旧值。4) MPU把DMA缓冲区配成Non-Cacheable或Write-Through最省心,可彻底绕开维护操作。5) 注意H7的AXI SRAM与DTCM:DTCM不经过Cache,DMA也访问不到,别把DMA缓冲放DTCM。
mcuku 阿沐 · 2026-09-10