liao6 发表于 2025-9-11 08:35

【每周分享】STM32串口通信过载溢出问题总结

@21小跑堂、#申请原创#
一、发现问题

用STMG070的4个串口中两个串口实时通信时,偶发某个串口通信挂掉,进入不了接收中断函数,但是能进入接收回调函数,另一个串口通信正常,其他程序正常运行?

二、分析定位问题

起初,以为是多串口通信,导致抢占资源,频繁访问中断,导致通信冲突;

于是,在接收回调函数中,各接收中断函数加入if, else if条件,同一时间只能进入一个串口接收中断,但是还是会偶发串口通信挂掉;

然后,网上查资料,看到HAL库的接收中断里面有加锁、解锁操作,数据量大会导致串口锁死,进入串口接收中断函数,STM32Cube_FW_G0_V1.6.0版本里面没有加锁;

然后,看到有说overrun导致过载溢出错误,串口接收死掉,仿真检测当串口通信挂掉时,果然overrun被置位,这里终于定位到了问题。

三、解决问题

overrun标志,就是状态寄存器ISR寄存器的bit3:ORE,如下图

提示:可以通过OVRDIS关闭ORE检测,如下图

三种解决方案:(推荐第3种)1.在串口故障回调函数中检测ORE标志,如果被置位,则清除,重新打开串口接收中断,代码如下:通过检测进入串口故障回调函数中,串口ORE置位清除的次数,发现进入几次之后,后边就进不来了,不知什么原因?2.STM32CubeMX串口配置中默认overrun默认使能,关闭该使能,但是,有丢包的风险。该方法未尝试。3.定时500ms,检测几个串口的ORE是否置位,置位则清除ORE标志,重新打开中断,这个比较稳定靠谱一些,即使串口接收回调函数异常,也不影响清除ORE标志。代码如下://定时检测OREvoid PS_Modules_Uart_Clear_ORE(void){      static uint16_t su16OreCnt = 0;
      su16OreCnt++;      if(su16OreCnt > 500)      {                su16OreCnt = 0;                if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_ORE) != RESET)                {                        __HAL_UART_CLEAR_OREFLAG(&huart1);                        HAL_UART_Receive_IT(&huart1,(uint8_t*)&rx, sizeof(rx));                }
                if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_ORE) != RESET)                {                        __HAL_UART_CLEAR_OREFLAG(&huart2);                        HAL_UART_Receive_IT(&huart2,(uint8_t*)&rx, sizeof(rx));                }
                if(__HAL_UART_GET_FLAG(&huart3, UART_FLAG_ORE) != RESET)                {                        __HAL_UART_CLEAR_OREFLAG(&huart3);                        HAL_UART_Receive_IT(&huart3,(uint8_t*)&rx, sizeof(rx));                }
                if(__HAL_UART_GET_FLAG(&huart4, UART_FLAG_ORE) != RESET)                {                        __HAL_UART_CLEAR_OREFLAG(&huart4);                        HAL_UART_Receive_IT(&huart4,(uint8_t*)&rx, sizeof(rx));                }      }}串口2和串口3通信压力测试2小时,通信均正常。    通过打印清除次数,发现串口3清除了3次,串口2清除了4次。四、为什么会出现overrun?还是要看这个ORE位 当RXFF = 1时,当移位寄存器中正在被接收到的数据转移到USART_RDR寄存器,该位由硬件设置。当RXFF = 1数据被转移到USART_RDR寄存器未完成时,又来一个数据,则发生过载溢出,ORE置位。STM32F1中这样解释:软件序列先读SR,再读CR,可将其清零。STM32G070也可通过串口中断标志位清除寄存器,将ORE标志清除,如下:

gaoyang9992006 发表于 2025-9-11 17:31

你发错板块了。

gaoyang9992006 发表于 2025-9-11 17:33

已帮你转移到ST板块。

xch 发表于 2025-9-12 09:37

太low了,不懂用 DMA

liao6 发表于 2025-9-12 09:58

xch 发表于 2025-9-12 09:37
太low了,不懂用 DMA

用DMA也要检查这个ORE寄存器噢,有这种风险存在,也要做防御性设计。

xch 发表于 2025-9-12 12:22

liao6 发表于 2025-9-12 09:58
用DMA也要检查这个ORE寄存器噢,有这种风险存在,也要做防御性设计。

果然不懂

liao6 发表于 2025-9-12 17:25

xch 发表于 2025-9-12 12:22
果然不懂

噢?请阁下发表一下高见。

xch 发表于 2025-9-12 17:46

liao6 发表于 2025-9-12 17:25
噢?请阁下发表一下高见。

DMA 的读写速率几乎与内存总线速度一半相当。
UART 接口 再快也得收10个bit才请求一次总线。如何overrun?

liao6 发表于 2025-9-14 09:07

xch 发表于 2025-9-12 17:46
DMA 的读写速率几乎与内存总线速度一半相当。
UART 接口 再快也得收10个bit才请求一次总线。如何overrun ...

单从速度上来说,DMA比串口快很多,这个ORE置位是多串口通信时STM32的寄存器bug,并不代表DMA就一定没有问题,要通过实际测试才能得出结论。

xch 发表于 2025-9-15 10:03

liao6 发表于 2025-9-14 09:07
单从速度上来说,DMA比串口快很多,这个ORE置位是多串口通信时STM32的寄存器bug,并不代表DMA就一定没有 ...

你一贯伟光正。厉害
页: [1]
查看完整版本: 【每周分享】STM32串口通信过载溢出问题总结