mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
mbed_error.c
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 #include <stdlib.h> 00018 #include <stdarg.h> 00019 #include <string.h> 00020 #include "device.h" 00021 #include "platform/mbed_crash_data_offsets.h" 00022 #include "platform/mbed_retarget.h" 00023 #include "platform/mbed_critical.h" 00024 #include "platform/mbed_error.h" 00025 #include "platform/mbed_error_hist.h" 00026 #include "platform/mbed_interface.h" 00027 #include "platform/mbed_power_mgmt.h" 00028 #ifdef MBED_CONF_RTOS_PRESENT 00029 #include "rtx_os.h" 00030 #endif 00031 00032 #if DEVICE_STDIO_MESSAGES 00033 #include <stdio.h> 00034 #endif 00035 #ifndef __STDC_FORMAT_MACROS 00036 #define __STDC_FORMAT_MACROS 00037 #endif 00038 #include <inttypes.h> 00039 00040 #ifndef NDEBUG 00041 #define ERROR_REPORT(ctx, error_msg, error_filename, error_line) print_error_report(ctx, error_msg, error_filename, error_line) 00042 static void print_error_report(const mbed_error_ctx *ctx, const char *, const char *error_filename, int error_line); 00043 #else 00044 #define ERROR_REPORT(ctx, error_msg, error_filename, error_line) ((void) 0) 00045 #endif 00046 00047 static core_util_atomic_flag error_in_progress = CORE_UTIL_ATOMIC_FLAG_INIT; 00048 static core_util_atomic_flag halt_in_progress = CORE_UTIL_ATOMIC_FLAG_INIT; 00049 static int error_count = 0; 00050 static mbed_error_ctx first_error_ctx = {0}; 00051 00052 #if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED 00053 //Global for populating the context in exception handler 00054 static mbed_error_ctx *const report_error_ctx = (mbed_error_ctx *)(ERROR_CONTEXT_LOCATION); 00055 static bool is_reboot_error_valid = false; 00056 #endif 00057 00058 static mbed_error_ctx last_error_ctx = {0}; 00059 static mbed_error_hook_t error_hook = NULL; 00060 static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsigned int error_value, const char *filename, int line_number, void *caller); 00061 00062 //Helper function to calculate CRC 00063 //NOTE: It would have been better to use MbedCRC implementation. But 00064 //MbedCRC uses table based calculation and we dont want to keep that table memory 00065 //used up for this purpose. Also we cannot force bitwise calculation in MbedCRC 00066 //and it also requires a new wrapper to be called from C implementation. Since 00067 //we dont have many uses cases to create a C wrapper for MbedCRC and the data 00068 //we calculate CRC on in this context is very less we will use a local 00069 //implementation here. 00070 static unsigned int compute_crc32(const void *data, int datalen) 00071 { 00072 const unsigned int polynomial = 0x04C11DB7; /* divisor is 32bit */ 00073 unsigned int crc = 0; /* CRC value is 32bit */ 00074 unsigned char *buf = (unsigned char *)data;//use a temp variable to make code readable and to avoid typecasting issues. 00075 00076 for (; datalen > 0; datalen--) { 00077 unsigned char b = *buf++; 00078 crc ^= (unsigned int)(b << 24); /* move byte into upper 8bit */ 00079 for (int i = 0; i < 8; i++) { 00080 /* is MSB 1 */ 00081 if ((crc & 0x80000000) != 0) { 00082 crc = (unsigned int)((crc << 1) ^ polynomial); 00083 } else { 00084 crc <<= 1; 00085 } 00086 } 00087 } 00088 00089 return crc; 00090 } 00091 00092 //Helper function to halt the system 00093 static MBED_NORETURN void mbed_halt_system(void) 00094 { 00095 // Prevent recursion if halt is called again during halt attempt - try 00096 // something simple instead. 00097 if (core_util_atomic_flag_test_and_set(&halt_in_progress)) { 00098 core_util_critical_section_enter(); 00099 __DSB(); 00100 for (;;) { 00101 __WFE(); // Not WFI, as don't want to wake for pending interrupts 00102 } 00103 } 00104 00105 //If in ISR context, call mbed_die directly 00106 if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) { 00107 mbed_die(); 00108 } 00109 00110 // In normal context, try orderly exit(1), which eventually calls mbed_die 00111 exit(1); 00112 } 00113 00114 WEAK MBED_NORETURN void error(const char *format, ...) 00115 { 00116 // Prevent recursion if error is called again during store+print attempt 00117 if (!core_util_atomic_flag_test_and_set(&error_in_progress)) { 00118 handle_error(MBED_ERROR_UNKNOWN, 0, NULL, 0, MBED_CALLER_ADDR()); 00119 ERROR_REPORT(&last_error_ctx, "Fatal Run-time error", NULL, 0); 00120 00121 #ifndef NDEBUG 00122 va_list arg; 00123 va_start(arg, format); 00124 mbed_error_vprintf(format, arg); 00125 va_end(arg); 00126 #endif 00127 } 00128 00129 mbed_halt_system(); 00130 } 00131 00132 //Set an error status with the error handling system 00133 static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsigned int error_value, const char *filename, int line_number, void *caller) 00134 { 00135 mbed_error_ctx current_error_ctx; 00136 00137 //Error status should always be < 0 00138 if (error_status >= 0) { 00139 //This is a weird situation, someone called mbed_error with invalid error code. 00140 //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 00141 error_status = MBED_ERROR_INVALID_ARGUMENT; 00142 } 00143 00144 //Clear the context capturing buffer 00145 memset(¤t_error_ctx, 0, sizeof(mbed_error_ctx)); 00146 //Capture error information 00147 current_error_ctx.error_status = error_status; 00148 current_error_ctx.error_address = (uint32_t)caller; 00149 current_error_ctx.error_value = error_value; 00150 #ifdef MBED_CONF_RTOS_PRESENT 00151 //Capture thread info 00152 osRtxThread_t *current_thread = osRtxInfo.thread.run.curr; 00153 current_error_ctx.thread_id = (uint32_t)current_thread; 00154 current_error_ctx.thread_entry_address = (uint32_t)current_thread->thread_addr; 00155 current_error_ctx.thread_stack_size = current_thread->stack_size; 00156 current_error_ctx.thread_stack_mem = (uint32_t)current_thread->stack_mem; 00157 current_error_ctx.thread_current_sp = (uint32_t)¤t_error_ctx; // Address local variable to get a stack pointer 00158 #endif //MBED_CONF_RTOS_PRESENT 00159 00160 #if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED 00161 //Capture filename/linenumber if provided 00162 //Index for tracking error_filename 00163 strncpy(current_error_ctx.error_filename, filename, MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN); 00164 current_error_ctx.error_line_number = line_number; 00165 #endif 00166 00167 //Prevent corruption by holding out other callers 00168 core_util_critical_section_enter(); 00169 00170 //Increment error count 00171 error_count++; 00172 00173 //Capture the first system error and store it 00174 if (error_count == 1) { //first error 00175 memcpy(&first_error_ctx, ¤t_error_ctx, sizeof(mbed_error_ctx)); 00176 } 00177 00178 //copy this error to last error 00179 memcpy(&last_error_ctx, ¤t_error_ctx, sizeof(mbed_error_ctx)); 00180 00181 #if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED 00182 //Log the error with error log 00183 mbed_error_hist_put(¤t_error_ctx); 00184 #endif 00185 00186 //Call the error hook if available 00187 if (error_hook != NULL) { 00188 error_hook(&last_error_ctx); 00189 } 00190 00191 core_util_critical_section_exit(); 00192 00193 return MBED_SUCCESS; 00194 } 00195 00196 WEAK void mbed_error_reboot_callback(mbed_error_ctx *error_context) 00197 { 00198 //Dont do anything here, let application override this if required. 00199 } 00200 00201 //Initialize Error handling system and report any errors detected on rebooted 00202 mbed_error_status_t mbed_error_initialize(void) 00203 { 00204 #if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED 00205 uint32_t crc_val = 0; 00206 00207 //Just check if we have valid value for error_status, if error_status is positive(which is not valid), no need to check crc 00208 if (report_error_ctx->error_status < 0) { 00209 crc_val = compute_crc32(report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx)); 00210 //Read report_error_ctx and check if CRC is correct, and with valid status code 00211 if ((report_error_ctx->crc_error_ctx == crc_val) && (report_error_ctx->is_error_processed == 0)) { 00212 is_reboot_error_valid = true; 00213 00214 //Call the mbed_error_reboot_callback, this enables applications to do some handling before we do the handling 00215 mbed_error_reboot_callback(report_error_ctx); 00216 00217 //We let the callback reset the error info, so check if its still valid and do the rest only if its still valid. 00218 if (report_error_ctx->error_reboot_count > 0) { 00219 00220 report_error_ctx->is_error_processed = 1;//Set the flag that we already processed this error 00221 crc_val = compute_crc32(report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx)); 00222 report_error_ctx->crc_error_ctx = crc_val; 00223 00224 //Enforce max-reboot only if auto reboot is enabled 00225 #if MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED 00226 if (report_error_ctx->error_reboot_count >= MBED_CONF_PLATFORM_ERROR_REBOOT_MAX) { 00227 mbed_halt_system(); 00228 } 00229 #endif 00230 } 00231 } 00232 } 00233 #endif 00234 return MBED_SUCCESS; 00235 } 00236 00237 //Return the first error 00238 mbed_error_status_t mbed_get_first_error(void) 00239 { 00240 //return the first error recorded 00241 return first_error_ctx.error_status; 00242 } 00243 00244 //Return the last error 00245 mbed_error_status_t mbed_get_last_error(void) 00246 { 00247 //return the last error recorded 00248 return last_error_ctx.error_status; 00249 } 00250 00251 //Gets the current error count 00252 int mbed_get_error_count(void) 00253 { 00254 //return the current error count 00255 return error_count; 00256 } 00257 00258 //Sets a non-fatal error 00259 mbed_error_status_t mbed_warning(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number) 00260 { 00261 return handle_error(error_status, error_value, filename, line_number, MBED_CALLER_ADDR()); 00262 } 00263 00264 //Sets a fatal error, this function is marked WEAK to be able to override this for some tests 00265 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) 00266 { 00267 // Prevent recursion if error is called again during store+print attempt 00268 if (!core_util_atomic_flag_test_and_set(&error_in_progress)) { 00269 //set the error reported 00270 (void) handle_error(error_status, error_value, filename, line_number, MBED_CALLER_ADDR()); 00271 00272 //On fatal errors print the error context/report 00273 ERROR_REPORT(&last_error_ctx, error_msg, filename, line_number); 00274 } 00275 00276 #if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED 00277 uint32_t crc_val = 0; 00278 crc_val = compute_crc32(report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx)); 00279 //Read report_error_ctx and check if CRC is correct for report_error_ctx 00280 if (report_error_ctx->crc_error_ctx == crc_val) { 00281 uint32_t current_reboot_count = report_error_ctx->error_reboot_count; 00282 last_error_ctx.error_reboot_count = current_reboot_count + 1; 00283 } else { 00284 last_error_ctx.error_reboot_count = 1; 00285 } 00286 last_error_ctx.is_error_processed = 0;//Set the flag that this is a new error 00287 //Update the struct with crc 00288 last_error_ctx.crc_error_ctx = compute_crc32(&last_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx)); 00289 //Protect report_error_ctx while we update it 00290 core_util_critical_section_enter(); 00291 memcpy(report_error_ctx, &last_error_ctx, sizeof(mbed_error_ctx)); 00292 core_util_critical_section_exit(); 00293 //We need not call delete_mbed_crc(crc_obj) here as we are going to reset the system anyway, and calling delete while handling a fatal error may cause nested exception 00294 #if MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED && (MBED_CONF_PLATFORM_ERROR_REBOOT_MAX > 0) 00295 #ifndef NDEBUG 00296 mbed_error_printf("\n= System will be rebooted due to a fatal error =\n"); 00297 if (report_error_ctx->error_reboot_count >= MBED_CONF_PLATFORM_ERROR_REBOOT_MAX) { 00298 //We have rebooted more than enough, hold the system here. 00299 mbed_error_printf("= Reboot count(=%ld) reached maximum, system will halt after rebooting =\n", report_error_ctx->error_reboot_count); 00300 } 00301 #endif 00302 system_reset();//do a system reset to get the system rebooted 00303 #endif 00304 #endif 00305 mbed_halt_system(); 00306 } 00307 00308 //Register an application defined callback with error handling 00309 mbed_error_status_t mbed_set_error_hook(mbed_error_hook_t error_hook_in) 00310 { 00311 //register the new hook/callback 00312 if (error_hook_in != NULL) { 00313 error_hook = error_hook_in; 00314 return MBED_SUCCESS; 00315 } 00316 00317 return MBED_ERROR_INVALID_ARGUMENT; 00318 } 00319 00320 //Reset the reboot error context 00321 mbed_error_status_t mbed_reset_reboot_error_info() 00322 { 00323 #if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED 00324 //Protect for thread safety 00325 core_util_critical_section_enter(); 00326 memset(report_error_ctx, 0, sizeof(mbed_error_ctx)); 00327 core_util_critical_section_exit(); 00328 #endif 00329 return MBED_SUCCESS; 00330 } 00331 00332 //Reset the reboot error context 00333 mbed_error_status_t mbed_reset_reboot_count() 00334 { 00335 #if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED 00336 if (is_reboot_error_valid) { 00337 uint32_t crc_val = 0; 00338 core_util_critical_section_enter(); 00339 report_error_ctx->error_reboot_count = 0;//Set reboot count to 0 00340 //Update CRC 00341 crc_val = compute_crc32(report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx)); 00342 report_error_ctx->crc_error_ctx = crc_val; 00343 core_util_critical_section_exit(); 00344 return MBED_SUCCESS; 00345 } 00346 #endif 00347 return MBED_ERROR_ITEM_NOT_FOUND; 00348 } 00349 00350 //Retrieve the reboot error context 00351 mbed_error_status_t mbed_get_reboot_error_info(mbed_error_ctx *error_info) 00352 { 00353 mbed_error_status_t status = MBED_ERROR_ITEM_NOT_FOUND; 00354 #if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED 00355 if (is_reboot_error_valid) { 00356 if (error_info != NULL) { 00357 memcpy(error_info, report_error_ctx, sizeof(mbed_error_ctx)); 00358 status = MBED_SUCCESS; 00359 } else { 00360 status = MBED_ERROR_INVALID_ARGUMENT; 00361 } 00362 } 00363 #endif 00364 return status; 00365 } 00366 00367 //Retrieve the first error context from error log 00368 mbed_error_status_t mbed_get_first_error_info(mbed_error_ctx *error_info) 00369 { 00370 memcpy(error_info, &first_error_ctx, sizeof(first_error_ctx)); 00371 return MBED_SUCCESS; 00372 } 00373 00374 //Retrieve the last error context from error log 00375 mbed_error_status_t mbed_get_last_error_info(mbed_error_ctx *error_info) 00376 { 00377 memcpy(error_info, &last_error_ctx, sizeof(mbed_error_ctx)); 00378 return MBED_SUCCESS; 00379 } 00380 00381 //Makes an mbed_error_status_t value 00382 mbed_error_status_t mbed_make_error(mbed_error_type_t error_type, mbed_module_type_t entity, mbed_error_code_t error_code) 00383 { 00384 switch (error_type) { 00385 case MBED_ERROR_TYPE_POSIX: 00386 if (error_code >= MBED_POSIX_ERROR_BASE && error_code <= MBED_SYSTEM_ERROR_BASE) { 00387 return -error_code; 00388 } 00389 break; 00390 00391 case MBED_ERROR_TYPE_SYSTEM: 00392 if (error_code >= MBED_SYSTEM_ERROR_BASE && error_code <= MBED_CUSTOM_ERROR_BASE) { 00393 return MAKE_MBED_ERROR(MBED_ERROR_TYPE_SYSTEM, entity, error_code); 00394 } 00395 break; 00396 00397 case MBED_ERROR_TYPE_CUSTOM: 00398 if (error_code >= MBED_CUSTOM_ERROR_BASE) { 00399 return MAKE_MBED_ERROR(MBED_ERROR_TYPE_CUSTOM, entity, error_code); 00400 } 00401 break; 00402 00403 default: 00404 break; 00405 } 00406 00407 //If we are passed incorrect values return a generic system error 00408 return MAKE_MBED_ERROR(MBED_ERROR_TYPE_SYSTEM, MBED_MODULE_UNKNOWN, MBED_ERROR_CODE_UNKNOWN); 00409 } 00410 00411 /** 00412 * Clears all the last error, error count and all entries in the error log. 00413 * @return 0 or MBED_SUCCESS on success. 00414 * 00415 */ 00416 mbed_error_status_t mbed_clear_all_errors(void) 00417 { 00418 mbed_error_status_t status = MBED_SUCCESS; 00419 00420 //Make sure we dont multiple clients resetting 00421 core_util_critical_section_enter(); 00422 //Clear the error and context capturing buffer 00423 memset(&last_error_ctx, 0, sizeof(mbed_error_ctx)); 00424 //reset error count to 0 00425 error_count = 0; 00426 #if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED 00427 status = mbed_error_hist_reset(); 00428 #endif 00429 core_util_critical_section_exit(); 00430 00431 return status; 00432 } 00433 00434 static const char *name_or_unnamed(const char *name) 00435 { 00436 return name ? name : "<unnamed>"; 00437 } 00438 00439 #if MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO && defined(MBED_CONF_RTOS_PRESENT) 00440 /* Prints info of a thread(using osRtxThread_t struct)*/ 00441 static void print_thread(const osRtxThread_t *thread) 00442 { 00443 mbed_error_printf("\n%s State: 0x%" PRIX8 " Entry: 0x%08" PRIX32 " Stack Size: 0x%08" PRIX32 " Mem: 0x%08" PRIX32 " SP: 0x%08" PRIX32, name_or_unnamed(thread->name), thread->state, thread->thread_addr, thread->stack_size, (uint32_t)thread->stack_mem, thread->sp); 00444 } 00445 00446 /* Prints thread info from a list */ 00447 static void print_threads_info(const osRtxThread_t *threads) 00448 { 00449 while (threads != NULL) { 00450 print_thread(threads); 00451 threads = threads->thread_next; 00452 } 00453 } 00454 #endif 00455 00456 #ifndef NDEBUG 00457 static void print_error_report(const mbed_error_ctx *ctx, const char *error_msg, const char *error_filename, int error_line) 00458 { 00459 int error_code = MBED_GET_ERROR_CODE(ctx->error_status); 00460 int error_module = MBED_GET_ERROR_MODULE(ctx->error_status); 00461 00462 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); 00463 00464 switch (error_code) { 00465 //These are errors reported by kernel handled from mbed_rtx_handlers 00466 case MBED_ERROR_CODE_RTOS_EVENT: 00467 mbed_error_printf("Kernel Error: 0x%" PRIX32 ", ", ctx->error_value); 00468 break; 00469 00470 case MBED_ERROR_CODE_RTOS_THREAD_EVENT: 00471 mbed_error_printf("Thread: 0x%" PRIX32 ", ", ctx->error_value); 00472 break; 00473 00474 case MBED_ERROR_CODE_RTOS_MUTEX_EVENT: 00475 mbed_error_printf("Mutex: 0x%" PRIX32 ", ", ctx->error_value); 00476 break; 00477 00478 case MBED_ERROR_CODE_RTOS_SEMAPHORE_EVENT: 00479 mbed_error_printf("Semaphore: 0x%" PRIX32 ", ", ctx->error_value); 00480 break; 00481 00482 case MBED_ERROR_CODE_RTOS_MEMORY_POOL_EVENT: 00483 mbed_error_printf("MemoryPool: 0x%" PRIX32 ", ", ctx->error_value); 00484 break; 00485 00486 case MBED_ERROR_CODE_RTOS_EVENT_FLAGS_EVENT: 00487 mbed_error_printf("EventFlags: 0x%" PRIX32 ", ", ctx->error_value); 00488 break; 00489 00490 case MBED_ERROR_CODE_RTOS_TIMER_EVENT: 00491 mbed_error_printf("Timer: 0x%" PRIX32 ", ", ctx->error_value); 00492 break; 00493 00494 case MBED_ERROR_CODE_RTOS_MESSAGE_QUEUE_EVENT: 00495 mbed_error_printf("MessageQueue: 0x%" PRIX32 ", ", ctx->error_value); 00496 break; 00497 00498 case MBED_ERROR_CODE_ASSERTION_FAILED: 00499 mbed_error_printf("Assertion failed: "); 00500 break; 00501 00502 default: 00503 //Nothing to do here, just print the error info down 00504 break; 00505 } 00506 mbed_error_puts(error_msg); 00507 mbed_error_printf("\nLocation: 0x%" PRIX32, ctx->error_address); 00508 00509 /* We print the filename passed in, not any filename in the context. This 00510 * avoids the console print for mbed_error being limited to the presence 00511 * and length of the filename storage. Note that although the MBED_ERROR 00512 * macro compiles out filenames unless platform.error-filename-capture-enabled 00513 * is turned on, MBED_ASSERT always passes filenames, and other direct 00514 * users of mbed_error() may also choose to. 00515 */ 00516 if (error_filename) { 00517 mbed_error_puts("\nFile: "); 00518 mbed_error_puts(error_filename); 00519 mbed_error_printf("+%d", error_line); 00520 } 00521 00522 mbed_error_printf("\nError Value: 0x%" PRIX32, ctx->error_value); 00523 #ifdef MBED_CONF_RTOS_PRESENT 00524 mbed_error_printf("\nCurrent Thread: %s Id: 0x%" PRIX32 " Entry: 0x%" PRIX32 " StackSize: 0x%" PRIX32 " StackMem: 0x%" PRIX32 " SP: 0x%" PRIX32 " ", 00525 name_or_unnamed(((osRtxThread_t *)ctx->thread_id)->name), 00526 ctx->thread_id, ctx->thread_entry_address, ctx->thread_stack_size, ctx->thread_stack_mem, ctx->thread_current_sp); 00527 #endif 00528 00529 #if MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO && defined(MBED_CONF_RTOS_PRESENT) 00530 mbed_error_printf("\nNext:"); 00531 print_thread(osRtxInfo.thread.run.next); 00532 00533 mbed_error_printf("\nReady:"); 00534 print_threads_info(osRtxInfo.thread.ready.thread_list); 00535 00536 mbed_error_printf("\nWait:"); 00537 print_threads_info(osRtxInfo.thread.wait_list); 00538 00539 mbed_error_printf("\nDelay:"); 00540 print_threads_info(osRtxInfo.thread.delay_list); 00541 #endif 00542 mbed_error_printf(MBED_CONF_PLATFORM_ERROR_DECODE_HTTP_URL_STR, ctx->error_status); 00543 mbed_error_printf("\n-- MbedOS Error Info --\n"); 00544 } 00545 #endif //ifndef NDEBUG 00546 00547 #if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED 00548 //Retrieve the error context from error log at the specified index 00549 mbed_error_status_t mbed_get_error_hist_info(int index, mbed_error_ctx *error_info) 00550 { 00551 return mbed_error_hist_get(index, error_info); 00552 } 00553 00554 //Retrieve the error log count 00555 int mbed_get_error_hist_count(void) 00556 { 00557 return mbed_error_hist_get_count(); 00558 } 00559 00560 mbed_error_status_t mbed_save_error_hist(const char *path) 00561 { 00562 mbed_error_status_t ret = MBED_SUCCESS; 00563 mbed_error_ctx ctx = {0}; 00564 int log_count = mbed_error_hist_get_count(); 00565 FILE *error_log_file = NULL; 00566 00567 //Ensure path is valid 00568 if (path == NULL) { 00569 ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_INVALID_ARGUMENT); 00570 goto exit; 00571 } 00572 00573 //Open the file for saving the error log info 00574 if ((error_log_file = fopen(path, "w")) == NULL) { 00575 ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OPEN_FAILED); 00576 goto exit; 00577 } 00578 00579 //First store the first and last errors 00580 if (fprintf(error_log_file, "\nFirst Error: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x\n", 00581 (unsigned int)first_error_ctx.error_status, 00582 (unsigned int)first_error_ctx.thread_id, 00583 (unsigned int)first_error_ctx.error_address, 00584 (unsigned int)first_error_ctx.error_value) <= 0) { 00585 ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_WRITE_FAILED); 00586 goto exit; 00587 } 00588 00589 if (fprintf(error_log_file, "\nLast Error: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x\n", 00590 (unsigned int)last_error_ctx.error_status, 00591 (unsigned int)last_error_ctx.thread_id, 00592 (unsigned int)last_error_ctx.error_address, 00593 (unsigned int)last_error_ctx.error_value) <= 0) { 00594 ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_WRITE_FAILED); 00595 goto exit; 00596 } 00597 00598 //Update with error log info 00599 while (--log_count >= 0) { 00600 mbed_error_hist_get(log_count, &ctx); 00601 //first line of file will be error log count 00602 if (fprintf(error_log_file, "\n%d: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x\n", 00603 log_count, 00604 (unsigned int)ctx.error_status, 00605 (unsigned int)ctx.thread_id, 00606 (unsigned int)ctx.error_address, 00607 (unsigned int)ctx.error_value) <= 0) { 00608 ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_WRITE_FAILED); 00609 goto exit; 00610 } 00611 } 00612 00613 exit: 00614 fclose(error_log_file); 00615 00616 return ret; 00617 } 00618 #endif 00619
Generated on Tue Jul 12 2022 20:41:15 by 1.7.2