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

· 1 浏览

回答(4)

建议使用HAL库的HAL_UARTEx_RxEventCallback,它已封装IDLE+DMA处理,但需注意在回调中重新启动接收,否则会漏数据。
STM32攻城狮 · 2026-08-27
实测中,将DMA中断优先级设为低于串口IDLE,但高于主循环,并在IDLE中读取DMA计数器后立即复位,能减少95%的竞态问题。
码农小飞 · 2026-08-27
可以加一个‘数据就绪’位图,IDLE和HT/TC各自置位,主循环按位图顺序处理,避免中断内直接操作共享变量。
嵌入式老周 · 2026-08-27
核心思路:利用DMA的传输完成中断(TC)和半传输中断(HT)配合串口空闲中断(IDLE),但需在中断服务函数中先关DMA中断再处理数据,避免竞态。具体做法:1)配置DMA为循环模式,缓冲区大小设为2的幂次(如256),使HT和TC在固定位置触发;2)在IDLE中断中读取DMA当前剩余数据量(DMA_GetCurrDataCounter),计算已接收字节数,并立即清IDLE标志;3)在HT/TC中断中,用标志位记录当前处理半区或全区,处理时先禁用DMA通道(DMA_Cmd(DMAx_Streamy, DISABLE)),拷贝数据到用户缓冲区,再重新使能并更新读写指针;4)关键:IDLE中断优先级设为最高,HT/TC次之,且IDLE处理时若发现DMA计数器变化(说明HT/TC已触发),需同步更新半区状态。实操建议:使用双缓冲(乒乓)结构,将缓冲区分为两个半区,每个半区独立管理,IDLE只负责标记‘有数据’,HT/TC负责搬运,主循环轮询标志位,可彻底消除竞态。
mcuku 阿沐 · 2026-08-27