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

[复制链接]
1159|10
liao6 发表于 2025-9-11 08:35 | 显示全部楼层 |阅读模式
@21小跑堂、#申请原创#
一、发现问题

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

二、分析定位问题

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

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

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

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

三、解决问题

  overrun标志,就是状态寄存器ISR寄存器的bit3:ORE,如下图
   1932268c217952e108.png
提示:可以通过OVRDIS关闭ORE检测,如下图
   5662668c217afca866.png

三种解决方案:(推荐第3种)

  1.在串口故障回调函数中检测ORE标志,如果被置位,则清除,重新打开串口接收中断,代码如下:

   3861268c217d137139.png

通过检测进入串口故障回调函数中,串口ORE置位清除的次数,发现进入几次之后,后边就进不来了,不知什么原因?

2.STM32CubeMX串口配置中默认overrun默认使能,关闭该使能,但是,有丢包的风险。该方法未尝试。

3.定时500ms,检测几个串口的ORE是否置位,置位则清除ORE标志,重新打开中断,这个比较稳定靠谱一些,即使串口接收回调函数异常,也不影响清除ORE标志。代码如下:

  //定时检测ORE

void 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位

   8637768c2185759ee0.png

当RXFF = 1时,当移位寄存器中正在被接收到的数据转移到USART_RDR寄存器,该位由硬件设置。当RXFF = 1数据被转移到USART_RDR寄存器未完成时,又来一个数据,则发生过载溢出,ORE置位。

  STM32F1中这样解释:

   4424968c218939bfb2.png

软件序列先读SR,再读CR,可将其清零。

STM32G070也可通过串口中断标志位清除寄存器,将ORE标志清除,如下:

   4875268c218d073d55.png



评论

@21小跑堂 管理员,你好,求原创审核哦!  发表于 2025-9-17 08:52
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 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就一定没有 ...

你一贯伟光正。厉害
您需要登录后才可以回帖 登录 | 注册

本版积分规则

51

主题

125

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部