Merge pull request #11970 from kjbracey-arm/fault_crash

Avoid crashes during fault handler
pull/12078/head
Martin Kojtal 2019-12-04 10:13:54 +01:00 committed by GitHub
commit 64d172c3bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 29 deletions

View File

@ -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 * FileHandle::write of the stderr device is. The default
* serial console is safe, either buffered or not. If the * serial console is safe, either buffered or not. If the
* console has not previously been initialized, an attempt * 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 * Special handling of `mbed_error` relaxes various system traps
* to increase the chance of initialization working. * to increase the chance of initialization working.
* *

View File

@ -21,6 +21,7 @@
#include <string.h> #include <string.h>
#include "device.h" #include "device.h"
#include "mbed_atomic.h"
#include "mbed_error.h" #include "mbed_error.h"
#include "mbed_interface.h" #include "mbed_interface.h"
#include "mbed_crash_data_offsets.h" #include "mbed_crash_data_offsets.h"
@ -39,12 +40,18 @@ mbed_fault_context_t fault_context;
mbed_fault_context_t *const mbed_fault_context = &fault_context; mbed_fault_context_t *const mbed_fault_context = &fault_context;
#endif #endif
extern bool mbed_error_in_progress;
//This is a handler function called from Fault handler to print the error information out. //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. //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) 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_status_t faultStatus = MBED_SUCCESS;
/* 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: "); mbed_error_printf("\n++ MbedOS Fault Handler ++\n\nFaultType: ");
switch (fault_type) { switch (fault_type) {
@ -74,6 +81,8 @@ void mbed_fault_handler(uint32_t fault_type, const mbed_fault_context_t *mbed_fa
print_context_info(); print_context_info();
mbed_error_printf("\n\n-- MbedOS Fault Handler --\n\n"); mbed_error_printf("\n\n-- MbedOS Fault Handler --\n\n");
core_util_atomic_store_bool(&mbed_error_in_progress, false);
}
//Now call mbed_error, to log the error and halt the system //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); mbed_error(faultStatus, "Fault exception", (unsigned int)mbed_fault_context_in, NULL, 0);

View File

@ -52,7 +52,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) #define ERROR_REPORT(ctx, error_msg, error_filename, error_line) ((void) 0)
#endif #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 core_util_atomic_flag halt_in_progress = CORE_UTIL_ATOMIC_FLAG_INIT;
static int error_count = 0; static int error_count = 0;
static mbed_error_ctx first_error_ctx = {0}; static mbed_error_ctx first_error_ctx = {0};
@ -92,7 +92,7 @@ static MBED_NORETURN void mbed_halt_system(void)
WEAK MBED_NORETURN void error(const char *format, ...) WEAK MBED_NORETURN void error(const char *format, ...)
{ {
// Prevent recursion if error is called again during store+print attempt // 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()); handle_error(MBED_ERROR_UNKNOWN, 0, NULL, 0, MBED_CALLER_ADDR());
ERROR_REPORT(&last_error_ctx, "Fatal Run-time error", NULL, 0); ERROR_REPORT(&last_error_ctx, "Fatal Run-time error", NULL, 0);
@ -269,7 +269,7 @@ int mbed_get_error_count(void)
//Reads the fatal error occurred" flag //Reads the fatal error occurred" flag
bool mbed_get_error_in_progress(void) 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 //Sets a non-fatal error
@ -282,7 +282,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) 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 // 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 //set the error reported
(void) handle_error(error_status, error_value, filename, line_number, MBED_CALLER_ADDR()); (void) handle_error(error_status, error_value, filename, line_number, MBED_CALLER_ADDR());