mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 31 06:02:27 2019 +0000
Revision:
1:9db0e321a9f4
updated based on mbed-os5.15.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 1:9db0e321a9f4 1 /* mbed Microcontroller Library
kenjiArai 1:9db0e321a9f4 2 * Copyright (c) 2006-2019 ARM Limited
kenjiArai 1:9db0e321a9f4 3 * SPDX-License-Identifier: Apache-2.0
kenjiArai 1:9db0e321a9f4 4 *
kenjiArai 1:9db0e321a9f4 5 * Licensed under the Apache License, Version 2.0 (the "License");
kenjiArai 1:9db0e321a9f4 6 * you may not use this file except in compliance with the License.
kenjiArai 1:9db0e321a9f4 7 * You may obtain a copy of the License at
kenjiArai 1:9db0e321a9f4 8 *
kenjiArai 1:9db0e321a9f4 9 * http://www.apache.org/licenses/LICENSE-2.0
kenjiArai 1:9db0e321a9f4 10 *
kenjiArai 1:9db0e321a9f4 11 * Unless required by applicable law or agreed to in writing, software
kenjiArai 1:9db0e321a9f4 12 * distributed under the License is distributed on an "AS IS" BASIS,
kenjiArai 1:9db0e321a9f4 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kenjiArai 1:9db0e321a9f4 14 * See the License for the specific language governing permissions and
kenjiArai 1:9db0e321a9f4 15 * limitations under the License.
kenjiArai 1:9db0e321a9f4 16 */
kenjiArai 1:9db0e321a9f4 17 #include <stdlib.h>
kenjiArai 1:9db0e321a9f4 18 #include <stdarg.h>
kenjiArai 1:9db0e321a9f4 19 #include <string.h>
kenjiArai 1:9db0e321a9f4 20 #include "device.h"
kenjiArai 1:9db0e321a9f4 21 #include "platform/source/mbed_crash_data_offsets.h"
kenjiArai 1:9db0e321a9f4 22 #include "platform/mbed_atomic.h"
kenjiArai 1:9db0e321a9f4 23 #include "platform/mbed_critical.h"
kenjiArai 1:9db0e321a9f4 24 #include "platform/mbed_error.h"
kenjiArai 1:9db0e321a9f4 25 #include "platform/source/mbed_error_hist.h"
kenjiArai 1:9db0e321a9f4 26 #include "platform/mbed_interface.h"
kenjiArai 1:9db0e321a9f4 27 #include "platform/mbed_power_mgmt.h"
kenjiArai 1:9db0e321a9f4 28 #include "platform/mbed_stats.h"
kenjiArai 1:9db0e321a9f4 29 #include "platform/source/TARGET_CORTEX_M/mbed_fault_handler.h"
kenjiArai 1:9db0e321a9f4 30 #include "drivers/MbedCRC.h"
kenjiArai 1:9db0e321a9f4 31 #include "mbed_rtx.h"
kenjiArai 1:9db0e321a9f4 32 #ifdef MBED_CONF_RTOS_PRESENT
kenjiArai 1:9db0e321a9f4 33 #include "rtx_os.h"
kenjiArai 1:9db0e321a9f4 34 #endif
kenjiArai 1:9db0e321a9f4 35
kenjiArai 1:9db0e321a9f4 36 #if DEVICE_STDIO_MESSAGES
kenjiArai 1:9db0e321a9f4 37 #include <stdio.h>
kenjiArai 1:9db0e321a9f4 38 #endif
kenjiArai 1:9db0e321a9f4 39 #ifndef __STDC_FORMAT_MACROS
kenjiArai 1:9db0e321a9f4 40 #define __STDC_FORMAT_MACROS
kenjiArai 1:9db0e321a9f4 41 #endif
kenjiArai 1:9db0e321a9f4 42 #include <inttypes.h>
kenjiArai 1:9db0e321a9f4 43
kenjiArai 1:9db0e321a9f4 44 #ifndef MAX
kenjiArai 1:9db0e321a9f4 45 #define MAX(a, b) ((a) > (b) ? (a) : (b))
kenjiArai 1:9db0e321a9f4 46 #endif
kenjiArai 1:9db0e321a9f4 47
kenjiArai 1:9db0e321a9f4 48 #ifndef NDEBUG
kenjiArai 1:9db0e321a9f4 49 #define ERROR_REPORT(ctx, error_msg, error_filename, error_line) print_error_report(ctx, error_msg, error_filename, error_line)
kenjiArai 1:9db0e321a9f4 50 static void print_error_report(const mbed_error_ctx *ctx, const char *, const char *error_filename, int error_line);
kenjiArai 1:9db0e321a9f4 51 #else
kenjiArai 1:9db0e321a9f4 52 #define ERROR_REPORT(ctx, error_msg, error_filename, error_line) ((void) 0)
kenjiArai 1:9db0e321a9f4 53 #endif
kenjiArai 1:9db0e321a9f4 54
kenjiArai 1:9db0e321a9f4 55 bool mbed_error_in_progress;
kenjiArai 1:9db0e321a9f4 56 static core_util_atomic_flag halt_in_progress = CORE_UTIL_ATOMIC_FLAG_INIT;
kenjiArai 1:9db0e321a9f4 57 static int error_count = 0;
kenjiArai 1:9db0e321a9f4 58 static mbed_error_ctx first_error_ctx = {0};
kenjiArai 1:9db0e321a9f4 59
kenjiArai 1:9db0e321a9f4 60 static mbed_error_ctx last_error_ctx = {0};
kenjiArai 1:9db0e321a9f4 61 static mbed_error_hook_t error_hook = NULL;
kenjiArai 1:9db0e321a9f4 62 static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsigned int error_value, const char *filename, int line_number, void *caller);
kenjiArai 1:9db0e321a9f4 63
kenjiArai 1:9db0e321a9f4 64 #if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
kenjiArai 1:9db0e321a9f4 65 //Global for populating the context in exception handler
kenjiArai 1:9db0e321a9f4 66 static mbed_error_ctx *const report_error_ctx = (mbed_error_ctx *)(ERROR_CONTEXT_LOCATION);
kenjiArai 1:9db0e321a9f4 67 static bool is_reboot_error_valid = false;
kenjiArai 1:9db0e321a9f4 68 #endif
kenjiArai 1:9db0e321a9f4 69
kenjiArai 1:9db0e321a9f4 70 //Helper function to halt the system
kenjiArai 1:9db0e321a9f4 71 static MBED_NORETURN void mbed_halt_system(void)
kenjiArai 1:9db0e321a9f4 72 {
kenjiArai 1:9db0e321a9f4 73 // Prevent recursion if halt is called again during halt attempt - try
kenjiArai 1:9db0e321a9f4 74 // something simple instead.
kenjiArai 1:9db0e321a9f4 75 if (core_util_atomic_flag_test_and_set(&halt_in_progress)) {
kenjiArai 1:9db0e321a9f4 76 core_util_critical_section_enter();
kenjiArai 1:9db0e321a9f4 77 __DSB();
kenjiArai 1:9db0e321a9f4 78 for (;;) {
kenjiArai 1:9db0e321a9f4 79 __WFE(); // Not WFI, as don't want to wake for pending interrupts
kenjiArai 1:9db0e321a9f4 80 }
kenjiArai 1:9db0e321a9f4 81 }
kenjiArai 1:9db0e321a9f4 82
kenjiArai 1:9db0e321a9f4 83 //If in ISR context, call mbed_die directly
kenjiArai 1:9db0e321a9f4 84 if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) {
kenjiArai 1:9db0e321a9f4 85 mbed_die();
kenjiArai 1:9db0e321a9f4 86 }
kenjiArai 1:9db0e321a9f4 87
kenjiArai 1:9db0e321a9f4 88 // In normal context, try orderly exit(1), which eventually calls mbed_die
kenjiArai 1:9db0e321a9f4 89 exit(1);
kenjiArai 1:9db0e321a9f4 90 }
kenjiArai 1:9db0e321a9f4 91
kenjiArai 1:9db0e321a9f4 92 WEAK MBED_NORETURN void error(const char *format, ...)
kenjiArai 1:9db0e321a9f4 93 {
kenjiArai 1:9db0e321a9f4 94 // Prevent recursion if error is called again during store+print attempt
kenjiArai 1:9db0e321a9f4 95 if (!core_util_atomic_exchange_bool(&mbed_error_in_progress, true)) {
kenjiArai 1:9db0e321a9f4 96 handle_error(MBED_ERROR_UNKNOWN, 0, NULL, 0, MBED_CALLER_ADDR());
kenjiArai 1:9db0e321a9f4 97 ERROR_REPORT(&last_error_ctx, "Fatal Run-time error", NULL, 0);
kenjiArai 1:9db0e321a9f4 98
kenjiArai 1:9db0e321a9f4 99 #ifndef NDEBUG
kenjiArai 1:9db0e321a9f4 100 va_list arg;
kenjiArai 1:9db0e321a9f4 101 va_start(arg, format);
kenjiArai 1:9db0e321a9f4 102 mbed_error_vprintf(format, arg);
kenjiArai 1:9db0e321a9f4 103 va_end(arg);
kenjiArai 1:9db0e321a9f4 104 // Add a newline to prevent any line buffering
kenjiArai 1:9db0e321a9f4 105 mbed_error_puts("\n");
kenjiArai 1:9db0e321a9f4 106 #endif
kenjiArai 1:9db0e321a9f4 107 }
kenjiArai 1:9db0e321a9f4 108
kenjiArai 1:9db0e321a9f4 109 mbed_halt_system();
kenjiArai 1:9db0e321a9f4 110 }
kenjiArai 1:9db0e321a9f4 111
kenjiArai 1:9db0e321a9f4 112 static inline bool mbed_error_is_hw_fault(mbed_error_status_t error_status)
kenjiArai 1:9db0e321a9f4 113 {
kenjiArai 1:9db0e321a9f4 114 return (error_status == MBED_ERROR_MEMMANAGE_EXCEPTION ||
kenjiArai 1:9db0e321a9f4 115 error_status == MBED_ERROR_BUSFAULT_EXCEPTION ||
kenjiArai 1:9db0e321a9f4 116 error_status == MBED_ERROR_USAGEFAULT_EXCEPTION ||
kenjiArai 1:9db0e321a9f4 117 error_status == MBED_ERROR_HARDFAULT_EXCEPTION);
kenjiArai 1:9db0e321a9f4 118 }
kenjiArai 1:9db0e321a9f4 119
kenjiArai 1:9db0e321a9f4 120 static bool mbed_error_is_handler(const mbed_error_ctx *ctx)
kenjiArai 1:9db0e321a9f4 121 {
kenjiArai 1:9db0e321a9f4 122 bool is_handler = false;
kenjiArai 1:9db0e321a9f4 123 if (ctx && mbed_error_is_hw_fault(ctx->error_status)) {
kenjiArai 1:9db0e321a9f4 124 mbed_fault_context_t *mfc = (mbed_fault_context_t *)ctx->error_value;
kenjiArai 1:9db0e321a9f4 125 if (mfc && !(mfc->EXC_RETURN & 0x8)) {
kenjiArai 1:9db0e321a9f4 126 is_handler = true;
kenjiArai 1:9db0e321a9f4 127 }
kenjiArai 1:9db0e321a9f4 128 }
kenjiArai 1:9db0e321a9f4 129 return is_handler;
kenjiArai 1:9db0e321a9f4 130 }
kenjiArai 1:9db0e321a9f4 131
kenjiArai 1:9db0e321a9f4 132 //Set an error status with the error handling system
kenjiArai 1:9db0e321a9f4 133 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)
kenjiArai 1:9db0e321a9f4 134 {
kenjiArai 1:9db0e321a9f4 135 mbed_error_ctx current_error_ctx;
kenjiArai 1:9db0e321a9f4 136
kenjiArai 1:9db0e321a9f4 137 //Error status should always be < 0
kenjiArai 1:9db0e321a9f4 138 if (error_status >= 0) {
kenjiArai 1:9db0e321a9f4 139 //This is a weird situation, someone called mbed_error with an invalid error code.
kenjiArai 1:9db0e321a9f4 140 //We will still handle the situation but change the error code to ERROR_INVALID_ARGUMENT, at least the context will have info on who called it
kenjiArai 1:9db0e321a9f4 141 error_status = MBED_ERROR_INVALID_ARGUMENT;
kenjiArai 1:9db0e321a9f4 142 }
kenjiArai 1:9db0e321a9f4 143
kenjiArai 1:9db0e321a9f4 144 //Clear the context capturing buffer
kenjiArai 1:9db0e321a9f4 145 memset(&current_error_ctx, 0, sizeof(mbed_error_ctx));
kenjiArai 1:9db0e321a9f4 146
kenjiArai 1:9db0e321a9f4 147 //Capture error information
kenjiArai 1:9db0e321a9f4 148 current_error_ctx.error_status = error_status;
kenjiArai 1:9db0e321a9f4 149 current_error_ctx.error_value = error_value;
kenjiArai 1:9db0e321a9f4 150 mbed_fault_context_t *mfc = NULL;
kenjiArai 1:9db0e321a9f4 151 if (mbed_error_is_hw_fault(error_status)) {
kenjiArai 1:9db0e321a9f4 152 mfc = (mbed_fault_context_t *)error_value;
kenjiArai 1:9db0e321a9f4 153 current_error_ctx.error_address = (uint32_t)mfc->PC_reg;
kenjiArai 1:9db0e321a9f4 154 // Note that this SP_reg is the correct SP value of the fault. PSP and MSP are slightly different due to HardFault_Handler.
kenjiArai 1:9db0e321a9f4 155 current_error_ctx.thread_current_sp = (uint32_t)mfc->SP_reg;
kenjiArai 1:9db0e321a9f4 156 // Note that the RTX thread itself is the same even under this fault exception handler.
kenjiArai 1:9db0e321a9f4 157 } else {
kenjiArai 1:9db0e321a9f4 158 current_error_ctx.error_address = (uint32_t)caller;
kenjiArai 1:9db0e321a9f4 159 current_error_ctx.thread_current_sp = (uint32_t)&current_error_ctx; // Address local variable to get a stack pointer
kenjiArai 1:9db0e321a9f4 160 }
kenjiArai 1:9db0e321a9f4 161
kenjiArai 1:9db0e321a9f4 162 #ifdef MBED_CONF_RTOS_PRESENT
kenjiArai 1:9db0e321a9f4 163 // Capture thread info in thread mode
kenjiArai 1:9db0e321a9f4 164 osRtxThread_t *current_thread = osRtxInfo.thread.run.curr;
kenjiArai 1:9db0e321a9f4 165 current_error_ctx.thread_id = (uint32_t)current_thread;
kenjiArai 1:9db0e321a9f4 166 current_error_ctx.thread_entry_address = (uint32_t)current_thread->thread_addr;
kenjiArai 1:9db0e321a9f4 167 current_error_ctx.thread_stack_size = current_thread->stack_size;
kenjiArai 1:9db0e321a9f4 168 current_error_ctx.thread_stack_mem = (uint32_t)current_thread->stack_mem;
kenjiArai 1:9db0e321a9f4 169 #endif //MBED_CONF_RTOS_PRESENT
kenjiArai 1:9db0e321a9f4 170
kenjiArai 1:9db0e321a9f4 171 #if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED
kenjiArai 1:9db0e321a9f4 172 //Capture filename/linenumber if provided
kenjiArai 1:9db0e321a9f4 173 //Index for tracking error_filename
kenjiArai 1:9db0e321a9f4 174 strncpy(current_error_ctx.error_filename, filename, MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN);
kenjiArai 1:9db0e321a9f4 175 current_error_ctx.error_line_number = line_number;
kenjiArai 1:9db0e321a9f4 176 #endif
kenjiArai 1:9db0e321a9f4 177
kenjiArai 1:9db0e321a9f4 178 //Prevent corruption by holding out other callers
kenjiArai 1:9db0e321a9f4 179 core_util_critical_section_enter();
kenjiArai 1:9db0e321a9f4 180
kenjiArai 1:9db0e321a9f4 181 //Increment error count
kenjiArai 1:9db0e321a9f4 182 error_count++;
kenjiArai 1:9db0e321a9f4 183
kenjiArai 1:9db0e321a9f4 184 //Capture the first system error and store it
kenjiArai 1:9db0e321a9f4 185 if (error_count == 1) { //first error
kenjiArai 1:9db0e321a9f4 186 memcpy(&first_error_ctx, &current_error_ctx, sizeof(mbed_error_ctx));
kenjiArai 1:9db0e321a9f4 187 }
kenjiArai 1:9db0e321a9f4 188
kenjiArai 1:9db0e321a9f4 189 //copy this error to last error
kenjiArai 1:9db0e321a9f4 190 memcpy(&last_error_ctx, &current_error_ctx, sizeof(mbed_error_ctx));
kenjiArai 1:9db0e321a9f4 191
kenjiArai 1:9db0e321a9f4 192 #if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED
kenjiArai 1:9db0e321a9f4 193 //Log the error with error log
kenjiArai 1:9db0e321a9f4 194 mbed_error_hist_put(&current_error_ctx);
kenjiArai 1:9db0e321a9f4 195 #endif
kenjiArai 1:9db0e321a9f4 196
kenjiArai 1:9db0e321a9f4 197 //Call the error hook if available
kenjiArai 1:9db0e321a9f4 198 if (error_hook != NULL) {
kenjiArai 1:9db0e321a9f4 199 error_hook(&last_error_ctx);
kenjiArai 1:9db0e321a9f4 200 }
kenjiArai 1:9db0e321a9f4 201
kenjiArai 1:9db0e321a9f4 202 core_util_critical_section_exit();
kenjiArai 1:9db0e321a9f4 203
kenjiArai 1:9db0e321a9f4 204 return MBED_SUCCESS;
kenjiArai 1:9db0e321a9f4 205 }
kenjiArai 1:9db0e321a9f4 206
kenjiArai 1:9db0e321a9f4 207 WEAK void mbed_error_reboot_callback(mbed_error_ctx *error_context)
kenjiArai 1:9db0e321a9f4 208 {
kenjiArai 1:9db0e321a9f4 209 //Dont do anything here, let application override this if required.
kenjiArai 1:9db0e321a9f4 210 }
kenjiArai 1:9db0e321a9f4 211
kenjiArai 1:9db0e321a9f4 212 //Initialize Error handling system and report any errors detected on rebooted
kenjiArai 1:9db0e321a9f4 213 mbed_error_status_t mbed_error_initialize(void)
kenjiArai 1:9db0e321a9f4 214 {
kenjiArai 1:9db0e321a9f4 215 #if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
kenjiArai 1:9db0e321a9f4 216 uint32_t crc_val = 0;
kenjiArai 1:9db0e321a9f4 217
kenjiArai 1:9db0e321a9f4 218 //Just check if we have valid value for error_status, if error_status is positive(which is not valid), no need to check crc
kenjiArai 1:9db0e321a9f4 219 if (report_error_ctx->error_status < 0) {
kenjiArai 1:9db0e321a9f4 220 crc_val = mbed_tiny_compute_crc32(report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
kenjiArai 1:9db0e321a9f4 221 //Read report_error_ctx and check if CRC is correct, and with valid status code
kenjiArai 1:9db0e321a9f4 222 if ((report_error_ctx->crc_error_ctx == crc_val) && (report_error_ctx->is_error_processed == 0)) {
kenjiArai 1:9db0e321a9f4 223 is_reboot_error_valid = true;
kenjiArai 1:9db0e321a9f4 224
kenjiArai 1:9db0e321a9f4 225 //Call the mbed_error_reboot_callback, this enables applications to do some handling before we do the handling
kenjiArai 1:9db0e321a9f4 226 mbed_error_reboot_callback(report_error_ctx);
kenjiArai 1:9db0e321a9f4 227
kenjiArai 1:9db0e321a9f4 228 //We let the callback reset the error info, so check if its still valid and do the rest only if its still valid.
kenjiArai 1:9db0e321a9f4 229 if (report_error_ctx->error_reboot_count > 0) {
kenjiArai 1:9db0e321a9f4 230
kenjiArai 1:9db0e321a9f4 231 report_error_ctx->is_error_processed = 1;//Set the flag that we already processed this error
kenjiArai 1:9db0e321a9f4 232 crc_val = mbed_tiny_compute_crc32(report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
kenjiArai 1:9db0e321a9f4 233 report_error_ctx->crc_error_ctx = crc_val;
kenjiArai 1:9db0e321a9f4 234
kenjiArai 1:9db0e321a9f4 235 //Enforce max-reboot only if auto reboot is enabled
kenjiArai 1:9db0e321a9f4 236 #if MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED
kenjiArai 1:9db0e321a9f4 237 if (report_error_ctx->error_reboot_count >= MBED_CONF_PLATFORM_ERROR_REBOOT_MAX) {
kenjiArai 1:9db0e321a9f4 238 mbed_halt_system();
kenjiArai 1:9db0e321a9f4 239 }
kenjiArai 1:9db0e321a9f4 240 #endif
kenjiArai 1:9db0e321a9f4 241 }
kenjiArai 1:9db0e321a9f4 242 }
kenjiArai 1:9db0e321a9f4 243 }
kenjiArai 1:9db0e321a9f4 244 #endif
kenjiArai 1:9db0e321a9f4 245 return MBED_SUCCESS;
kenjiArai 1:9db0e321a9f4 246 }
kenjiArai 1:9db0e321a9f4 247
kenjiArai 1:9db0e321a9f4 248 //Return the first error
kenjiArai 1:9db0e321a9f4 249 mbed_error_status_t mbed_get_first_error(void)
kenjiArai 1:9db0e321a9f4 250 {
kenjiArai 1:9db0e321a9f4 251 //return the first error recorded
kenjiArai 1:9db0e321a9f4 252 return first_error_ctx.error_status;
kenjiArai 1:9db0e321a9f4 253 }
kenjiArai 1:9db0e321a9f4 254
kenjiArai 1:9db0e321a9f4 255 //Return the last error
kenjiArai 1:9db0e321a9f4 256 mbed_error_status_t mbed_get_last_error(void)
kenjiArai 1:9db0e321a9f4 257 {
kenjiArai 1:9db0e321a9f4 258 //return the last error recorded
kenjiArai 1:9db0e321a9f4 259 return last_error_ctx.error_status;
kenjiArai 1:9db0e321a9f4 260 }
kenjiArai 1:9db0e321a9f4 261
kenjiArai 1:9db0e321a9f4 262 //Gets the current error count
kenjiArai 1:9db0e321a9f4 263 int mbed_get_error_count(void)
kenjiArai 1:9db0e321a9f4 264 {
kenjiArai 1:9db0e321a9f4 265 //return the current error count
kenjiArai 1:9db0e321a9f4 266 return error_count;
kenjiArai 1:9db0e321a9f4 267 }
kenjiArai 1:9db0e321a9f4 268
kenjiArai 1:9db0e321a9f4 269 //Reads the fatal error occurred" flag
kenjiArai 1:9db0e321a9f4 270 bool mbed_get_error_in_progress(void)
kenjiArai 1:9db0e321a9f4 271 {
kenjiArai 1:9db0e321a9f4 272 return core_util_atomic_load_bool(&mbed_error_in_progress);
kenjiArai 1:9db0e321a9f4 273 }
kenjiArai 1:9db0e321a9f4 274
kenjiArai 1:9db0e321a9f4 275 //Sets a non-fatal error
kenjiArai 1:9db0e321a9f4 276 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)
kenjiArai 1:9db0e321a9f4 277 {
kenjiArai 1:9db0e321a9f4 278 return handle_error(error_status, error_value, filename, line_number, MBED_CALLER_ADDR());
kenjiArai 1:9db0e321a9f4 279 }
kenjiArai 1:9db0e321a9f4 280
kenjiArai 1:9db0e321a9f4 281 //Sets a fatal error, this function is marked WEAK to be able to override this for some tests
kenjiArai 1:9db0e321a9f4 282 WEAK MBED_NORETURN mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number)
kenjiArai 1:9db0e321a9f4 283 {
kenjiArai 1:9db0e321a9f4 284 // Prevent recursion if error is called again during store+print attempt
kenjiArai 1:9db0e321a9f4 285 if (!core_util_atomic_exchange_bool(&mbed_error_in_progress, true)) {
kenjiArai 1:9db0e321a9f4 286 //set the error reported
kenjiArai 1:9db0e321a9f4 287 (void) handle_error(error_status, error_value, filename, line_number, MBED_CALLER_ADDR());
kenjiArai 1:9db0e321a9f4 288
kenjiArai 1:9db0e321a9f4 289 //On fatal errors print the error context/report
kenjiArai 1:9db0e321a9f4 290 ERROR_REPORT(&last_error_ctx, error_msg, filename, line_number);
kenjiArai 1:9db0e321a9f4 291 }
kenjiArai 1:9db0e321a9f4 292
kenjiArai 1:9db0e321a9f4 293 #if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
kenjiArai 1:9db0e321a9f4 294 uint32_t crc_val = 0;
kenjiArai 1:9db0e321a9f4 295 crc_val = mbed_tiny_compute_crc32(report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
kenjiArai 1:9db0e321a9f4 296 //Read report_error_ctx and check if CRC is correct for report_error_ctx
kenjiArai 1:9db0e321a9f4 297 if (report_error_ctx->crc_error_ctx == crc_val) {
kenjiArai 1:9db0e321a9f4 298 uint32_t current_reboot_count = report_error_ctx->error_reboot_count;
kenjiArai 1:9db0e321a9f4 299 last_error_ctx.error_reboot_count = current_reboot_count + 1;
kenjiArai 1:9db0e321a9f4 300 } else {
kenjiArai 1:9db0e321a9f4 301 last_error_ctx.error_reboot_count = 1;
kenjiArai 1:9db0e321a9f4 302 }
kenjiArai 1:9db0e321a9f4 303 last_error_ctx.is_error_processed = 0;//Set the flag that this is a new error
kenjiArai 1:9db0e321a9f4 304 //Update the struct with crc
kenjiArai 1:9db0e321a9f4 305 last_error_ctx.crc_error_ctx = mbed_tiny_compute_crc32(&last_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
kenjiArai 1:9db0e321a9f4 306 //Protect report_error_ctx while we update it
kenjiArai 1:9db0e321a9f4 307 core_util_critical_section_enter();
kenjiArai 1:9db0e321a9f4 308 memcpy(report_error_ctx, &last_error_ctx, sizeof(mbed_error_ctx));
kenjiArai 1:9db0e321a9f4 309 core_util_critical_section_exit();
kenjiArai 1:9db0e321a9f4 310 //We need not call delete_mbed_crc(crc_obj) here as we are going to reset the system anyway, and calling delete while handling a fatal error may cause nested exception
kenjiArai 1:9db0e321a9f4 311 #if MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED && (MBED_CONF_PLATFORM_ERROR_REBOOT_MAX > 0)
kenjiArai 1:9db0e321a9f4 312 #ifndef NDEBUG
kenjiArai 1:9db0e321a9f4 313 mbed_error_printf("\n= System will be rebooted due to a fatal error =\n");
kenjiArai 1:9db0e321a9f4 314 if (report_error_ctx->error_reboot_count >= MBED_CONF_PLATFORM_ERROR_REBOOT_MAX) {
kenjiArai 1:9db0e321a9f4 315 //We have rebooted more than enough, hold the system here.
kenjiArai 1:9db0e321a9f4 316 mbed_error_printf("= Reboot count(=%" PRIi32") reached maximum, system will halt after rebooting =\n", report_error_ctx->error_reboot_count);
kenjiArai 1:9db0e321a9f4 317 }
kenjiArai 1:9db0e321a9f4 318 #endif
kenjiArai 1:9db0e321a9f4 319 system_reset();//do a system reset to get the system rebooted
kenjiArai 1:9db0e321a9f4 320 #endif
kenjiArai 1:9db0e321a9f4 321 #endif
kenjiArai 1:9db0e321a9f4 322 mbed_halt_system();
kenjiArai 1:9db0e321a9f4 323 }
kenjiArai 1:9db0e321a9f4 324
kenjiArai 1:9db0e321a9f4 325 //Register an application defined callback with error handling
kenjiArai 1:9db0e321a9f4 326 mbed_error_status_t mbed_set_error_hook(mbed_error_hook_t error_hook_in)
kenjiArai 1:9db0e321a9f4 327 {
kenjiArai 1:9db0e321a9f4 328 //register the new hook/callback
kenjiArai 1:9db0e321a9f4 329 if (error_hook_in != NULL) {
kenjiArai 1:9db0e321a9f4 330 error_hook = error_hook_in;
kenjiArai 1:9db0e321a9f4 331 return MBED_SUCCESS;
kenjiArai 1:9db0e321a9f4 332 }
kenjiArai 1:9db0e321a9f4 333
kenjiArai 1:9db0e321a9f4 334 return MBED_ERROR_INVALID_ARGUMENT;
kenjiArai 1:9db0e321a9f4 335 }
kenjiArai 1:9db0e321a9f4 336
kenjiArai 1:9db0e321a9f4 337 //Reset the reboot error context
kenjiArai 1:9db0e321a9f4 338 mbed_error_status_t mbed_reset_reboot_error_info()
kenjiArai 1:9db0e321a9f4 339 {
kenjiArai 1:9db0e321a9f4 340 #if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
kenjiArai 1:9db0e321a9f4 341 //Protect for thread safety
kenjiArai 1:9db0e321a9f4 342 core_util_critical_section_enter();
kenjiArai 1:9db0e321a9f4 343 memset(report_error_ctx, 0, sizeof(mbed_error_ctx));
kenjiArai 1:9db0e321a9f4 344 core_util_critical_section_exit();
kenjiArai 1:9db0e321a9f4 345 #endif
kenjiArai 1:9db0e321a9f4 346 return MBED_SUCCESS;
kenjiArai 1:9db0e321a9f4 347 }
kenjiArai 1:9db0e321a9f4 348
kenjiArai 1:9db0e321a9f4 349 //Reset the reboot error context
kenjiArai 1:9db0e321a9f4 350 mbed_error_status_t mbed_reset_reboot_count()
kenjiArai 1:9db0e321a9f4 351 {
kenjiArai 1:9db0e321a9f4 352 #if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
kenjiArai 1:9db0e321a9f4 353 if (is_reboot_error_valid) {
kenjiArai 1:9db0e321a9f4 354 uint32_t crc_val = 0;
kenjiArai 1:9db0e321a9f4 355 core_util_critical_section_enter();
kenjiArai 1:9db0e321a9f4 356 report_error_ctx->error_reboot_count = 0;//Set reboot count to 0
kenjiArai 1:9db0e321a9f4 357 //Update CRC
kenjiArai 1:9db0e321a9f4 358 crc_val = mbed_tiny_compute_crc32(report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
kenjiArai 1:9db0e321a9f4 359 report_error_ctx->crc_error_ctx = crc_val;
kenjiArai 1:9db0e321a9f4 360 core_util_critical_section_exit();
kenjiArai 1:9db0e321a9f4 361 return MBED_SUCCESS;
kenjiArai 1:9db0e321a9f4 362 }
kenjiArai 1:9db0e321a9f4 363 #endif
kenjiArai 1:9db0e321a9f4 364 return MBED_ERROR_ITEM_NOT_FOUND;
kenjiArai 1:9db0e321a9f4 365 }
kenjiArai 1:9db0e321a9f4 366
kenjiArai 1:9db0e321a9f4 367 //Retrieve the reboot error context
kenjiArai 1:9db0e321a9f4 368 mbed_error_status_t mbed_get_reboot_error_info(mbed_error_ctx *error_info)
kenjiArai 1:9db0e321a9f4 369 {
kenjiArai 1:9db0e321a9f4 370 mbed_error_status_t status = MBED_ERROR_ITEM_NOT_FOUND;
kenjiArai 1:9db0e321a9f4 371 #if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
kenjiArai 1:9db0e321a9f4 372 if (is_reboot_error_valid) {
kenjiArai 1:9db0e321a9f4 373 if (error_info != NULL) {
kenjiArai 1:9db0e321a9f4 374 memcpy(error_info, report_error_ctx, sizeof(mbed_error_ctx));
kenjiArai 1:9db0e321a9f4 375 status = MBED_SUCCESS;
kenjiArai 1:9db0e321a9f4 376 } else {
kenjiArai 1:9db0e321a9f4 377 status = MBED_ERROR_INVALID_ARGUMENT;
kenjiArai 1:9db0e321a9f4 378 }
kenjiArai 1:9db0e321a9f4 379 }
kenjiArai 1:9db0e321a9f4 380 #endif
kenjiArai 1:9db0e321a9f4 381 return status;
kenjiArai 1:9db0e321a9f4 382 }
kenjiArai 1:9db0e321a9f4 383
kenjiArai 1:9db0e321a9f4 384 //Retrieve the first error context from error log
kenjiArai 1:9db0e321a9f4 385 mbed_error_status_t mbed_get_first_error_info(mbed_error_ctx *error_info)
kenjiArai 1:9db0e321a9f4 386 {
kenjiArai 1:9db0e321a9f4 387 memcpy(error_info, &first_error_ctx, sizeof(first_error_ctx));
kenjiArai 1:9db0e321a9f4 388 return MBED_SUCCESS;
kenjiArai 1:9db0e321a9f4 389 }
kenjiArai 1:9db0e321a9f4 390
kenjiArai 1:9db0e321a9f4 391 //Retrieve the last error context from error log
kenjiArai 1:9db0e321a9f4 392 mbed_error_status_t mbed_get_last_error_info(mbed_error_ctx *error_info)
kenjiArai 1:9db0e321a9f4 393 {
kenjiArai 1:9db0e321a9f4 394 memcpy(error_info, &last_error_ctx, sizeof(mbed_error_ctx));
kenjiArai 1:9db0e321a9f4 395 return MBED_SUCCESS;
kenjiArai 1:9db0e321a9f4 396 }
kenjiArai 1:9db0e321a9f4 397
kenjiArai 1:9db0e321a9f4 398 //Makes an mbed_error_status_t value
kenjiArai 1:9db0e321a9f4 399 mbed_error_status_t mbed_make_error(mbed_error_type_t error_type, mbed_module_type_t entity, mbed_error_code_t error_code)
kenjiArai 1:9db0e321a9f4 400 {
kenjiArai 1:9db0e321a9f4 401 switch (error_type) {
kenjiArai 1:9db0e321a9f4 402 case MBED_ERROR_TYPE_POSIX:
kenjiArai 1:9db0e321a9f4 403 if (error_code >= MBED_POSIX_ERROR_BASE && error_code <= MBED_SYSTEM_ERROR_BASE) {
kenjiArai 1:9db0e321a9f4 404 return -error_code;
kenjiArai 1:9db0e321a9f4 405 }
kenjiArai 1:9db0e321a9f4 406 break;
kenjiArai 1:9db0e321a9f4 407
kenjiArai 1:9db0e321a9f4 408 case MBED_ERROR_TYPE_SYSTEM:
kenjiArai 1:9db0e321a9f4 409 if (error_code >= MBED_SYSTEM_ERROR_BASE && error_code <= MBED_CUSTOM_ERROR_BASE) {
kenjiArai 1:9db0e321a9f4 410 return MAKE_MBED_ERROR(MBED_ERROR_TYPE_SYSTEM, entity, error_code);
kenjiArai 1:9db0e321a9f4 411 }
kenjiArai 1:9db0e321a9f4 412 break;
kenjiArai 1:9db0e321a9f4 413
kenjiArai 1:9db0e321a9f4 414 case MBED_ERROR_TYPE_CUSTOM:
kenjiArai 1:9db0e321a9f4 415 if (error_code >= MBED_CUSTOM_ERROR_BASE) {
kenjiArai 1:9db0e321a9f4 416 return MAKE_MBED_ERROR(MBED_ERROR_TYPE_CUSTOM, entity, error_code);
kenjiArai 1:9db0e321a9f4 417 }
kenjiArai 1:9db0e321a9f4 418 break;
kenjiArai 1:9db0e321a9f4 419
kenjiArai 1:9db0e321a9f4 420 default:
kenjiArai 1:9db0e321a9f4 421 break;
kenjiArai 1:9db0e321a9f4 422 }
kenjiArai 1:9db0e321a9f4 423
kenjiArai 1:9db0e321a9f4 424 //If we are passed incorrect values return a generic system error
kenjiArai 1:9db0e321a9f4 425 return MAKE_MBED_ERROR(MBED_ERROR_TYPE_SYSTEM, MBED_MODULE_UNKNOWN, MBED_ERROR_CODE_UNKNOWN);
kenjiArai 1:9db0e321a9f4 426 }
kenjiArai 1:9db0e321a9f4 427
kenjiArai 1:9db0e321a9f4 428 /**
kenjiArai 1:9db0e321a9f4 429 * Clears all the last error, error count and all entries in the error log.
kenjiArai 1:9db0e321a9f4 430 * @return 0 or MBED_SUCCESS on success.
kenjiArai 1:9db0e321a9f4 431 *
kenjiArai 1:9db0e321a9f4 432 */
kenjiArai 1:9db0e321a9f4 433 mbed_error_status_t mbed_clear_all_errors(void)
kenjiArai 1:9db0e321a9f4 434 {
kenjiArai 1:9db0e321a9f4 435 mbed_error_status_t status = MBED_SUCCESS;
kenjiArai 1:9db0e321a9f4 436
kenjiArai 1:9db0e321a9f4 437 //Make sure we dont multiple clients resetting
kenjiArai 1:9db0e321a9f4 438 core_util_critical_section_enter();
kenjiArai 1:9db0e321a9f4 439 //Clear the error and context capturing buffer
kenjiArai 1:9db0e321a9f4 440 memset(&last_error_ctx, 0, sizeof(mbed_error_ctx));
kenjiArai 1:9db0e321a9f4 441 //reset error count to 0
kenjiArai 1:9db0e321a9f4 442 error_count = 0;
kenjiArai 1:9db0e321a9f4 443 #if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED
kenjiArai 1:9db0e321a9f4 444 status = mbed_error_hist_reset();
kenjiArai 1:9db0e321a9f4 445 #endif
kenjiArai 1:9db0e321a9f4 446 core_util_critical_section_exit();
kenjiArai 1:9db0e321a9f4 447
kenjiArai 1:9db0e321a9f4 448 return status;
kenjiArai 1:9db0e321a9f4 449 }
kenjiArai 1:9db0e321a9f4 450
kenjiArai 1:9db0e321a9f4 451 #ifdef MBED_CONF_RTOS_PRESENT
kenjiArai 1:9db0e321a9f4 452 static inline const char *name_or_unnamed(const osRtxThread_t *thread)
kenjiArai 1:9db0e321a9f4 453 {
kenjiArai 1:9db0e321a9f4 454 const char *unnamed = "<unnamed>";
kenjiArai 1:9db0e321a9f4 455
kenjiArai 1:9db0e321a9f4 456 if (!thread) {
kenjiArai 1:9db0e321a9f4 457 return unnamed;
kenjiArai 1:9db0e321a9f4 458 }
kenjiArai 1:9db0e321a9f4 459
kenjiArai 1:9db0e321a9f4 460 const char *name = thread->name;
kenjiArai 1:9db0e321a9f4 461 return name ? name : unnamed;
kenjiArai 1:9db0e321a9f4 462 }
kenjiArai 1:9db0e321a9f4 463 #endif // MBED_CONF_RTOS_PRESENT
kenjiArai 1:9db0e321a9f4 464
kenjiArai 1:9db0e321a9f4 465 #if MBED_STACK_DUMP_ENABLED
kenjiArai 1:9db0e321a9f4 466 /** Prints stack dump from given stack information.
kenjiArai 1:9db0e321a9f4 467 * The arguments should be given in address raw value to check alignment.
kenjiArai 1:9db0e321a9f4 468 * @param stack_start The address of stack start.
kenjiArai 1:9db0e321a9f4 469 * @param stack_size The size of stack
kenjiArai 1:9db0e321a9f4 470 * @param stack_sp The stack pointer currently at. */
kenjiArai 1:9db0e321a9f4 471 static void print_stack_dump_core(uint32_t stack_start, uint32_t stack_size, uint32_t stack_sp, const char *postfix)
kenjiArai 1:9db0e321a9f4 472 {
kenjiArai 1:9db0e321a9f4 473 #if MBED_STACK_DUMP_ENABLED
kenjiArai 1:9db0e321a9f4 474 #define STACK_DUMP_WIDTH 8
kenjiArai 1:9db0e321a9f4 475 #define INT_ALIGN_MASK (~(sizeof(int) - 1))
kenjiArai 1:9db0e321a9f4 476 mbed_error_printf("\nStack Dump: %s", postfix);
kenjiArai 1:9db0e321a9f4 477 uint32_t st_end = (stack_start + stack_size) & INT_ALIGN_MASK;
kenjiArai 1:9db0e321a9f4 478 uint32_t st = (stack_sp) & INT_ALIGN_MASK;
kenjiArai 1:9db0e321a9f4 479 for (; st < st_end; st += sizeof(int) * STACK_DUMP_WIDTH) {
kenjiArai 1:9db0e321a9f4 480 mbed_error_printf("\n0x%08" PRIX32 ":", st);
kenjiArai 1:9db0e321a9f4 481 for (int i = 0; i < STACK_DUMP_WIDTH; i++) {
kenjiArai 1:9db0e321a9f4 482 uint32_t st_cur = st + i * sizeof(int);
kenjiArai 1:9db0e321a9f4 483 if (st_cur >= st_end) {
kenjiArai 1:9db0e321a9f4 484 break;
kenjiArai 1:9db0e321a9f4 485 }
kenjiArai 1:9db0e321a9f4 486 uint32_t st_val = *((uint32_t *)st_cur);
kenjiArai 1:9db0e321a9f4 487 mbed_error_printf("0x%08" PRIX32 " ", st_val);
kenjiArai 1:9db0e321a9f4 488 }
kenjiArai 1:9db0e321a9f4 489 }
kenjiArai 1:9db0e321a9f4 490 mbed_error_printf("\n");
kenjiArai 1:9db0e321a9f4 491 #endif // MBED_STACK_DUMP_ENABLED
kenjiArai 1:9db0e321a9f4 492 }
kenjiArai 1:9db0e321a9f4 493
kenjiArai 1:9db0e321a9f4 494 static void print_stack_dump(uint32_t stack_start, uint32_t stack_size, uint32_t stack_sp, const mbed_error_ctx *ctx)
kenjiArai 1:9db0e321a9f4 495 {
kenjiArai 1:9db0e321a9f4 496 if (ctx && mbed_error_is_handler(ctx)) {
kenjiArai 1:9db0e321a9f4 497 // Stack dump extra for handler stack which may have accessed MSP.
kenjiArai 1:9db0e321a9f4 498 mbed_fault_context_t *mfc = (mbed_fault_context_t *)ctx->error_value;
kenjiArai 1:9db0e321a9f4 499 uint32_t msp_sp = mfc->MSP;
kenjiArai 1:9db0e321a9f4 500 uint32_t psp_sp = mfc->PSP;
kenjiArai 1:9db0e321a9f4 501 if (mfc && !(mfc->EXC_RETURN & 0x4)) {
kenjiArai 1:9db0e321a9f4 502 // MSP mode. Then SP_reg is more correct.
kenjiArai 1:9db0e321a9f4 503 msp_sp = mfc->SP_reg;
kenjiArai 1:9db0e321a9f4 504 } else {
kenjiArai 1:9db0e321a9f4 505 // PSP mode. Then SP_reg is more correct.
kenjiArai 1:9db0e321a9f4 506 psp_sp = mfc->SP_reg;
kenjiArai 1:9db0e321a9f4 507 }
kenjiArai 1:9db0e321a9f4 508 uint32_t msp_size = MAX(0, (int)INITIAL_SP - (int)msp_sp);
kenjiArai 1:9db0e321a9f4 509 print_stack_dump_core(msp_sp, msp_size, msp_sp, "MSP");
kenjiArai 1:9db0e321a9f4 510
kenjiArai 1:9db0e321a9f4 511 stack_sp = psp_sp;
kenjiArai 1:9db0e321a9f4 512 }
kenjiArai 1:9db0e321a9f4 513
kenjiArai 1:9db0e321a9f4 514 print_stack_dump_core(stack_start, stack_size, stack_sp, "PSP");
kenjiArai 1:9db0e321a9f4 515 }
kenjiArai 1:9db0e321a9f4 516 #endif // MBED_STACK_DUMP_ENABLED
kenjiArai 1:9db0e321a9f4 517
kenjiArai 1:9db0e321a9f4 518 #if MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO && defined(MBED_CONF_RTOS_PRESENT)
kenjiArai 1:9db0e321a9f4 519 /* Prints info of a thread(using osRtxThread_t struct)*/
kenjiArai 1:9db0e321a9f4 520 static void print_thread(const osRtxThread_t *thread)
kenjiArai 1:9db0e321a9f4 521 {
kenjiArai 1:9db0e321a9f4 522 uint32_t stack_mem = (uint32_t)thread->stack_mem;
kenjiArai 1:9db0e321a9f4 523 mbed_error_printf("\n%s State: 0x%" PRIX8 " Entry: 0x%08" PRIX32 " Stack Size: 0x%08" PRIX32 " Mem: 0x%08" PRIX32 " SP: 0x%08" PRIX32, name_or_unnamed(thread), thread->state, thread->thread_addr, thread->stack_size, stack_mem, thread->sp);
kenjiArai 1:9db0e321a9f4 524
kenjiArai 1:9db0e321a9f4 525 #if MBED_STACK_DUMP_ENABLED
kenjiArai 1:9db0e321a9f4 526 print_stack_dump(stack_mem, thread->stack_size, thread->sp, NULL);
kenjiArai 1:9db0e321a9f4 527 #endif
kenjiArai 1:9db0e321a9f4 528 }
kenjiArai 1:9db0e321a9f4 529
kenjiArai 1:9db0e321a9f4 530 /* Prints thread info from a list */
kenjiArai 1:9db0e321a9f4 531 static void print_threads_info(const osRtxThread_t *threads)
kenjiArai 1:9db0e321a9f4 532 {
kenjiArai 1:9db0e321a9f4 533 while (threads != NULL) {
kenjiArai 1:9db0e321a9f4 534 print_thread(threads);
kenjiArai 1:9db0e321a9f4 535 threads = threads->thread_next;
kenjiArai 1:9db0e321a9f4 536 }
kenjiArai 1:9db0e321a9f4 537 }
kenjiArai 1:9db0e321a9f4 538 #endif
kenjiArai 1:9db0e321a9f4 539
kenjiArai 1:9db0e321a9f4 540 #ifndef NDEBUG
kenjiArai 1:9db0e321a9f4 541 #define GET_TARGET_NAME_STR(tgt_name) #tgt_name
kenjiArai 1:9db0e321a9f4 542 #define GET_TARGET_NAME(tgt_name) GET_TARGET_NAME_STR(tgt_name)
kenjiArai 1:9db0e321a9f4 543 static void print_error_report(const mbed_error_ctx *ctx, const char *error_msg, const char *error_filename, int error_line)
kenjiArai 1:9db0e321a9f4 544 {
kenjiArai 1:9db0e321a9f4 545 int error_code = MBED_GET_ERROR_CODE(ctx->error_status);
kenjiArai 1:9db0e321a9f4 546 int error_module = MBED_GET_ERROR_MODULE(ctx->error_status);
kenjiArai 1:9db0e321a9f4 547
kenjiArai 1:9db0e321a9f4 548 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);
kenjiArai 1:9db0e321a9f4 549
kenjiArai 1:9db0e321a9f4 550 switch (error_code) {
kenjiArai 1:9db0e321a9f4 551 //These are errors reported by kernel handled from mbed_rtx_handlers
kenjiArai 1:9db0e321a9f4 552 case MBED_ERROR_CODE_RTOS_EVENT:
kenjiArai 1:9db0e321a9f4 553 mbed_error_printf("Kernel Error: 0x%" PRIX32 ", ", ctx->error_value);
kenjiArai 1:9db0e321a9f4 554 break;
kenjiArai 1:9db0e321a9f4 555
kenjiArai 1:9db0e321a9f4 556 case MBED_ERROR_CODE_RTOS_THREAD_EVENT:
kenjiArai 1:9db0e321a9f4 557 mbed_error_printf("Thread: 0x%" PRIX32 ", ", ctx->error_value);
kenjiArai 1:9db0e321a9f4 558 break;
kenjiArai 1:9db0e321a9f4 559
kenjiArai 1:9db0e321a9f4 560 case MBED_ERROR_CODE_RTOS_MUTEX_EVENT:
kenjiArai 1:9db0e321a9f4 561 mbed_error_printf("Mutex: 0x%" PRIX32 ", ", ctx->error_value);
kenjiArai 1:9db0e321a9f4 562 break;
kenjiArai 1:9db0e321a9f4 563
kenjiArai 1:9db0e321a9f4 564 case MBED_ERROR_CODE_RTOS_SEMAPHORE_EVENT:
kenjiArai 1:9db0e321a9f4 565 mbed_error_printf("Semaphore: 0x%" PRIX32 ", ", ctx->error_value);
kenjiArai 1:9db0e321a9f4 566 break;
kenjiArai 1:9db0e321a9f4 567
kenjiArai 1:9db0e321a9f4 568 case MBED_ERROR_CODE_RTOS_MEMORY_POOL_EVENT:
kenjiArai 1:9db0e321a9f4 569 mbed_error_printf("MemoryPool: 0x%" PRIX32 ", ", ctx->error_value);
kenjiArai 1:9db0e321a9f4 570 break;
kenjiArai 1:9db0e321a9f4 571
kenjiArai 1:9db0e321a9f4 572 case MBED_ERROR_CODE_RTOS_EVENT_FLAGS_EVENT:
kenjiArai 1:9db0e321a9f4 573 mbed_error_printf("EventFlags: 0x%" PRIX32 ", ", ctx->error_value);
kenjiArai 1:9db0e321a9f4 574 break;
kenjiArai 1:9db0e321a9f4 575
kenjiArai 1:9db0e321a9f4 576 case MBED_ERROR_CODE_RTOS_TIMER_EVENT:
kenjiArai 1:9db0e321a9f4 577 mbed_error_printf("Timer: 0x%" PRIX32 ", ", ctx->error_value);
kenjiArai 1:9db0e321a9f4 578 break;
kenjiArai 1:9db0e321a9f4 579
kenjiArai 1:9db0e321a9f4 580 case MBED_ERROR_CODE_RTOS_MESSAGE_QUEUE_EVENT:
kenjiArai 1:9db0e321a9f4 581 mbed_error_printf("MessageQueue: 0x%" PRIX32 ", ", ctx->error_value);
kenjiArai 1:9db0e321a9f4 582 break;
kenjiArai 1:9db0e321a9f4 583
kenjiArai 1:9db0e321a9f4 584 case MBED_ERROR_CODE_ASSERTION_FAILED:
kenjiArai 1:9db0e321a9f4 585 mbed_error_printf("Assertion failed: ");
kenjiArai 1:9db0e321a9f4 586 break;
kenjiArai 1:9db0e321a9f4 587
kenjiArai 1:9db0e321a9f4 588 default:
kenjiArai 1:9db0e321a9f4 589 //Nothing to do here, just print the error info down
kenjiArai 1:9db0e321a9f4 590 break;
kenjiArai 1:9db0e321a9f4 591 }
kenjiArai 1:9db0e321a9f4 592 mbed_error_puts(error_msg);
kenjiArai 1:9db0e321a9f4 593 mbed_error_printf("\nLocation: 0x%" PRIX32, ctx->error_address);
kenjiArai 1:9db0e321a9f4 594
kenjiArai 1:9db0e321a9f4 595 /* We print the filename passed in, not any filename in the context. This
kenjiArai 1:9db0e321a9f4 596 * avoids the console print for mbed_error being limited to the presence
kenjiArai 1:9db0e321a9f4 597 * and length of the filename storage. Note that although the MBED_ERROR
kenjiArai 1:9db0e321a9f4 598 * macro compiles out filenames unless platform.error-filename-capture-enabled
kenjiArai 1:9db0e321a9f4 599 * is turned on, MBED_ASSERT always passes filenames, and other direct
kenjiArai 1:9db0e321a9f4 600 * users of mbed_error() may also choose to.
kenjiArai 1:9db0e321a9f4 601 */
kenjiArai 1:9db0e321a9f4 602 if (error_filename) {
kenjiArai 1:9db0e321a9f4 603 mbed_error_puts("\nFile: ");
kenjiArai 1:9db0e321a9f4 604 mbed_error_puts(error_filename);
kenjiArai 1:9db0e321a9f4 605 mbed_error_printf("+%d", error_line);
kenjiArai 1:9db0e321a9f4 606 }
kenjiArai 1:9db0e321a9f4 607
kenjiArai 1:9db0e321a9f4 608 mbed_error_printf("\nError Value: 0x%" PRIX32, ctx->error_value);
kenjiArai 1:9db0e321a9f4 609 #ifdef MBED_CONF_RTOS_PRESENT
kenjiArai 1:9db0e321a9f4 610 bool is_handler = mbed_error_is_handler(ctx);
kenjiArai 1:9db0e321a9f4 611 mbed_error_printf("\nCurrent Thread: %s%s Id: 0x%" PRIX32 " Entry: 0x%" PRIX32 " StackSize: 0x%" PRIX32 " StackMem: 0x%" PRIX32 " SP: 0x%" PRIX32 " ",
kenjiArai 1:9db0e321a9f4 612 name_or_unnamed((osRtxThread_t *)ctx->thread_id), is_handler ? " <handler>" : "",
kenjiArai 1:9db0e321a9f4 613 ctx->thread_id, ctx->thread_entry_address, ctx->thread_stack_size, ctx->thread_stack_mem, ctx->thread_current_sp);
kenjiArai 1:9db0e321a9f4 614 #endif
kenjiArai 1:9db0e321a9f4 615
kenjiArai 1:9db0e321a9f4 616 #if MBED_STACK_DUMP_ENABLED
kenjiArai 1:9db0e321a9f4 617 print_stack_dump(ctx->thread_stack_mem, ctx->thread_stack_size, ctx->thread_current_sp, ctx);
kenjiArai 1:9db0e321a9f4 618 #endif
kenjiArai 1:9db0e321a9f4 619
kenjiArai 1:9db0e321a9f4 620 #if MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO && defined(MBED_CONF_RTOS_PRESENT)
kenjiArai 1:9db0e321a9f4 621 mbed_error_printf("\nNext:");
kenjiArai 1:9db0e321a9f4 622 print_thread(osRtxInfo.thread.run.next);
kenjiArai 1:9db0e321a9f4 623
kenjiArai 1:9db0e321a9f4 624 mbed_error_printf("\nReady:");
kenjiArai 1:9db0e321a9f4 625 print_threads_info(osRtxInfo.thread.ready.thread_list);
kenjiArai 1:9db0e321a9f4 626
kenjiArai 1:9db0e321a9f4 627 mbed_error_printf("\nWait:");
kenjiArai 1:9db0e321a9f4 628 print_threads_info(osRtxInfo.thread.wait_list);
kenjiArai 1:9db0e321a9f4 629
kenjiArai 1:9db0e321a9f4 630 mbed_error_printf("\nDelay:");
kenjiArai 1:9db0e321a9f4 631 print_threads_info(osRtxInfo.thread.delay_list);
kenjiArai 1:9db0e321a9f4 632 #endif
kenjiArai 1:9db0e321a9f4 633 #if !defined(MBED_SYS_STATS_ENABLED)
kenjiArai 1:9db0e321a9f4 634 mbed_error_printf("\nFor more info, visit: https://mbed.com/s/error?error=0x%08X&tgt=" GET_TARGET_NAME(TARGET_NAME), ctx->error_status);
kenjiArai 1:9db0e321a9f4 635 #else
kenjiArai 1:9db0e321a9f4 636 mbed_stats_sys_t sys_stats;
kenjiArai 1:9db0e321a9f4 637 mbed_stats_sys_get(&sys_stats);
kenjiArai 1:9db0e321a9f4 638 mbed_error_printf("\nFor more info, visit: https://mbed.com/s/error?error=0x%08X&osver=%" PRId32 "&core=0x%08" PRIX32 "&comp=%d&ver=%" PRIu32 "&tgt=" GET_TARGET_NAME(TARGET_NAME), ctx->error_status, sys_stats.os_version, sys_stats.cpu_id, sys_stats.compiler_id, sys_stats.compiler_version);
kenjiArai 1:9db0e321a9f4 639 #endif
kenjiArai 1:9db0e321a9f4 640
kenjiArai 1:9db0e321a9f4 641 mbed_error_printf("\n-- MbedOS Error Info --\n");
kenjiArai 1:9db0e321a9f4 642 }
kenjiArai 1:9db0e321a9f4 643 #endif //ifndef NDEBUG
kenjiArai 1:9db0e321a9f4 644
kenjiArai 1:9db0e321a9f4 645
kenjiArai 1:9db0e321a9f4 646 #if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED
kenjiArai 1:9db0e321a9f4 647 //Retrieve the error context from error log at the specified index
kenjiArai 1:9db0e321a9f4 648 mbed_error_status_t mbed_get_error_hist_info(int index, mbed_error_ctx *error_info)
kenjiArai 1:9db0e321a9f4 649 {
kenjiArai 1:9db0e321a9f4 650 return mbed_error_hist_get(index, error_info);
kenjiArai 1:9db0e321a9f4 651 }
kenjiArai 1:9db0e321a9f4 652
kenjiArai 1:9db0e321a9f4 653 //Retrieve the error log count
kenjiArai 1:9db0e321a9f4 654 int mbed_get_error_hist_count(void)
kenjiArai 1:9db0e321a9f4 655 {
kenjiArai 1:9db0e321a9f4 656 return mbed_error_hist_get_count();
kenjiArai 1:9db0e321a9f4 657 }
kenjiArai 1:9db0e321a9f4 658
kenjiArai 1:9db0e321a9f4 659 mbed_error_status_t mbed_save_error_hist(const char *path)
kenjiArai 1:9db0e321a9f4 660 {
kenjiArai 1:9db0e321a9f4 661 mbed_error_status_t ret = MBED_SUCCESS;
kenjiArai 1:9db0e321a9f4 662 mbed_error_ctx ctx = {0};
kenjiArai 1:9db0e321a9f4 663 int log_count = mbed_error_hist_get_count();
kenjiArai 1:9db0e321a9f4 664 FILE *error_log_file = NULL;
kenjiArai 1:9db0e321a9f4 665
kenjiArai 1:9db0e321a9f4 666 //Ensure path is valid
kenjiArai 1:9db0e321a9f4 667 if (path == NULL) {
kenjiArai 1:9db0e321a9f4 668 ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_INVALID_ARGUMENT);
kenjiArai 1:9db0e321a9f4 669 goto exit;
kenjiArai 1:9db0e321a9f4 670 }
kenjiArai 1:9db0e321a9f4 671
kenjiArai 1:9db0e321a9f4 672 //Open the file for saving the error log info
kenjiArai 1:9db0e321a9f4 673 if ((error_log_file = fopen(path, "w")) == NULL) {
kenjiArai 1:9db0e321a9f4 674 ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OPEN_FAILED);
kenjiArai 1:9db0e321a9f4 675 goto exit;
kenjiArai 1:9db0e321a9f4 676 }
kenjiArai 1:9db0e321a9f4 677
kenjiArai 1:9db0e321a9f4 678 //First store the first and last errors
kenjiArai 1:9db0e321a9f4 679 if (fprintf(error_log_file, "\nFirst Error: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x\n",
kenjiArai 1:9db0e321a9f4 680 (unsigned int)first_error_ctx.error_status,
kenjiArai 1:9db0e321a9f4 681 (unsigned int)first_error_ctx.thread_id,
kenjiArai 1:9db0e321a9f4 682 (unsigned int)first_error_ctx.error_address,
kenjiArai 1:9db0e321a9f4 683 (unsigned int)first_error_ctx.error_value) <= 0) {
kenjiArai 1:9db0e321a9f4 684 ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_WRITE_FAILED);
kenjiArai 1:9db0e321a9f4 685 goto exit;
kenjiArai 1:9db0e321a9f4 686 }
kenjiArai 1:9db0e321a9f4 687
kenjiArai 1:9db0e321a9f4 688 if (fprintf(error_log_file, "\nLast Error: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x\n",
kenjiArai 1:9db0e321a9f4 689 (unsigned int)last_error_ctx.error_status,
kenjiArai 1:9db0e321a9f4 690 (unsigned int)last_error_ctx.thread_id,
kenjiArai 1:9db0e321a9f4 691 (unsigned int)last_error_ctx.error_address,
kenjiArai 1:9db0e321a9f4 692 (unsigned int)last_error_ctx.error_value) <= 0) {
kenjiArai 1:9db0e321a9f4 693 ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_WRITE_FAILED);
kenjiArai 1:9db0e321a9f4 694 goto exit;
kenjiArai 1:9db0e321a9f4 695 }
kenjiArai 1:9db0e321a9f4 696
kenjiArai 1:9db0e321a9f4 697 //Update with error log info
kenjiArai 1:9db0e321a9f4 698 while (--log_count >= 0) {
kenjiArai 1:9db0e321a9f4 699 mbed_error_hist_get(log_count, &ctx);
kenjiArai 1:9db0e321a9f4 700 //first line of file will be error log count
kenjiArai 1:9db0e321a9f4 701 if (fprintf(error_log_file, "\n%d: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x\n",
kenjiArai 1:9db0e321a9f4 702 log_count,
kenjiArai 1:9db0e321a9f4 703 (unsigned int)ctx.error_status,
kenjiArai 1:9db0e321a9f4 704 (unsigned int)ctx.thread_id,
kenjiArai 1:9db0e321a9f4 705 (unsigned int)ctx.error_address,
kenjiArai 1:9db0e321a9f4 706 (unsigned int)ctx.error_value) <= 0) {
kenjiArai 1:9db0e321a9f4 707 ret = MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_WRITE_FAILED);
kenjiArai 1:9db0e321a9f4 708 goto exit;
kenjiArai 1:9db0e321a9f4 709 }
kenjiArai 1:9db0e321a9f4 710 }
kenjiArai 1:9db0e321a9f4 711
kenjiArai 1:9db0e321a9f4 712 exit:
kenjiArai 1:9db0e321a9f4 713 fclose(error_log_file);
kenjiArai 1:9db0e321a9f4 714
kenjiArai 1:9db0e321a9f4 715 return ret;
kenjiArai 1:9db0e321a9f4 716 }
kenjiArai 1:9db0e321a9f4 717 #endif