@@ -94,7 +94,7 @@ extern PCD_HandleTypeDef pcd_handle;
94
94
95
95
#include "py/mphal.h"
96
96
97
- char * fmt_hex (uint32_t val , char * buf ) {
97
+ STATIC char * fmt_hex (uint32_t val , char * buf ) {
98
98
const char * hexDig = "0123456789abcdef" ;
99
99
100
100
buf [0 ] = hexDig [(val >> 28 ) & 0x0f ];
@@ -110,30 +110,32 @@ char *fmt_hex(uint32_t val, char *buf) {
110
110
return buf ;
111
111
}
112
112
113
- void print_reg (const char * label , uint32_t val ) {
113
+ STATIC void print_reg (const char * label , uint32_t val ) {
114
114
char hexStr [9 ];
115
115
116
116
mp_hal_stdout_tx_str (label );
117
117
mp_hal_stdout_tx_str (fmt_hex (val , hexStr ));
118
118
mp_hal_stdout_tx_str ("\r\n" );
119
119
}
120
- #endif // REPORT_HARD_FAULT_REGS
121
120
122
- /**
123
- * @brief This function handles NMI exception.
124
- * @param None
125
- * @retval None
126
- */
127
- void NMI_Handler (void ) {
128
- }
121
+ // The ARMv7M Architecture manual (section B.1.5.6) says that upon entry
122
+ // to an exception, that the registers will be in the following order on the
123
+ // // stack: R0, R1, R2, R3, R12, LR, PC, XPSR
124
+
125
+ typedef struct {
126
+ uint32_t r0 , r1 , r2 , r3 , r12 , lr , pc , xpsr ;
127
+ } ExceptionRegisters_t ;
128
+
129
+ void HardFault_C_Handler (ExceptionRegisters_t * regs ) {
130
+ print_reg ("R0 " , regs -> r0 );
131
+ print_reg ("R1 " , regs -> r1 );
132
+ print_reg ("R2 " , regs -> r2 );
133
+ print_reg ("R3 " , regs -> r3 );
134
+ print_reg ("R12 " , regs -> r12 );
135
+ print_reg ("LR " , regs -> lr );
136
+ print_reg ("PC " , regs -> pc );
137
+ print_reg ("XPSR " , regs -> xpsr );
129
138
130
- /**
131
- * @brief This function handles Hard Fault exception.
132
- * @param None
133
- * @retval None
134
- */
135
- void HardFault_Handler (void ) {
136
- #if REPORT_HARD_FAULT_REGS
137
139
uint32_t cfsr = SCB -> CFSR ;
138
140
139
141
print_reg ("HFSR " , SCB -> HFSR );
@@ -144,13 +146,49 @@ void HardFault_Handler(void) {
144
146
if (cfsr & 0x8000 ) {
145
147
print_reg ("BFAR " , SCB -> BFAR );
146
148
}
147
- #endif // REPORT_HARD_FAULT_REGS
149
+ /* Go to infinite loop when Hard Fault exception occurs */
150
+ while (1 ) {
151
+ __fatal_error ("HardFault" );
152
+ }
153
+ }
148
154
155
+ // Naked functions have no compiler generated gunk, so are the best thing to
156
+ // use for asm functions.
157
+ __attribute__((naked ))
158
+ void HardFault_Handler (void ) {
159
+
160
+ // From the ARMv7M Architecture Reference Manual, section B.1.5.6
161
+ // on entry to the
8000
Exception, the LR register contains, amongst other
162
+ // things, the value of CONTROL.SPSEL. This can be found in bit 3.
163
+ //
164
+ // If CONTROL.SPSEL is 0, then the exception was stacked up using the
165
+ // main stack pointer (aka MSP). If CONTROL.SPSEL is 1, then the exception
166
+ // was stacked up using the process stack pointer (aka PSP).
167
+
168
+ __asm volatile (
169
+ " tst lr, #4 \n" // Test Bit 3 to see which stack pointer we should use.
170
+ " ite eq \n" // Tell the assembler that the nest 2 instructions are if-then-else
171
+ " mrseq r0, msp \n" // Make R0 point to main stack pointer
172
+ " mrsne r0, psp \n" // Make R0 point to process stack pointer
173
+ " b HardFault_C_Handler \n" // Off to C land
174
+ );
175
+ }
176
+ #else
177
+ void HardFault_Handler (void ) {
149
178
/* Go to infinite loop when Hard Fault exception occurs */
150
179
while (1 ) {
151
180
__fatal_error ("HardFault" );
152
181
}
153
182
}
183
+ #endif // REPORT_HARD_FAULT_REGS
184
+
185
+ /**
186
+ * @brief This function handles NMI exception.
187
+ * @param None
188
+ * @retval None
189
+ */
190
+ void NMI_Handler (void ) {
191
+ }
154
192
155
193
/**
156
194
* @brief This function handles Memory Manage exception.
0 commit comments