Skip to content

Commit bc7e217

Browse files
committed
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`.
1 parent b0751bf commit bc7e217

File tree

3 files changed

+42
-33
lines changed

3 files changed

+42
-33
lines changed

platform/mbed_interface.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ void mbed_error_vprintf(const char *format, va_list arg) MBED_PRINTF(1, 0);
168168
* FileHandle::write of the stderr device is. The default
169169
* serial console is safe, either buffered or not. If the
170170
* console has not previously been initialized, an attempt
171-
* to use this from interrupt may during console initialization.
171+
* to use this from interrupt may crash during console initialization.
172172
* Special handling of `mbed_error` relaxes various system traps
173173
* to increase the chance of initialization working.
174174
*

platform/source/TARGET_CORTEX_M/mbed_fault_handler.c

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <string.h>
2222

2323
#include "device.h"
24+
#include "mbed_atomic.h"
2425
#include "mbed_error.h"
2526
#include "mbed_interface.h"
2627
#include "mbed_crash_data_offsets.h"
@@ -39,41 +40,49 @@ mbed_fault_context_t fault_context;
3940
mbed_fault_context_t *const mbed_fault_context = &fault_context;
4041
#endif
4142

43+
extern bool mbed_error_in_progress;
44+
4245
//This is a handler function called from Fault handler to print the error information out.
4346
//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.
4447
void mbed_fault_handler(uint32_t fault_type, const mbed_fault_context_t *mbed_fault_context_in)
4548
{
4649
mbed_error_status_t faultStatus = MBED_SUCCESS;
4750

48-
mbed_error_printf("\n++ MbedOS Fault Handler ++\n\nFaultType: ");
49-
50-
switch (fault_type) {
51-
case MEMMANAGE_FAULT_EXCEPTION:
52-
mbed_error_printf("MemManageFault");
53-
faultStatus = MBED_ERROR_MEMMANAGE_EXCEPTION;
54-
break;
55-
56-
case BUS_FAULT_EXCEPTION:
57-
mbed_error_printf("BusFault");
58-
faultStatus = MBED_ERROR_BUSFAULT_EXCEPTION;
59-
break;
60-
61-
case USAGE_FAULT_EXCEPTION:
62-
mbed_error_printf("UsageFault");
63-
faultStatus = MBED_ERROR_USAGEFAULT_EXCEPTION;
64-
break;
65-
66-
//There is no way we can hit this code without getting an exception, so we have the default treated like hardfault
67-
case HARD_FAULT_EXCEPTION:
68-
default:
69-
mbed_error_printf("HardFault");
70-
faultStatus = MBED_ERROR_HARDFAULT_EXCEPTION;
71-
break;
72-
}
73-
mbed_error_printf("\n\nContext:");
74-
print_context_info();
51+
/* Need to set the flag to ensure prints do not trigger a "mutex in ISR" trap
52+
* if they're first prints since boot and we have to init the I/O system.
53+
*/
54+
if (!core_util_atomic_exchange_bool(&mbed_error_in_progress, true)) {
55+
mbed_error_printf("\n++ MbedOS Fault Handler ++\n\nFaultType: ");
56+
57+
switch (fault_type) {
58+
case MEMMANAGE_FAULT_EXCEPTION:
59+
mbed_error_printf("MemManageFault");
60+
faultStatus = MBED_ERROR_MEMMANAGE_EXCEPTION;
61+
break;
62+
63+
case BUS_FAULT_EXCEPTION:
64+
mbed_error_printf("BusFault");
65+
faultStatus = MBED_ERROR_BUSFAULT_EXCEPTION;
66+
break;
67+
68+
case USAGE_FAULT_EXCEPTION:
69+
mbed_error_printf("UsageFault");
70+
faultStatus = MBED_ERROR_USAGEFAULT_EXCEPTION;
71+
break;
72+
73+
//There is no way we can hit this code without getting an exception, so we have the default treated like hardfault
74+
case HARD_FAULT_EXCEPTION:
75+
default:
76+
mbed_error_printf("HardFault");
77+
faultStatus = MBED_ERROR_HARDFAULT_EXCEPTION;
78+
break;
79+
}
80+
mbed_error_printf("\n\nContext:");
81+
print_context_info();
7582

76-
mbed_error_printf("\n\n-- MbedOS Fault Handler --\n\n");
83+
mbed_error_printf("\n\n-- MbedOS Fault Handler --\n\n");
84+
core_util_atomic_store_bool(&mbed_error_in_progress, false);
85+
}
7786

7887
//Now call mbed_error, to log the error and halt the system
7988
mbed_error(faultStatus, "Fault exception", (unsigned int)mbed_fault_context_in, NULL, 0);

platform/source/mbed_error.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ static void print_error_report(const mbed_error_ctx *ctx, const char *, const ch
5151
#define ERROR_REPORT(ctx, error_msg, error_filename, error_line) ((void) 0)
5252
#endif
5353

54-
static bool error_in_progress;
54+
bool mbed_error_in_progress;
5555
static core_util_atomic_flag halt_in_progress = CORE_UTIL_ATOMIC_FLAG_INIT;
5656
static int error_count = 0;
5757
static mbed_error_ctx first_error_ctx = {0};
@@ -121,7 +121,7 @@ static MBED_NORETURN void mbed_halt_system(void)
121121
WEAK MBED_NORETURN void error(const char *format, ...)
122122
{
123123
// Prevent recursion if error is called again during store+print attempt
124-
if (!core_util_atomic_exchange_bool(&error_in_progress, true)) {
124+
if (!core_util_atomic_exchange_bool(&mbed_error_in_progress, true)) {
125125
handle_error(MBED_ERROR_UNKNOWN, 0, NULL, 0, MBED_CALLER_ADDR());
126126
ERROR_REPORT(&last_error_ctx, "Fatal Run-time error", NULL, 0);
127127

@@ -298,7 +298,7 @@ int mbed_get_error_count(void)
298298
//Reads the fatal error occurred" flag
299299
bool mbed_get_error_in_progress(void)
300300
{
301-
return core_util_atomic_load_bool(&error_in_progress);
301+
return core_util_atomic_load_bool(&mbed_error_in_progress);
302302
}
303303

304304
//Sets a non-fatal error
@@ -311,7 +311,7 @@ mbed_error_status_t mbed_warning(mbed_error_status_t error_status, const char *e
311311
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)
312312
{
313313
// Prevent recursion if error is called again during store+print attempt
314-
if (!core_util_atomic_exchange_bool(&error_in_progress, true)) {
314+
if (!core_util_atomic_exchange_bool(&mbed_error_in_progress, true)) {
315315
//set the error reported
316316
(void) handle_error(error_status, error_value, filename, line_number, MBED_CALLER_ADDR());
317317

0 commit comments

Comments
 (0)