Modified for BG96
Fork of mbed-dev by
platform/mbed_error.c@186:707f6e361f3e, 2018-06-22 (annotated)
- Committer:
- Anna Bridge
- Date:
- Fri Jun 22 16:45:37 2018 +0100
- Revision:
- 186:707f6e361f3e
- Parent:
- 167:e84263d55307
- Child:
- 187:0387e8f68319
mbed-dev library. Release version 162
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
<> | 149:156823d33999 | 1 | /* mbed Microcontroller Library |
<> | 149:156823d33999 | 2 | * Copyright (c) 2006-2013 ARM Limited |
<> | 149:156823d33999 | 3 | * |
<> | 149:156823d33999 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
<> | 149:156823d33999 | 5 | * you may not use this file except in compliance with the License. |
<> | 149:156823d33999 | 6 | * You may obtain a copy of the License at |
<> | 149:156823d33999 | 7 | * |
<> | 149:156823d33999 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
<> | 149:156823d33999 | 9 | * |
<> | 149:156823d33999 | 10 | * Unless required by applicable law or agreed to in writing, software |
<> | 149:156823d33999 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
<> | 149:156823d33999 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
<> | 149:156823d33999 | 13 | * See the License for the specific language governing permissions and |
<> | 149:156823d33999 | 14 | * limitations under the License. |
<> | 149:156823d33999 | 15 | */ |
<> | 149:156823d33999 | 16 | #include <stdlib.h> |
<> | 149:156823d33999 | 17 | #include <stdarg.h> |
Anna Bridge |
186:707f6e361f3e | 18 | #include <string.h> |
<> | 149:156823d33999 | 19 | #include "device.h" |
Anna Bridge |
186:707f6e361f3e | 20 | #include "platform/mbed_critical.h" |
<> | 149:156823d33999 | 21 | #include "platform/mbed_error.h" |
Anna Bridge |
186:707f6e361f3e | 22 | #include "platform/mbed_error_hist.h" |
<> | 149:156823d33999 | 23 | #include "platform/mbed_interface.h" |
Anna Bridge |
186:707f6e361f3e | 24 | #ifdef MBED_CONF_RTOS_PRESENT |
Anna Bridge |
186:707f6e361f3e | 25 | #include "rtx_os.h" |
Anna Bridge |
186:707f6e361f3e | 26 | #endif |
Anna Bridge |
186:707f6e361f3e | 27 | |
<> | 149:156823d33999 | 28 | #if DEVICE_STDIO_MESSAGES |
<> | 149:156823d33999 | 29 | #include <stdio.h> |
<> | 149:156823d33999 | 30 | #endif |
<> | 149:156823d33999 | 31 | |
Anna Bridge |
186:707f6e361f3e | 32 | //Helper macro to get the current SP |
Anna Bridge |
186:707f6e361f3e | 33 | #define GET_CURRENT_SP(sp) \ |
Anna Bridge |
186:707f6e361f3e | 34 | { \ |
Anna Bridge |
186:707f6e361f3e | 35 | /*If in Handler mode we are always using MSP*/ \ |
Anna Bridge |
186:707f6e361f3e | 36 | if( __get_IPSR() != 0U ) { \ |
Anna Bridge |
186:707f6e361f3e | 37 | sp = __get_MSP(); \ |
Anna Bridge |
186:707f6e361f3e | 38 | } else { \ |
Anna Bridge |
186:707f6e361f3e | 39 | /*Look into CONTROL.SPSEL value*/ \ |
Anna Bridge |
186:707f6e361f3e | 40 | if ((__get_CONTROL() & 2U) == 0U) { \ |
Anna Bridge |
186:707f6e361f3e | 41 | sp = __get_MSP();/*Read MSP*/ \ |
Anna Bridge |
186:707f6e361f3e | 42 | } else { \ |
Anna Bridge |
186:707f6e361f3e | 43 | sp = __get_PSP();/*Read PSP*/ \ |
Anna Bridge |
186:707f6e361f3e | 44 | } \ |
Anna Bridge |
186:707f6e361f3e | 45 | } \ |
Anna Bridge |
186:707f6e361f3e | 46 | } |
Anna Bridge |
186:707f6e361f3e | 47 | |
Anna Bridge |
186:707f6e361f3e | 48 | |
AnnaBridge | 167:e84263d55307 | 49 | static uint8_t error_in_progress = 0; |
Anna Bridge |
186:707f6e361f3e | 50 | static int error_count = 0; |
Anna Bridge |
186:707f6e361f3e | 51 | static mbed_error_ctx first_error_ctx = {0}; |
Anna Bridge |
186:707f6e361f3e | 52 | static mbed_error_ctx last_error_ctx = {0}; |
Anna Bridge |
186:707f6e361f3e | 53 | static mbed_error_hook_t error_hook = NULL; |
Anna Bridge |
186:707f6e361f3e | 54 | static void print_error_report(mbed_error_ctx *ctx, const char *); |
Anna Bridge |
186:707f6e361f3e | 55 | static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsigned int error_value, const char *filename, int line_number); |
Anna Bridge |
186:707f6e361f3e | 56 | |
Anna Bridge |
186:707f6e361f3e | 57 | //Helper function to halt the system |
Anna Bridge |
186:707f6e361f3e | 58 | static void mbed_halt_system(void) |
Anna Bridge |
186:707f6e361f3e | 59 | { |
Anna Bridge |
186:707f6e361f3e | 60 | //If not in ISR context exit, otherwise spin on WFI |
Anna Bridge |
186:707f6e361f3e | 61 | if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) { |
Anna Bridge |
186:707f6e361f3e | 62 | for(;;) { |
Anna Bridge |
186:707f6e361f3e | 63 | __WFI(); |
Anna Bridge |
186:707f6e361f3e | 64 | } |
Anna Bridge |
186:707f6e361f3e | 65 | } else { |
Anna Bridge |
186:707f6e361f3e | 66 | //exit eventually calls mbed_die |
Anna Bridge |
186:707f6e361f3e | 67 | exit(1); |
Anna Bridge |
186:707f6e361f3e | 68 | } |
Anna Bridge |
186:707f6e361f3e | 69 | } |
AnnaBridge | 167:e84263d55307 | 70 | |
<> | 149:156823d33999 | 71 | WEAK void error(const char* format, ...) { |
AnnaBridge | 167:e84263d55307 | 72 | |
AnnaBridge | 167:e84263d55307 | 73 | // Prevent recursion if error is called again |
AnnaBridge | 167:e84263d55307 | 74 | if (error_in_progress) { |
AnnaBridge | 167:e84263d55307 | 75 | return; |
AnnaBridge | 167:e84263d55307 | 76 | } |
Anna Bridge |
186:707f6e361f3e | 77 | |
Anna Bridge |
186:707f6e361f3e | 78 | //Call handle_error/print_error_report permanently setting error_in_progress flag |
Anna Bridge |
186:707f6e361f3e | 79 | handle_error(MBED_ERROR_UNKNOWN, 0, NULL, 0); |
Anna Bridge |
186:707f6e361f3e | 80 | print_error_report(&last_error_ctx, "Fatal Run-time error"); |
AnnaBridge | 167:e84263d55307 | 81 | error_in_progress = 1; |
AnnaBridge | 167:e84263d55307 | 82 | |
<> | 149:156823d33999 | 83 | #ifndef NDEBUG |
<> | 149:156823d33999 | 84 | va_list arg; |
<> | 149:156823d33999 | 85 | va_start(arg, format); |
<> | 149:156823d33999 | 86 | mbed_error_vfprintf(format, arg); |
<> | 149:156823d33999 | 87 | va_end(arg); |
<> | 149:156823d33999 | 88 | #endif |
<> | 149:156823d33999 | 89 | exit(1); |
<> | 149:156823d33999 | 90 | } |
Anna Bridge |
186:707f6e361f3e | 91 | |
Anna Bridge |
186:707f6e361f3e | 92 | //Set an error status with the error handling system |
Anna Bridge |
186:707f6e361f3e | 93 | static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsigned int error_value, const char *filename, int line_number) |
Anna Bridge |
186:707f6e361f3e | 94 | { |
Anna Bridge |
186:707f6e361f3e | 95 | mbed_error_ctx current_error_ctx; |
Anna Bridge |
186:707f6e361f3e | 96 | |
Anna Bridge |
186:707f6e361f3e | 97 | //Error status should always be < 0 |
Anna Bridge |
186:707f6e361f3e | 98 | if(error_status >= 0) { |
Anna Bridge |
186:707f6e361f3e | 99 | //This is a weird situation, someone called mbed_error with invalid error code. |
Anna Bridge |
186:707f6e361f3e | 100 | //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 |
Anna Bridge |
186:707f6e361f3e | 101 | error_status = MBED_ERROR_INVALID_ARGUMENT; |
Anna Bridge |
186:707f6e361f3e | 102 | } |
Anna Bridge |
186:707f6e361f3e | 103 | |
Anna Bridge |
186:707f6e361f3e | 104 | //Prevent corruption by holding out other callers |
Anna Bridge |
186:707f6e361f3e | 105 | //and we also need this until we remove the "error" call completely |
Anna Bridge |
186:707f6e361f3e | 106 | while (error_in_progress == 1); |
Anna Bridge |
186:707f6e361f3e | 107 | |
Anna Bridge |
186:707f6e361f3e | 108 | //Use critsect here, as we don't want inadvertant modification of this global variable |
Anna Bridge |
186:707f6e361f3e | 109 | core_util_critical_section_enter(); |
Anna Bridge |
186:707f6e361f3e | 110 | error_in_progress = 1; |
Anna Bridge |
186:707f6e361f3e | 111 | core_util_critical_section_exit(); |
Anna Bridge |
186:707f6e361f3e | 112 | |
Anna Bridge |
186:707f6e361f3e | 113 | //Increment error count |
Anna Bridge |
186:707f6e361f3e | 114 | error_count++; |
Anna Bridge |
186:707f6e361f3e | 115 | |
Anna Bridge |
186:707f6e361f3e | 116 | //Clear the context capturing buffer |
Anna Bridge |
186:707f6e361f3e | 117 | memset(¤t_error_ctx, sizeof(mbed_error_ctx), 0); |
Anna Bridge |
186:707f6e361f3e | 118 | //Capture error information |
Anna Bridge |
186:707f6e361f3e | 119 | current_error_ctx.error_status = error_status; |
Anna Bridge |
186:707f6e361f3e | 120 | current_error_ctx.error_address = (uint32_t)MBED_CALLER_ADDR(); |
Anna Bridge |
186:707f6e361f3e | 121 | current_error_ctx.error_value = error_value; |
Anna Bridge |
186:707f6e361f3e | 122 | #ifdef MBED_CONF_RTOS_PRESENT |
Anna Bridge |
186:707f6e361f3e | 123 | //Capture thread info |
Anna Bridge |
186:707f6e361f3e | 124 | osRtxThread_t *current_thread = osRtxInfo.thread.run.curr; |
Anna Bridge |
186:707f6e361f3e | 125 | current_error_ctx.thread_id = (uint32_t)current_thread; |
Anna Bridge |
186:707f6e361f3e | 126 | current_error_ctx.thread_entry_address = (uint32_t)current_thread->thread_addr; |
Anna Bridge |
186:707f6e361f3e | 127 | current_error_ctx.thread_stack_size = current_thread->stack_size; |
Anna Bridge |
186:707f6e361f3e | 128 | current_error_ctx.thread_stack_mem = (uint32_t)current_thread->stack_mem; |
Anna Bridge |
186:707f6e361f3e | 129 | #ifdef TARGET_CORTEX_M |
Anna Bridge |
186:707f6e361f3e | 130 | GET_CURRENT_SP(current_error_ctx.thread_current_sp); |
Anna Bridge |
186:707f6e361f3e | 131 | #endif //TARGET_CORTEX_M |
Anna Bridge |
186:707f6e361f3e | 132 | |
Anna Bridge |
186:707f6e361f3e | 133 | #endif //MBED_CONF_RTOS_PRESENT |
Anna Bridge |
186:707f6e361f3e | 134 | |
Anna Bridge |
186:707f6e361f3e | 135 | #ifdef MBED_CONF_ERROR_FILENAME_CAPTURE_ENABLED |
Anna Bridge |
186:707f6e361f3e | 136 | //Capture filename/linenumber if provided |
Anna Bridge |
186:707f6e361f3e | 137 | //Index for tracking error_filename |
Anna Bridge |
186:707f6e361f3e | 138 | memset(¤t_error_ctx.error_filename, 0, MBED_CONF_MAX_ERROR_FILENAME_LEN); |
Anna Bridge |
186:707f6e361f3e | 139 | strncpy(current_error_ctx.error_filename, filename, MBED_CONF_MAX_ERROR_FILENAME_LEN); |
Anna Bridge |
186:707f6e361f3e | 140 | current_error_ctx.error_line_number = line_number; |
Anna Bridge |
186:707f6e361f3e | 141 | #endif |
Anna Bridge |
186:707f6e361f3e | 142 | |
Anna Bridge |
186:707f6e361f3e | 143 | //Capture the fist system error and store it |
Anna Bridge |
186:707f6e361f3e | 144 | if(error_count == 1) { //first error |
Anna Bridge |
186:707f6e361f3e | 145 | memcpy(&first_error_ctx, ¤t_error_ctx, sizeof(mbed_error_ctx)); |
Anna Bridge |
186:707f6e361f3e | 146 | } |
Anna Bridge |
186:707f6e361f3e | 147 | |
Anna Bridge |
186:707f6e361f3e | 148 | //copy this error to last error |
Anna Bridge |
186:707f6e361f3e | 149 | memcpy(&last_error_ctx, ¤t_error_ctx, sizeof(mbed_error_ctx)); |
Anna Bridge |
186:707f6e361f3e | 150 | |
Anna Bridge |
186:707f6e361f3e | 151 | #ifndef MBED_CONF_ERROR_HIST_DISABLED |
Anna Bridge |
186:707f6e361f3e | 152 | //Log the error with error log |
Anna Bridge |
186:707f6e361f3e | 153 | mbed_error_hist_put(¤t_error_ctx); |
Anna Bridge |
186:707f6e361f3e | 154 | #endif |
Anna Bridge |
186:707f6e361f3e | 155 | |
Anna Bridge |
186:707f6e361f3e | 156 | //Call the error hook if available |
Anna Bridge |
186:707f6e361f3e | 157 | if(error_hook != NULL) { |
Anna Bridge |
186:707f6e361f3e | 158 | error_hook(&last_error_ctx); |
Anna Bridge |
186:707f6e361f3e | 159 | } |
Anna Bridge |
186:707f6e361f3e | 160 | |
Anna Bridge |
186:707f6e361f3e | 161 | error_in_progress = 0; |
Anna Bridge |
186:707f6e361f3e | 162 | |
Anna Bridge |
186:707f6e361f3e | 163 | return MBED_SUCCESS; |
Anna Bridge |
186:707f6e361f3e | 164 | } |
Anna Bridge |
186:707f6e361f3e | 165 | |
Anna Bridge |
186:707f6e361f3e | 166 | //Return the first error |
Anna Bridge |
186:707f6e361f3e | 167 | mbed_error_status_t mbed_get_first_error(void) |
Anna Bridge |
186:707f6e361f3e | 168 | { |
Anna Bridge |
186:707f6e361f3e | 169 | //return the first error recorded |
Anna Bridge |
186:707f6e361f3e | 170 | return first_error_ctx.error_status; |
Anna Bridge |
186:707f6e361f3e | 171 | } |
Anna Bridge |
186:707f6e361f3e | 172 | |
Anna Bridge |
186:707f6e361f3e | 173 | //Return the last error |
Anna Bridge |
186:707f6e361f3e | 174 | mbed_error_status_t mbed_get_last_error(void) |
Anna Bridge |
186:707f6e361f3e | 175 | { |
Anna Bridge |
186:707f6e361f3e | 176 | //return the last error recorded |
Anna Bridge |
186:707f6e361f3e | 177 | return last_error_ctx.error_status; |
Anna Bridge |
186:707f6e361f3e | 178 | } |
Anna Bridge |
186:707f6e361f3e | 179 | |
Anna Bridge |
186:707f6e361f3e | 180 | //Gets the current error count |
Anna Bridge |
186:707f6e361f3e | 181 | int mbed_get_error_count(void) |
Anna Bridge |
186:707f6e361f3e | 182 | { |
Anna Bridge |
186:707f6e361f3e | 183 | //return the current error count |
Anna Bridge |
186:707f6e361f3e | 184 | return error_count; |
Anna Bridge |
186:707f6e361f3e | 185 | } |
Anna Bridge |
186:707f6e361f3e | 186 | |
Anna Bridge |
186:707f6e361f3e | 187 | //Sets a fatal error |
Anna Bridge |
186:707f6e361f3e | 188 | 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) |
Anna Bridge |
186:707f6e361f3e | 189 | { |
Anna Bridge |
186:707f6e361f3e | 190 | return handle_error(error_status, error_value, filename, line_number); |
Anna Bridge |
186:707f6e361f3e | 191 | } |
Anna Bridge |
186:707f6e361f3e | 192 | |
Anna Bridge |
186:707f6e361f3e | 193 | //Sets a fatal error |
Anna Bridge |
186:707f6e361f3e | 194 | 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) |
Anna Bridge |
186:707f6e361f3e | 195 | { |
Anna Bridge |
186:707f6e361f3e | 196 | //set the error reported and then halt the system |
Anna Bridge |
186:707f6e361f3e | 197 | if( MBED_SUCCESS != handle_error(error_status, error_value, filename, line_number) ) |
Anna Bridge |
186:707f6e361f3e | 198 | return MBED_ERROR_FAILED_OPERATION; |
Anna Bridge |
186:707f6e361f3e | 199 | |
Anna Bridge |
186:707f6e361f3e | 200 | //On fatal errors print the error context/report |
Anna Bridge |
186:707f6e361f3e | 201 | print_error_report(&last_error_ctx, error_msg); |
Anna Bridge |
186:707f6e361f3e | 202 | mbed_halt_system(); |
Anna Bridge |
186:707f6e361f3e | 203 | |
Anna Bridge |
186:707f6e361f3e | 204 | return MBED_ERROR_FAILED_OPERATION; |
Anna Bridge |
186:707f6e361f3e | 205 | } |
Anna Bridge |
186:707f6e361f3e | 206 | |
Anna Bridge |
186:707f6e361f3e | 207 | //Register an application defined callback with error handling |
Anna Bridge |
186:707f6e361f3e | 208 | mbed_error_status_t mbed_set_error_hook(mbed_error_hook_t error_hook_in) |
Anna Bridge |
186:707f6e361f3e | 209 | { |
Anna Bridge |
186:707f6e361f3e | 210 | //register the new hook/callback |
Anna Bridge |
186:707f6e361f3e | 211 | if( error_hook_in != NULL ) { |
Anna Bridge |
186:707f6e361f3e | 212 | error_hook = error_hook_in; |
Anna Bridge |
186:707f6e361f3e | 213 | return MBED_SUCCESS; |
Anna Bridge |
186:707f6e361f3e | 214 | } |
Anna Bridge |
186:707f6e361f3e | 215 | |
Anna Bridge |
186:707f6e361f3e | 216 | return MBED_ERROR_INVALID_ARGUMENT; |
Anna Bridge |
186:707f6e361f3e | 217 | } |
Anna Bridge |
186:707f6e361f3e | 218 | |
Anna Bridge |
186:707f6e361f3e | 219 | //Retrieve the first error context from error log |
Anna Bridge |
186:707f6e361f3e | 220 | mbed_error_status_t mbed_get_first_error_info (mbed_error_ctx *error_info) |
Anna Bridge |
186:707f6e361f3e | 221 | { |
Anna Bridge |
186:707f6e361f3e | 222 | memcpy(error_info, &first_error_ctx, sizeof(first_error_ctx)); |
Anna Bridge |
186:707f6e361f3e | 223 | return MBED_SUCCESS; |
Anna Bridge |
186:707f6e361f3e | 224 | } |
Anna Bridge |
186:707f6e361f3e | 225 | |
Anna Bridge |
186:707f6e361f3e | 226 | //Retrieve the last error context from error log |
Anna Bridge |
186:707f6e361f3e | 227 | mbed_error_status_t mbed_get_last_error_info (mbed_error_ctx *error_info) |
Anna Bridge |
186:707f6e361f3e | 228 | { |
Anna Bridge |
186:707f6e361f3e | 229 | memcpy(error_info, &last_error_ctx, sizeof(mbed_error_ctx)); |
Anna Bridge |
186:707f6e361f3e | 230 | return MBED_SUCCESS; |
Anna Bridge |
186:707f6e361f3e | 231 | } |
Anna Bridge |
186:707f6e361f3e | 232 | |
Anna Bridge |
186:707f6e361f3e | 233 | //Makes an mbed_error_status_t value |
Anna Bridge |
186:707f6e361f3e | 234 | mbed_error_status_t mbed_make_error(mbed_error_type_t error_type, mbed_module_type_t entity, mbed_error_code_t error_code) |
Anna Bridge |
186:707f6e361f3e | 235 | { |
Anna Bridge |
186:707f6e361f3e | 236 | switch(error_type) |
Anna Bridge |
186:707f6e361f3e | 237 | { |
Anna Bridge |
186:707f6e361f3e | 238 | case MBED_ERROR_TYPE_POSIX: |
Anna Bridge |
186:707f6e361f3e | 239 | if(error_code >= MBED_POSIX_ERROR_BASE && error_code <= MBED_SYSTEM_ERROR_BASE) |
Anna Bridge |
186:707f6e361f3e | 240 | return -error_code; |
Anna Bridge |
186:707f6e361f3e | 241 | break; |
Anna Bridge |
186:707f6e361f3e | 242 | |
Anna Bridge |
186:707f6e361f3e | 243 | case MBED_ERROR_TYPE_SYSTEM: |
Anna Bridge |
186:707f6e361f3e | 244 | if(error_code >= MBED_SYSTEM_ERROR_BASE && error_code <= MBED_CUSTOM_ERROR_BASE) |
Anna Bridge |
186:707f6e361f3e | 245 | return MAKE_MBED_ERROR(MBED_ERROR_TYPE_SYSTEM, entity, error_code); |
Anna Bridge |
186:707f6e361f3e | 246 | break; |
Anna Bridge |
186:707f6e361f3e | 247 | |
Anna Bridge |
186:707f6e361f3e | 248 | case MBED_ERROR_TYPE_CUSTOM: |
Anna Bridge |
186:707f6e361f3e | 249 | if(error_code >= MBED_CUSTOM_ERROR_BASE) |
Anna Bridge |
186:707f6e361f3e | 250 | return MAKE_MBED_ERROR(MBED_ERROR_TYPE_CUSTOM, entity, error_code); |
Anna Bridge |
186:707f6e361f3e | 251 | break; |
Anna Bridge |
186:707f6e361f3e | 252 | |
Anna Bridge |
186:707f6e361f3e | 253 | default: |
Anna Bridge |
186:707f6e361f3e | 254 | break; |
Anna Bridge |
186:707f6e361f3e | 255 | } |
Anna Bridge |
186:707f6e361f3e | 256 | |
Anna Bridge |
186:707f6e361f3e | 257 | //If we are passed incorrect values return a generic system error |
Anna Bridge |
186:707f6e361f3e | 258 | return MAKE_MBED_ERROR(MBED_ERROR_TYPE_SYSTEM, MBED_MODULE_UNKNOWN, MBED_ERROR_CODE_UNKNOWN); |
Anna Bridge |
186:707f6e361f3e | 259 | } |
Anna Bridge |
186:707f6e361f3e | 260 | |
Anna Bridge |
186:707f6e361f3e | 261 | /** |
Anna Bridge |
186:707f6e361f3e | 262 | * Clears all the last error, error count and all entries in the error log. |
Anna Bridge |
186:707f6e361f3e | 263 | * @return 0 or MBED_SUCCESS on success. |
Anna Bridge |
186:707f6e361f3e | 264 | * |
Anna Bridge |
186:707f6e361f3e | 265 | */ |
Anna Bridge |
186:707f6e361f3e | 266 | mbed_error_status_t mbed_clear_all_errors(void) |
Anna Bridge |
186:707f6e361f3e | 267 | { |
Anna Bridge |
186:707f6e361f3e | 268 | mbed_error_status_t status = MBED_SUCCESS; |
Anna Bridge |
186:707f6e361f3e | 269 | |
Anna Bridge |
186:707f6e361f3e | 270 | //Make sure we dont multiple clients resetting |
Anna Bridge |
186:707f6e361f3e | 271 | core_util_critical_section_enter(); |
Anna Bridge |
186:707f6e361f3e | 272 | //Clear the error and context capturing buffer |
Anna Bridge |
186:707f6e361f3e | 273 | memset(&last_error_ctx, sizeof(mbed_error_ctx), 0); |
Anna Bridge |
186:707f6e361f3e | 274 | //reset error count to 0 |
Anna Bridge |
186:707f6e361f3e | 275 | error_count = 0; |
Anna Bridge |
186:707f6e361f3e | 276 | #ifndef MBED_CONF_ERROR_HIST_DISABLED |
Anna Bridge |
186:707f6e361f3e | 277 | status = mbed_error_hist_reset(); |
Anna Bridge |
186:707f6e361f3e | 278 | #endif |
Anna Bridge |
186:707f6e361f3e | 279 | core_util_critical_section_exit(); |
Anna Bridge |
186:707f6e361f3e | 280 | |
Anna Bridge |
186:707f6e361f3e | 281 | return status; |
Anna Bridge |
186:707f6e361f3e | 282 | } |
Anna Bridge |
186:707f6e361f3e | 283 | |
Anna Bridge |
186:707f6e361f3e | 284 | #ifndef MBED_CONF_ERROR_HIST_DISABLED |
Anna Bridge |
186:707f6e361f3e | 285 | //Retrieve the error context from error log at the specified index |
Anna Bridge |
186:707f6e361f3e | 286 | mbed_error_status_t mbed_get_error_hist_info (int index, mbed_error_ctx *error_info) |
Anna Bridge |
186:707f6e361f3e | 287 | { |
Anna Bridge |
186:707f6e361f3e | 288 | return mbed_error_hist_get(index, error_info); |
Anna Bridge |
186:707f6e361f3e | 289 | } |
Anna Bridge |
186:707f6e361f3e | 290 | |
Anna Bridge |
186:707f6e361f3e | 291 | //Retrieve the error log count |
Anna Bridge |
186:707f6e361f3e | 292 | int mbed_get_error_hist_count(void) |
Anna Bridge |
186:707f6e361f3e | 293 | { |
Anna Bridge |
186:707f6e361f3e | 294 | return mbed_error_hist_get_count(); |
Anna Bridge |
186:707f6e361f3e | 295 | } |
Anna Bridge |
186:707f6e361f3e | 296 | |
Anna Bridge |
186:707f6e361f3e | 297 | mbed_error_status_t mbed_save_error_hist(const char *path) |
Anna Bridge |
186:707f6e361f3e | 298 | { |
Anna Bridge |
186:707f6e361f3e | 299 | mbed_error_status_t ret = MBED_SUCCESS; |
Anna Bridge |
186:707f6e361f3e | 300 | mbed_error_ctx ctx = {0}; |
Anna Bridge |
186:707f6e361f3e | 301 | int log_count = mbed_error_hist_get_count(); |
Anna Bridge |
186:707f6e361f3e | 302 | FILE *error_log_file = NULL; |
Anna Bridge |
186:707f6e361f3e | 303 | |
Anna Bridge |
186:707f6e361f3e | 304 | //Ensure path is valid |
Anna Bridge |
186:707f6e361f3e | 305 | if(path==NULL) { |
Anna Bridge |
186:707f6e361f3e | 306 | ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_INVALID_ARGUMENT); |
Anna Bridge |
186:707f6e361f3e | 307 | goto exit; |
Anna Bridge |
186:707f6e361f3e | 308 | } |
Anna Bridge |
186:707f6e361f3e | 309 | |
Anna Bridge |
186:707f6e361f3e | 310 | //Open the file for saving the error log info |
Anna Bridge |
186:707f6e361f3e | 311 | if((error_log_file = fopen( path, "w" ) ) == NULL){ |
Anna Bridge |
186:707f6e361f3e | 312 | ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OPEN_FAILED); |
Anna Bridge |
186:707f6e361f3e | 313 | goto exit; |
Anna Bridge |
186:707f6e361f3e | 314 | } |
Anna Bridge |
186:707f6e361f3e | 315 | |
Anna Bridge |
186:707f6e361f3e | 316 | //First store the first and last errors |
Anna Bridge |
186:707f6e361f3e | 317 | if(fprintf(error_log_file, "\nFirst Error: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x\n", |
Anna Bridge |
186:707f6e361f3e | 318 | (unsigned int)first_error_ctx.error_status, |
Anna Bridge |
186:707f6e361f3e | 319 | (unsigned int)first_error_ctx.thread_id, |
Anna Bridge |
186:707f6e361f3e | 320 | (unsigned int)first_error_ctx.error_address, |
Anna Bridge |
186:707f6e361f3e | 321 | (unsigned int)first_error_ctx.error_value) <= 0) { |
Anna Bridge |
186:707f6e361f3e | 322 | ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_WRITE_FAILED); |
Anna Bridge |
186:707f6e361f3e | 323 | goto exit; |
Anna Bridge |
186:707f6e361f3e | 324 | } |
Anna Bridge |
186:707f6e361f3e | 325 | |
Anna Bridge |
186:707f6e361f3e | 326 | if(fprintf(error_log_file, "\nLast Error: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x\n", |
Anna Bridge |
186:707f6e361f3e | 327 | (unsigned int)last_error_ctx.error_status, |
Anna Bridge |
186:707f6e361f3e | 328 | (unsigned int)last_error_ctx.thread_id, |
Anna Bridge |
186:707f6e361f3e | 329 | (unsigned int)last_error_ctx.error_address, |
Anna Bridge |
186:707f6e361f3e | 330 | (unsigned int)last_error_ctx.error_value) <= 0) { |
Anna Bridge |
186:707f6e361f3e | 331 | ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_WRITE_FAILED); |
Anna Bridge |
186:707f6e361f3e | 332 | goto exit; |
Anna Bridge |
186:707f6e361f3e | 333 | } |
Anna Bridge |
186:707f6e361f3e | 334 | |
Anna Bridge |
186:707f6e361f3e | 335 | //Update with error log info |
Anna Bridge |
186:707f6e361f3e | 336 | while(--log_count >= 0) { |
Anna Bridge |
186:707f6e361f3e | 337 | mbed_error_hist_get(log_count, &ctx); |
Anna Bridge |
186:707f6e361f3e | 338 | //first line of file will be error log count |
Anna Bridge |
186:707f6e361f3e | 339 | if(fprintf(error_log_file, "\n%d: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x\n", |
Anna Bridge |
186:707f6e361f3e | 340 | log_count, |
Anna Bridge |
186:707f6e361f3e | 341 | (unsigned int)ctx.error_status, |
Anna Bridge |
186:707f6e361f3e | 342 | (unsigned int)ctx.thread_id, |
Anna Bridge |
186:707f6e361f3e | 343 | (unsigned int)ctx.error_address, |
Anna Bridge |
186:707f6e361f3e | 344 | (unsigned int)ctx.error_value) <= 0) { |
Anna Bridge |
186:707f6e361f3e | 345 | ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_WRITE_FAILED); |
Anna Bridge |
186:707f6e361f3e | 346 | goto exit; |
Anna Bridge |
186:707f6e361f3e | 347 | } |
Anna Bridge |
186:707f6e361f3e | 348 | } |
Anna Bridge |
186:707f6e361f3e | 349 | |
Anna Bridge |
186:707f6e361f3e | 350 | exit: |
Anna Bridge |
186:707f6e361f3e | 351 | fclose(error_log_file); |
Anna Bridge |
186:707f6e361f3e | 352 | |
Anna Bridge |
186:707f6e361f3e | 353 | return ret; |
Anna Bridge |
186:707f6e361f3e | 354 | } |
Anna Bridge |
186:707f6e361f3e | 355 | |
Anna Bridge |
186:707f6e361f3e | 356 | static void print_error_report(mbed_error_ctx *ctx, const char *error_msg) |
Anna Bridge |
186:707f6e361f3e | 357 | { |
Anna Bridge |
186:707f6e361f3e | 358 | uint32_t error_code = MBED_GET_ERROR_CODE(ctx->error_status); |
Anna Bridge |
186:707f6e361f3e | 359 | uint32_t error_module = MBED_GET_ERROR_MODULE(ctx->error_status); |
Anna Bridge |
186:707f6e361f3e | 360 | |
Anna Bridge |
186:707f6e361f3e | 361 | 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); |
Anna Bridge |
186:707f6e361f3e | 362 | |
Anna Bridge |
186:707f6e361f3e | 363 | //Report error info based on error code, some errors require different |
Anna Bridge |
186:707f6e361f3e | 364 | //error_vals[1] contains the error code |
Anna Bridge |
186:707f6e361f3e | 365 | if(error_code == MBED_ERROR_CODE_HARDFAULT_EXCEPTION || |
Anna Bridge |
186:707f6e361f3e | 366 | error_code == MBED_ERROR_CODE_MEMMANAGE_EXCEPTION || |
Anna Bridge |
186:707f6e361f3e | 367 | error_code == MBED_ERROR_CODE_BUSFAULT_EXCEPTION || |
Anna Bridge |
186:707f6e361f3e | 368 | error_code == MBED_ERROR_CODE_USAGEFAULT_EXCEPTION ) { |
Anna Bridge |
186:707f6e361f3e | 369 | mbed_error_printf(error_msg); |
Anna Bridge |
186:707f6e361f3e | 370 | mbed_error_printf("\nLocation: 0x%x\n", ctx->error_value); |
Anna Bridge |
186:707f6e361f3e | 371 | } else { |
Anna Bridge |
186:707f6e361f3e | 372 | switch (error_code) { |
Anna Bridge |
186:707f6e361f3e | 373 | //These are errors reported by kernel handled from mbed_rtx_handlers |
Anna Bridge |
186:707f6e361f3e | 374 | case MBED_ERROR_CODE_RTOS_EVENT: |
Anna Bridge |
186:707f6e361f3e | 375 | mbed_error_printf("Kernel Error: 0x%x, ", ctx->error_value); |
Anna Bridge |
186:707f6e361f3e | 376 | break; |
Anna Bridge |
186:707f6e361f3e | 377 | |
Anna Bridge |
186:707f6e361f3e | 378 | case MBED_ERROR_CODE_RTOS_THREAD_EVENT: |
Anna Bridge |
186:707f6e361f3e | 379 | mbed_error_printf("Thread: 0x%x, ", ctx->error_value); |
Anna Bridge |
186:707f6e361f3e | 380 | break; |
Anna Bridge |
186:707f6e361f3e | 381 | |
Anna Bridge |
186:707f6e361f3e | 382 | case MBED_ERROR_CODE_RTOS_MUTEX_EVENT: |
Anna Bridge |
186:707f6e361f3e | 383 | mbed_error_printf("Mutex: 0x%x, ", ctx->error_value); |
Anna Bridge |
186:707f6e361f3e | 384 | break; |
Anna Bridge |
186:707f6e361f3e | 385 | |
Anna Bridge |
186:707f6e361f3e | 386 | case MBED_ERROR_CODE_RTOS_SEMAPHORE_EVENT: |
Anna Bridge |
186:707f6e361f3e | 387 | mbed_error_printf("Semaphore: 0x%x, ", ctx->error_value); |
Anna Bridge |
186:707f6e361f3e | 388 | break; |
Anna Bridge |
186:707f6e361f3e | 389 | |
Anna Bridge |
186:707f6e361f3e | 390 | case MBED_ERROR_CODE_RTOS_MEMORY_POOL_EVENT: |
Anna Bridge |
186:707f6e361f3e | 391 | mbed_error_printf("MemoryPool: 0x%x, ", ctx->error_value); |
Anna Bridge |
186:707f6e361f3e | 392 | break; |
Anna Bridge |
186:707f6e361f3e | 393 | |
Anna Bridge |
186:707f6e361f3e | 394 | case MBED_ERROR_CODE_RTOS_EVENT_FLAGS_EVENT: |
Anna Bridge |
186:707f6e361f3e | 395 | mbed_error_printf("EventFlags: 0x%x, ", ctx->error_value); |
Anna Bridge |
186:707f6e361f3e | 396 | break; |
Anna Bridge |
186:707f6e361f3e | 397 | |
Anna Bridge |
186:707f6e361f3e | 398 | case MBED_ERROR_CODE_RTOS_TIMER_EVENT: |
Anna Bridge |
186:707f6e361f3e | 399 | mbed_error_printf("Timer: 0x%x, ", ctx->error_value); |
Anna Bridge |
186:707f6e361f3e | 400 | break; |
Anna Bridge |
186:707f6e361f3e | 401 | |
Anna Bridge |
186:707f6e361f3e | 402 | case MBED_ERROR_CODE_RTOS_MESSAGE_QUEUE_EVENT: |
Anna Bridge |
186:707f6e361f3e | 403 | mbed_error_printf("MessageQueue: 0x%x, ", ctx->error_value); |
Anna Bridge |
186:707f6e361f3e | 404 | break; |
Anna Bridge |
186:707f6e361f3e | 405 | |
Anna Bridge |
186:707f6e361f3e | 406 | default: |
Anna Bridge |
186:707f6e361f3e | 407 | //Nothing to do here, just print the error info down |
Anna Bridge |
186:707f6e361f3e | 408 | break; |
Anna Bridge |
186:707f6e361f3e | 409 | } |
Anna Bridge |
186:707f6e361f3e | 410 | mbed_error_printf(error_msg, NULL); |
Anna Bridge |
186:707f6e361f3e | 411 | mbed_error_printf("\nLocation: 0x%x", ctx->error_address); |
Anna Bridge |
186:707f6e361f3e | 412 | #if defined(MBED_CONF_ERROR_FILENAME_CAPTURE_ENABLED) && !defined(NDEBUG) |
Anna Bridge |
186:707f6e361f3e | 413 | if(NULL != ctx->error_filename) { |
Anna Bridge |
186:707f6e361f3e | 414 | //for string, we must pass address of a ptr which has the address of the string |
Anna Bridge |
186:707f6e361f3e | 415 | mbed_error_printf("\nFile:%s+%d", ctx->error_filename, ctx->error_line_number); |
Anna Bridge |
186:707f6e361f3e | 416 | } |
Anna Bridge |
186:707f6e361f3e | 417 | #endif |
Anna Bridge |
186:707f6e361f3e | 418 | |
Anna Bridge |
186:707f6e361f3e | 419 | #ifdef TARGET_CORTEX_M |
Anna Bridge |
186:707f6e361f3e | 420 | mbed_error_printf("\nError Value: 0x%x\nCurrent Thread: Id: 0x%x Entry: 0x%x StackSize: 0x%x StackMem: 0x%x SP: 0x%x ", |
Anna Bridge |
186:707f6e361f3e | 421 | ctx->error_value, ctx->thread_id, ctx->thread_entry_address, ctx->thread_stack_size, ctx->thread_stack_mem, ctx->thread_current_sp); |
Anna Bridge |
186:707f6e361f3e | 422 | #else |
Anna Bridge |
186:707f6e361f3e | 423 | //For Cortex-A targets we dont have support to capture the current SP |
Anna Bridge |
186:707f6e361f3e | 424 | mbed_error_printf("\nError Value: 0x%x\nCurrent Thread: Id: 0x%x Entry: 0x%x StackSize: 0x%x StackMem: 0x%x ", |
Anna Bridge |
186:707f6e361f3e | 425 | ctx->error_value, ctx->thread_id, ctx->thread_entry_address, ctx->thread_stack_size, ctx->thread_stack_mem); |
Anna Bridge |
186:707f6e361f3e | 426 | #endif //TARGET_CORTEX_M |
Anna Bridge |
186:707f6e361f3e | 427 | } |
Anna Bridge |
186:707f6e361f3e | 428 | |
Anna Bridge |
186:707f6e361f3e | 429 | mbed_error_printf("\n-- MbedOS Error Info --\n"); |
Anna Bridge |
186:707f6e361f3e | 430 | } |
Anna Bridge |
186:707f6e361f3e | 431 | |
Anna Bridge |
186:707f6e361f3e | 432 | |
Anna Bridge |
186:707f6e361f3e | 433 | #endif |
Anna Bridge |
186:707f6e361f3e | 434 |