硬汉嵌入式论坛

 找回密码
 立即注册
查看: 6919|回复: 22
收起左侧

[技术讨论] STM32的UART,被长时间大量灌输数据后死机

  [复制链接]

65

主题

432

回帖

632

积分

金牌会员

积分
632
发表于 2020-7-22 09:30:23 | 显示全部楼层 |阅读模式
我一个产品,用的是STM32F105RBT6,485接口,用户挂载了多个这种产品联网,主机不断的轮询各个设备,不定过多长时间,就有死机的,经过一夜测试之后,不死机的没几个,里面我用了uCOS2,刚开始我还以为是系统死掉了,后来就改软件吧,在uCOS2里加上了各种共享全局变量的保护,都保护上了,然后打开了STM32的看门狗,这样折腾之后,经过前面的实验,确实一个死机的都没有了,但是用户的主机有记录,所有的设备都曾经死机过,只不过是被狗给咬醒的,今天我一朋友跟我说,他的产品也是因为这个问题死机,原因是他的用户也是疯狂的往串口里发数据,造成跟我的产品一样的现象,不定过多久就挂了,他说百度上查,STM32的UART就是有这个BUG,这么著名的MCU,难道这真的是个公开的BUG吗?
回复

使用道具 举报

36

主题

2039

回帖

2147

积分

至尊会员

积分
2147
发表于 2020-7-22 09:47:55 | 显示全部楼层
楼主可以把串口驱动做成最简单,容易维护的串口中断方式。

在中断里面把所有的错误标识都做个检查,不出意外,应该有触发这些错误的情况
Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better.
回复

使用道具 举报

65

主题

432

回帖

632

积分

金牌会员

积分
632
 楼主| 发表于 2020-7-22 09:59:54 | 显示全部楼层
我现在用的就是中断方式,听说的这个BUG就是STM32的串口中断方式连续大量接收数据的时候死机。。。。。。
回复

使用道具 举报

82

主题

401

回帖

667

积分

金牌会员

积分
667
QQ
发表于 2020-7-22 10:03:51 | 显示全部楼层
我要碰到过这种问题,要在中断函数里清除溢出错误(ORE)中断标志。
武汉天纵鹏元科技有限公司。承接嵌入式项目开发,相关技术交流。STM32,物联网,工业控制方向。QQ  408137104
回复

使用道具 举报

82

主题

401

回帖

667

积分

金牌会员

积分
667
QQ
发表于 2020-7-22 10:10:53 | 显示全部楼层
仰慕大神 已久  能否加个QQ 408137104   向大神学习学习
武汉天纵鹏元科技有限公司。承接嵌入式项目开发,相关技术交流。STM32,物联网,工业控制方向。QQ  408137104
回复

使用道具 举报

334

主题

2032

回帖

3039

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3039
发表于 2020-7-22 10:14:19 | 显示全部楼层
“被狗咬醒的”。。。。。。我不禁笑出了声啊。。。。。
回复

使用道具 举报

1

主题

73

回帖

76

积分

初级会员

积分
76
发表于 2020-7-22 10:47:33 | 显示全部楼层
用法就不对,不要用中断接收大量数据,换成DMA,减少不必要的中断,加入乒乓缓冲即可解决问题
回复

使用道具 举报

39

主题

928

回帖

1050

积分

至尊会员

积分
1050
发表于 2020-7-22 11:28:15 | 显示全部楼层
这个跟STM32无关吧?连续大量接收数据,还用中断。不知道你的波特率用的是多大的,假设是57600,理论极限约每秒5760个数据,对应5760次中断,大约每174us进一次中断。这还只是串口通信,你程序里面肯定还有不少其它中断吧?另外,这个死机大概率是存数据的时候内存溢出了,你这样测试:在中断中将接收到的数据放到一个固定的变量,而不是更新到数组队列中。放到一个固定的变量不会内存溢出,就能测试出来了。
回复

使用道具 举报

2

主题

8

回帖

14

积分

新手上路

积分
14
发表于 2020-7-22 11:42:38 | 显示全部楼层
if(USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET) 点个灯
回复

使用道具 举报

65

主题

432

回帖

632

积分

金牌会员

积分
632
 楼主| 发表于 2020-7-22 14:09:54 | 显示全部楼层
如果出现 USART_FLAG_ORE 这个错误,不清除的话,会出现什么情况?
回复

使用道具 举报

6

主题

636

回帖

654

积分

金牌会员

