在串口数据轰炸后,程序HardFault_Handler()了

时间:2021-04-10 15:58:47


程序初始化后,用SSCOM32串口调试助手以1ms为间隔向设备发送数据。结果没有隔半分钟,系统就进入了HardFault异常了。

我很明确这个异常100%是由于访问了非法地址引起。多半是由于内存溢出或者访问越界所致。但我就很难明白到底是怎么个内存访问非法。

HardFault_Hander()定义如下:

void HardFault_Handler(void)
{
  uint32_t r_sp ;

  r_sp = __get_PSP(); //获取SP的值
  PERROR(ERROR,Memory Access Error!);
  Panic(r_sp);
 
  while (1);
}

如果存在内存溢出,就会打印部分系统信息,并进入while(1)死循环。

当我将PendSV_Handle()的优先级改为最低后,很少出现这个问题了。

 

但还是会有系统死掉的情况。

在系统中,我开启了USART1、USART2、USART3的接收中断RXE,其它中断都没有开。系统在运行中,能触发的中断有:

SysClock_handler
PendSV_handler
USART1_handler
USART2_handler
USART3_handler
如果只往USART1发送数据,那么只剩SysClock,PendSV,USART1,三个中断源。

我现在往USART1狂发数据。持续了5min左右,系统死了。

单步调试时,发现在没有往USART1发数据时候,USART1中断还是不断触发,完全占用了所有的CPU资源。导致PendSV_Handler中断执行不了,故无法进行任务切换。

而在USART1中断中看,只有USART1->SR中的TXE置位。另我不解的是,USART1->TXEIE=0,按道理这不应该会有中断触发的。

 

问题解决了!
我将中断处理函数改成了:

void USART1_IRQHandler(void) { 
uint32_t State = USART1->SR; //读状态
uint16_t RxData = USART1->DR; //读数据,清除其它状态标志

OSIntEnter();
if( State & USART_FLAG_RXNE ){
//接收处理……
}
OSIntExit();
}

也就是说,不管它是由于什么引起的中断,一进来就读SR与DR,这样可以清掉许多状态位,如:PE,RXNE,IDLE,ORE,NE,FE,PE。
正说库中注解所言:
  *   - PE (Parity error), FE (Framing error), NE (Noise error), ORE (OverRun  
  *     error) and IDLE (Idle line detected) pending bits are cleared by  
  *     software sequence: a read operation to USART_SR register  
  *     (USART_GetITStatus()) followed by a read operation to USART_DR register  
  *     (USART_ReceiveData()). 
  *   - RXNE pending bit can be also cleared by a read to the USART_DR register  
  *     (USART_ReceiveData()). 
  *   - TC pending bit can be also cleared by software sequence: a read  
  *     operation to USART_SR register (USART_GetITStatus()) followed by a write  
  *     operation to USART_DR register (USART_SendData()). 

我花了三天时间调个这BUG,希望有遇到类似问题的朋友有所帮助。

 

详细参考:http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=4917509&bbs_id=9999