Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
platform/mbed_error.c@187:fa51feb62426, 2018-10-09 (annotated)
- Committer:
- pmcorreia
- Date:
- Tue Oct 09 14:42:37 2018 +0000
- Revision:
- 187:fa51feb62426
- Parent:
- 186:707f6e361f3e
Updated version to work with F446RE
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 |
