Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error handling configuration updates and Optimization for exception handling #7214

Merged
merged 3 commits into from
Jun 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions TESTS/mbed_platform/error_handling/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -261,7 +261,7 @@ void test_error_hook()
TEST_ASSERT(sem_status > 0);
}

#ifdef MBED_TEST_SIM_BLOCKDEVICE
#if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED && defined(MBED_TEST_SIM_BLOCKDEVICE)

// test configuration
#ifndef MBED_TEST_FILESYSTEM
Expand Down Expand Up @@ -351,12 +351,12 @@ 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),
#endif //MBED_CONF_RTOS_PRESENT
#ifdef MBED_TEST_SIM_BLOCKDEVICE
#if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED && defined(MBED_TEST_SIM_BLOCKDEVICE)
Case("Test error save log", test_save_error_log),
#endif //MBED_TEST_SIM_BLOCKDEVICE
#endif //MBED_CONF_ERROR_HIST_DISABLED
Expand Down
224 changes: 124 additions & 100 deletions platform/mbed_error.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#define GET_CURRENT_SP(sp) \
{ \
/*If in Handler mode we are always using MSP*/ \
if( __get_IPSR() != 0U ) { \
if ( __get_IPSR() != 0U ) { \
sp = __get_MSP(); \
} else { \
/*Look into CONTROL.SPSEL value*/ \
Expand Down Expand Up @@ -95,7 +95,7 @@ static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsign
mbed_error_ctx current_error_ctx;

//Error status should always be < 0
if(error_status >= 0) {
if (error_status >= 0) {
//This is a weird situation, someone called mbed_error with invalid error code.
//We will still handle the situation but change the error code to ERROR_INVALID_ARGUMENT, atleast the context will have info on who called it
error_status = MBED_ERROR_INVALID_ARGUMENT;
Expand Down Expand Up @@ -132,29 +132,29 @@ 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(&current_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(&current_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

//Capture the fist system error and store it
if(error_count == 1) { //first error
if (error_count == 1) { //first error
memcpy(&first_error_ctx, &current_error_ctx, sizeof(mbed_error_ctx));
}

//copy this error to last error
memcpy(&last_error_ctx, &current_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(&current_error_ctx);
#endif

//Call the error hook if available
if(error_hook != NULL) {
if (error_hook != NULL) {
error_hook(&last_error_ctx);
}

Expand Down Expand Up @@ -190,11 +190,11 @@ 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
if( MBED_SUCCESS != handle_error(error_status, error_value, filename, line_number) )
if ( MBED_SUCCESS != handle_error(error_status, error_value, filename, line_number))
return MBED_ERROR_FAILED_OPERATION;

//On fatal errors print the error context/report
Expand All @@ -208,7 +208,7 @@ WEAK mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char
mbed_error_status_t mbed_set_error_hook(mbed_error_hook_t error_hook_in)
{
//register the new hook/callback
if( error_hook_in != NULL ) {
if ( error_hook_in != NULL ) {
error_hook = error_hook_in;
return MBED_SUCCESS;
}
Expand Down Expand Up @@ -236,17 +236,17 @@ mbed_error_status_t mbed_make_error(mbed_error_type_t error_type, mbed_module_ty
switch(error_type)
{
case MBED_ERROR_TYPE_POSIX:
if(error_code >= MBED_POSIX_ERROR_BASE && error_code <= MBED_SYSTEM_ERROR_BASE)
if (error_code >= MBED_POSIX_ERROR_BASE && error_code <= MBED_SYSTEM_ERROR_BASE)
return -error_code;
break;

case MBED_ERROR_TYPE_SYSTEM:
if(error_code >= MBED_SYSTEM_ERROR_BASE && error_code <= MBED_CUSTOM_ERROR_BASE)
if (error_code >= MBED_SYSTEM_ERROR_BASE && error_code <= MBED_CUSTOM_ERROR_BASE)
return MAKE_MBED_ERROR(MBED_ERROR_TYPE_SYSTEM, entity, error_code);
break;

case MBED_ERROR_TYPE_CUSTOM:
if(error_code >= MBED_CUSTOM_ERROR_BASE)
if (error_code >= MBED_CUSTOM_ERROR_BASE)
return MAKE_MBED_ERROR(MBED_ERROR_TYPE_CUSTOM, entity, error_code);
break;

Expand All @@ -273,15 +273,117 @@ 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();

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)
{
Expand All @@ -302,19 +404,19 @@ mbed_error_status_t mbed_save_error_hist(const char *path)
FILE *error_log_file = NULL;

//Ensure path is valid
if(path==NULL) {
if (path==NULL) {
ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_INVALID_ARGUMENT);
goto exit;
}

//Open the file for saving the error log info
if((error_log_file = fopen( path, "w" ) ) == NULL){
if ((error_log_file = fopen( path, "w" )) == NULL){
ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OPEN_FAILED);
goto exit;
}

//First store the first and last errors
if(fprintf(error_log_file, "\nFirst Error: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x\n",
if (fprintf(error_log_file, "\nFirst Error: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x\n",
(unsigned int)first_error_ctx.error_status,
(unsigned int)first_error_ctx.thread_id,
(unsigned int)first_error_ctx.error_address,
Expand All @@ -323,7 +425,7 @@ mbed_error_status_t mbed_save_error_hist(const char *path)
goto exit;
}

if(fprintf(error_log_file, "\nLast Error: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x\n",
if (fprintf(error_log_file, "\nLast Error: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x\n",
(unsigned int)last_error_ctx.error_status,
(unsigned int)last_error_ctx.thread_id,
(unsigned int)last_error_ctx.error_address,
Expand All @@ -333,10 +435,10 @@ mbed_error_status_t mbed_save_error_hist(const char *path)
}

//Update with error log info
while(--log_count >= 0) {
while (--log_count >= 0) {
mbed_error_hist_get(log_count, &ctx);
//first line of file will be error log count
if(fprintf(error_log_file, "\n%d: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x\n",
if (fprintf(error_log_file, "\n%d: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x\n",
log_count,
(unsigned int)ctx.error_status,
(unsigned int)ctx.thread_id,
Expand All @@ -352,83 +454,5 @@ mbed_error_status_t mbed_save_error_hist(const char *path)

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

Loading