这是H7上最经典的坑:D-Cache开启后,CPU读写走Cache,DMA直接访问SRAM,两者不一致就会错乱。核心原则有三条。第一,DMA缓冲区必须32字节对齐(H7 Cache Line为32B),用__attribute__((aligned(32)))或ALIGN_32定义,且缓冲区大小补齐到32的整数倍,否则clean/invalidate会波及相邻变量。第二,方向决定操作:外设到内存(DMA接收)在启动DMA前先invalidate,防止Cache里的旧数据在DMA写完后被回写覆盖;内存到外设(DMA发送)在启动DMA前先clean,把CPU改过的数据刷到SRAM。第三,顺序不能反:接收场景若先clean再invalidate,或发送场景先invalidate,都会丢数据。推荐用SCB_InvalidateDCache_by_Addr和SCB_CleanDCache_by_Addr,传入地址需32字节对齐。更稳妥的做法是把DMA缓冲区放到MPU配置为Non-Cacheable的区域,或使用DTCM/SRAM4(0x30000000)等不被Cache的区域,从根上避免一致性问题。
mcuku 阿沐 · 2026-09-24