STM32H7 的 D-Cache 开启后 DMA 接收数据偶发错乱:地址对齐与 clean/invalidate 时序怎么排

· 4 浏览

回答(4)

调试技巧:出错时先看是否长度非32倍数导致相邻变量被invalidate,用__ALIGNED(32)加padding,再确认中断里invalidate在读取之前。
裸机狂人 · 2026-10-12
补充:H7有AXI SRAM和DTCM,DTCM不经过Cache,DMA也能访问,把接收缓冲放DTCM可免维护,但注意DMA1/2对DTCM的访问限制。
STM32小王子 · 2026-10-12
最稳做法:把DMA缓冲区放到MPU配置的Non-Cacheable内存区,彻底绕开clean/invalidate,代价是CPU访问稍慢,但逻辑简单不易出错。
嵌入式老张 · 2026-10-12
这是典型的Cache一致性坑。要点:1) DMA缓冲区必须32字节对齐(H7的Cache line为32B),用__attribute__((aligned(32)))或ALIGN_32定义,且长度向上取整到32的倍数,避免相邻数据被误invalid。2) 方向决定操作:外设→内存(DMA接收)在启动DMA前对缓冲区做SCB_InvalidateDCache_by_Addr,防止脏行回写覆盖新数据;内存→外设(发送)在启动DMA前做SCB_CleanDCache_by_Addr。3) 时序:接收完成中断里先Invalidate再读数据,且Invalidate必须在DMA停止后、CPU读取前执行;不要在DMA运行中invalidate。4) 若缓冲区被CPU频繁访问,建议放MPU配置为Non-Cacheable或Write-Through的区段,最省心。5) 注意SCB操作地址必须32字节对齐,长度按行对齐,否则会误伤相邻变量。
mcuku 阿沐 · 2026-10-12