Skip to content

Commit 27c149e

Browse files
committed
stmhal: Add pyb.fault_debug() function, to control hard-fault behaviour.
This new function controls what happens on a hard-fault: - debugging disabled: board will do a reset - debugging enabled: board will print registers and stack and flash LEDs The default is disabled, ie to do a reset. This is different to previous behaviour which flashed the LEDs and waited indefinitely.
1 parent bffda45 commit 27c149e

5 files changed

Lines changed: 34 additions & 13 deletions

File tree

docs/library/pyb.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,19 @@ Reset related functions
8080

8181
Activate the bootloader without BOOT\* pins.
8282

83+
.. function:: fault_debug(value)
84+
85+
Enable or disable hard-fault debugging. A hard-fault is when there is a fatal
86+
error in the underlying system, like an invalid memory access.
87+
88+
If the `value` argument is `False` then the board will automatically reset if
89+
there is a hard fault.
90+
91+
If `value` is `True` then, when the board has a hard fault, it will print the
92+
registers and the stack trace, and then cycle the LEDs indefinitely.
93+
94+
The default value is disabled, i.e. to automatically reset.
95+
8396
Interrupt related functions
8497
---------------------------
8598

stmhal/modpyb.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "lib/oofatfs/ff.h"
3939
#include "lib/oofatfs/diskio.h"
4040
#include "gccollect.h"
41+
#include "stm32_it.h"
4142
#include "irq.h"
4243
#include "systick.h"
4344
#include "led.h"
@@ -64,6 +65,12 @@
6465
#include "extmod/vfs.h"
6566
#include "extmod/utime_mphal.h"
6667

68+
STATIC mp_obj_t pyb_fault_debug(mp_obj_t value) {
69+
pyb_hard_fault_debug = mp_obj_is_true(value);
70+
return mp_const_none;
71+
}
72+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_fault_debug_obj, pyb_fault_debug);
73+
6774
/// \function millis()
6875
/// Returns the number of milliseconds since the board was last reset.
6976
///
@@ -131,6 +138,8 @@ MP_DECLARE_CONST_FUN_OBJ_KW(pyb_main_obj); // defined in main.c
131138
STATIC const mp_map_elem_t pyb_module_globals_table[] = {
132139
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_pyb) },
133140

141+
{ MP_OBJ_NEW_QSTR(MP_QSTR_fault_debug), (mp_obj_t)&pyb_fault_debug_obj },
142+
134143
{ MP_OBJ_NEW_QSTR(MP_QSTR_bootloader), (mp_obj_t)&machine_bootloader_obj },
135144
{ MP_OBJ_NEW_QSTR(MP_QSTR_hard_reset), (mp_obj_t)&machine_reset_obj },
136145
{ MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&machine_info_obj },

stmhal/stm32_it.c

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
#include STM32_HAL_H
7272

7373
#include "py/obj.h"
74+
#include "py/mphal.h"
7475
#include "pendsv.h"
7576
#include "irq.h"
7677
#include "pybthread.h"
@@ -95,11 +96,6 @@ extern PCD_HandleTypeDef pcd_hs_handle;
9596
// Set the following to 1 to get some more information on the Hard Fault
9697
// More information about decoding the fault registers can be found here:
9798
// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0646a/Cihdjcfc.html
98-
#define REPORT_HARD_FAULT_REGS 0
99-
100-
#if REPORT_HARD_FAULT_REGS
101-
102-
#include "py/mphal.h"
10399

104100
STATIC char *fmt_hex(uint32_t val, char *buf) {
105101
const char *hexDig = "0123456789abcdef";
@@ -142,7 +138,13 @@ typedef struct {
142138
uint32_t r0, r1, r2, r3, r12, lr, pc, xpsr;
143139
} ExceptionRegisters_t;
144140

141+
int pyb_hard_fault_debug = 0;
142+
145143
void HardFault_C_Handler(ExceptionRegisters_t *regs) {
144+
if (!pyb_hard_fault_debug) {
145+
NVIC_SystemReset();
146+
}
147+
146148
// We need to disable the USB so it doesn't try to write data out on
147149
// the VCP and then block indefinitely waiting for the buffer to drain.
148150
pyb_usb_flags = 0;
@@ -209,14 +211,6 @@ void HardFault_Handler(void) {
209211
" b HardFault_C_Handler \n" // Off to C land
210212
);
211213
}
212-
#else
213-
void HardFault_Handler(void) {
214-
/* Go to infinite loop when Hard Fault exception occurs */
215-
while (1) {
216-
__fatal_error("HardFault");
217-
}
218-
}
219-
#endif // REPORT_HARD_FAULT_REGS
220214

221215
/**
222216
* @brief This function handles NMI exception.

stmhal/stm32_it.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@
6363
******************************************************************************
6464
*/
6565

66+
extern int pyb_hard_fault_debug;
67+
6668
void NMI_Handler(void);
6769
void HardFault_Handler(void);
6870
void MemManage_Handler(void);

tests/pyb/pyb1.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,6 @@
4040
print(len(pyb.unique_id()))
4141

4242
pyb.wfi()
43+
44+
pyb.fault_debug(True)
45+
pyb.fault_debug(False)

0 commit comments

Comments
 (0)