mirror of https://github.com/ARMmbed/mbed-os.git
commit
29e9619002
|
@ -56,30 +56,35 @@ void mbed_error_printf(const char *format, ...)
|
||||||
|
|
||||||
void mbed_error_vprintf(const char *format, va_list arg)
|
void mbed_error_vprintf(const char *format, va_list arg)
|
||||||
{
|
{
|
||||||
core_util_critical_section_enter();
|
|
||||||
char buffer[132];
|
char buffer[132];
|
||||||
int size = vsnprintf(buffer, sizeof buffer, format, arg);
|
int size = vsnprintf(buffer, sizeof buffer, format, arg);
|
||||||
if (size >= sizeof buffer) {
|
if (size >= sizeof buffer) {
|
||||||
/* Output was truncated - indicate by overwriting last 4 bytes of buffer
|
/* Output was truncated - indicate by overwriting tail of buffer
|
||||||
* with ellipsis and newline.
|
* with ellipsis, newline and null terminator.
|
||||||
* (Note that although vsnprintf always leaves a NUL terminator, we
|
|
||||||
* don't need a terminator and can use the entire buffer)
|
|
||||||
*/
|
*/
|
||||||
memcpy(&buffer[sizeof buffer - 4], "...\n", 4);
|
static const char ellipsis[] = "...\n";
|
||||||
size = sizeof buffer;
|
memcpy(&buffer[sizeof buffer - sizeof ellipsis], ellipsis, sizeof ellipsis);
|
||||||
}
|
}
|
||||||
|
if (size > 0) {
|
||||||
|
mbed_error_puts(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mbed_error_puts(const char *str)
|
||||||
|
{
|
||||||
|
core_util_critical_section_enter();
|
||||||
#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES || MBED_CONF_PLATFORM_STDIO_CONVERT_TTY_NEWLINES
|
#if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES || MBED_CONF_PLATFORM_STDIO_CONVERT_TTY_NEWLINES
|
||||||
char stdio_out_prev = '\0';
|
char stdio_out_prev = '\0';
|
||||||
for (int i = 0; i < size; i++) {
|
for (; *str != '\0'; str++) {
|
||||||
if (buffer[i] == '\n' && stdio_out_prev != '\r') {
|
if (*str == '\n' && stdio_out_prev != '\r') {
|
||||||
const char cr = '\r';
|
const char cr = '\r';
|
||||||
write(STDERR_FILENO, &cr, 1);
|
write(STDERR_FILENO, &cr, 1);
|
||||||
}
|
}
|
||||||
write(STDERR_FILENO, &buffer[i], 1);
|
write(STDERR_FILENO, str, 1);
|
||||||
stdio_out_prev = buffer[i];
|
stdio_out_prev = *str;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
write(STDERR_FILENO, buffer, size);
|
write(STDERR_FILENO, str, strlen(str));
|
||||||
#endif
|
#endif
|
||||||
core_util_critical_section_exit();
|
core_util_critical_section_exit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,26 +29,11 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//Helper macro to get the current SP
|
|
||||||
#define GET_CURRENT_SP(sp) \
|
|
||||||
{ \
|
|
||||||
/*If in Handler mode we are always using MSP*/ \
|
|
||||||
if ( __get_IPSR() != 0U ) { \
|
|
||||||
sp = __get_MSP(); \
|
|
||||||
} else { \
|
|
||||||
/*Look into CONTROL.SPSEL value*/ \
|
|
||||||
if ((__get_CONTROL() & 2U) == 0U) { \
|
|
||||||
sp = __get_MSP();/*Read MSP*/ \
|
|
||||||
} else { \
|
|
||||||
sp = __get_PSP();/*Read PSP*/ \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
#define ERROR_REPORT(ctx, error_msg) print_error_report(ctx, error_msg)
|
#define ERROR_REPORT(ctx, error_msg, error_filename, error_line) print_error_report(ctx, error_msg, error_filename, error_line)
|
||||||
|
static void print_error_report(const mbed_error_ctx *ctx, const char *, const char *error_filename, int error_line);
|
||||||
#else
|
#else
|
||||||
#define ERROR_REPORT(ctx, error_msg) ((void) 0)
|
#define ERROR_REPORT(ctx, error_msg, error_filename, error_line) ((void) 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static uint8_t error_in_progress = 0;
|
static uint8_t error_in_progress = 0;
|
||||||
|
@ -56,7 +41,6 @@ static int error_count = 0;
|
||||||
static mbed_error_ctx first_error_ctx = {0};
|
static mbed_error_ctx first_error_ctx = {0};
|
||||||
static mbed_error_ctx last_error_ctx = {0};
|
static mbed_error_ctx last_error_ctx = {0};
|
||||||
static mbed_error_hook_t error_hook = NULL;
|
static mbed_error_hook_t error_hook = NULL;
|
||||||
static void print_error_report(mbed_error_ctx *ctx, const char *);
|
|
||||||
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);
|
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);
|
||||||
|
|
||||||
//Helper function to halt the system
|
//Helper function to halt the system
|
||||||
|
@ -83,7 +67,7 @@ WEAK void error(const char *format, ...)
|
||||||
|
|
||||||
//Call handle_error/print_error_report permanently setting error_in_progress flag
|
//Call handle_error/print_error_report permanently setting error_in_progress flag
|
||||||
handle_error(MBED_ERROR_UNKNOWN, 0, NULL, 0, MBED_CALLER_ADDR());
|
handle_error(MBED_ERROR_UNKNOWN, 0, NULL, 0, MBED_CALLER_ADDR());
|
||||||
ERROR_REPORT(&last_error_ctx, "Fatal Run-time error");
|
ERROR_REPORT(&last_error_ctx, "Fatal Run-time error", NULL, 0);
|
||||||
error_in_progress = 1;
|
error_in_progress = 1;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
@ -132,16 +116,12 @@ static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsign
|
||||||
current_error_ctx.thread_entry_address = (uint32_t)current_thread->thread_addr;
|
current_error_ctx.thread_entry_address = (uint32_t)current_thread->thread_addr;
|
||||||
current_error_ctx.thread_stack_size = current_thread->stack_size;
|
current_error_ctx.thread_stack_size = current_thread->stack_size;
|
||||||
current_error_ctx.thread_stack_mem = (uint32_t)current_thread->stack_mem;
|
current_error_ctx.thread_stack_mem = (uint32_t)current_thread->stack_mem;
|
||||||
#ifdef TARGET_CORTEX_M
|
current_error_ctx.thread_current_sp = (uint32_t)¤t_error_ctx; // Address local variable to get a stack pointer
|
||||||
GET_CURRENT_SP(current_error_ctx.thread_current_sp);
|
|
||||||
#endif //TARGET_CORTEX_M
|
|
||||||
|
|
||||||
#endif //MBED_CONF_RTOS_PRESENT
|
#endif //MBED_CONF_RTOS_PRESENT
|
||||||
|
|
||||||
#if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED
|
#if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED
|
||||||
//Capture filename/linenumber if provided
|
//Capture filename/linenumber if provided
|
||||||
//Index for tracking error_filename
|
//Index for tracking error_filename
|
||||||
memset(¤t_error_ctx.error_filename, 0, MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN);
|
|
||||||
strncpy(current_error_ctx.error_filename, filename, MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN);
|
strncpy(current_error_ctx.error_filename, filename, MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN);
|
||||||
current_error_ctx.error_line_number = line_number;
|
current_error_ctx.error_line_number = line_number;
|
||||||
#endif
|
#endif
|
||||||
|
@ -205,7 +185,7 @@ WEAK mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char
|
||||||
}
|
}
|
||||||
|
|
||||||
//On fatal errors print the error context/report
|
//On fatal errors print the error context/report
|
||||||
ERROR_REPORT(&last_error_ctx, error_msg);
|
ERROR_REPORT(&last_error_ctx, error_msg, filename, line_number);
|
||||||
mbed_halt_system();
|
mbed_halt_system();
|
||||||
|
|
||||||
return MBED_ERROR_FAILED_OPERATION;
|
return MBED_ERROR_FAILED_OPERATION;
|
||||||
|
@ -290,15 +270,20 @@ mbed_error_status_t mbed_clear_all_errors(void)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *name_or_unnamed(const char *name)
|
||||||
|
{
|
||||||
|
return name ? name : "<unnamed>";
|
||||||
|
}
|
||||||
|
|
||||||
#if MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO && defined(MBED_CONF_RTOS_PRESENT)
|
#if MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO && defined(MBED_CONF_RTOS_PRESENT)
|
||||||
/* Prints info of a thread(using osRtxThread_t struct)*/
|
/* Prints info of a thread(using osRtxThread_t struct)*/
|
||||||
static void print_thread(osRtxThread_t *thread)
|
static void print_thread(const osRtxThread_t *thread)
|
||||||
{
|
{
|
||||||
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);
|
mbed_error_printf("\n%s State: 0x%X Entry: 0x%08X Stack Size: 0x%08X Mem: 0x%08X SP: 0x%08X", name_or_unnamed(thread->name), thread->state, thread->thread_addr, thread->stack_size, (uint32_t)thread->stack_mem, thread->sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prints thread info from a list */
|
/* Prints thread info from a list */
|
||||||
static void print_threads_info(osRtxThread_t *threads)
|
static void print_threads_info(const osRtxThread_t *threads)
|
||||||
{
|
{
|
||||||
while (threads != NULL) {
|
while (threads != NULL) {
|
||||||
print_thread(threads);
|
print_thread(threads);
|
||||||
|
@ -308,7 +293,7 @@ static void print_threads_info(osRtxThread_t *threads)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
static void print_error_report(mbed_error_ctx *ctx, const char *error_msg)
|
static void print_error_report(const mbed_error_ctx *ctx, const char *error_msg, const char *error_filename, int error_line)
|
||||||
{
|
{
|
||||||
uint32_t error_code = MBED_GET_ERROR_CODE(ctx->error_status);
|
uint32_t error_code = MBED_GET_ERROR_CODE(ctx->error_status);
|
||||||
uint32_t error_module = MBED_GET_ERROR_MODULE(ctx->error_status);
|
uint32_t error_module = MBED_GET_ERROR_MODULE(ctx->error_status);
|
||||||
|
@ -357,41 +342,41 @@ static void print_error_report(mbed_error_ctx *ctx, const char *error_msg)
|
||||||
//Nothing to do here, just print the error info down
|
//Nothing to do here, just print the error info down
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mbed_error_printf(error_msg);
|
mbed_error_puts(error_msg);
|
||||||
mbed_error_printf("\nLocation: 0x%X", ctx->error_address);
|
mbed_error_printf("\nLocation: 0x%X", ctx->error_address);
|
||||||
|
|
||||||
#if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED && !defined(NDEBUG)
|
/* We print the filename passed in, not any filename in the context. This
|
||||||
if ((NULL != ctx->error_filename[0]) && (ctx->error_line_number != 0)) {
|
* avoids the console print for mbed_error being limited to the presence
|
||||||
//for string, we must pass address of a ptr which has the address of the string
|
* and length of the filename storage. Note that although the MBED_ERROR
|
||||||
mbed_error_printf("\nFile:%s+%d", ctx->error_filename, ctx->error_line_number);
|
* macro compiles out filenames unless platform.error-filename-capture-enabled
|
||||||
|
* is turned on, MBED_ASSERT always passes filenames, and other direct
|
||||||
|
* users of mbed_error() may also choose to.
|
||||||
|
*/
|
||||||
|
if (error_filename) {
|
||||||
|
mbed_error_puts("\nFile: ");
|
||||||
|
mbed_error_puts(error_filename);
|
||||||
|
mbed_error_printf("+%d", error_line);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
mbed_error_printf("\nError Value: 0x%X", ctx->error_value);
|
mbed_error_printf("\nError Value: 0x%X", ctx->error_value);
|
||||||
#ifdef TARGET_CORTEX_M
|
#ifdef MBED_CONF_RTOS_PRESENT
|
||||||
mbed_error_printf("\nCurrent Thread: Id: 0x%X Entry: 0x%X StackSize: 0x%X StackMem: 0x%X SP: 0x%X ",
|
mbed_error_printf("\nCurrent Thread: %s Id: 0x%X Entry: 0x%X StackSize: 0x%X StackMem: 0x%X SP: 0x%X ",
|
||||||
|
name_or_unnamed(((osRtxThread_t *)ctx->thread_id)->name),
|
||||||
ctx->thread_id, ctx->thread_entry_address, ctx->thread_stack_size, ctx->thread_stack_mem, ctx->thread_current_sp);
|
ctx->thread_id, ctx->thread_entry_address, ctx->thread_stack_size, ctx->thread_stack_mem, ctx->thread_current_sp);
|
||||||
#else
|
#endif
|
||||||
//For Cortex-A targets we dont have support to capture the current SP
|
|
||||||
mbed_error_printf("\nCurrent Thread: Id: 0x%X Entry: 0x%X StackSize: 0x%X StackMem: 0x%X ",
|
|
||||||
ctx->thread_id, ctx->thread_entry_address, ctx->thread_stack_size, ctx->thread_stack_mem);
|
|
||||||
#endif //TARGET_CORTEX_M
|
|
||||||
|
|
||||||
#if MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO && defined(MBED_CONF_RTOS_PRESENT)
|
#if MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO && defined(MBED_CONF_RTOS_PRESENT)
|
||||||
mbed_error_printf("\nNext:");
|
mbed_error_printf("\nNext:");
|
||||||
print_thread(osRtxInfo.thread.run.next);
|
print_thread(osRtxInfo.thread.run.next);
|
||||||
|
|
||||||
|
mbed_error_printf("\nReady:");
|
||||||
|
print_threads_info(osRtxInfo.thread.ready.thread_list);
|
||||||
|
|
||||||
mbed_error_printf("\nWait:");
|
mbed_error_printf("\nWait:");
|
||||||
osRtxThread_t *threads = (osRtxThread_t *)&osRtxInfo.thread.wait_list;
|
print_threads_info(osRtxInfo.thread.wait_list);
|
||||||
print_threads_info(threads);
|
|
||||||
|
|
||||||
mbed_error_printf("\nDelay:");
|
mbed_error_printf("\nDelay:");
|
||||||
threads = (osRtxThread_t *)&osRtxInfo.thread.delay_list;
|
print_threads_info(osRtxInfo.thread.delay_list);
|
||||||
print_threads_info(threads);
|
|
||||||
|
|
||||||
mbed_error_printf("\nIdle:");
|
|
||||||
threads = (osRtxThread_t *)&osRtxInfo.thread.idle;
|
|
||||||
print_threads_info(threads);
|
|
||||||
#endif
|
#endif
|
||||||
mbed_error_printf(MBED_CONF_PLATFORM_ERROR_DECODE_HTTP_URL_STR, ctx->error_status);
|
mbed_error_printf(MBED_CONF_PLATFORM_ERROR_DECODE_HTTP_URL_STR, ctx->error_status);
|
||||||
mbed_error_printf("\n-- MbedOS Error Info --\n");
|
mbed_error_printf("\n-- MbedOS Error Info --\n");
|
||||||
|
|
|
@ -127,6 +127,9 @@ void mbed_die(void);
|
||||||
* handling a crash.
|
* handling a crash.
|
||||||
*
|
*
|
||||||
* @note Synchronization level: Interrupt safe
|
* @note Synchronization level: Interrupt safe
|
||||||
|
* @note This uses an internal 128-byte buffer to format the string,
|
||||||
|
* so the output may be truncated. If you need to write a potentially
|
||||||
|
* long string, use mbed_error_puts.
|
||||||
*
|
*
|
||||||
* @param format C string that contains data stream to be printed.
|
* @param format C string that contains data stream to be printed.
|
||||||
* Code snippets below show valid format.
|
* Code snippets below show valid format.
|
||||||
|
@ -149,6 +152,20 @@ void mbed_error_printf(const char *format, ...);
|
||||||
*/
|
*/
|
||||||
void mbed_error_vprintf(const char *format, va_list arg);
|
void mbed_error_vprintf(const char *format, va_list arg);
|
||||||
|
|
||||||
|
/** Print out an error message. This is typically called when
|
||||||
|
* handling a crash.
|
||||||
|
*
|
||||||
|
* Unlike mbed_error_printf, there is no limit to the maximum output
|
||||||
|
* length. Unlike standard puts, but like standard fputs, this does not
|
||||||
|
* append a '\n' character.
|
||||||
|
*
|
||||||
|
* @note Synchronization level: Interrupt safe
|
||||||
|
*
|
||||||
|
* @param str C string that contains data stream to be printed.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void mbed_error_puts(const char *str);
|
||||||
|
|
||||||
/** @deprecated Renamed to mbed_error_vprintf to match functionality */
|
/** @deprecated Renamed to mbed_error_vprintf to match functionality */
|
||||||
MBED_DEPRECATED_SINCE("mbed-os-5.11",
|
MBED_DEPRECATED_SINCE("mbed-os-5.11",
|
||||||
"Renamed to mbed_error_vprintf to match functionality.")
|
"Renamed to mbed_error_vprintf to match functionality.")
|
||||||
|
|
Loading…
Reference in New Issue