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.
This commit is contained in:
Damien George 2017-02-06 13:19:52 +11:00
parent bffda45154
commit 27c149efe0
5 changed files with 34 additions and 13 deletions

View File

@ -80,6 +80,19 @@ Reset related functions
Activate the bootloader without BOOT\* pins.
.. function:: fault_debug(value)
Enable or disable hard-fault debugging. A hard-fault is when there is a fatal
error in the underlying system, like an invalid memory access.
If the `value` argument is `False` then the board will automatically reset if
there is a hard fault.
If `value` is `True` then, when the board has a hard fault, it will print the
registers and the stack trace, and then cycle the LEDs indefinitely.
The default value is disabled, i.e. to automatically reset.
Interrupt related functions
---------------------------

View File

@ -38,6 +38,7 @@
#include "lib/oofatfs/ff.h"
#include "lib/oofatfs/diskio.h"
#include "gccollect.h"
#include "stm32_it.h"
#include "irq.h"
#include "systick.h"
#include "led.h"
@ -64,6 +65,12 @@
#include "extmod/vfs.h"
#include "extmod/utime_mphal.h"
STATIC mp_obj_t pyb_fault_debug(mp_obj_t value) {
pyb_hard_fault_debug = mp_obj_is_true(value);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_fault_debug_obj, pyb_fault_debug);
/// \function millis()
/// Returns the number of milliseconds since the board was last reset.
///
@ -131,6 +138,8 @@ MP_DECLARE_CONST_FUN_OBJ_KW(pyb_main_obj); // defined in main.c
STATIC const mp_map_elem_t pyb_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_pyb) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_fault_debug), (mp_obj_t)&pyb_fault_debug_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_bootloader), (mp_obj_t)&machine_bootloader_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_hard_reset), (mp_obj_t)&machine_reset_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&machine_info_obj },

View File

@ -71,6 +71,7 @@
#include STM32_HAL_H
#include "py/obj.h"
#include "py/mphal.h"
#include "pendsv.h"
#include "irq.h"
#include "pybthread.h"
@ -95,11 +96,6 @@ extern PCD_HandleTypeDef pcd_hs_handle;
// Set the following to 1 to get some more information on the Hard Fault
// More information about decoding the fault registers can be found here:
// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0646a/Cihdjcfc.html
#define REPORT_HARD_FAULT_REGS 0
#if REPORT_HARD_FAULT_REGS
#include "py/mphal.h"
STATIC char *fmt_hex(uint32_t val, char *buf) {
const char *hexDig = "0123456789abcdef";
@ -142,7 +138,13 @@ typedef struct {
uint32_t r0, r1, r2, r3, r12, lr, pc, xpsr;
} ExceptionRegisters_t;
int pyb_hard_fault_debug = 0;
void HardFault_C_Handler(ExceptionRegisters_t *regs) {
if (!pyb_hard_fault_debug) {
NVIC_SystemReset();
}
// We need to disable the USB so it doesn't try to write data out on
// the VCP and then block indefinitely waiting for the buffer to drain.
pyb_usb_flags = 0;
@ -209,14 +211,6 @@ void HardFault_Handler(void) {
" b HardFault_C_Handler \n" // Off to C land
);
}
#else
void HardFault_Handler(void) {
/* Go to infinite loop when Hard Fault exception occurs */
while (1) {
__fatal_error("HardFault");
}
}
#endif // REPORT_HARD_FAULT_REGS
/**
* @brief This function handles NMI exception.

View File

@ -63,6 +63,8 @@
******************************************************************************
*/
extern int pyb_hard_fault_debug;
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);

View File

@ -40,3 +40,6 @@ pyb.sync()
print(len(pyb.unique_id()))
pyb.wfi()
pyb.fault_debug(True)
pyb.fault_debug(False)