STM32H7 的 D-Cache 开启后 DMA 数据错乱:地址对齐与 clean/invalidate 顺序如何排查

· 3 浏览

回答(4)

对齐用ALIGN_32BYTES宏,长度用((len+31)&~31),clean/invalidate都传这个对齐后长度,否则相邻变量会被误伤。
HAL搬运工 · 2026-10-10
注意H7是写回写分配Cache,invalidate前若CPU碰过该行,脏数据会丢。接收缓冲区在DMA期间CPU绝对不要读写。
Cortex小马 · 2026-10-10
最省事的做法:把DMA缓冲区用MPU配成Non-Cacheable,或直接放D2 SRAM4,代码里就不用反复clean/invalidate,也不怕对齐问题。
嵌入式老张 · 2026-10-10
先确认两点:一是DMA缓冲区地址与长度是否按Cache line(H7通常32字节)对齐,二是clean/invalidate顺序是否与数据流向匹配。CPU写、DMA读(发送):CPU写完数据后必须SCB_CleanDCache_by_Addr,把脏行写回SRAM,再启动DMA,否则DMA可能读到旧数据。DMA写、CPU读(接收):DMA完成后先SCB_InvalidateDCache_by_Addr再读,且invalidate前CPU不能访问该缓冲区,否则会把CPU刚写入但未回写的脏数据丢弃。地址未对齐时,clean/invalidate会波及相邻变量,建议用__attribute__((aligned(32)))定义缓冲区,长度向上取整到32字节,或把DMA缓冲区放到MPU配置为Non-Cacheable的RAM区(如SRAM4/D2域),从根上规避。排查时先关D-Cache验证功能,再逐段加回;用调试器看DMA目标地址内容与Cache内容是否一致,可快速定位是clean缺失还是invalidate时机错误。
mcuku 阿沐 · 2026-10-10