diff --git a/TESTS/mbed_platform/error_handling/main.cpp b/TESTS/mbed_platform/error_handling/main.cpp index 145ba801d5..2fffb59cb1 100644 --- a/TESTS/mbed_platform/error_handling/main.cpp +++ b/TESTS/mbed_platform/error_handling/main.cpp @@ -132,12 +132,12 @@ void test_error_context_capture() TEST_ASSERT_EQUAL_UINT((uint32_t)current_thread->thread_addr, error_ctx.thread_entry_address); TEST_ASSERT_EQUAL_UINT((uint32_t)current_thread->stack_size, error_ctx.thread_stack_size); TEST_ASSERT_EQUAL_UINT((uint32_t)current_thread->stack_mem, error_ctx.thread_stack_mem); -#ifdef MBED_CONF_ERROR_FILENAME_CAPTURE_ENABLED +#if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED TEST_ASSERT_EQUAL_STRING(MBED_FILENAME, error_ctx.error_filename); #endif } -#ifndef MBED_CONF_ERROR_HIST_DISABLED +#if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED /** Test error logging functionality */ void test_error_logging() @@ -351,7 +351,7 @@ Case cases[] = { Case("Test error context capture", test_error_context_capture), #endif //MBED_CONF_RTOS_PRESENT Case("Test error hook", test_error_hook), -#ifndef MBED_CONF_ERROR_HIST_DISABLED +#if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED Case("Test error logging", test_error_logging), #if MBED_CONF_RTOS_PRESENT Case("Test error handling multi-threaded", test_error_logging_multithread), diff --git a/platform/mbed_error.c b/platform/mbed_error.c index 57f231cc3e..71031d051b 100644 --- a/platform/mbed_error.c +++ b/platform/mbed_error.c @@ -132,11 +132,11 @@ static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsign #endif //MBED_CONF_RTOS_PRESENT -#ifdef MBED_CONF_ERROR_FILENAME_CAPTURE_ENABLED +#ifdef MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED //Capture filename/linenumber if provided //Index for tracking error_filename - memset(¤t_error_ctx.error_filename, 0, MBED_CONF_MAX_ERROR_FILENAME_LEN); - strncpy(current_error_ctx.error_filename, filename, MBED_CONF_MAX_ERROR_FILENAME_LEN); + memset(¤t_error_ctx.error_filename, 0, MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN); + strncpy(current_error_ctx.error_filename, filename, MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN); current_error_ctx.error_line_number = line_number; #endif @@ -148,7 +148,7 @@ static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsign //copy this error to last error memcpy(&last_error_ctx, ¤t_error_ctx, sizeof(mbed_error_ctx)); -#ifndef MBED_CONF_ERROR_HIST_DISABLED +#if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED //Log the error with error log mbed_error_hist_put(¤t_error_ctx); #endif @@ -190,7 +190,7 @@ mbed_error_status_t mbed_warning(mbed_error_status_t error_status, const char *e return handle_error(error_status, error_value, filename, line_number); } -//Sets a fatal error +//Sets a fatal error, this function is marked WEAK to be able to override this for some tests WEAK 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) { //set the error reported and then halt the system @@ -273,7 +273,7 @@ mbed_error_status_t mbed_clear_all_errors(void) memset(&last_error_ctx, sizeof(mbed_error_ctx), 0); //reset error count to 0 error_count = 0; -#ifndef MBED_CONF_ERROR_HIST_DISABLED +#if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED status = mbed_error_hist_reset(); #endif core_util_critical_section_exit(); @@ -281,7 +281,109 @@ mbed_error_status_t mbed_clear_all_errors(void) return status; } -#ifndef MBED_CONF_ERROR_HIST_DISABLED +#if MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO && defined(MBED_CONF_RTOS_PRESENT) +/* Prints info of a thread(using osRtxThread_t struct)*/ +static void print_thread(osRtxThread_t *thread) +{ + mbed_error_printf("\nState: 0x%08X Entry: 0x%08X Stack Size: 0x%08X Mem: 0x%08X SP: 0x%08X", thread->state, thread->thread_addr, thread->stack_size, (uint32_t)thread->stack_mem, thread->sp); +} + +/* Prints thread info from a list */ +static void print_threads_info(osRtxThread_t *threads) +{ + while(threads != NULL) { + print_thread( threads ); + threads = threads->thread_next; + } +} +#endif + +static void print_error_report(mbed_error_ctx *ctx, const char *error_msg) +{ + uint32_t error_code = MBED_GET_ERROR_CODE(ctx->error_status); + uint32_t error_module = MBED_GET_ERROR_MODULE(ctx->error_status); + + mbed_error_printf("\n\n++ MbedOS Error Info ++\nError Status: 0x%X Code: %d Module: %d\nError Message: ", ctx->error_status, error_code, error_module); + + switch (error_code) { + //These are errors reported by kernel handled from mbed_rtx_handlers + case MBED_ERROR_CODE_RTOS_EVENT: + mbed_error_printf("Kernel Error: 0x%X, ", ctx->error_value); + break; + + case MBED_ERROR_CODE_RTOS_THREAD_EVENT: + mbed_error_printf("Thread: 0x%X, ", ctx->error_value); + break; + + case MBED_ERROR_CODE_RTOS_MUTEX_EVENT: + mbed_error_printf("Mutex: 0x%X, ", ctx->error_value); + break; + + case MBED_ERROR_CODE_RTOS_SEMAPHORE_EVENT: + mbed_error_printf("Semaphore: 0x%X, ", ctx->error_value); + break; + + case MBED_ERROR_CODE_RTOS_MEMORY_POOL_EVENT: + mbed_error_printf("MemoryPool: 0x%X, ", ctx->error_value); + break; + + case MBED_ERROR_CODE_RTOS_EVENT_FLAGS_EVENT: + mbed_error_printf("EventFlags: 0x%X, ", ctx->error_value); + break; + + case MBED_ERROR_CODE_RTOS_TIMER_EVENT: + mbed_error_printf("Timer: 0x%X, ", ctx->error_value); + break; + + case MBED_ERROR_CODE_RTOS_MESSAGE_QUEUE_EVENT: + mbed_error_printf("MessageQueue: 0x%X, ", ctx->error_value); + break; + + default: + //Nothing to do here, just print the error info down + break; + } + mbed_error_printf(error_msg); + mbed_error_printf("\nLocation: 0x%X", ctx->error_address); + +#if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED && !defined(NDEBUG) + if((NULL != ctx->error_filename[0]) && (ctx->error_line_number != 0)) { + //for string, we must pass address of a ptr which has the address of the string + mbed_error_printf("\nFile:%s+%d", ctx->error_filename, ctx->error_line_number); + } +#endif + + mbed_error_printf("\nError Value: 0x%X", ctx->error_value); +#ifdef TARGET_CORTEX_M + mbed_error_printf("\nCurrent Thread: Id: 0x%X Entry: 0x%X StackSize: 0x%X StackMem: 0x%X SP: 0x%X ", + ctx->thread_id, ctx->thread_entry_address, ctx->thread_stack_size, ctx->thread_stack_mem, ctx->thread_current_sp); +#else + //For Cortex-A targets we dont have support to capture the current SP + mbed_error_printf("\nCurrent Thread: Id: 0x%X Entry: 0x%X StackSize: 0x%X StackMem: 0x%X ", + ctx->thread_id, ctx->thread_entry_address, ctx->thread_stack_size, ctx->thread_stack_mem); +#endif //TARGET_CORTEX_M + +#if MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO && defined(MBED_CONF_RTOS_PRESENT) + mbed_error_printf("\nNext:"); + print_thread(osRtxInfo.thread.run.next); + + mbed_error_printf("\nWait:"); + osRtxThread_t *threads = (osRtxThread_t *)&osRtxInfo.thread.wait_list; + print_threads_info(threads); + + mbed_error_printf("\nDelay:"); + threads = (osRtxThread_t *)&osRtxInfo.thread.delay_list; + print_threads_info(threads); + + mbed_error_printf("\nIdle:"); + threads = (osRtxThread_t *)&osRtxInfo.thread.idle; + print_threads_info(threads); +#endif + + mbed_error_printf("\n-- MbedOS Error Info --\n"); +} + +#if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED //Retrieve the error context from error log at the specified index mbed_error_status_t mbed_get_error_hist_info (int index, mbed_error_ctx *error_info) { @@ -352,83 +454,5 @@ exit: return ret; } - -static void print_error_report(mbed_error_ctx *ctx, const char *error_msg) -{ - uint32_t error_code = MBED_GET_ERROR_CODE(ctx->error_status); - uint32_t error_module = MBED_GET_ERROR_MODULE(ctx->error_status); - - mbed_error_printf("\n\n++ MbedOS Error Info ++\nError Status: 0x%x Code: %d Module: %d\nError Message: ", ctx->error_status, error_code, error_module); - - //Report error info based on error code, some errors require different - //error_vals[1] contains the error code - if(error_code == MBED_ERROR_CODE_HARDFAULT_EXCEPTION || - error_code == MBED_ERROR_CODE_MEMMANAGE_EXCEPTION || - error_code == MBED_ERROR_CODE_BUSFAULT_EXCEPTION || - error_code == MBED_ERROR_CODE_USAGEFAULT_EXCEPTION ) { - mbed_error_printf(error_msg); - mbed_error_printf("\nLocation: 0x%x\n", ctx->error_value); - } else { - switch (error_code) { - //These are errors reported by kernel handled from mbed_rtx_handlers - case MBED_ERROR_CODE_RTOS_EVENT: - mbed_error_printf("Kernel Error: 0x%x, ", ctx->error_value); - break; - - case MBED_ERROR_CODE_RTOS_THREAD_EVENT: - mbed_error_printf("Thread: 0x%x, ", ctx->error_value); - break; - - case MBED_ERROR_CODE_RTOS_MUTEX_EVENT: - mbed_error_printf("Mutex: 0x%x, ", ctx->error_value); - break; - - case MBED_ERROR_CODE_RTOS_SEMAPHORE_EVENT: - mbed_error_printf("Semaphore: 0x%x, ", ctx->error_value); - break; - - case MBED_ERROR_CODE_RTOS_MEMORY_POOL_EVENT: - mbed_error_printf("MemoryPool: 0x%x, ", ctx->error_value); - break; - - case MBED_ERROR_CODE_RTOS_EVENT_FLAGS_EVENT: - mbed_error_printf("EventFlags: 0x%x, ", ctx->error_value); - break; - - case MBED_ERROR_CODE_RTOS_TIMER_EVENT: - mbed_error_printf("Timer: 0x%x, ", ctx->error_value); - break; - - case MBED_ERROR_CODE_RTOS_MESSAGE_QUEUE_EVENT: - mbed_error_printf("MessageQueue: 0x%x, ", ctx->error_value); - break; - - default: - //Nothing to do here, just print the error info down - break; - } - mbed_error_printf(error_msg, NULL); - mbed_error_printf("\nLocation: 0x%x", ctx->error_address); -#if defined(MBED_CONF_ERROR_FILENAME_CAPTURE_ENABLED) && !defined(NDEBUG) - if(NULL != ctx->error_filename) { - //for string, we must pass address of a ptr which has the address of the string - mbed_error_printf("\nFile:%s+%d", ctx->error_filename, ctx->error_line_number); - } -#endif - -#ifdef TARGET_CORTEX_M - mbed_error_printf("\nError Value: 0x%x\nCurrent Thread: Id: 0x%x Entry: 0x%x StackSize: 0x%x StackMem: 0x%x SP: 0x%x ", - ctx->error_value, ctx->thread_id, ctx->thread_entry_address, ctx->thread_stack_size, ctx->thread_stack_mem, ctx->thread_current_sp); -#else - //For Cortex-A targets we dont have support to capture the current SP - mbed_error_printf("\nError Value: 0x%x\nCurrent Thread: Id: 0x%x Entry: 0x%x StackSize: 0x%x StackMem: 0x%x ", - ctx->error_value, ctx->thread_id, ctx->thread_entry_address, ctx->thread_stack_size, ctx->thread_stack_mem); -#endif //TARGET_CORTEX_M - } - - mbed_error_printf("\n-- MbedOS Error Info --\n"); -} - - #endif diff --git a/platform/mbed_error.h b/platform/mbed_error.h index b266baf03b..39951fcb9b 100644 --- a/platform/mbed_error.h +++ b/platform/mbed_error.h @@ -30,15 +30,15 @@ extern "C" { #endif /** Define this macro to include filenames in error context. For release builds, do not include filename to save memory. - * MBED_CONF_ERROR_FILENAME_CAPTURE_ENABLED + * MBED_PLATFORM_CONF_ERROR_FILENAME_CAPTURE_ENABLED */ /** Define this macro to disable error logging, note that the first and last error capture will still be active by default. - * MBED_CONF_ERROR_HIST_DISABLED + * MBED_PLATFORM_CONF_ERROR_HIST_DISABLED */ -#ifndef MBED_CONF_MAX_ERROR_FILENAME_LEN -#define MBED_CONF_MAX_ERROR_FILENAME_LEN 16 +#ifndef MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN +#define MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN 16 #endif #define MBED_ERROR_STATUS_CODE_MASK (0x0000FFFF) @@ -147,7 +147,7 @@ typedef int mbed_error_status_t; #define MBED_WARNING1( error_status, error_msg, error_value ) mbed_warning( error_status, (const char *)NULL, (uint32_t)error_value, NULL, 0 ) #define MBED_WARNING( error_status, error_msg ) mbed_warning( error_status, (const char *)NULL, (uint32_t)0, NULL, 0 ) #else - #if defined(MBED_CONF_ERROR_FILENAME_CAPTURE_ENABLED) + #if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED #define MBED_WARNING1( error_status, error_msg, error_value ) mbed_warning( error_status, (const char *)error_msg, (uint32_t)error_value, (const char *)MBED_FILENAME, __LINE__ ) #define MBED_WARNING( error_status, error_msg ) mbed_warning( error_status, (const char *)error_msg, (uint32_t)0 , (const char *)MBED_FILENAME, __LINE__ ) #else @@ -179,7 +179,7 @@ typedef int mbed_error_status_t; #define MBED_ERROR1( error_status, error_msg, error_value ) mbed_error( error_status, (const char *)NULL, (uint32_t)error_value, NULL, 0 ) #define MBED_ERROR( error_status, error_msg ) mbed_error( error_status, (const char *)NULL, (uint32_t)0 , NULL, 0 ) #else - #if defined(MBED_CONF_ERROR_FILENAME_CAPTURE_ENABLED) + #if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED #define MBED_ERROR1( error_status, error_msg, error_value ) mbed_error( error_status, (const char *)error_msg, (uint32_t)error_value, (const char *)MBED_FILENAME, __LINE__ ) #define MBED_ERROR( error_status, error_msg ) mbed_error( error_status, (const char *)error_msg, (uint32_t)0 , (const char *)MBED_FILENAME, __LINE__ ) #else @@ -812,8 +812,8 @@ typedef struct _mbed_error_ctx { uint32_t thread_stack_size; uint32_t thread_stack_mem; uint32_t thread_current_sp; -#ifdef MBED_CONF_ERROR_FILENAME_CAPTURE_ENABLED - char error_filename[MBED_CONF_MAX_ERROR_FILENAME_LEN]; +#ifdef MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN + char error_filename[MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN]; uint32_t error_line_number; #endif } mbed_error_ctx; diff --git a/platform/mbed_error_hist.c b/platform/mbed_error_hist.c index 3420a78553..9fa228a456 100644 --- a/platform/mbed_error_hist.c +++ b/platform/mbed_error_hist.c @@ -21,10 +21,10 @@ #include "platform/mbed_critical.h" #include "platform/mbed_interface.h" -#ifndef MBED_CONF_ERROR_HIST_DISABLED +#if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED #include "platform/mbed_error_hist.h" -static mbed_error_ctx mbed_error_ctx_log[MBED_CONF_ERROR_HIST_SIZE] = {0}; +static mbed_error_ctx mbed_error_ctx_log[MBED_CONF_PLATFORM_ERROR_HIST_SIZE] = {0}; static int error_log_count = -1; mbed_error_status_t mbed_error_hist_put(mbed_error_ctx *error_ctx) @@ -36,7 +36,7 @@ mbed_error_status_t mbed_error_hist_put(mbed_error_ctx *error_ctx) core_util_critical_section_enter(); error_log_count++; - memcpy(&mbed_error_ctx_log[error_log_count % MBED_CONF_ERROR_HIST_SIZE], error_ctx, sizeof(mbed_error_ctx) ); + memcpy(&mbed_error_ctx_log[error_log_count % MBED_CONF_PLATFORM_ERROR_HIST_SIZE], error_ctx, sizeof(mbed_error_ctx) ); core_util_critical_section_exit(); return MBED_SUCCESS; @@ -45,17 +45,17 @@ mbed_error_status_t mbed_error_hist_put(mbed_error_ctx *error_ctx) mbed_error_status_t mbed_error_hist_get(int index, mbed_error_ctx *error_ctx) { //Return error if index is more than max log size - if(index >= MBED_CONF_ERROR_HIST_SIZE) { + if(index >= MBED_CONF_PLATFORM_ERROR_HIST_SIZE) { return MBED_ERROR_INVALID_ARGUMENT; } core_util_critical_section_enter(); //calculate the index where we want to pick the ctx - if(error_log_count >= MBED_CONF_ERROR_HIST_SIZE) { - index = (error_log_count + index + 1) % MBED_CONF_ERROR_HIST_SIZE; + if(error_log_count >= MBED_CONF_PLATFORM_ERROR_HIST_SIZE) { + index = (error_log_count + index + 1) % MBED_CONF_PLATFORM_ERROR_HIST_SIZE; } core_util_critical_section_exit(); - memcpy(error_ctx, &mbed_error_ctx_log[index % MBED_CONF_ERROR_HIST_SIZE], sizeof(mbed_error_ctx) ); + memcpy(error_ctx, &mbed_error_ctx_log[index % MBED_CONF_PLATFORM_ERROR_HIST_SIZE], sizeof(mbed_error_ctx) ); return MBED_SUCCESS; } @@ -64,7 +64,7 @@ mbed_error_ctx *mbed_error_hist_get_entry(void) { core_util_critical_section_enter(); error_log_count++; - mbed_error_ctx *ctx = &mbed_error_ctx_log[error_log_count % MBED_CONF_ERROR_HIST_SIZE]; + mbed_error_ctx *ctx = &mbed_error_ctx_log[error_log_count % MBED_CONF_PLATFORM_ERROR_HIST_SIZE]; core_util_critical_section_exit(); return ctx; @@ -76,7 +76,7 @@ mbed_error_status_t mbed_error_hist_get_last_error(mbed_error_ctx *error_ctx) return MBED_ERROR_ITEM_NOT_FOUND; } core_util_critical_section_enter(); - memcpy(error_ctx, &mbed_error_ctx_log[error_log_count % MBED_CONF_ERROR_HIST_SIZE], sizeof(mbed_error_ctx) ); + memcpy(error_ctx, &mbed_error_ctx_log[error_log_count % MBED_CONF_PLATFORM_ERROR_HIST_SIZE], sizeof(mbed_error_ctx) ); core_util_critical_section_exit(); return MBED_SUCCESS; @@ -84,7 +84,7 @@ mbed_error_status_t mbed_error_hist_get_last_error(mbed_error_ctx *error_ctx) int mbed_error_hist_get_count() { - return (error_log_count >= MBED_CONF_ERROR_HIST_SIZE? MBED_CONF_ERROR_HIST_SIZE:error_log_count+1); + return (error_log_count >= MBED_CONF_PLATFORM_ERROR_HIST_SIZE? MBED_CONF_PLATFORM_ERROR_HIST_SIZE:error_log_count+1); } mbed_error_status_t mbed_error_hist_reset() diff --git a/platform/mbed_error_hist.h b/platform/mbed_error_hist.h index b4380237e4..0ac7c99e27 100644 --- a/platform/mbed_error_hist.h +++ b/platform/mbed_error_hist.h @@ -16,11 +16,11 @@ #ifndef MBED_ERROR_HIST_H #define MBED_ERROR_HIST_H -#ifndef MBED_CONF_ERROR_HIST_SIZE - #define MBED_CONF_ERROR_HIST_SIZE 4 +#ifndef MBED_CONF_PLATFORM_ERROR_HIST_SIZE + #define MBED_CONF_PLATFORM_ERROR_HIST_SIZE 4 #else - #if MBED_CONF_ERROR_HIST_SIZE == 0 - #define MBED_CONF_ERROR_HIST_SIZE 1 + #if MBED_CONF_PLATFORM_ERROR_HIST_SIZE == 0 + #define MBED_CONF_PLATFORM_ERROR_HIST_SIZE 1 #endif #endif diff --git a/platform/mbed_lib.json b/platform/mbed_lib.json index 50dbc0d7a3..2779ec7c5c 100644 --- a/platform/mbed_lib.json +++ b/platform/mbed_lib.json @@ -39,6 +39,31 @@ "poll-use-lowpower-timer": { "help": "Enable use of low power timer class for poll(). May cause missing events.", "value": false + }, + + "error-hist-enabled": { + "help": "Enable for error history tracking.", + "value": false + }, + + "error-hist-size": { + "help": "Set the number of most recent errors the system keeps in its history, needs error-hist-enabled set to true for this to work.", + "value": 4 + }, + + "error-filename-capture-enabled": { + "help": "Enables capture of filename and line number as part of error context capture, this works only for debug and develop builds. On release builds, filename capture is always disabled", + "value": false + }, + + "error-all-threads-info": { + "help": "Reports all the threads in the system as part of error report.", + "value": false + }, + + "max-error-filename-len": { + "help": "Sets the maximum length of buffer used for capturing the filename in error context. This needs error-filename-capture-enabled feature.", + "value": 16 } }, "target_overrides": {