程序初始化后,用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