STM32H7 的 DCache 与 DMA 缓冲区一致性:地址对齐、Clean/Invalidate 时机与踩坑复盘

· 1 浏览

回答(4)

推荐用MPU配置DMA缓冲区为Normal Non-Cacheable,配合__attribute__((section(".dma_buffer"))),彻底避免Clean/Invalidate,代码更简洁。
H7调参侠 · 2026-09-21
实测踩坑:H7的Cache Line是32字节,但SCB_CleanDCache_by_Addr要求地址32字节对齐,否则HardFault。用HAL库的SCB_InvalidateDCache_by_Addr前务必检查对齐。
夜行码农 · 2026-09-21
最稳方案:把DMA缓冲区放到DTCM或SRAM4,这些区域默认不经过DCache,无需维护,但注意DMA1/2能否访问。
嵌入式老白 · 2026-09-21
STM32H7的DCache与DMA一致性核心是:DMA外设不经过Cache直接访问内存,而CPU可能缓存了旧数据。必须保证缓冲区地址按Cache Line(32字节)对齐,且大小是32字节整数倍,否则Clean/Invalidate会误伤相邻数据。发送方向(内存到外设):CPU写数据后,先SCB_CleanDCache_by_Addr再启动DMA。接收方向(外设到内存):启动DMA前先SCB_InvalidateDCache_by_Addr(或Clean+Invalidate),DMA完成后再Invalidate一次,然后CPU才能读。注意:Invalidate会丢弃未回写的脏数据,所以若CPU在DMA期间碰过该缓冲区,必须用Clean+Invalidate。常见坑:1) 栈上变量做DMA缓冲区,地址不对齐且可能被优化;2) 在中断里调用Cache维护函数,但地址未按32字节对齐;3) 使用MPU将DMA缓冲区配置为Write-Through或Non-Cacheable,可一劳永逸但牺牲性能。推荐用__attribute__((aligned(32)))定义全局数组,并封装安全API。
mcuku 阿沐 · 2026-09-21