zoukankan      html  css  js  c++  java
  • STM32 串口接收大量数据导致死机

    http://blog.csdn.net/origin333/article/details/49992383

    以下文章出自上面的链接。感谢原创作者的分享。

    在一项目中,使用STM32作为主控,程序运行一段时间后概率出现主循环卡死现象。

    问题分析如下:

    1、程序USART2不停接收并处理串口数据,波特率115200;

    2、主循环卡死;

    3、USART1中断及TIM2中断响应函数运行正常;(USART1及TIM2中断优先级均比USART2高)

    4、出现现象后,拔掉USART2的接收数据线,现象不能回复正常;

    5、出现现象后,拔掉后再插入USART2的接收数据线,现象不能回复正常;

    6、并未出现HardFault现象;

    基于以上4点,可能原因如下:

    1、USART2接收中断标志没有清除;

    2、堆栈数据溢出,导致程序异常;

            3、USART2中断重入导致异常;

    4、USART2中断函数被异常响应;

            5、USART2中断ERR;

    对于以上可能原因一一分析:

    1、中断接收标志清楚问题:

    (1)USART2接收中断响应函数如下:

     1 void USART2_Istr(void)
     2 {  
     3     if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
     4     {   
     5         USART_ClearFlag(USART2, USART_FLAG_RXNE);
     6         USART_ClearITPendingBit(USART2, USART_IT_RXNE);
     7         Data = USART_ReceiveData(USART2);
     8         //Process Data
     9     }
    10 }

    (2)出现现象后,通过Usart1中断获取到如下信息:

    a. USART_GetITStatus(USART2,  USART_IT_RXNE)  == RESET

    b. USART_GetFlagStatus(USART2,  USART_FLAG_RXNE)  == RESET

    c. 执行USART_ClearFlag(USART2, USART_FLAG_RXNE)及 USART_ClearITPendingBit(USART2, USART_IT_RXNE)后无法恢复正常;

     结论:与USART2 RXNE中断标志无关。

    2、堆栈数据溢出,导致程序异常;

    (1)使用2倍栈空间,问题存在,概率不会降低;

    (2)使用0.5倍栈空间,问题存在,概率不会提高;

    (3)使用0.25倍栈空间,程序运行进入HardFault;

    结论:与堆栈无关。

    3、USART2中断重入导致异常;

    (1)使用标志法,确认出现问题时,中断响应函数没有重入;

    结论:中断响应函数没有重入。

    4、USART2中断函数被异常响应;

    (1)USART2中断函数可以被正常调用,只是不停进入中断响应函数,卡死主循环;

    (2)检查程序Map,没发现与中断响应函数地址相同的函数;

    (3)检查中断向量表,没发现异常;

    结论:中断函数没有被异常调用;

    5、USART2中断ERR;

    (1)关闭USART2中断,主循环恢复正常;

    (2)启动USART2中断,主循环卡死;

    (3)获取到DR=0x0000;

    (4)USART_GetITStatus取到:RXNE=0,PE=0,TXE=0,TC=0,IDLE=0,LBD=0,CTS=0,ERR=0,ORE=0,NE=0,FE=0;

    (5)通过USART_ClearITPendingBit清除CTS,LBD,TXE,TC,RXNE,IDLE,ORE,NE,FE,PE均无法恢复正常;

    (6)通过USART_GetFlagStatus:

      a.第一次:CTS=0,LBD=0,TXE=1,TC=1,RXNE=0,IDLE=1,ORE=1,NE=0,FE=0,PE=0

    b.第二次:CTS=0,LBD=0,TXE=1,TC=1,RXNE=0,IDLE=0,ORE=0,NE=0,FE=0,PE=0

    c.第三次:CTS=0,LBD=0,TXE=1,TC=1,RXNE=0,IDLE=0,ORE=0,NE=0,FE=0,PE=0

    (7)通过USART_ClearFlag清除CTS,LBD,TXE,TC,RXNE,IDLE,ORE,NE,FE,PE均无法恢复正常;

    分析:

    (1)为什么通过USART_GetITStatus获取了所有中断标志,均为RESET(TC、TXE中断没开),还会进中断?

    (2)为什么通过USART_ClearITPendingBit清除了所有中断标志,还会进入中断?

    (3)为什么关闭USART2中断后再次启动它还会进入卡死状态?

    (4)为什么通过USART_GetFlagStatus第一次和第二次读的不一样?而且USART_ClearFlag清掉所有Flag,也没法恢复正常?

    带着以上几个疑问,查看了参考手册,才恍然大悟!如下:

    (1)打开RXNEIE,默认会同时打开RXNE和ORE中断。

    (2)必须第一时间清零RXNE,如没及时清零,下一帧数据过来时就会产生Overrun error!

    (3)错误就是ORE导致的

    出现错误时,读了RXNE=0,出错应该是上图打勾的情况,如下

    (4)如文档说明,要清除ORE中断需要按顺序读取USART_SR和USART_DR寄存器!

    那就是说USART_ClearFlag清掉所有Flag后,还必须读一遍USART_DR寄存器!

          经过测试出现问题后依次读读取USART_SR和USART_DR,程序回复正常!

    (5)那还有一个问题,为什么USART_GetITStatus读不到ORE中断标志?

    读USART_GetITStatus函数就知道了,只有CR3的EIE置1且SR的ORE置1,读出来USART_GetITStatus(USART2,  USART_IT_ORE)  才是 SET。

    见CR3的EIE位说明。

    解决办法,出现通过接收时,通过USART_GetFlagStatus读取ORE,若不为RESET,则读取DR数据丢弃。

    修改如下:

     1 void USART2_NewIstr(void)
     2 {  
     3     if (USART_GetFlagStatus(USART2, USART_FLAG_PE) != RESET)
     4    {
     5        USART_ReceiveData(USART2);
     6      USART_ClearFlag(USART2, USART_FLAG_PE);
     7    }
     8     
     9    if (USART_GetFlagStatus(USART2, USART_FLAG_ORE) != RESET)
    10    {
    11        USART_ReceiveData(USART2);
    12      USART_ClearFlag(USART2, USART_FLAG_ORE);
    13    }
    14     
    15     if (USART_GetFlagStatus(USART2, USART_FLAG_FE) != RESET)
    16    {
    17        USART_ReceiveData(USART2);
    18       USART_ClearFlag(USART2, USART_FLAG_FE);
    19    }
    20     
    21     if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
    22     {   
    23         USART_ClearFlag(USART2, USART_FLAG_RXNE);
    24         USART_ClearITPendingBit(USART2, USART_IT_RXNE);
    25         Data = USART_ReceiveData(USART2);
    26     }
    27 }

    总结:

    1、看文档!看文档!还是看文档!(重要的事情要说3遍)

    2、库函数用的时候,也要注意其实现,稍有不慎就可能用错。

    3、注意USART_GetFlagStatus与USART_GetITStatus的区别,还有中断响应机制。

    4、任意时候都要考虑出错处理。

    查了一下 ,也有人遇到了相同的情况,可参考:

    http://blog.csdn.net/love_maomao/article/details/8234039

  • 相关阅读:
    五种提高 SQL 性能的方法
    join 使用详解方式
    关于MagicAjax的用法
    收藏几段SQL Server语句和存储过程
    ubuntu nfs配置 以及mount.nfs:access denied by server while mounting问题解决
    Hisi开发板上 SQLite3.3.8移植
    父进程非阻塞回收子进程(适用LINUX下C语言的clientserver模型)
    busybox asm/page.h: No such find.
    ubuntu11.10 samba服务器配置
    errno定义
  • 原文地址:https://www.cnblogs.com/qdrs/p/7701327.html
Copyright © 2011-2022 走看看