积分
654
QQ
发表于 2020-7-22 14:29:57 | 显示全部楼层
不清楚不就是串口挂了不接收数据了嘛
回复

使用道具 举报

2

主题

55

回帖

61

积分

初级会员

积分
61
发表于 2020-7-22 22:53:12 | 显示全部楼层
ore这么著名的问题都不处理啊,不清就是狂进串口中断了
回复

使用道具 举报

5

主题

85

回帖

100

积分

初级会员

积分
100
发表于 2020-7-23 10:13:26 | 显示全部楼层
byccc 发表于 2020-7-22 09:47
楼主可以把串口驱动做成最简单,容易维护的串口中断方式。

在中断里面把所有的错误标识都做个检查,不出 ...

同意二楼说法
回复

使用道具 举报

3

主题

66

回帖

75

积分

初级会员

积分
75
发表于 2020-7-23 13:18:10 | 显示全部楼层
自己处理完了交给hal库去处理 hal库会把该清理的标志给清了
回复

使用道具 举报

4

主题

17

回帖

29

积分

新手上路

积分
29
发表于 2020-9-9 11:56:27 | 显示全部楼层
楼主搞定没有?  我也出现了类似问题。。都是被狗咬醒的,,运行十几个小时咬醒一次,我串口中断只用来发数据,并没有接收。
回复

使用道具 举报

73

主题

1193

回帖

1412

积分

至尊会员

积分
1412
发表于 2020-9-9 13:02:36 | 显示全部楼层
请问楼主要dma+定时器的接收串口数据的方案吗?
回复

使用道具 举报

8

主题

135

回帖

159

积分

初级会员

积分
159
发表于 2020-9-9 16:01:17 | 显示全部楼层
之前就遇到过进入ORE中断假死的状况,用的是F0系列
回复

使用道具 举报

4

主题

17

回帖

29

积分

新手上路

积分
29
发表于 2020-9-9 16:41:15 | 显示全部楼层
tcs_stm32 发表于 2020-9-9 16:01
之前就遇到过进入ORE中断假死的状况,用的是F0系列

也是中断大量接收数据的情况吗
回复

使用道具 举报

29

主题

514

回帖

606

积分

金牌会员

积分
606
QQ
发表于 2020-12-19 16:13:43 | 显示全部楼层
我刚经历的产品定时器中断固定要走一定占有率的数据运算。串口屏的数据走走串口过来,调试过程开了另外一个串口抓包。发现屏交互的数据多了,打印也接着躲起来,两个中断叠加(主要是打印非常耗资源)产品运行就会堵塞,在数据量大的节点类似卡死。

首先:我临时开打印是我个人引入的问题,临时关掉打印就没事了。但是也正因为这个,也能通过压力测试,测出当前通信节奏匹配有问题。
接着:到了经典的问题,银行系统效率慢考虑的侧重点就是数据安全优先,牺牲速度。
最后:我跟屏厂家沟通,把通信节奏把控好,确保原定时器中断稳定采集12路AD数据。
Releasing your creativity
回复

使用道具 举报

6

主题

27

回帖

45

积分

新手上路

积分
45
发表于 2021-1-7 10:58:00 | 显示全部楼层


//请看我一直使用的串口中断接收与发送的代码,一直运行的非常好

/*----------------------------------------------------------------------------
* Name:    Usart.c
* Purpose: USART usage for STM32
* Version: V1.10
*----------------------------------------------------------------------------
* 关于usart接收中断的BUG和注意事项:
* 1.USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
*   使能了接收中断,那么ORE中断也同时被开启了。
*
* 2.ORE中断只能使用USART_GetFlagStatus(USART1, USART_FLAG_ORE)
*   读到(没有使能USART_IT_ERR中断时)
*----------------------------------------------------------------------------*/


#define TBUF_SIZE   256          /*** Must be a power of 2 (2,4,8,16,32,64,128,256,512,...) ***/
#define RBUF_SIZE   256     /*** Must be a power of 2 (2,4,8,16,32,64,128,256,512,...) ***/


struct buf_st {
  unsigned int in;                     // Next In Index
  unsigned int out;                   // Next Out Index
  char buf [RBUF_SIZE];           // Buffer
};

static struct buf_st rbuf = { 0, 0, };
#define SIO_RBUFLEN ((unsigned short)(rbuf.in - rbuf.out))

static struct buf_st tbuf = { 0, 0, };
#define SIO_TBUFLEN ((unsigned short)(tbuf.in - tbuf.out))

static unsigned int tx_restart = 1;         // NZ if TX restart is required




