打印
[其他ST产品]

STM32串口DAM接收253字节就死机原因排查

[复制链接]
362|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
g36xcv|  楼主 | 2023-1-30 10:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
日前做了一个方案,是关于STM32通过M5311连接MQTT服务器进行通信的。在各项参数测试完毕后,通过MQTT服务器下发了一个300bytes的设备参数配置指令,结果直接死机了。经过多次测试,问题现象具体确定为MQTT服务器发送253字节可以正常,发送大于254字节以上STM32必死机。

为定位问题原因,于是分开测试。先测试STM32的串口通信,串口DMA接收了500字节也正常。再单独测试M5311,串口发送了300字节也正常。这就郁闷了,俩单独都没问题,为啥到一起就死机了。

使用特权

评论回复
评论
g36xcv 2023-1-30 10:58 回复TA
———————————————— 版权声明:本文为CSDN博主「ydgd118」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/ydgd118/article/details/125502244 
沙发
g36xcv|  楼主 | 2023-1-30 10:56 | 只看该作者
先怀疑是串口接收缓存不够,于是检查了一下,是1000字节,绰绰有余的啊!
再怀疑是串口ORE溢出导致死机,结果程序里跟踪了半天,没问题,它是被冤枉的。
检查串口波形,发现STM32的好像波特率稍微低了一点点,不过相互都能识别,应该是在误差范围内。把波特率调整了一点,问题涛声依旧啊。
再怀疑是DMA错误,程序跟踪检查,没错儿。

使用特权

评论回复
板凳
g36xcv|  楼主 | 2023-1-30 10:57 | 只看该作者
实在没办法了,那就跟踪串口中断函数把。在各个if–else里都添加了打印语句,一路跟踪下来,发现串口中断处理也是很完美的。它也是被冤枉的。

使用特权

评论回复
地板
g36xcv|  楼主 | 2023-1-30 10:57 | 只看该作者
本帖最后由 g36xcv 于 2023-1-30 12:40 编辑

在串口中断处理完成以后,是服务器指令解析函数,最后检查它。居然问题就是它导致的!收到串口数据后,它先把数据搬运到另一个缓存数组,然后打开DMA接收下一批数据。问题就出在搬的时候,使用了for循环,而且使用了循环变量是uint8_t,但是退出循环的判断条件是超出255的,也就是无意间变成了死循环。所以死机了。

使用特权

评论回复
5
g36xcv|  楼主 | 2023-1-30 12:42 | 只看该作者
/********************************************************************
函 数 名:void Data_Transfer_To_Cache(void)
功能:数据缓存到另一个数组,然后立即再次打开DMA进行接收
参数:无
返回值:无
***********************************************************************/       
uint8_t Data_Transfer_To_Cache(void)
{
        //先立即转存,然后打开DMA接收,再进行判断
        uint8_t data_err = 0;
        Clear_Tmp_Sz();
        if(UART3_Rx_len<TP_LENGTH)//防止数组意外越界
        {
                for(uint16_t i=0;i<UART3_Rx_len;i++)
                {
                        tmp_rx_sz[i] = UART3_Rx_buffer[i];
                }
                tmp_i = UART3_Rx_len;
        }
        else       
        {
                data_err = 1;
        }
        DMA_UART3_Start();//清空接收缓存,打开DMA继续接收
       
//        printf("\r\n%s\r\n",tmp_rx_sz);
        if(data_err)
        {
                printf("数据超出缓存!\r\n");
                return 0;
        }
        else
        {
                return 1;       
        }
}

使用特权

评论回复
6
g36xcv|  楼主 | 2023-1-30 12:43 | 只看该作者
这个函数负责搬砖,其中用的for(uint8_t i=0; i<UART3_Rx_len; i++)循环,在UART3_Rx_len大于255的时候,就陷入了死循环。这个是从以前的项目上直接copy过来的,根本没有考虑到这个 i 会出问题。

使用特权

评论回复
7
g36xcv|  楼主 | 2023-1-30 12:44 | 只看该作者
花了2天时间,从硬件到软件查了个遍,连串口波形都检查了,一个小小的问题浪费了很多时间,这是个教训。希望大家引以为戒吧,以后移植copy代码时候得仔细啊,或者干脆写这种循环的代码,i变量一律使用uint32_t类型,这个不可能出不去了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

25

主题

262

帖子

0

粉丝