基于SMT32L476的hardfault分析处理

一、硬件环境:

       STM32L476

二、软件环境:

freeRTOS系统下跑了4个任务;

三、hardfault原因分析,典型原因是访问非法空间,具体情况如下:

1、使用未被初始化的指针;

2、数组越界访问;

3、使用指向变量的指针,比如在mian函数中定义了一个结构体或者一个数组缓存,在其他函数中通过传递过来的指针(指向结构体或者数组缓存)来访问该结构体或者数组缓存;(原因是:结构体或者数组缓存可能被优化掉,导致指针成为野指针) 如果需要通过指针来访问,可将结构体或者数组缓存用static修饰;

4、如果存在freeROTS等操作系统,则可能是分配给任务的堆栈过小。

四、调试方法:

1、将STM32启动文件startup_stm32l476xx.s中的

HardFault_Handler\
                PROC
               EXPORT  HardFault_Handler          [WEAK]
               B       .
               ENDP

修改为:

HardFault_Handler\
                PROC
IMPORT hard_fault_handler  
TST LR, #4  
ITE EQ  
MRSEQ R0, MSP  
MRSNE R0, PSP  
B hard_fault_handler
                ENDP

2、在stm32l4xx_it.c文件中定义hard_fault_handler函数

void hard_fault_handler(unsigned int * hardfault_args)
{
printf("R0 = %0.8x\r\n", hardfault_args[0]);
printf("R1 = %0.8x\r\n", hardfault_args[1]);
printf("R2 = %0.8x\r\n", hardfault_args[2]);
printf("R3 = %0.8x\r\n", hardfault_args[3]);
printf("R12 = %0.8x\r\n", hardfault_args[4]);
printf("LR = %0.8x\r\n", hardfault_args[5]);
printf("PC = %0.8x\r\n", hardfault_args[6]);
printf("PSR = %0.8x\r\n", hardfault_args[7]);
printf("BFAR = %0.8lx\r\n", (*((volatile unsigned long *)(0xE000ED38))));
printf("CFSR = %0.8lx\r\n", (*((volatile unsigned long *)(0xE000ED28))));
printf("HFSR = %0.8lx\r\n", (*((volatile unsigned long *)(0xE000ED2C))));
printf("DFSR = %0.8lx\r\n", (*((volatile unsigned long *)(0xE000ED30))));
printf("AFSR = %0.8lx\r\n", (*((volatile unsigned long *)(0xE000ED3C))));

while(1)
{
}
}

五、结果分析

1、出现hardfault通过串口打印结果如下:

R0 = 00000001
R1 = 20001970
R2 = 00000002
R3 = 08005475
R12 = 00000000
LR = 08006e5d
PC = 080068ee
PSR = 81000200
BFAR = 054604f8
CFSR = 00008200
HFSR = 40000000
DFSR = 00000008
AFSR = 00000000

2、由于LR的地址为0x08006e5d,因此查看对应的map文件,寻找和0x08006e5d相关的位置,如下图所示:

基于SMT32L476的hardfault分析处理_第1张图片

由图可知,问题应该是在uxTaskGetSystemState函数中,在结合源代码分析,该uxTaskGetSystemState函数是在freeRTOS的空闲任务中被调用的,猜测是否是该空闲任务的堆栈分配过小导致的hardhault,于是将堆栈增大一倍,再次运行,结果正常,未出现hardfault。


你可能感兴趣的:(STM32,FreeRTOS)