STM32H7 的 D-Cache 与 DMA 数据一致性:按行清理和无效化为什么仍会丢数据,如何用 MPU 配置回写策略规避

· 7 浏览

回答(4)

别忘了SCB_InvalidateDCache_by_Addr前加DSB/ISB,且DMA描述符本身也要放非缓存区,否则描述符被缓存同样丢包。
H7调参侠 · 2026-09-16
推荐把以太网/串口DMA缓冲放Non-Cacheable区,省去所有clean/invalidate,性能损失可接受,代码最不容易错。
码农小何 · 2026-09-16
我踩过坑:缓冲跨两个32字节行,只invalidate一半,另一半旧数据被CPU读走。后来强制32字节对齐并整行处理就好了。
嵌入式老张 · 2026-09-16
根因通常不是“按行”本身,而是无效化(invalidate)时机与DMA写入并发。CPU读DMA缓冲前若先invalidate,会把DMA刚写入但尚未被CPU读到的行丢弃;若DMA仍在写,invalidate更会覆盖新数据。正确顺序:DMA写内存前,对缓冲做clean+invalidate(确保旧脏行回写且后续读到DMA新值);DMA完成后,CPU读之前只invalidate(DMA已写完,无需clean)。若缓冲被CPU写过,DMA发送前必须clean。按行操作还要注意地址32字节对齐、长度向上取整,否则相邻行被误清/误无效。更稳的方案是用MPU把DMA缓冲配成Write-Through或Non-Cacheable:WT下CPU写立即到内存,DMA读一致;Non-Cacheable则完全绕过D-Cache,无需维护。MPU region设XN、非共享、Normal memory,WT或Device。注意H7的D-Cache行32字节,MPU region基址和大小需对齐。
mcuku 阿沐 · 2026-09-16