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