一、硬件环境:
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相关的位置,如下图所示:
由图可知,问题应该是在uxTaskGetSystemState函数中,在结合源代码分析,该uxTaskGetSystemState函数是在freeRTOS的空闲任务中被调用的,猜测是否是该空闲任务的堆栈分配过小导致的hardhault,于是将堆栈增大一倍,再次运行,结果正常,未出现hardfault。