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


程序初始化后,用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,三个中断源。
【STM32|在串口数据轰炸后,程序HardFault_Handler()了】我现在往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 = https://www.it610.com/article/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

    推荐阅读