1 | void Dummy_Handler(void)
|
2 | { volatile int i,j,p;
|
3 |
|
4 | HardFault_HandlerAsm();
|
5 | while (1) {
|
6 | i=__get_IPSR();
|
7 | j=__get_APSR();
|
8 | p=__get_xPSR();
|
9 | }
|
10 | }
|
11 | /**
|
12 | * HardFault_HandlerAsm:
|
13 | * Alternative Hard Fault handler to help debug the reason for a fault.
|
14 | * To use, edit the vector table to reference this function in the HardFault vector
|
15 | * This code is suitable for Cortex-M3 and Cortex-M0 cores
|
16 | */
|
17 |
|
18 | // Use the 'naked' attribute so that C stacking is not used.
|
19 | __attribute__((naked))
|
20 | void HardFault_HandlerAsm(void)
|
21 | { /*
|
22 | * Get the appropriate stack pointer, depending on our mode,
|
23 | * and use it as the parameter to the C handler. This function
|
24 | * will never return
|
25 | */
|
26 |
|
27 | __asm( ".syntax unified\n"
|
28 | "MOVS R0, #4 \n"
|
29 | "MOV R1, LR \n"
|
30 | "TST R0, R1 \n"
|
31 | "BEQ _MSP \n"
|
32 | "MRS R0, PSP \n"
|
33 | "B HardFault_HandlerC \n"
|
34 | "_MSP: \n"
|
35 | "MRS R0, MSP \n"
|
36 | "B HardFault_HandlerC \n"
|
37 | ".syntax divided\n") ;
|
38 | }
|
39 |
|
40 | /**
|
41 | * HardFaultHandler_C:
|
42 | * This is called from the HardFault_HandlerAsm with a pointer the Fault stack
|
43 | * as the parameter. We can then read the values from the stack and place them
|
44 | * into local variables for ease of reading.
|
45 | * We then read the various Fault Status and Address Registers to help decode
|
46 | * cause of the fault.
|
47 | * The function ends with a BKPT instruction to force control back into the debugger
|
48 | */
|
49 | void HardFault_HandlerC(unsigned long *hardfault_args){
|
50 | volatile unsigned long stacked_r0 ;
|
51 | volatile unsigned long stacked_r1 ;
|
52 | volatile unsigned long stacked_r2 ;
|
53 | volatile unsigned long stacked_r3 ;
|
54 | volatile unsigned long stacked_r12 ;
|
55 | volatile unsigned long stacked_lr ;
|
56 | volatile unsigned long stacked_pc ;
|
57 | volatile unsigned long stacked_psr ;
|
58 | volatile unsigned long _CFSR ;
|
59 | volatile unsigned long _HFSR ;
|
60 | volatile unsigned long _DFSR ;
|
61 | volatile unsigned long _AFSR ;
|
62 | volatile unsigned long _BFAR ;
|
63 | volatile unsigned long _MMAR ;
|
64 |
|
65 | stacked_r0 = ((unsigned long)hardfault_args[0]) ;
|
66 | stacked_r1 = ((unsigned long)hardfault_args[1]) ;
|
67 | stacked_r2 = ((unsigned long)hardfault_args[2]) ;
|
68 | stacked_r3 = ((unsigned long)hardfault_args[3]) ;
|
69 | stacked_r12 = ((unsigned long)hardfault_args[4]) ;
|
70 | stacked_lr = ((unsigned long)hardfault_args[5]) ;
|
71 | stacked_pc = ((unsigned long)hardfault_args[6]) ;
|
72 | stacked_psr = ((unsigned long)hardfault_args[7]) ;
|
73 |
|
74 | // Configurable Fault Status Register
|
75 | // Consists of MMSR, BFSR and UFSR
|
76 | _CFSR = (*((volatile unsigned long *)(0xE000ED28))) ;
|
77 |
|
78 | // Hard Fault Status Register
|
79 | _HFSR = (*((volatile unsigned long *)(0xE000ED2C))) ;
|
80 |
|
81 | // Debug Fault Status Register
|
82 | _DFSR = (*((volatile unsigned long *)(0xE000ED30))) ;
|
83 |
|
84 | // Auxiliary Fault Status Register
|
85 | _AFSR = (*((volatile unsigned long *)(0xE000ED3C))) ;
|
86 |
|
87 | // Read the Fault Address Registers. These may not contain valid values.
|
88 | // Check BFARVALID/MMARVALID to see if they are valid values
|
89 | // MemManage Fault Address Register
|
90 | _MMAR = (*((volatile unsigned long *)(0xE000ED34))) ;
|
91 | // Bus Fault Address Register
|
92 | _BFAR = (*((volatile unsigned long *)(0xE000ED38))) ;
|
93 |
|
94 | __asm("BKPT #0\n") ; // Break into the debugger
|
95 |
|
96 | }
|
97 | /**
|
98 | * \brief Default interrupt handler for unused IRQs.
|
99 | __get_IPSR();:
|
100 | ISR_NUMBER (IPSR[8:0])
|
101 | =0 Thread mode
|
102 | =1 Reserved
|
103 | =2 NMI
|
104 | =3 HardFault
|
105 | =4 MemManage
|
106 | =5 BusFault
|
107 | =6 UsageFault
|
108 | =7-10 Reserved
|
109 | =11 SVCall
|
110 | =12 Reserved for Debug
|
111 | =13 Reserved
|
112 | =14 PendSV
|
113 | =15 SysTick
|
114 | =16 IRQ0
|
115 | ...
|
116 | =n+15 IRQ(n-1)
|
117 |
|
118 |
|
119 | */
|