- Timestamp:
- Apr 5, 2019, 9:26:53 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
asp3_tinet_ecnl_arm/trunk/asp3_dcre/mbed/platform/mbed_error.c
r352 r374 16 16 #include <stdlib.h> 17 17 #include <stdarg.h> 18 #include <string.h> 18 19 #include "device.h" 19 #include "platform/mbed_ toolchain.h"20 #include "platform/mbed_critical.h" 20 21 #include "platform/mbed_error.h" 22 #include "platform/mbed_error_hist.h" 21 23 #include "platform/mbed_interface.h" 24 #ifdef MBED_CONF_RTOS_PRESENT 25 #include "rtx_os.h" 26 #endif 27 22 28 #if DEVICE_STDIO_MESSAGES 23 29 #include <stdio.h> 24 30 #endif 25 31 26 WEAK void error(const char* format, ...) { 32 #define MBED_CONF_PLATFORM_ERROR_DECODE_HTTP_URL_STR "\nFor more info, visit: https://armmbed.github.io/mbedos-error/?error=0x%08X" // set by library:platform 33 34 //Helper macro to get the current SP 35 #define GET_CURRENT_SP(sp) \ 36 { \ 37 /*If in Handler mode we are always using MSP*/ \ 38 if ( __get_IPSR() != 0U ) { \ 39 sp = __get_MSP(); \ 40 } else { \ 41 /*Look into CONTROL.SPSEL value*/ \ 42 if ((__get_CONTROL() & 2U) == 0U) { \ 43 sp = __get_MSP();/*Read MSP*/ \ 44 } else { \ 45 sp = __get_PSP();/*Read PSP*/ \ 46 } \ 47 } \ 48 } 49 50 #ifndef NDEBUG 51 #define ERROR_REPORT(ctx, error_msg) print_error_report(ctx, error_msg) 52 #else 53 #define ERROR_REPORT(ctx, error_msg) ((void) 0) 54 #endif 55 56 static uint8_t error_in_progress = 0; 57 static int error_count = 0; 58 static mbed_error_ctx first_error_ctx = {0}; 59 static mbed_error_ctx last_error_ctx = {0}; 60 static mbed_error_hook_t error_hook = NULL; 61 static void print_error_report(mbed_error_ctx *ctx, const char *); 62 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); 63 64 //Helper function to halt the system 65 static void mbed_halt_system(void) 66 { 67 //If not in ISR context exit, otherwise spin on WFI 68 if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) { 69 for (;;) { 70 __WFI(); 71 } 72 } else { 73 //exit eventually calls mbed_die 74 exit(1); 75 } 76 } 77 78 WEAK void error(const char *format, ...) 79 { 80 81 // Prevent recursion if error is called again 82 if (error_in_progress) { 83 return; 84 } 85 86 //Call handle_error/print_error_report permanently setting error_in_progress flag 87 handle_error(MBED_ERROR_UNKNOWN, 0, NULL, 0, MBED_CALLER_ADDR()); 88 ERROR_REPORT(&last_error_ctx, "Fatal Run-time error"); 89 error_in_progress = 1; 90 27 91 #ifndef NDEBUG 28 92 va_list arg; … … 33 97 exit(1); 34 98 } 99 100 //Set an error status with the error handling system 101 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) 102 { 103 mbed_error_ctx current_error_ctx; 104 105 //Error status should always be < 0 106 if (error_status >= 0) { 107 //This is a weird situation, someone called mbed_error with invalid error code. 108 //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 109 error_status = MBED_ERROR_INVALID_ARGUMENT; 110 } 111 112 //Prevent corruption by holding out other callers 113 //and we also need this until we remove the "error" call completely 114 while (error_in_progress == 1); 115 116 //Use critsect here, as we don't want inadvertant modification of this global variable 117 core_util_critical_section_enter(); 118 error_in_progress = 1; 119 core_util_critical_section_exit(); 120 121 //Increment error count 122 error_count++; 123 124 //Clear the context capturing buffer 125 memset(¤t_error_ctx, sizeof(mbed_error_ctx), 0); 126 //Capture error information 127 current_error_ctx.error_status = error_status; 128 current_error_ctx.error_address = (uint32_t)caller; 129 current_error_ctx.error_value = error_value; 130 #if 0 //def MBED_CONF_RTOS_PRESENT 131 //Capture thread info 132 osRtxThread_t *current_thread = osRtxInfo.thread.run.curr; 133 current_error_ctx.thread_id = (uint32_t)current_thread; 134 current_error_ctx.thread_entry_address = (uint32_t)current_thread->thread_addr; 135 current_error_ctx.thread_stack_size = current_thread->stack_size; 136 current_error_ctx.thread_stack_mem = (uint32_t)current_thread->stack_mem; 137 #ifdef TARGET_CORTEX_M 138 GET_CURRENT_SP(current_error_ctx.thread_current_sp); 139 #endif //TARGET_CORTEX_M 140 141 #endif //MBED_CONF_RTOS_PRESENT 142 143 #if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED 144 //Capture filename/linenumber if provided 145 //Index for tracking error_filename 146 memset(¤t_error_ctx.error_filename, 0, MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN); 147 strncpy(current_error_ctx.error_filename, filename, MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN); 148 current_error_ctx.error_line_number = line_number; 149 #endif 150 151 //Capture the fist system error and store it 152 if (error_count == 1) { //first error 153 memcpy(&first_error_ctx, ¤t_error_ctx, sizeof(mbed_error_ctx)); 154 } 155 156 //copy this error to last error 157 memcpy(&last_error_ctx, ¤t_error_ctx, sizeof(mbed_error_ctx)); 158 159 #if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED 160 //Log the error with error log 161 mbed_error_hist_put(¤t_error_ctx); 162 #endif 163 164 //Call the error hook if available 165 if (error_hook != NULL) { 166 error_hook(&last_error_ctx); 167 } 168 169 error_in_progress = 0; 170 171 return MBED_SUCCESS; 172 } 173 174 //Return the first error 175 mbed_error_status_t mbed_get_first_error(void) 176 { 177 //return the first error recorded 178 return first_error_ctx.error_status; 179 } 180 181 //Return the last error 182 mbed_error_status_t mbed_get_last_error(void) 183 { 184 //return the last error recorded 185 return last_error_ctx.error_status; 186 } 187 188 //Gets the current error count 189 int mbed_get_error_count(void) 190 { 191 //return the current error count 192 return error_count; 193 } 194 195 //Sets a fatal error 196 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) 197 { 198 return handle_error(error_status, error_value, filename, line_number, MBED_CALLER_ADDR()); 199 } 200 201 //Sets a fatal error, this function is marked WEAK to be able to override this for some tests 202 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) 203 { 204 //set the error reported and then halt the system 205 if (MBED_SUCCESS != handle_error(error_status, error_value, filename, line_number, MBED_CALLER_ADDR())) { 206 return MBED_ERROR_FAILED_OPERATION; 207 } 208 209 //On fatal errors print the error context/report 210 ERROR_REPORT(&last_error_ctx, error_msg); 211 mbed_halt_system(); 212 213 return MBED_ERROR_FAILED_OPERATION; 214 } 215 216 //Register an application defined callback with error handling 217 mbed_error_status_t mbed_set_error_hook(mbed_error_hook_t error_hook_in) 218 { 219 //register the new hook/callback 220 if (error_hook_in != NULL) { 221 error_hook = error_hook_in; 222 return MBED_SUCCESS; 223 } 224 225 return MBED_ERROR_INVALID_ARGUMENT; 226 } 227 228 //Retrieve the first error context from error log 229 mbed_error_status_t mbed_get_first_error_info(mbed_error_ctx *error_info) 230 { 231 memcpy(error_info, &first_error_ctx, sizeof(first_error_ctx)); 232 return MBED_SUCCESS; 233 } 234 235 //Retrieve the last error context from error log 236 mbed_error_status_t mbed_get_last_error_info(mbed_error_ctx *error_info) 237 { 238 memcpy(error_info, &last_error_ctx, sizeof(mbed_error_ctx)); 239 return MBED_SUCCESS; 240 } 241 242 //Makes an mbed_error_status_t value 243 mbed_error_status_t mbed_make_error(mbed_error_type_t error_type, mbed_module_type_t entity, mbed_error_code_t error_code) 244 { 245 switch (error_type) { 246 case MBED_ERROR_TYPE_POSIX: 247 if (error_code >= MBED_POSIX_ERROR_BASE && error_code <= MBED_SYSTEM_ERROR_BASE) { 248 return -error_code; 249 } 250 break; 251 252 case MBED_ERROR_TYPE_SYSTEM: 253 if (error_code >= MBED_SYSTEM_ERROR_BASE && error_code <= MBED_CUSTOM_ERROR_BASE) { 254 return MAKE_MBED_ERROR(MBED_ERROR_TYPE_SYSTEM, entity, error_code); 255 } 256 break; 257 258 case MBED_ERROR_TYPE_CUSTOM: 259 if (error_code >= MBED_CUSTOM_ERROR_BASE) { 260 return MAKE_MBED_ERROR(MBED_ERROR_TYPE_CUSTOM, entity, error_code); 261 } 262 break; 263 264 default: 265 break; 266 } 267 268 //If we are passed incorrect values return a generic system error 269 return MAKE_MBED_ERROR(MBED_ERROR_TYPE_SYSTEM, MBED_MODULE_UNKNOWN, MBED_ERROR_CODE_UNKNOWN); 270 } 271 272 /** 273 * Clears all the last error, error count and all entries in the error log. 274 * @return 0 or MBED_SUCCESS on success. 275 * 276 */ 277 mbed_error_status_t mbed_clear_all_errors(void) 278 { 279 mbed_error_status_t status = MBED_SUCCESS; 280 281 //Make sure we dont multiple clients resetting 282 core_util_critical_section_enter(); 283 //Clear the error and context capturing buffer 284 memset(&last_error_ctx, sizeof(mbed_error_ctx), 0); 285 //reset error count to 0 286 error_count = 0; 287 #if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED 288 status = mbed_error_hist_reset(); 289 #endif 290 core_util_critical_section_exit(); 291 292 return status; 293 } 294 295 #if MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO && defined(MBED_CONF_RTOS_PRESENT) 296 /* Prints info of a thread(using osRtxThread_t struct)*/ 297 static void print_thread(osRtxThread_t *thread) 298 { 299 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); 300 } 301 302 /* Prints thread info from a list */ 303 static void print_threads_info(osRtxThread_t *threads) 304 { 305 while (threads != NULL) { 306 print_thread(threads); 307 threads = threads->thread_next; 308 } 309 } 310 #endif 311 312 #ifndef NDEBUG 313 static void print_error_report(mbed_error_ctx *ctx, const char *error_msg) 314 { 315 uint32_t error_code = MBED_GET_ERROR_CODE(ctx->error_status); 316 uint32_t error_module = MBED_GET_ERROR_MODULE(ctx->error_status); 317 318 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); 319 320 switch (error_code) { 321 //These are errors reported by kernel handled from mbed_rtx_handlers 322 case MBED_ERROR_CODE_RTOS_EVENT: 323 mbed_error_printf("Kernel Error: 0x%X, ", ctx->error_value); 324 break; 325 326 case MBED_ERROR_CODE_RTOS_THREAD_EVENT: 327 mbed_error_printf("Thread: 0x%X, ", ctx->error_value); 328 break; 329 330 case MBED_ERROR_CODE_RTOS_MUTEX_EVENT: 331 mbed_error_printf("Mutex: 0x%X, ", ctx->error_value); 332 break; 333 334 case MBED_ERROR_CODE_RTOS_SEMAPHORE_EVENT: 335 mbed_error_printf("Semaphore: 0x%X, ", ctx->error_value); 336 break; 337 338 case MBED_ERROR_CODE_RTOS_MEMORY_POOL_EVENT: 339 mbed_error_printf("MemoryPool: 0x%X, ", ctx->error_value); 340 break; 341 342 case MBED_ERROR_CODE_RTOS_EVENT_FLAGS_EVENT: 343 mbed_error_printf("EventFlags: 0x%X, ", ctx->error_value); 344 break; 345 346 case MBED_ERROR_CODE_RTOS_TIMER_EVENT: 347 mbed_error_printf("Timer: 0x%X, ", ctx->error_value); 348 break; 349 350 case MBED_ERROR_CODE_RTOS_MESSAGE_QUEUE_EVENT: 351 mbed_error_printf("MessageQueue: 0x%X, ", ctx->error_value); 352 break; 353 354 default: 355 //Nothing to do here, just print the error info down 356 break; 357 } 358 mbed_error_printf(error_msg); 359 mbed_error_printf("\nLocation: 0x%X", ctx->error_address); 360 361 #if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED && !defined(NDEBUG) 362 if ((NULL != ctx->error_filename[0]) && (ctx->error_line_number != 0)) { 363 //for string, we must pass address of a ptr which has the address of the string 364 mbed_error_printf("\nFile:%s+%d", ctx->error_filename, ctx->error_line_number); 365 } 366 #endif 367 368 mbed_error_printf("\nError Value: 0x%X", ctx->error_value); 369 #ifdef TARGET_CORTEX_M 370 mbed_error_printf("\nCurrent Thread: Id: 0x%X Entry: 0x%X StackSize: 0x%X StackMem: 0x%X SP: 0x%X ", 371 ctx->thread_id, ctx->thread_entry_address, ctx->thread_stack_size, ctx->thread_stack_mem, ctx->thread_current_sp); 372 #else 373 //For Cortex-A targets we dont have support to capture the current SP 374 mbed_error_printf("\nCurrent Thread: Id: 0x%X Entry: 0x%X StackSize: 0x%X StackMem: 0x%X ", 375 ctx->thread_id, ctx->thread_entry_address, ctx->thread_stack_size, ctx->thread_stack_mem); 376 #endif //TARGET_CORTEX_M 377 378 #if MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO && defined(MBED_CONF_RTOS_PRESENT) 379 mbed_error_printf("\nNext:"); 380 print_thread(osRtxInfo.thread.run.next); 381 382 mbed_error_printf("\nWait:"); 383 osRtxThread_t *threads = (osRtxThread_t *)&osRtxInfo.thread.wait_list; 384 print_threads_info(threads); 385 386 mbed_error_printf("\nDelay:"); 387 threads = (osRtxThread_t *)&osRtxInfo.thread.delay_list; 388 print_threads_info(threads); 389 390 mbed_error_printf("\nIdle:"); 391 threads = (osRtxThread_t *)&osRtxInfo.thread.idle; 392 print_threads_info(threads); 393 #endif 394 mbed_error_printf(MBED_CONF_PLATFORM_ERROR_DECODE_HTTP_URL_STR, ctx->error_status); 395 mbed_error_printf("\n-- MbedOS Error Info --\n"); 396 } 397 #endif //ifndef NDEBUG 398 399 #if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED 400 //Retrieve the error context from error log at the specified index 401 mbed_error_status_t mbed_get_error_hist_info(int index, mbed_error_ctx *error_info) 402 { 403 return mbed_error_hist_get(index, error_info); 404 } 405 406 //Retrieve the error log count 407 int mbed_get_error_hist_count(void) 408 { 409 return mbed_error_hist_get_count(); 410 } 411 412 mbed_error_status_t mbed_save_error_hist(const char *path) 413 { 414 mbed_error_status_t ret = MBED_SUCCESS; 415 mbed_error_ctx ctx = {0}; 416 int log_count = mbed_error_hist_get_count(); 417 FILE *error_log_file = NULL; 418 419 //Ensure path is valid 420 if (path == NULL) { 421 ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_INVALID_ARGUMENT); 422 goto exit; 423 } 424 425 //Open the file for saving the error log info 426 if ((error_log_file = fopen(path, "w")) == NULL) { 427 ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OPEN_FAILED); 428 goto exit; 429 } 430 431 //First store the first and last errors 432 if (fprintf(error_log_file, "\nFirst Error: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x\n", 433 (unsigned int)first_error_ctx.error_status, 434 (unsigned int)first_error_ctx.thread_id, 435 (unsigned int)first_error_ctx.error_address, 436 (unsigned int)first_error_ctx.error_value) <= 0) { 437 ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_WRITE_FAILED); 438 goto exit; 439 } 440 441 if (fprintf(error_log_file, "\nLast Error: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x\n", 442 (unsigned int)last_error_ctx.error_status, 443 (unsigned int)last_error_ctx.thread_id, 444 (unsigned int)last_error_ctx.error_address, 445 (unsigned int)last_error_ctx.error_value) <= 0) { 446 ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_WRITE_FAILED); 447 goto exit; 448 } 449 450 //Update with error log info 451 while (--log_count >= 0) { 452 mbed_error_hist_get(log_count, &ctx); 453 //first line of file will be error log count 454 if (fprintf(error_log_file, "\n%d: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x\n", 455 log_count, 456 (unsigned int)ctx.error_status, 457 (unsigned int)ctx.thread_id, 458 (unsigned int)ctx.error_address, 459 (unsigned int)ctx.error_value) <= 0) { 460 ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_WRITE_FAILED); 461 goto exit; 462 } 463 } 464 465 exit: 466 fclose(error_log_file); 467 468 return ret; 469 } 470 #endif 471
Note:
See TracChangeset
for help on using the changeset viewer.