mirror of https://github.com/ARMmbed/mbed-os.git
Avoid crashes during fault handler
If the fault handler was hit before the stdio console was used and initialised, the initialisation code caused a "mutex in ISR" trap, stopping the register dump from happening. Temporarily set the `error_in_progress` flag at the top of the fault handler, and restore it before calling `mbed_error`. Take the opportunity to suppress fault dumps on recursive crashes, much as is done inside `mbed_error`.pull/11970/head
parent
b0751bf507
commit
fc05d51bcd
|
@ -168,7 +168,7 @@ void mbed_error_vprintf(const char *format, va_list arg) MBED_PRINTF(1, 0);
|
|||
* FileHandle::write of the stderr device is. The default
|
||||
* serial console is safe, either buffered or not. If the
|
||||
* console has not previously been initialized, an attempt
|
||||
* to use this from interrupt may during console initialization.
|
||||
* to use this from interrupt may crash during console initialization.
|
||||
* Special handling of `mbed_error` relaxes various system traps
|
||||
* to increase the chance of initialization working.
|
||||
*
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "device.h"
|
||||
#include "mbed_atomic.h"
|
||||
#include "mbed_error.h"
|
||||
#include "mbed_interface.h"
|
||||
#include "mbed_crash_data_offsets.h"
|
||||
|
@ -39,41 +40,49 @@ mbed_fault_context_t fault_context;
|
|||
mbed_fault_context_t *const mbed_fault_context = &fault_context;
|
||||
#endif
|
||||
|
||||
extern bool mbed_error_in_progress;
|
||||
|
||||
//This is a handler function called from Fault handler to print the error information out.
|
||||
//This runs in fault context and uses special functions(defined in mbed_rtx_fault_handler.c) to print the information without using C-lib support.
|
||||
void mbed_fault_handler(uint32_t fault_type, const mbed_fault_context_t *mbed_fault_context_in)
|
||||
{
|
||||
mbed_error_status_t faultStatus = MBED_SUCCESS;
|
||||
|
||||
mbed_error_printf("\n++ MbedOS Fault Handler ++\n\nFaultType: ");
|
||||
/* Need to set the flag to ensure prints do not trigger a "mutex in ISR" trap
|
||||
* if they're first prints since boot and we have to init the I/O system.
|
||||
*/
|
||||
if (!core_util_atomic_exchange_bool(&mbed_error_in_progress, true)) {
|
||||
mbed_error_printf("\n++ MbedOS Fault Handler ++\n\nFaultType: ");
|
||||
|
||||
switch (fault_type) {
|
||||
case MEMMANAGE_FAULT_EXCEPTION:
|
||||
mbed_error_printf("MemManageFault");
|
||||
faultStatus = MBED_ERROR_MEMMANAGE_EXCEPTION;
|
||||
break;
|
||||
switch (fault_type) {
|
||||
case MEMMANAGE_FAULT_EXCEPTION:
|
||||
mbed_error_printf("MemManageFault");
|
||||
faultStatus = MBED_ERROR_MEMMANAGE_EXCEPTION;
|
||||
break;
|
||||
|
||||
case BUS_FAULT_EXCEPTION:
|
||||
mbed_error_printf("BusFault");
|
||||
faultStatus = MBED_ERROR_BUSFAULT_EXCEPTION;
|
||||
break;
|
||||
case BUS_FAULT_EXCEPTION:
|
||||
mbed_error_printf("BusFault");
|
||||
faultStatus = MBED_ERROR_BUSFAULT_EXCEPTION;
|
||||
break;
|
||||
|
||||
case USAGE_FAULT_EXCEPTION:
|
||||
mbed_error_printf("UsageFault");
|
||||
faultStatus = MBED_ERROR_USAGEFAULT_EXCEPTION;
|
||||
break;
|
||||
case USAGE_FAULT_EXCEPTION:
|
||||
mbed_error_printf("UsageFault");
|
||||
faultStatus = MBED_ERROR_USAGEFAULT_EXCEPTION;
|
||||
break;
|
||||
|
||||
//There is no way we can hit this code without getting an exception, so we have the default treated like hardfault
|
||||
case HARD_FAULT_EXCEPTION:
|
||||
default:
|
||||
mbed_error_printf("HardFault");
|
||||
faultStatus = MBED_ERROR_HARDFAULT_EXCEPTION;
|
||||
break;
|
||||
//There is no way we can hit this code without getting an exception, so we have the default treated like hardfault
|
||||
case HARD_FAULT_EXCEPTION:
|
||||
default:
|
||||
mbed_error_printf("HardFault");
|
||||
faultStatus = MBED_ERROR_HARDFAULT_EXCEPTION;
|
||||
break;
|
||||
}
|
||||
mbed_error_printf("\n\nContext:");
|
||||
print_context_info();
|
||||
|
||||
mbed_error_printf("\n\n-- MbedOS Fault Handler --\n\n");
|
||||
core_util_atomic_store_bool(&mbed_error_in_progress, false);
|
||||
}
|
||||
mbed_error_printf("\n\nContext:");
|
||||
print_context_info();
|
||||
|
||||
mbed_error_printf("\n\n-- MbedOS Fault Handler --\n\n");
|
||||
|
||||
//Now call mbed_error, to log the error and halt the system
|
||||
mbed_error(faultStatus, "Fault exception", (unsigned int)mbed_fault_context_in, NULL, 0);
|
||||
|
|
|
@ -51,7 +51,7 @@ static void print_error_report(const mbed_error_ctx *ctx, const char *, const ch
|
|||
#define ERROR_REPORT(ctx, error_msg, error_filename, error_line) ((void) 0)
|
||||
#endif
|
||||
|
||||
static bool error_in_progress;
|
||||
bool mbed_error_in_progress;
|
||||
static core_util_atomic_flag halt_in_progress = CORE_UTIL_ATOMIC_FLAG_INIT;
|
||||
static int error_count = 0;
|
||||
static mbed_error_ctx first_error_ctx = {0};
|
||||
|
@ -121,7 +121,7 @@ static MBED_NORETURN void mbed_halt_system(void)
|
|||
WEAK MBED_NORETURN void error(const char *format, ...)
|
||||
{
|
||||
// Prevent recursion if error is called again during store+print attempt
|
||||
if (!core_util_atomic_exchange_bool(&error_in_progress, true)) {
|
||||
if (!core_util_atomic_exchange_bool(&mbed_error_in_progress, true)) {
|
||||
handle_error(MBED_ERROR_UNKNOWN, 0, NULL, 0, MBED_CALLER_ADDR());
|
||||
ERROR_REPORT(&last_error_ctx, "Fatal Run-time error", NULL, 0);
|
||||
|
||||
|
@ -298,7 +298,7 @@ int mbed_get_error_count(void)
|
|||
//Reads the fatal error occurred" flag
|
||||
bool mbed_get_error_in_progress(void)
|
||||
{
|
||||
return core_util_atomic_load_bool(&error_in_progress);
|
||||
return core_util_atomic_load_bool(&mbed_error_in_progress);
|
||||
}
|
||||
|
||||
//Sets a non-fatal error
|
||||
|
@ -311,7 +311,7 @@ mbed_error_status_t mbed_warning(mbed_error_status_t error_status, const char *e
|
|||
WEAK MBED_NORETURN mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number)
|
||||
{
|
||||
// Prevent recursion if error is called again during store+print attempt
|
||||
if (!core_util_atomic_exchange_bool(&error_in_progress, true)) {
|
||||
if (!core_util_atomic_exchange_bool(&mbed_error_in_progress, true)) {
|
||||
//set the error reported
|
||||
(void) handle_error(error_status, error_value, filename, line_number, MBED_CALLER_ADDR());
|
||||
|
||||
|
|
Loading…
Reference in New Issue