@@ -94,7 +94,7 @@ extern PCD_HandleTypeDef pcd_handle;
9494
9595#include "py/mphal.h"
9696
97- char * fmt_hex (uint32_t val , char * buf ) {
97+ STATIC char * fmt_hex (uint32_t val , char * buf ) {
9898 const char * hexDig = "0123456789abcdef" ;
9999
100100 buf [0 ] = hexDig [(val >> 28 ) & 0x0f ];
@@ -110,30 +110,32 @@ char *fmt_hex(uint32_t val, char *buf) {
110110 return buf ;
111111}
112112
113- void print_reg (const char * label , uint32_t val ) {
113+ STATIC void print_reg (const char * label , uint32_t val ) {
114114 char hexStr [9 ];
115115
116116 mp_hal_stdout_tx_str (label );
117117 mp_hal_stdout_tx_str (fmt_hex (val , hexStr ));
118118 mp_hal_stdout_tx_str ("\r\n" );
119119}
120- #endif // REPORT_HARD_FAULT_REGS
121120
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 );
129138
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
137139 uint32_t cfsr = SCB -> CFSR ;
138140
139141 print_reg ("HFSR " , SCB -> HFSR );
@@ -144,13 +146,49 @@ void HardFault_Handler(void) {
144146 if (cfsr & 0x8000 ) {
145147 print_reg ("BFAR " , SCB -> BFAR );
146148 }
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+ }
148154
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 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 ) {
149178 /* Go to infinite loop when Hard Fault exception occurs */
150179 while (1 ) {
151180 __fatal_error ("HardFault" );
152181 }
153182}
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+ }
154192
155193/**
156194 * @brief This function handles Memory Manage exception.
0 commit comments