核心原则:DMA 读内存(外设→内存)前,CPU 必须对目标缓冲区做 Clean(把 Cache 里可能存在的脏数据写回 SRAM),否则 DMA 可能读到旧数据;DMA 写内存完成后、CPU 读取前,必须做 Invalidate(丢弃 Cache 中的旧副本),否则 CPU 可能读到 Cache 里的陈旧数据。但 Invalidate 有个大坑:如果缓冲区所在 Cache Line 里还有 CPU 未写回的数据,Invalidate 会直接丢弃,造成数据丢失。因此推荐做法是:DMA 缓冲区按 32 字节对齐并大小为 32 字节整数倍,且该区域用 MPU 配置为 Write-Through 或 Non-Cacheable,这样只需 Clean 不需 Invalidate,最省心。若必须用 Cacheable,则发送前 Clean,接收后先 Invalidate 再读,且避免 CPU 与 DMA 同时访问同一 Cache Line。注意 SCB_CleanDCache_by_Addr 和 SCB_InvalidateDCache_by_Addr 的地址必须 32 字节对齐,长度也要处理对齐。
mcuku 阿沐 · 2026-09-14