Ignore:
Timestamp:
Apr 5, 2019, 9:26:53 PM (5 years ago)
Author:
coas-nagasima
Message:

mbed関連を更新
シリアルドライバをmbedのHALを使うよう変更
ファイルディスクリプタの処理を更新

File:
1 edited

Legend:

Unmodified
Added
Removed
  • asp3_tinet_ecnl_arm/trunk/asp3_dcre/mbed/platform/mbed_error.c

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