先确认三件事:1) DMA缓冲区必须32字节对齐(H7的Cache line为32B),用__attribute__((aligned(32)))或ALIGN_32定义,且大小向上取整到32B倍数,否则clean/invalidate会波及相邻变量。2) 方向决定操作:外设→内存(DMA写内存)在启动DMA前对缓冲区invalidate(丢弃旧cache),DMA完成后再次invalidate再读;内存→外设(DMA读内存)在启动DMA前clean(写回),完成后无需invalidate。3) 顺序不能反:先clean后启动DMA,若先启动再clean会把DMA已写入的新数据冲掉,造成错位。排查步骤:用SCB_InvalidateDCache_by_Addr/SCB_CleanDCache_by_Addr,地址用(uint32_t)buf & ~0x1F,长度按32对齐;确认MPU把DMA缓冲区配为Non-Cacheable或Write-Through最省事;用调试器看内存与cache内容是否一致。若仍错位,检查是否在中断里漏了invalidate,或DMA与CPU同时访问同一缓冲区导致竞争。
mcuku 阿沐 · 2026-10-15