STM32H7 的 DCache 与 DMA 缓冲区一致性:地址对齐、Clean/Invalidate 顺序与踩坑复现

· 3 浏览

回答(4)

注意Invalidate的副作用:如果CPU在DMA传输期间写入了缓冲区,Invalidate会丢弃这些写操作。正确顺序是DMA完成中断里先Invalidate再读,且期间CPU不要碰缓冲区。
Cache踩坑人 · 2026-09-29
实际项目建议:DMA缓冲区放DTCM或SRAM4(无Cache区域),或者用MPU配置为Device/Strongly Ordered,省去手动维护Cache的麻烦。
H7实战派 · 2026-09-29
补充:H7的Cache行是32字节,但Clean/Invalidate按地址范围操作时,若范围跨越行边界,会操作整行。所以缓冲区首地址和长度都按32对齐最安全。
嵌入式老白 · 2026-09-29
STM32H7的DCache与DMA一致性核心是:DMA外设不经过Cache直接访问物理内存,而CPU可能缓存了旧数据。关键操作:1) 缓冲区地址必须32字节对齐(DCache行大小),大小也建议32字节倍数,否则Clean/Invalidate会误伤相邻数据。2) 发送方向(CPU写→DMA读):先写数据,再执行SCB_CleanDCache_by_Addr,然后启动DMA。3) 接收方向(DMA写→CPU读):启动DMA前先SCB_InvalidateDCache_by_Addr,DMA完成后再次Invalidate,再读数据。注意:Invalidate前必须确保CPU没有未写回的脏数据,否则会丢失。推荐使用MPU将DMA缓冲区配置为Write-Through或Non-Cacheable,可彻底避免一致性问题。踩坑复现:若缓冲区未对齐,Invalidate会清除相邻变量,导致程序跑飞;若接收时先Invalidate后DMA,但CPU在DMA期间访问了该缓冲区,会读到旧值。建议用__attribute__((aligned(32)))定义缓冲区,并优先使用MPU方案。
mcuku 阿沐 · 2026-09-29