问题描述
SoC:SmartFusion2
处理器:Cortex-M3
OS:FreeRTOS v9.0.0
IDE:SoftConsole v4.0
在软件运行期间,发生异常并使用无效的PC进入HardFault。我不知道原因以及如何跟踪。
HardFault_Handler_c
在void HardFault_Handler_c(unsigned int *hardfault_args)
{
//...
stack[0] = xTime.SysSec.u32Data;
stack[1] = xTime.MicroSec.u32Data;
stack[2] = ((unsigned long) hardfault_args[0]);
stack[3] = ((unsigned long) hardfault_args[1]);
stack[4] = ((unsigned long) hardfault_args[2]);
stack[5] = ((unsigned long) hardfault_args[3]);
stack[6] = ((unsigned long) hardfault_args[4]);
stack[7] = ((unsigned long) hardfault_args[5]);
stack[8] = ((unsigned long) hardfault_args[6]);
stack[9] = ((unsigned long) hardfault_args[7]);
stack[10] = (*((volatile unsigned char *)(0xE000ED28)));
stack[11] = (*((volatile unsigned char *)(0xE000ED29)));
stack[12] = (*((volatile unsigned short int *)(0xE000ED2A)));
stack[13] = (*((volatile unsigned long *)(0xE000ED2C)));
stack[14] = (*((volatile unsigned long *)(0xE000ED30)));
stack[15] = (*((volatile unsigned long *)(0xE000ED34)));
stack[16] = (*((volatile unsigned long *)(0xE000ED38)));
//...
while (1);
}
函数中,获取发生异常时压入堆栈的寄存器的值。
ind r0 r1 r2 r3 r12 lr PC PSR MFSR BFSR UFSR HFSR DFSR MMAR BFAR
1 C4000000 BE58F8E1 C4000000 BE58F8E1 FFFFFC1A FFFFFFFD EA820302 61000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
2 61EE71CA 001FE93E 00000000 001FE93E DA2BF364 FFFFFFFD EB410000 A0000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
3 79701455 00144F49 00000000 00144F49 25FD6439 FFFFFFFD EB410000 20000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
4 CC75E094 0014C068 00000000 001B850B 66924D58 FFFFFFFD EB410000 A0000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
5 849F9982 0019F6D7 80000000 00114A21 119DB886 FFFFFFFD F006E502 A0000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
6 295737D9 00180C72 80000000 001A5AD2 20000000 FFFFFFFD EB410000 A0000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
7 3E95C344 0011ECCA 00000000 00145F30 4B940BCC FFFFFFFD EB410000 00000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
8 00000000 00138000 00000000 00199999 00000000 FFFFFFFD EB410000 A0000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
9 B1894BAF 0016BC15 80000000 001A4910 7E070C6B FFFFFFFD EB410000 80000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
10 00000000 00000000 00000000 00000000 FFFFFFFF FFFFFFFD EA820302 41000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
11 00000014 00080000 A5FF8640 008A6357 3E97FE19 FFFFFFFD EA4F0342 81000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
12 70000000 001BA7B7 F8988C00 01A81E6F 08000000 FFFFFFFD F44F0232 20000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
13 3546B3A0 00000007 00000000 0017D90D F9892400 FFFFFFFD EB410000 20000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
14 00000000 00000007 00000000 001921FB 00000000 FFFFFFFD EB410000 A0000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
15 00000000 001A7C00 80000000 001179EC 00000000 FFFFFFFD EB410000 A0000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
16 B99C0540 00152E49 00000000 001B8F39 73954D80 FFFFFFFD EB410000 80000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
17 A7DBD1DC 001BAE2C 80000000 001AA887 4DABDB1C FFFFFFFD EB410000 80000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
18 7AE147AE 001FAE14 80000000 0017DE1B BE908A20 FFFFFFFD EB410000 20000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
19 00000001 3FF00000 00000000 00000000 7FE00000 FFFFFFFD 5C6CEA7E 21000034 00000001 00000000 00000000 40000000 00000000 E000ED34 E000ED38
FabricIrq2_IRQHandler
从表中可以看出,对于每个异常,栈中推送的IPSR中存储的异常号为0x34,它与中断向量表中的void FabricIrq2_IRQHandler( void )
{
IP_can_isr();
}
相对应。在此中断中,我们处理CAN数据接收。
IP_can_isr()
在程序的每个循环中都会触发CAN中断,但是该问题并不经常发生,并且需要很长时间才能发生一次。
我不知道异常发生在哪里。如有必要,我可以添加一些其他代码来捕获更多信息。
我认为IP_can_isr()
函数中不会发生该异常,因为在lr
函数中发生该异常时,{{1}}寄存器不能为0xFFFFFFFD。
解决方法
由于发生在IP_can_isr()函数中,因此lr寄存器不能为0xFFFFFFFD。
是的,可以。任何体面的编译器都可以优化对简单b IP_can_isr
(分支指令)的tail调用。在执行IP_can_isr函数的过程中,它将“异常返回”值保留在LR
寄存器中。
如果堆叠的PC是垃圾,则可能在某处有缓冲区溢出。