STM32 使用 DMA 双缓冲传输时,如何避免缓存一致性问题并正确配置半传输中断?

· 1 浏览

回答(4)

使用双缓冲时,可结合空闲中断(IDLE)实现不定长接收,但需注意半传输中断与空闲中断的优先级,避免嵌套冲突。
驱动开发阿明 · 2026-08-27
半传输中断中,务必先读取NDTR寄存器,因为中断触发时DMA可能已继续传输,直接处理缓冲区可能导致数据覆盖。
STM32小能手 · 2026-08-27
建议将DMA缓冲区放在DTCM或SRAM,并关闭该区域的缓存(如MPU配置),这样可从根本上避免一致性问题,简化代码。
嵌入式老周 · 2026-08-27
在STM32上使用DMA双缓冲时,缓存一致性问题主要源于CPU和DMA对同一内存区域的访问顺序不一致。首先,确保DMA缓冲区定义在非缓存区(如SRAM)或使用__attribute__((section(".noncacheable")))属性,避免DMA写入被CPU缓存延迟。其次,配置DMA时,启用双缓冲模式(DMA_SxCR的DBM位),并设置两个缓冲区地址(M0AR和M1AR)。半传输中断(HT)在DMA传输到缓冲区一半时触发,此时CPU可安全处理第一个缓冲区,而DMA继续写入第二个。为避免竞争,在HT中断中处理数据前,需先读取DMA的NDTR寄存器确认当前传输位置,并确保处理完成后清除中断标志。实操建议:使用HAL库时,在HAL_DMA_IRQHandler中调用HAL_DMA_HT_Callback,并在回调中通过__HAL_DMA_GET_COUNTER检查剩余数据,再处理缓冲区。同时,启用内存屏障(__DMB())确保CPU读写顺序。若使用DCache(如STM32H7),需在DMA传输前调用SCB_CleanDCache_by_Addr,传输后调用SCB_InvalidateDCache_by_Addr,并确保缓冲区地址对齐到32字节。
mcuku 阿沐 · 2026-08-27

🧰 配套工具

⏱️ 定时器计算器