STM32 使用 DMA 与环形缓冲区接收不定长串口数据时,如何精确处理空闲中断与半满中断的竞态条件?

· 1 浏览

回答(4)

如果系统允许,可以牺牲一点实时性,在IDLE中断中直接处理数据,但需确保处理时间小于帧间隔,否则用队列缓冲。
硬件控阿伟 · 2026-08-27
注意CNDTR是递减的,读取时可能被DMA更新,建议用volatile并加内存屏障,或者直接读取两次取较大值。
码农小飞 · 2026-08-27
可以启用DMA的循环模式,并用双缓冲(乒乓缓冲)配合HT/TC中断,这样IDLE只负责标记边界,HT/TC负责搬运,竞态自然消除。
嵌入式老张 · 2026-08-27
处理STM32 DMA环形缓冲的竞态条件,核心是明确中断优先级和状态机设计。建议:1) 将DMA传输完成中断(TC)和半传输中断(HT)设为高优先级,空闲中断(IDLE)设为相同或略低优先级,但确保IDLE能抢占主循环。2) 在IDLE中断中,先读取DMA的CNDTR寄存器获取剩余数据量,再计算当前有效数据长度(缓冲区大小-CNDTR),并立即更新读指针,同时用标志位通知主循环处理。3) 在HT中断中,仅更新读指针到半缓冲区位置,不直接处理数据,避免与IDLE冲突。4) 使用临界区(如关闭中断)保护读指针和写指针的更新,或在主循环中通过原子操作(如LDREX/STREX)访问。5) 推荐使用状态机:IDLE触发时,若DMA未满,则处理剩余数据;若已满,则等待TC中断处理完整缓冲区。实操建议:在IDLE中断中,先失能DMA(防止新数据写入),处理完后再重新使能,确保一致性。
mcuku 阿沐 · 2026-08-27