/*------------------------------------------------------------------------------
  buffer_Init
  initialize the buffers
*------------------------------------------------------------------------------*/
void uart_buffer_Init (void) {

  tbuf.in = 0;                                    // Clear com buffer indexes
  tbuf.out = 0;
  tx_restart = 1;

  rbuf.in = 0;
  rbuf.out = 0;
}


/*------------------------------------------------------------------------------
  SenChar
  transmit a character
*------------------------------------------------------------------------------*/
int SendChar (int c) {
  struct buf_st *p = &tbuf;

  if (SIO_TBUFLEN >= TBUF_SIZE)        /* If the buffer is full  */
    return (-1);                /* return an error value  */

  p->buf [p->in & (TBUF_SIZE - 1)] = c;   /* Add data to the transmit buffer.   */
  p->in++;

  if (tx_restart) {         /* If TX interrupt is disabled  */
    tx_restart = 0;                       /*  enable it   */
    USART1->CR1 |= USART_SR_TXE;          /* enable TX interrupt   */
  }
       
  return (0);
}


/*------------------------------------------------------------------------------
  GetKey
  receive a character
*------------------------------------------------------------------------------*/
char  GetKey (void) {
  struct buf_st *p = &rbuf;

  if (SIO_RBUFLEN == 0)
    return (char)-1;

  return (p->buf [(p->out++) & (RBUF_SIZE - 1)]);
}



/*----------------------------------------------------------------------------
  USART1_IRQHandler
  Handles USART1 global interrupt request.
*----------------------------------------------------------------------------*/
void USART1_IRQHandler (void)
{
   volatile unsigned short rcv_rd;
   volatile unsigned int IIR;
   struct buf_st *p;       

   #if OS_CRITICAL_METHOD == 3   
     OS_CPU_SR  cpu_sr = 0;
   #endif

    OS_ENTER_CRITICAL();
    OSIntNesting++;
    OS_EXIT_CRITICAL();
       
    IIR = USART1->SR;
    if (IIR & USART_FLAG_RXNE) {       // read interrupt
      USART1->SR &= ~USART_FLAG_RXNE;         // clear interrupt

      p = &rbuf;

      if (((p->in - p->out) & ~(RBUF_SIZE-1)) == 0) {
        p->buf [p->in & (RBUF_SIZE-1)] = (USART1->DR & 0x1FF);
        p->in++;
      }       
      else //继续读取
        rcv_rd=        (USART1->DR & 0x1FF);                       
    }

    if (IIR & USART_FLAG_TXE) {
      USART1->SR &= ~USART_FLAG_TXE;        // clear interrupt
      p = &tbuf;
      if (p->in != p->out) {
         USART1->DR = (p->buf [p->out & (TBUF_SIZE-1)] & 0x1FF);
         p->out++;
         tx_restart = 0;
      }else {
          tx_restart = 1;
         USART1->CR1 &= ~USART_FLAG_TXE;  // disable TX interrupt if nothing to send
      }
    }               
               
    //如果发生溢出需要先读SR,再读DR寄存器 则可清除不断入中断的问题
    if(USART_GetFlagStatus(USART1,USART_FLAG_ORE)==SET){

        USART_ClearFlag(USART1,USART_FLAG_ORE);       //读SR
        USART_ReceiveData(USART1);         //读DR
    }                       

               
    OSIntExit();       
}




回复

使用道具 举报

65

主题

432

回帖

632

积分

金牌会员

积分
632
 楼主| 发表于 2021-1-7 11:52:41 | 显示全部楼层
领教了,我按你的处理方式改下代码试试效果
回复

使用道具 举报

75

主题

684

回帖

909

积分

金牌会员

积分
909
发表于 2021-1-7 21:18:48 | 显示全部楼层
建议大量数据不要使用RX中断,采用空闲中断加DMA,双缓冲来做。http://www.armbbs.cn/forum.php?m ... d=101026&extra=,或者如果从机愿意把通讯频度降低,你就不用改。我前两天刚遇到过,开发上位机的人不愿意改,我就只能做大手术把原来接的二手代码改成这个机制。
回复

使用道具 举报

0

主题

124

回帖

124

积分

初级会员

积分
124
发表于 2021-1-8 16:59:38 | 显示全部楼层
不管用不用DMA,那怕是115200,  每个字节有87us的时间, 那怕是同时处理三组串口不停的收发, 都绝不应该有问题。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-4-29 11:23 , Processed in 0.233333 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表