mirror of https://github.com/ARMmbed/mbed-os.git
Fix crc calculation error, code-style issues and other fixes
parent
f1926c0ea9
commit
423b52e1c3
|
@ -29,11 +29,12 @@
|
|||
#define MSG_KEY_DEVICE_READY "crash_reporting_ready"
|
||||
#define MSG_KEY_DEVICE_ERROR "crash_reporting_inject_error"
|
||||
|
||||
void mbed_error_reboot_callback(mbed_error_ctx *error_context) {
|
||||
void mbed_error_reboot_callback(mbed_error_ctx *error_context)
|
||||
{
|
||||
TEST_ASSERT_EQUAL_UINT(MBED_ERROR_OUT_OF_MEMORY, error_context->error_status);
|
||||
TEST_ASSERT_EQUAL_UINT(1, error_context->error_reboot_count);
|
||||
mbed_reset_reboot_error_info();
|
||||
|
||||
|
||||
//Send the ready msg to host to indicate test pass
|
||||
greentea_send_kv(MSG_KEY_DEVICE_READY, MSG_VALUE_DUMMY);
|
||||
}
|
||||
|
@ -46,12 +47,15 @@ void test_crash_reporting()
|
|||
static char _key[MSG_KEY_LEN + 1] = { };
|
||||
static char _value[MSG_VALUE_LEN + 1] = { };
|
||||
|
||||
printf("\nWaiting for inject error\n");
|
||||
greentea_parse_kv(_key, _value, MSG_KEY_LEN, MSG_VALUE_LEN);
|
||||
printf("\nGot inject error\n");
|
||||
if (strcmp(_key, MSG_KEY_DEVICE_ERROR) == 0) {
|
||||
printf("\nErroring...\n");
|
||||
MBED_ERROR1(MBED_ERROR_OUT_OF_MEMORY, "Executing crash reporting test.", 0xDEADBAD);
|
||||
TEST_ASSERT_MESSAGE(0, "crash_reporting() error call failed.");
|
||||
}
|
||||
|
||||
printf("\nWaiting for inject error");
|
||||
TEST_ASSERT_MESSAGE(0, "Unexpected message received.");
|
||||
}
|
||||
|
||||
|
|
|
@ -24,28 +24,28 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
|
||||
#if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
|
||||
extern uint32_t Image$$RW_m_crash_data$$ZI$$Base[];
|
||||
extern uint32_t Image$$RW_m_crash_data$$ZI$$Size;
|
||||
#define __CRASH_DATA_RAM_START__ Image$$RW_m_crash_data$$ZI$$Base
|
||||
#define __CRASH_DATA_RAM_SIZE__ Image$$RW_m_crash_data$$ZI$$Size
|
||||
#elif defined(__ICCARM__)
|
||||
extern uint32_t __CRASH_DATA_RAM_START__[];
|
||||
extern uint32_t __CRASH_DATA_RAM_END__[];
|
||||
#define __CRASH_DATA_RAM_SIZE__ (__CRASH_DATA_RAM_END__ - __CRASH_DATA_RAM_START__)
|
||||
#elif defined(__GNUC__)
|
||||
extern uint32_t __CRASH_DATA_RAM_START__[];
|
||||
extern uint32_t __CRASH_DATA_RAM_END__[];
|
||||
#define __CRASH_DATA_RAM_SIZE__ (__CRASH_DATA_RAM_END__ - __CRASH_DATA_RAM_START__)
|
||||
#endif /* defined(__CC_ARM) */
|
||||
|
||||
/* Offset definitions for context capture */
|
||||
#define FAULT_CONTEXT_OFFSET (0x0)
|
||||
#define FAULT_CONTEXT_SIZE (0x80 / 4) //32 words(128 bytes) for Fault Context
|
||||
#define ERROR_CONTEXT_OFFSET (FAULT_CONTEXT_OFFSET + FAULT_CONTEXT_SIZE)
|
||||
#define ERROR_CONTEXT_SIZE (0x80 / 4) //32 words(128 bytes) bytes for Error Context
|
||||
#define FAULT_CONTEXT_LOCATION (__CRASH_DATA_RAM_START__ + FAULT_CONTEXT_OFFSET)
|
||||
#define ERROR_CONTEXT_LOCATION (__CRASH_DATA_RAM_START__ + ERROR_CONTEXT_OFFSET)
|
||||
#if defined(__CC_ARM) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
|
||||
extern uint32_t Image$$RW_m_crash_data$$ZI$$Base[];
|
||||
extern uint32_t Image$$RW_m_crash_data$$ZI$$Size;
|
||||
#define __CRASH_DATA_RAM_START__ Image$$RW_m_crash_data$$ZI$$Base
|
||||
#define __CRASH_DATA_RAM_SIZE__ Image$$RW_m_crash_data$$ZI$$Size
|
||||
#elif defined(__ICCARM__)
|
||||
extern uint32_t __CRASH_DATA_RAM_START__[];
|
||||
extern uint32_t __CRASH_DATA_RAM_END__[];
|
||||
#define __CRASH_DATA_RAM_SIZE__ (__CRASH_DATA_RAM_END__ - __CRASH_DATA_RAM_START__)
|
||||
#elif defined(__GNUC__)
|
||||
extern uint32_t __CRASH_DATA_RAM_START__[];
|
||||
extern uint32_t __CRASH_DATA_RAM_END__[];
|
||||
#define __CRASH_DATA_RAM_SIZE__ (__CRASH_DATA_RAM_END__ - __CRASH_DATA_RAM_START__)
|
||||
#endif /* defined(__CC_ARM) */
|
||||
|
||||
/* Offset definitions for context capture */
|
||||
#define FAULT_CONTEXT_OFFSET (0x0)
|
||||
#define FAULT_CONTEXT_SIZE (0x80 / 4) //32 words(128 bytes) for Fault Context
|
||||
#define ERROR_CONTEXT_OFFSET (FAULT_CONTEXT_OFFSET + FAULT_CONTEXT_SIZE)
|
||||
#define ERROR_CONTEXT_SIZE (0x80 / 4) //32 words(128 bytes) bytes for Error Context
|
||||
#define FAULT_CONTEXT_LOCATION (__CRASH_DATA_RAM_START__ + FAULT_CONTEXT_OFFSET)
|
||||
#define ERROR_CONTEXT_LOCATION (__CRASH_DATA_RAM_START__ + ERROR_CONTEXT_OFFSET)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#define ERROR_REPORT(ctx, error_msg, error_filename, error_line, print_thread_info) print_error_report(ctx, error_msg, error_filename, error_line, print_thread_info)
|
||||
static void print_error_report(const mbed_error_ctx *ctx, const char *, const char *error_filename, int error_line, bool print_thread_info);
|
||||
#else
|
||||
#define ERROR_REPORT(ctx, error_msg, error_filename, error_line) ((void) 0)
|
||||
#define ERROR_REPORT(ctx, error_msg, error_filename, error_line, print_thread_info) ((void) 0)
|
||||
#endif
|
||||
|
||||
static core_util_atomic_flag error_in_progress = CORE_UTIL_ATOMIC_FLAG_INIT;
|
||||
|
@ -49,9 +49,9 @@ static int error_count = 0;
|
|||
static mbed_error_ctx first_error_ctx = {0};
|
||||
|
||||
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
|
||||
//Global for populating the context in exception handler
|
||||
static mbed_error_ctx *const report_error_ctx=(mbed_error_ctx *)(ERROR_CONTEXT_LOCATION);
|
||||
static bool is_reboot_error_valid = false;
|
||||
//Global for populating the context in exception handler
|
||||
static mbed_error_ctx *const report_error_ctx = (mbed_error_ctx *)(ERROR_CONTEXT_LOCATION);
|
||||
static bool is_reboot_error_valid = false;
|
||||
#endif
|
||||
|
||||
static mbed_error_ctx last_error_ctx = {0};
|
||||
|
@ -61,19 +61,20 @@ static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsign
|
|||
//Helper function to calculate CRC
|
||||
//NOTE: It would have been better to use MbedCRC implementation. But
|
||||
//MbedCRC uses table based calculation and we dont want to keep that table memory
|
||||
//used up for this purpose. Also we cannot force bitwise calculation in MbedCRC
|
||||
//used up for this purpose. Also we cannot force bitwise calculation in MbedCRC
|
||||
//and it also requires a new wrapper to be called from C implementation. Since
|
||||
//we dont have many uses cases to create a C wrapper for MbedCRC and the data
|
||||
//we calculate CRC on in this context is very less we will use a local
|
||||
//we calculate CRC on in this context is very less we will use a local
|
||||
//implementation here.
|
||||
static unsigned int compute_crc32(void *data, int datalen)
|
||||
static unsigned int compute_crc32(const void *data, int datalen)
|
||||
{
|
||||
const unsigned int polynomial = 0x04C11DB7; /* divisor is 32bit */
|
||||
unsigned int crc = 0; /* CRC value is 32bit */
|
||||
|
||||
for ( ;datalen>=0; datalen-- ) {
|
||||
unsigned char b = (*(unsigned char *)data);
|
||||
crc ^= (unsigned int )(b << 24); /* move byte into upper 8bit */
|
||||
unsigned char *buf = (unsigned char *)data;//use a temp variable to make code readable and to avoid typecasting issues.
|
||||
|
||||
for (; datalen>0; datalen-- ) {
|
||||
unsigned char b = *buf++;
|
||||
crc ^= (unsigned int)(b << 24); /* move byte into upper 8bit */
|
||||
for (int i = 0; i < 8; i++) {
|
||||
/* is MSB 1 */
|
||||
if ((crc & 0x80000000) != 0) {
|
||||
|
@ -191,7 +192,8 @@ static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsign
|
|||
return MBED_SUCCESS;
|
||||
}
|
||||
|
||||
WEAK void mbed_error_reboot_callback(mbed_error_ctx *error_context) {
|
||||
WEAK void mbed_error_reboot_callback(mbed_error_ctx *error_context)
|
||||
{
|
||||
//Dont do anything here, let application override this if required.
|
||||
}
|
||||
|
||||
|
@ -200,32 +202,35 @@ mbed_error_status_t mbed_error_initialize(void)
|
|||
{
|
||||
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
|
||||
uint32_t crc_val = 0;
|
||||
crc_val = 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
|
||||
if ((report_error_ctx->crc_error_ctx == crc_val) && (report_error_ctx->is_error_processed == 0) && (report_error_ctx->error_status < 0)) {
|
||||
is_reboot_error_valid = true;
|
||||
#if MBED_CONF_PLATFORM_REBOOT_CRASH_REPORT_ENABLED && !defined(NDEBUG)
|
||||
//Report the error info
|
||||
mbed_error_printf("\n== Your last reboot was triggered by an error, below is the error information ==");
|
||||
ERROR_REPORT( report_error_ctx, "System rebooted due to fatal error", MBED_FILENAME, __LINE__, false );
|
||||
#endif
|
||||
//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);
|
||||
|
||||
//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) {
|
||||
crc_val = 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
|
||||
if ((report_error_ctx->crc_error_ctx == crc_val) && (report_error_ctx->is_error_processed == 0)) {
|
||||
is_reboot_error_valid = true;
|
||||
#if MBED_CONF_PLATFORM_REBOOT_CRASH_REPORT_ENABLED && !defined(NDEBUG)
|
||||
//Report the error info
|
||||
mbed_error_printf("\n== Your last reboot was triggered by an error, below is the error information ==");
|
||||
ERROR_REPORT(report_error_ctx, "System rebooted due to fatal error", MBED_FILENAME, __LINE__, false);
|
||||
#endif
|
||||
//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);
|
||||
|
||||
//Enforce max-reboot only if auto reboot is enabled
|
||||
#if MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED
|
||||
if ( report_error_ctx->error_reboot_count >= MBED_CONF_PLATFORM_ERROR_REBOOT_MAX ) {
|
||||
//We have rebooted more than enough, hold the system here.
|
||||
mbed_error_printf("\n== Reboot count(=%ld) exceeded maximum, system halting ==\n", report_error_ctx->error_reboot_count);
|
||||
mbed_halt_system();
|
||||
//Enforce max-reboot only if auto reboot is enabled
|
||||
#if MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED
|
||||
if (report_error_ctx->error_reboot_count >= MBED_CONF_PLATFORM_ERROR_REBOOT_MAX) {
|
||||
//We have rebooted more than enough, hold the system here.
|
||||
mbed_error_printf("\n== Reboot count(=%ld) exceeded maximum, system halting ==\n", report_error_ctx->error_reboot_count);
|
||||
mbed_halt_system();
|
||||
}
|
||||
#endif
|
||||
report_error_ctx->is_error_processed = 1;//Set the flag that we already processed this error
|
||||
crc_val = compute_crc32(report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
|
||||
report_error_ctx->crc_error_ctx = crc_val;
|
||||
}
|
||||
#endif
|
||||
report_error_ctx->is_error_processed = 1;//Set the flag that we already processed this error
|
||||
crc_val = compute_crc32( report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx) );
|
||||
report_error_ctx->crc_error_ctx = crc_val;
|
||||
}
|
||||
#endif
|
||||
|
||||
return MBED_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -267,10 +272,10 @@ WEAK MBED_NORETURN mbed_error_status_t mbed_error(mbed_error_status_t error_stat
|
|||
//On fatal errors print the error context/report
|
||||
ERROR_REPORT(&last_error_ctx, error_msg, filename, line_number, true);
|
||||
}
|
||||
|
||||
|
||||
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
|
||||
uint32_t crc_val = 0;
|
||||
crc_val = compute_crc32( report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx) );
|
||||
crc_val = 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
|
||||
if (report_error_ctx->crc_error_ctx == crc_val) {
|
||||
uint32_t current_reboot_count = report_error_ctx->error_reboot_count;
|
||||
|
@ -280,7 +285,7 @@ WEAK MBED_NORETURN mbed_error_status_t mbed_error(mbed_error_status_t error_stat
|
|||
}
|
||||
last_error_ctx.is_error_processed = 0;//Set the flag that this is a new error
|
||||
//Update the struct with crc
|
||||
last_error_ctx.crc_error_ctx = compute_crc32( &last_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx) );
|
||||
last_error_ctx.crc_error_ctx = compute_crc32(&last_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
|
||||
//Protect report_error_ctx while we update it
|
||||
core_util_critical_section_enter();
|
||||
memcpy(report_error_ctx, &last_error_ctx, sizeof(mbed_error_ctx));
|
||||
|
@ -291,8 +296,6 @@ WEAK MBED_NORETURN mbed_error_status_t mbed_error(mbed_error_status_t error_stat
|
|||
#endif
|
||||
#endif
|
||||
mbed_halt_system();
|
||||
|
||||
return MBED_ERROR_FAILED_OPERATION;
|
||||
}
|
||||
|
||||
//Register an application defined callback with error handling
|
||||
|
@ -313,10 +316,10 @@ mbed_error_status_t mbed_reset_reboot_error_info()
|
|||
#if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
|
||||
//Protect for thread safety
|
||||
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();
|
||||
#endif
|
||||
return MBED_SUCCESS;
|
||||
return MBED_SUCCESS;
|
||||
}
|
||||
|
||||
//Reset the reboot error context
|
||||
|
@ -328,13 +331,13 @@ mbed_error_status_t mbed_reset_reboot_count()
|
|||
core_util_critical_section_enter();
|
||||
report_error_ctx->error_reboot_count = 0;//Set reboot count to 0
|
||||
//Update CRC
|
||||
crc_val = compute_crc32( report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx) );
|
||||
crc_val = compute_crc32(report_error_ctx, offsetof(mbed_error_ctx, crc_error_ctx));
|
||||
report_error_ctx->crc_error_ctx = crc_val;
|
||||
core_util_critical_section_exit();
|
||||
return MBED_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
return MBED_ERROR_ITEM_NOT_FOUND;
|
||||
return MBED_ERROR_ITEM_NOT_FOUND;
|
||||
}
|
||||
|
||||
//Retrieve the reboot error context
|
||||
|
@ -350,7 +353,7 @@ mbed_error_status_t mbed_get_reboot_error_info(mbed_error_ctx *error_info)
|
|||
status = MBED_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -831,7 +831,7 @@ typedef struct _mbed_error_ctx {
|
|||
int32_t error_reboot_count;//everytime we write this struct we increment this value by 1, irrespective of time between reboots. Note that the data itself might change, but everytime we reboot due to error we update this count by 1
|
||||
int32_t is_error_processed;//once this error is processed set this value to 1
|
||||
uint32_t crc_error_ctx;//crc_error_ctx should always be the last member in this struct
|
||||
#endif
|
||||
#endif
|
||||
} mbed_error_ctx;
|
||||
|
||||
/** To generate a fatal compile-time error, you can use the pre-processor #error directive.
|
||||
|
@ -935,10 +935,10 @@ typedef void (*mbed_error_hook_t)(const mbed_error_ctx *error_ctx);
|
|||
|
||||
|
||||
/**
|
||||
* Callback function for reporting error context during boot up. When MbedOS error handling system detects a fatal error
|
||||
* Callback function for reporting error context during boot up. When MbedOS error handling system detects a fatal error
|
||||
* it will auto-reboot the system(if MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED is enabled) after capturing the
|
||||
* error info in special crash data RAM region. Once rebooted, MbedOS initialization routines will call this function with a pointer to
|
||||
* the captured mbed_error_ctx structure. If application implementation needs to receive this callback, mbed_error_reboot_callback
|
||||
* error info in special crash data RAM region. Once rebooted, MbedOS initialization routines will call this function with a pointer to
|
||||
* the captured mbed_error_ctx structure. If application implementation needs to receive this callback, mbed_error_reboot_callback
|
||||
* function should be overriden with custom implementation. By default it's defined as a WEAK function in mbed_error.c.
|
||||
* Note that this callback will be invoked before the system starts executing main() function. So the implementation of
|
||||
* the callback should be aware any resource limitations/availability of resources which are yet to be initialized by application main().
|
||||
|
@ -950,10 +950,10 @@ typedef void (*mbed_error_hook_t)(const mbed_error_ctx *error_ctx);
|
|||
void mbed_error_reboot_callback(mbed_error_ctx *error_context);
|
||||
|
||||
/**
|
||||
* Initialize error handling system, this is called by the mbed-os boot sequence. This is not required to be called by Application unless the boot sequence is overridden by the system implementation.
|
||||
* Initialize error handling system, this is called by the mbed-os boot sequence. This is not required to be called by Application unless the boot sequence is overridden by the system implementation.
|
||||
* NOTE: This function also prints the error report to serial terminal if MBED_CONF_PLATFORM_REBOOT_CRASH_REPORT_ENABLED is enabled.
|
||||
* If MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED is enabled and if the current reboot count exceeds MBED_CONF_PLATFORM_ERROR_REBOOT_MAX the system will halt when this function is called,
|
||||
* and in such cases the caller will not get the control back. Also note that calling this function may trigger mbed_error_reboot_callback() if application side overides mbed_error_reboot_callback().
|
||||
* and in such cases the caller will not get the control back. Also note that calling this function may trigger mbed_error_reboot_callback() if application side overides mbed_error_reboot_callback().
|
||||
* @return MBED_SUCCESS on success.
|
||||
*
|
||||
*/
|
||||
|
@ -965,13 +965,13 @@ mbed_error_status_t mbed_error_initialize(void);
|
|||
* @param error_info Pointer to mbed_error_ctx struct allocated by the caller. This is the mbed_error_ctx info captured as part of the fatal error which triggered the reboot.
|
||||
* @return 0 or MBED_SUCCESS on success.
|
||||
* MBED_ERROR_INVALID_ARGUMENT in case of invalid error_info pointer
|
||||
* MBED_ERROR_ITEM_NOT_FOUND if no reboot context is currently captured by the system
|
||||
* MBED_ERROR_ITEM_NOT_FOUND if no reboot context is currently captured by the system
|
||||
*
|
||||
*/
|
||||
mbed_error_status_t mbed_get_reboot_error_info(mbed_error_ctx *error_info);
|
||||
|
||||
/**
|
||||
* Calling this function resets the current reboot context captured by the system(stored in special crash data RAM region).
|
||||
* Calling this function resets the current reboot context captured by the system(stored in special crash data RAM region).
|
||||
* @return MBED_SUCCESS on success.
|
||||
* MBED_ERROR_ITEM_NOT_FOUND if no reboot context is currently captured by the system
|
||||
*/
|
||||
|
@ -979,7 +979,7 @@ mbed_error_status_t mbed_reset_reboot_error_info(void);
|
|||
|
||||
/**
|
||||
* Calling this function resets the current reboot count stored as part of error context captured in special crash data RAM region.
|
||||
* The function will also update the CRC value stored as part of error context accordingly.
|
||||
* The function will also update the CRC value stored as part of error context accordingly.
|
||||
* @return MBED_SUCCESS on success.
|
||||
* MBED_ERROR_ITEM_NOT_FOUND if no reboot context is currently captured by the system
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue