Streamline crash data access

Use correctly-typed external definition for the crash data region, and
eliminate unnecessary pointer indirection.

Results in a small ROM saving even with crash capture disabled, as there
was a pointer for the fault context store in either case. The pointer
isn't needed, as the context store location is fixed according to the
configuration flag.
pull/12824/head
Kevin Bracey 2020-04-17 15:54:30 +03:00
parent 03ce9190f9
commit b6a7a0896e
8 changed files with 115 additions and 67 deletions

View File

@ -36,7 +36,7 @@ static mbed_error_ctx saved_error_ctx = {0};
void mbed_error_reboot_callback(mbed_error_ctx *error_context) void mbed_error_reboot_callback(mbed_error_ctx *error_context)
{ {
TEST_ASSERT_EQUAL_UINT((uint32_t)error_context, ERROR_CONTEXT_LOCATION); TEST_ASSERT_EQUAL_PTR(error_context, &MBED_CRASH_DATA);
memcpy(&saved_error_ctx, error_context, sizeof(mbed_error_ctx)); memcpy(&saved_error_ctx, error_context, sizeof(mbed_error_ctx));
mbed_reset_reboot_error_info(); mbed_reset_reboot_error_info();

View File

@ -18,11 +18,15 @@
#ifndef MBED_FAULT_HANDLER_H #ifndef MBED_FAULT_HANDLER_H
#define MBED_FAULT_HANDLER_H #define MBED_FAULT_HANDLER_H
#include "mbed_toolchain.h"
#include "mbed_error.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
//Fault context struct //Fault context struct
#ifdef TARGET_CORTEX_M
//WARNING: DO NOT CHANGE THIS STRUCT WITHOUT MAKING CORRESPONDING CHANGES in except.S files. //WARNING: DO NOT CHANGE THIS STRUCT WITHOUT MAKING CORRESPONDING CHANGES in except.S files.
//Offset of these registers are used by fault handler in except.S //Offset of these registers are used by fault handler in except.S
typedef struct { typedef struct {
@ -48,13 +52,44 @@ typedef struct {
uint32_t EXC_RETURN; uint32_t EXC_RETURN;
uint32_t CONTROL; uint32_t CONTROL;
} mbed_fault_context_t; } mbed_fault_context_t;
#elif defined TARGET_CORTEX_A
// This is not currently used, but would be a plausible implementation
typedef struct {
uint32_t R0_reg;
uint32_t R1_reg;
uint32_t R2_reg;
uint32_t R3_reg;
uint32_t R4_reg;
uint32_t R5_reg;
uint32_t R6_reg;
uint32_t R7_reg;
uint32_t R8_reg;
uint32_t R9_reg;
uint32_t R10_reg;
uint32_t R11_reg;
uint32_t R12_reg;
uint32_t SP_reg;
uint32_t LR_reg;
uint32_t PC_reg;
uint32_t CPSR;
uint32_t SP_usr;
uint32_t LR_usr;
} mbed_fault_context_t;
#else
// Dummy for mbed_crash_data_t
typedef struct {
} mbed_fault_context_t;
#endif
//Fault type definitions //Fault type definitions
#ifdef TARGET_CORTEX_M
//WARNING: DO NOT CHANGE THESE VALUES WITHOUT MAKING CORRESPONDING CHANGES in except.S files. //WARNING: DO NOT CHANGE THESE VALUES WITHOUT MAKING CORRESPONDING CHANGES in except.S files.
#define HARD_FAULT_EXCEPTION (0x10) //Keep some gap between values for any future insertion/expansion #define HARD_FAULT_EXCEPTION (0x10) //Keep some gap between values for any future insertion/expansion
#define MEMMANAGE_FAULT_EXCEPTION (0x20) #define MEMMANAGE_FAULT_EXCEPTION (0x20)
#define BUS_FAULT_EXCEPTION (0x30) #define BUS_FAULT_EXCEPTION (0x30)
#define USAGE_FAULT_EXCEPTION (0x40) #define USAGE_FAULT_EXCEPTION (0x40)
#endif
//This is a handler function called from Fault handler to print the error information out. //This is a handler function called from Fault handler to print the error information out.
//This runs in fault context and uses special functions(defined in mbed_fault_handler.c) to print the information without using C-lib support. //This runs in fault context and uses special functions(defined in mbed_fault_handler.c) to print the information without using C-lib support.
@ -65,7 +100,7 @@ MBED_NORETURN void mbed_fault_handler(uint32_t fault_type, const mbed_fault_cont
* @param fault_context Pointer to mbed_fault_context_t struct allocated by the caller. This is the mbed_fault_context_t info captured as part of the fatal exception which triggered the reboot. * @param fault_context Pointer to mbed_fault_context_t struct allocated by the caller. This is the mbed_fault_context_t info captured as part of the fatal exception which triggered the reboot.
* @return 0 or MBED_SUCCESS on success. * @return 0 or MBED_SUCCESS on success.
* MBED_ERROR_INVALID_ARGUMENT in case of invalid error_info pointer * MBED_ERROR_INVALID_ARGUMENT in case of invalid error_info pointer
* MBED_ERROR_ITEM_NOT_FOUND if no reboot context is currently captured by teh system * MBED_ERROR_ITEM_NOT_FOUND if no reboot context is currently captured by the system
* *
*/ */
mbed_error_status_t mbed_get_reboot_fault_context(mbed_fault_context_t *fault_context); mbed_error_status_t mbed_get_reboot_fault_context(mbed_fault_context_t *fault_context);

View File

@ -69,6 +69,9 @@ Fault_Handler\
PROC PROC
EXPORT Fault_Handler EXPORT Fault_Handler
#if (DOMAIN_NS == 1) #if (DOMAIN_NS == 1)
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
#define mbed_fault_context |Image$$RW_m_crash_data$$ZI$$Base|
#endif
IMPORT mbed_fault_context IMPORT mbed_fault_context
IMPORT mbed_fault_handler IMPORT mbed_fault_handler
@ -82,7 +85,6 @@ Fault_Handler\
Fault_Handler_Continue Fault_Handler_Continue
LDR R7,=mbed_fault_context LDR R7,=mbed_fault_context
LDR R7,[R7]
LDMIA R6!,{R0-R3} LDMIA R6!,{R0-R3}
STMIA R7!,{R0-R3} ; Capture R0..R3 STMIA R7!,{R0-R3} ; Capture R0..R3
POP {R0-R3} POP {R0-R3}
@ -110,8 +112,7 @@ Fault_Handler_Continue2
MRS R6,CONTROL MRS R6,CONTROL
STMIA R7!,{R0,R1,R5,R6} ; Capture PSP,MSP,EXC_RETURN,CONTROL STMIA R7!,{R0,R1,R5,R6} ; Capture PSP,MSP,EXC_RETURN,CONTROL
MOV R0,R12 MOV R0,R12
MOVS R1,R7 LDR R1,=mbed_fault_context
SUBS R1,#21*4
BL mbed_fault_handler ; mbed_fault_handler does not return BL mbed_fault_handler ; mbed_fault_handler does not return
#else #else
B . B .

View File

@ -104,6 +104,10 @@ UsageFault_Handler:
Fault_Handler: Fault_Handler:
#if (DOMAIN_NS == 1) #if (DOMAIN_NS == 1)
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
#define mbed_fault_context __CRASH_DATA_RAM_START__
#endif
MOV R12,R3 MOV R12,R3
PUSH {R4-R7} PUSH {R4-R7}
ADD R6,SP,#16 ADD R6,SP,#16
@ -114,7 +118,6 @@ Fault_Handler:
Fault_Handler_Continue: Fault_Handler_Continue:
LDR R7,=mbed_fault_context LDR R7,=mbed_fault_context
LDR R7,[R7]
LDMIA R6!,{R0-R3} LDMIA R6!,{R0-R3}
STMIA R7!,{R0-R3} // Capture R0..R3 STMIA R7!,{R0-R3} // Capture R0..R3
POP {R0-R3} POP {R0-R3}
@ -143,8 +146,7 @@ Fault_Handler_Continue2:
MRS R6,CONTROL MRS R6,CONTROL
STMIA R7!,{R0,R1,R5,R6} // Capture PSP,MSP,EXC_RETURN,CONTROL STMIA R7!,{R0,R1,R5,R6} // Capture PSP,MSP,EXC_RETURN,CONTROL
MOV R0,R12 MOV R0,R12
MOV R1,R7 LDR R1,=mbed_fault_context
SUBS R1,R1,#21*4
BL mbed_fault_handler // mbed_fault_handler does not return BL mbed_fault_handler // mbed_fault_handler does not return
#else #else
B . B .

View File

@ -63,6 +63,9 @@ UsageFault_Handler
Fault_Handler Fault_Handler
EXPORT Fault_Handler EXPORT Fault_Handler
#if (DOMAIN_NS == 1) #if (DOMAIN_NS == 1)
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
#define mbed_fault_context __CRASH_DATA_RAM_START__
#endif
IMPORT mbed_fault_context IMPORT mbed_fault_context
IMPORT mbed_fault_handler IMPORT mbed_fault_handler
@ -76,7 +79,6 @@ Fault_Handler
Fault_Handler_Continue Fault_Handler_Continue
LDR R7,=mbed_fault_context LDR R7,=mbed_fault_context
LDR R7,[R7]
LDMIA R6!,{R0-R3} LDMIA R6!,{R0-R3}
STMIA R7!,{R0-R3} ; Capture R0..R3 STMIA R7!,{R0-R3} ; Capture R0..R3
POP {R0-R3} POP {R0-R3}
@ -104,8 +106,7 @@ Fault_Handler_Continue2
MRS R6,CONTROL MRS R6,CONTROL
STMIA R7!,{R0,R1,R5,R6} ; Capture PSP,MSP,EXC_RETURN,CONTROL STMIA R7!,{R0,R1,R5,R6} ; Capture PSP,MSP,EXC_RETURN,CONTROL
MOV R0,R12 MOV R0,R12
MOVS R1,R7 LDR R1,=mbed_fault_context
SUBS R1,#21*4
BL mbed_fault_handler ; mbed_fault_handler does not return BL mbed_fault_handler ; mbed_fault_handler does not return
#else #else
B . B .

View File

@ -34,11 +34,9 @@
void print_context_info(void); void print_context_info(void);
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED #if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
//Global for populating the context in exception handler #define mbed_fault_context MBED_CRASH_DATA.fault.context
mbed_fault_context_t *const mbed_fault_context = (mbed_fault_context_t *)(FAULT_CONTEXT_LOCATION);
#else #else
mbed_fault_context_t fault_context; mbed_fault_context_t mbed_fault_context;
mbed_fault_context_t *const mbed_fault_context = &fault_context;
#endif #endif
extern bool mbed_error_in_progress; extern bool mbed_error_in_progress;
@ -94,7 +92,7 @@ MBED_NOINLINE void print_context_info(void)
{ {
//Context Regs //Context Regs
for (int i = 0; i < 13; i++) { for (int i = 0; i < 13; i++) {
mbed_error_printf("\nR%-4d: %08" PRIX32, i, ((uint32_t *)(mbed_fault_context))[i]); mbed_error_printf("\nR%-4d: %08" PRIX32, i, (&mbed_fault_context.R0_reg)[i]);
} }
mbed_error_printf("\nSP : %08" PRIX32 mbed_error_printf("\nSP : %08" PRIX32
@ -102,8 +100,8 @@ MBED_NOINLINE void print_context_info(void)
"\nPC : %08" PRIX32 "\nPC : %08" PRIX32
"\nxPSR : %08" PRIX32 "\nxPSR : %08" PRIX32
"\nPSP : %08" PRIX32 "\nPSP : %08" PRIX32
"\nMSP : %08" PRIX32, mbed_fault_context->SP_reg, mbed_fault_context->LR_reg, mbed_fault_context->PC_reg, "\nMSP : %08" PRIX32, mbed_fault_context.SP_reg, mbed_fault_context.LR_reg, mbed_fault_context.PC_reg,
mbed_fault_context->xPSR, mbed_fault_context->PSP, mbed_fault_context->MSP); mbed_fault_context.xPSR, mbed_fault_context.PSP, mbed_fault_context.MSP);
//Capture CPUID to get core/cpu info //Capture CPUID to get core/cpu info
mbed_error_printf("\nCPUID: %08" PRIX32, SCB->CPUID); mbed_error_printf("\nCPUID: %08" PRIX32, SCB->CPUID);
@ -129,12 +127,12 @@ MBED_NOINLINE void print_context_info(void)
#endif #endif
//Print Mode //Print Mode
if (mbed_fault_context->EXC_RETURN & 0x8) { if (mbed_fault_context.EXC_RETURN & 0x8) {
mbed_error_printf("\nMode : Thread"); mbed_error_printf("\nMode : Thread");
//Print Priv level in Thread mode - We capture CONTROL reg which reflects the privilege. //Print Priv level in Thread mode - We capture CONTROL reg which reflects the privilege.
//Note that the CONTROL register captured still reflects the privilege status of the //Note that the CONTROL register captured still reflects the privilege status of the
//thread mode eventhough we are in Handler mode by the time we capture it. //thread mode eventhough we are in Handler mode by the time we capture it.
if (mbed_fault_context->CONTROL & 0x1) { if (mbed_fault_context.CONTROL & 0x1) {
mbed_error_printf("\nPriv : User"); mbed_error_printf("\nPriv : User");
} else { } else {
mbed_error_printf("\nPriv : Privileged"); mbed_error_printf("\nPriv : Privileged");
@ -144,7 +142,7 @@ MBED_NOINLINE void print_context_info(void)
mbed_error_printf("\nPriv : Privileged"); mbed_error_printf("\nPriv : Privileged");
} }
//Print Return Stack //Print Return Stack
if (mbed_fault_context->EXC_RETURN & 0x4) { if (mbed_fault_context.EXC_RETURN & 0x4) {
mbed_error_printf("\nStack: PSP"); mbed_error_printf("\nStack: PSP");
} else { } else {
mbed_error_printf("\nStack: MSP"); mbed_error_printf("\nStack: MSP");
@ -158,7 +156,7 @@ mbed_error_status_t mbed_get_reboot_fault_context(mbed_fault_context_t *fault_co
if (fault_context == NULL) { if (fault_context == NULL) {
return MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_INVALID_ARGUMENT); return MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_INVALID_ARGUMENT);
} }
memcpy(fault_context, mbed_fault_context, sizeof(mbed_fault_context_t)); *fault_context = mbed_fault_context;
status = MBED_SUCCESS; status = MBED_SUCCESS;
#endif #endif
return status; return status;

View File

@ -17,6 +17,9 @@
#ifndef MBED_CRASH_DATA_INFO_H #ifndef MBED_CRASH_DATA_INFO_H
#define MBED_CRASH_DATA_INFO_H #define MBED_CRASH_DATA_INFO_H
#include "platform/internal/mbed_fault_handler.h"
#include "platform/mbed_error.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -25,25 +28,28 @@ extern "C" {
/** \ingroup mbed-os-internal */ /** \ingroup mbed-os-internal */
/** \addtogroup platform-internal-api */ /** \addtogroup platform-internal-api */
/** @{*/ /** @{*/
#if defined(__ARMCC_VERSION) // Any changes here must be reflected in except.S if they affect the fault handler.
extern uint32_t Image$$RW_m_crash_data$$ZI$$Base[]; // The fault context is first to keep it simple for the assembler.
extern uint32_t Image$$RW_m_crash_data$$ZI$$Size; typedef struct mbed_crash_data {
#define __CRASH_DATA_RAM_START__ Image$$RW_m_crash_data$$ZI$$Base union {
#elif defined(__ICCARM__) mbed_fault_context_t context;
extern uint32_t __CRASH_DATA_RAM_START__[]; int pad[32];
extern uint32_t __CRASH_DATA_RAM_END__[]; } fault;
#elif defined(__GNUC__) union {
extern uint32_t __CRASH_DATA_RAM_START__[]; mbed_error_ctx context;
extern uint32_t __CRASH_DATA_RAM_END__[]; int pad[32];
#endif /* defined(__CC_ARM) */ } error;
} mbed_crash_data_t;
/* Offset definitions for context capture */ #if defined(__ARMCC_VERSION)
#define FAULT_CONTEXT_OFFSET (0x0) #define MBED_CRASH_DATA Image$$RW_m_crash_data$$ZI$$Base
#define FAULT_CONTEXT_SIZE (0x80 / 4) //32 words(128 bytes) for Fault Context #elif defined(__ICCARM__)
#define ERROR_CONTEXT_OFFSET (FAULT_CONTEXT_OFFSET + FAULT_CONTEXT_SIZE) #define MBED_CRASH_DATA __CRASH_DATA_RAM_START__
#define ERROR_CONTEXT_SIZE (0x80 / 4) //32 words(128 bytes) bytes for Error Context #elif defined(__GNUC__)
#define FAULT_CONTEXT_LOCATION (__CRASH_DATA_RAM_START__ + FAULT_CONTEXT_OFFSET) #define MBED_CRASH_DATA __CRASH_DATA_RAM_START__
#define ERROR_CONTEXT_LOCATION (__CRASH_DATA_RAM_START__ + ERROR_CONTEXT_OFFSET) #endif
extern mbed_crash_data_t MBED_CRASH_DATA;
/**@}*/ /**@}*/
#endif #endif

View File

@ -26,7 +26,7 @@
#include "platform/mbed_interface.h" #include "platform/mbed_interface.h"
#include "platform/mbed_power_mgmt.h" #include "platform/mbed_power_mgmt.h"
#include "platform/mbed_stats.h" #include "platform/mbed_stats.h"
#include "platform/source/TARGET_CORTEX_M/mbed_fault_handler.h" #include "platform/internal/mbed_fault_handler.h"
#include "drivers/MbedCRC.h" #include "drivers/MbedCRC.h"
#include "mbed_rtx.h" #include "mbed_rtx.h"
#ifdef MBED_CONF_RTOS_PRESENT #ifdef MBED_CONF_RTOS_PRESENT
@ -62,8 +62,7 @@ static mbed_error_hook_t error_hook = NULL;
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);
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED #if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
//Global for populating the context in exception handler #define report_error_ctx MBED_CRASH_DATA.error.context
static mbed_error_ctx *const report_error_ctx = (mbed_error_ctx *)(ERROR_CONTEXT_LOCATION);
static bool is_reboot_error_valid = false; static bool is_reboot_error_valid = false;
#endif #endif
@ -122,9 +121,15 @@ static bool mbed_error_is_handler(const mbed_error_ctx *ctx)
bool is_handler = false; bool is_handler = false;
if (ctx && mbed_error_is_hw_fault(ctx->error_status)) { if (ctx && mbed_error_is_hw_fault(ctx->error_status)) {
mbed_fault_context_t *mfc = (mbed_fault_context_t *)ctx->error_value; mbed_fault_context_t *mfc = (mbed_fault_context_t *)ctx->error_value;
#ifdef TARGET_CORTEX_M
if (mfc && !(mfc->EXC_RETURN & 0x8)) { if (mfc && !(mfc->EXC_RETURN & 0x8)) {
is_handler = true; is_handler = true;
} }
#elif defined TARGET_CORTEX_A
if (mfc && (mfc->CPSR & 0x1F) != 0x10) {
is_handler = true;
}
#endif
} }
return is_handler; return is_handler;
} }
@ -183,11 +188,11 @@ static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsign
//Capture the first system error and store it //Capture the first system error and store it
if (error_count == 1) { //first error if (error_count == 1) { //first error
memcpy(&first_error_ctx, &current_error_ctx, sizeof(mbed_error_ctx)); first_error_ctx = current_error_ctx;
} }
//copy this error to last error //copy this error to last error
memcpy(&last_error_ctx, &current_error_ctx, sizeof(mbed_error_ctx)); last_error_ctx = current_error_ctx;
#if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED #if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED
//Log the error with error log //Log the error with error log
@ -223,25 +228,25 @@ mbed_error_status_t mbed_error_initialize(void)
uint32_t crc_val = 0; uint32_t crc_val = 0;
//Just check if we have valid value for error_status, if error_status is positive(which is not valid), no need to check crc //Just check if we have valid value for error_status, if error_status is positive(which is not valid), no need to check crc
if (report_error_ctx->error_status < 0) { if (report_error_ctx.error_status < 0) {
crc_val = mbed_tiny_compute_crc32(report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx)); crc_val = mbed_tiny_compute_crc32(&report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
//Read report_error_ctx and check if CRC is correct, and with valid status code //Read report_error_ctx and check if CRC is correct, and with valid status code
if ((report_error_ctx->crc_error_ctx == crc_val) && (report_error_ctx->is_error_processed == 0)) { if ((report_error_ctx.crc_error_ctx == crc_val) && (report_error_ctx.is_error_processed == 0)) {
is_reboot_error_valid = true; is_reboot_error_valid = true;
//Call the mbed_error_reboot_callback, this enables applications to do some handling before we do the handling //Call the mbed_error_reboot_callback, this enables applications to do some handling before we do the handling
mbed_error_reboot_callback(report_error_ctx); mbed_error_reboot_callback(&report_error_ctx);
//We let the callback reset the error info, so check if its still valid and do the rest only if its still valid. //We let the callback reset the error info, so check if its still valid and do the rest only if its still valid.
if (report_error_ctx->error_reboot_count > 0) { if (report_error_ctx.error_reboot_count > 0) {
report_error_ctx->is_error_processed = 1;//Set the flag that we already processed this error report_error_ctx.is_error_processed = 1;//Set the flag that we already processed this error
crc_val = mbed_tiny_compute_crc32(report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx)); crc_val = mbed_tiny_compute_crc32(&report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
report_error_ctx->crc_error_ctx = crc_val; report_error_ctx.crc_error_ctx = crc_val;
//Enforce max-reboot only if auto reboot is enabled //Enforce max-reboot only if auto reboot is enabled
#if MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED #if MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED
if (report_error_ctx->error_reboot_count >= MBED_CONF_PLATFORM_ERROR_REBOOT_MAX) { if (report_error_ctx.error_reboot_count >= MBED_CONF_PLATFORM_ERROR_REBOOT_MAX) {
mbed_halt_system(); mbed_halt_system();
} }
#endif #endif
@ -299,10 +304,10 @@ WEAK MBED_NORETURN mbed_error_status_t mbed_error(mbed_error_status_t error_stat
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED #if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
uint32_t crc_val = 0; uint32_t crc_val = 0;
crc_val = mbed_tiny_compute_crc32(report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx)); crc_val = mbed_tiny_compute_crc32(&report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
//Read report_error_ctx and check if CRC is correct for report_error_ctx //Read report_error_ctx and check if CRC is correct for report_error_ctx
if (report_error_ctx->crc_error_ctx == crc_val) { if (report_error_ctx.crc_error_ctx == crc_val) {
uint32_t current_reboot_count = report_error_ctx->error_reboot_count; uint32_t current_reboot_count = report_error_ctx.error_reboot_count;
last_error_ctx.error_reboot_count = current_reboot_count + 1; last_error_ctx.error_reboot_count = current_reboot_count + 1;
} else { } else {
last_error_ctx.error_reboot_count = 1; last_error_ctx.error_reboot_count = 1;
@ -312,15 +317,15 @@ WEAK MBED_NORETURN mbed_error_status_t mbed_error(mbed_error_status_t error_stat
last_error_ctx.crc_error_ctx = mbed_tiny_compute_crc32(&last_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx)); last_error_ctx.crc_error_ctx = mbed_tiny_compute_crc32(&last_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
//Protect report_error_ctx while we update it //Protect report_error_ctx while we update it
core_util_critical_section_enter(); core_util_critical_section_enter();
memcpy(report_error_ctx, &last_error_ctx, sizeof(mbed_error_ctx)); report_error_ctx = last_error_ctx;
core_util_critical_section_exit(); core_util_critical_section_exit();
//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 //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
#if MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED && (MBED_CONF_PLATFORM_ERROR_REBOOT_MAX > 0) #if MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED && (MBED_CONF_PLATFORM_ERROR_REBOOT_MAX > 0)
#ifndef NDEBUG #ifndef NDEBUG
mbed_error_printf("\n= System will be rebooted due to a fatal error =\n"); mbed_error_printf("\n= System will be rebooted due to a fatal error =\n");
if (report_error_ctx->error_reboot_count >= MBED_CONF_PLATFORM_ERROR_REBOOT_MAX) { if (report_error_ctx.error_reboot_count >= MBED_CONF_PLATFORM_ERROR_REBOOT_MAX) {
//We have rebooted more than enough, hold the system here. //We have rebooted more than enough, hold the system here.
mbed_error_printf("= Reboot count(=%" PRIi32") reached maximum, system will halt after rebooting =\n", report_error_ctx->error_reboot_count); mbed_error_printf("= Reboot count(=%" PRIi32") reached maximum, system will halt after rebooting =\n", report_error_ctx.error_reboot_count);
} }
#endif #endif
system_reset();//do a system reset to get the system rebooted system_reset();//do a system reset to get the system rebooted
@ -348,7 +353,7 @@ mbed_error_status_t mbed_reset_reboot_error_info()
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED #if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
//Protect for thread safety //Protect for thread safety
core_util_critical_section_enter(); core_util_critical_section_enter();
memset(report_error_ctx, 0, sizeof(mbed_error_ctx)); memset(&report_error_ctx, 0, sizeof(mbed_error_ctx));
core_util_critical_section_exit(); core_util_critical_section_exit();
#endif #endif
return MBED_SUCCESS; return MBED_SUCCESS;
@ -361,10 +366,10 @@ mbed_error_status_t mbed_reset_reboot_count()
if (is_reboot_error_valid) { if (is_reboot_error_valid) {
uint32_t crc_val = 0; uint32_t crc_val = 0;
core_util_critical_section_enter(); core_util_critical_section_enter();
report_error_ctx->error_reboot_count = 0;//Set reboot count to 0 report_error_ctx.error_reboot_count = 0;//Set reboot count to 0
//Update CRC //Update CRC
crc_val = mbed_tiny_compute_crc32(report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx)); crc_val = mbed_tiny_compute_crc32(&report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
report_error_ctx->crc_error_ctx = crc_val; report_error_ctx.crc_error_ctx = crc_val;
core_util_critical_section_exit(); core_util_critical_section_exit();
return MBED_SUCCESS; return MBED_SUCCESS;
} }
@ -379,7 +384,7 @@ mbed_error_status_t mbed_get_reboot_error_info(mbed_error_ctx *error_info)
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED #if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
if (is_reboot_error_valid) { if (is_reboot_error_valid) {
if (error_info != NULL) { if (error_info != NULL) {
memcpy(error_info, report_error_ctx, sizeof(mbed_error_ctx)); *error_info = report_error_ctx;
status = MBED_SUCCESS; status = MBED_SUCCESS;
} else { } else {
status = MBED_ERROR_INVALID_ARGUMENT; status = MBED_ERROR_INVALID_ARGUMENT;
@ -392,14 +397,14 @@ mbed_error_status_t mbed_get_reboot_error_info(mbed_error_ctx *error_info)
//Retrieve the first error context from error log //Retrieve the first error context from error log
mbed_error_status_t mbed_get_first_error_info(mbed_error_ctx *error_info) mbed_error_status_t mbed_get_first_error_info(mbed_error_ctx *error_info)
{ {
memcpy(error_info, &first_error_ctx, sizeof(first_error_ctx)); *error_info = first_error_ctx;
return MBED_SUCCESS; return MBED_SUCCESS;
} }
//Retrieve the last error context from error log //Retrieve the last error context from error log
mbed_error_status_t mbed_get_last_error_info(mbed_error_ctx *error_info) mbed_error_status_t mbed_get_last_error_info(mbed_error_ctx *error_info)
{ {
memcpy(error_info, &last_error_ctx, sizeof(mbed_error_ctx)); *error_info = last_error_ctx;
return MBED_SUCCESS; return MBED_SUCCESS;
} }