概述
日前做了一个方案,是关于STM32通过M5311连接MQTT服务器进行通信的。在各项参数测试完毕后,通过MQTT服务器下发了一个300bytes的设备参数配置指令,结果直接死机了。经过多次测试,问题现象具体确定为MQTT服务器发送253字节可以正常,发送大于254字节以上STM32必死机。
为定位问题原因,于是分开测试。先测试STM32的串口通信,串口DMA接收了500字节也正常。再单独测试M5311,串口发送了300字节也正常。这就郁闷了,俩单独都没问题,为啥到一起就死机了。
- 先怀疑是串口接收缓存不够,于是检查了一下,是1000字节,绰绰有余的啊!
- 再怀疑是串口ORE溢出导致死机,结果程序里跟踪了半天,没问题,它是被冤枉的。
- 检查串口波形,发现STM32的好像波特率稍微低了一点点,不过相互都能识别,应该是在误差范围内。把波特率调整了一点,问题涛声依旧啊。
- 再怀疑是DMA错误,程序跟踪检查,没错儿。
- 实在没办法了,那就跟踪串口中断函数把。在各个if–else里都添加了打印语句,一路跟踪下来,发现串口中断处理也是很完美的。它也是被冤枉的。
- 在串口中断处理完成以后,是服务器指令解析函数,最后检查它。居然问题就是它导致的!收到串口数据后,它先把数据搬运到另一个缓存数组,然后打开DMA接收下一批数据。问题就出在搬的时候,使用了for循环,而且使用了循环变量是uint8_t,但是退出循环的判断条件是超出255的,也就是无意间变成了死循环。所以死机了。
/********************************************************************
函 数 名: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("rn%srn",tmp_rx_sz);
if(data_err)
{
printf("数据超出缓存!rn");
return 0;
}
else
{
return 1;
}
}
这个函数负责搬砖,其中用的for(uint8_t i=0; i<UART3_Rx_len; i++)循环,在UART3_Rx_len大于255的时候,就陷入了死循环。这个是从以前的项目上直接copy过来的,根本没有考虑到这个 i 会出问题。
花了2天时间,从硬件到软件查了个遍,连串口波形都检查了,一个小小的问题浪费了很多时间,这是个教训。希望大家引以为戒吧,以后移植copy代码时候得仔细啊,或者干脆写这种循环的代码,i变量一律使用uint32_t类型,这个不可能出不去了。
最后
以上就是还单身万宝路为你收集整理的STM32串口DAM接收253字节就死机原因排查的全部内容,希望文章能够帮你解决STM32串口DAM接收253字节就死机原因排查所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复