Skip to content

Commit

Permalink
HardFault_Handler() collects full MPU context (#201)
Browse files Browse the repository at this point in the history
* ems, mc4plus, mc2plus: added diagnostic messages which send the mpu context on fatal error
advanced application versions for ems, mc4plus, mc2plus

* enabled the divide-by-zero trap
  • Loading branch information
marcoaccame authored Sep 21, 2021
1 parent 0ddb274 commit 302b88f
Show file tree
Hide file tree
Showing 15 changed files with 395 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ static void s_hal_core_cfg_on_fatalerror(hal_fatalerror_t errorcode, const char
des->handlertype = fatalerror_handler_hal;
des->handlererrorcode = errorcode;
des->param = NULL;
des->mpucontext = NULL;
eo_fatalerror_Restart(eo_fatalerror_GetHandle(), des);
#else
#warning DONTUSE_EOtheFatalError is defined, are you sure?
Expand Down Expand Up @@ -165,6 +166,18 @@ static void myheap_delete(void* mem)

#if !defined(DONTUSE_EOtheFatalError)

void hw_handler_hf(fatal_error_handler_t feh, uint32_t *arg)
{
fatal_error_descriptor_t *des = eo_fatalerror_GetDescriptor(eo_fatalerror_GetHandle());
des->handlertype = feh;
des->handlererrorcode = 100;
des->forfutureuse0 = 0x12;
des->forfutureuse1 = 0x23;
des->param = NULL;
des->mpucontext = arg;
eo_fatalerror_Restart(eo_fatalerror_GetHandle(), des);
}

void hw_handler(fatal_error_handler_t feh)
{
fatal_error_descriptor_t *des = eo_fatalerror_GetDescriptor(eo_fatalerror_GetHandle());
Expand All @@ -173,6 +186,7 @@ void hw_handler(fatal_error_handler_t feh)
des->forfutureuse0 = 0x12;
des->forfutureuse1 = 0x23;
des->param = NULL;
des->mpucontext = NULL;
eo_fatalerror_Restart(eo_fatalerror_GetHandle(), des);
}

Expand All @@ -181,10 +195,10 @@ void NMI_Handler(void)
hw_handler(fatalerror_handler_hw_NMI);
}

void HardFault_Handler(void)
{
hw_handler(fatalerror_handler_hw_HardFault);
}
//void HardFault_Handler(void)
//{
// hw_handler(fatalerror_handler_hw_HardFault);
//}

void MemManage_Handler(void)
{
Expand Down Expand Up @@ -216,6 +230,81 @@ void RTC_Alarm_IRQHandler(void)
hw_handler(fatalerror_handler_hw_Default);
}

// from ...
// https://stackoverflow.com/questions/57286072/how-can-i-save-the-call-stack-from-an-exception-handler-in-cortex-m4
void McuHardFault_HandlerC(uint32_t *hardfault_args)
{
// static volatile uint32_t stacked_r0 __attribute__((unused));
// static volatile uint32_t stacked_r1 __attribute__((unused));
// static volatile uint32_t stacked_r2 __attribute__((unused));
// static volatile uint32_t stacked_r3 __attribute__((unused));
// static volatile uint32_t stacked_r12 __attribute__((unused));
// static volatile uint32_t stacked_lr __attribute__((unused));
// static volatile uint32_t stacked_pc __attribute__((unused));
// static volatile uint32_t stacked_psr __attribute__((unused));
// static volatile uint32_t _CFSR __attribute__((unused));
// static volatile uint32_t _HFSR __attribute__((unused));
// static volatile uint32_t _DFSR __attribute__((unused));
// static volatile uint32_t _AFSR __attribute__((unused));
// static volatile uint32_t _BFAR __attribute__((unused));
// static volatile uint32_t _MMAR __attribute__((unused));
// stacked_r0 = ((uint32_t)hardfault_args[0]);
// stacked_r1 = ((uint32_t)hardfault_args[1]);
// stacked_r2 = ((uint32_t)hardfault_args[2]);
// stacked_r3 = ((uint32_t)hardfault_args[3]);
// stacked_r12 = ((uint32_t)hardfault_args[4]);
// stacked_lr = ((uint32_t)hardfault_args[5]);
// stacked_pc = ((uint32_t)hardfault_args[6]);
// stacked_psr = ((uint32_t)hardfault_args[7]);

// /* Configurable Fault Status Register */
// /* Consists of MMSR, BFSR and UFSR */
// _CFSR = (*((volatile uint32_t *)(0xE000ED28)));

// /* Hard Fault Status Register */
// _HFSR = (*((volatile uint32_t *)(0xE000ED2C)));

// /* Debug Fault Status Register */
// _DFSR = (*((volatile uint32_t *)(0xE000ED30)));

// /* Auxiliary Fault Status Register */
// _AFSR = (*((volatile uint32_t *)(0xE000ED3C)));


// /* Read the Fault Address Registers. */
// /* These may not contain valid values. */
// /* Check BFARVALID/MMARVALID to see */
// /* if they are valid values */
// /* MemManage Fault Address Register */
// _MMAR = (*((volatile uint32_t *)(0xE000ED34)));
// /* Bus Fault Address Register */
// _BFAR = (*((volatile uint32_t *)(0xE000ED38)));

// marco.accame: must now pass all the above variables to this function
hw_handler_hf(fatalerror_handler_hw_HardFault, hardfault_args);
//__asm("BKPT #0\n") ; /* cause the debugger to stop */
}

void HardFault_Handler(void) __attribute__((naked));
void HardFault_Handler(void)
{
__asm volatile (
".syntax unified \n" /* needed for the 'adds r1,#2' below */
" movs r0,#4 \n" /* load bit mask into R0 */
" mov r1, lr \n" /* load link register into R1 */
" tst r0, r1 \n" /* compare with bitmask */
" beq _MSP \n" /* if bitmask is set: stack pointer is in PSP. Otherwise in MSP */
" mrs r0, psp \n" /* otherwise: stack pointer is in PSP */
" b _GetPC \n" /* go to part which loads the PC */
"_MSP: \n" /* stack pointer is in MSP register */
" mrs r0, msp \n" /* load stack pointer into R0 */
"_GetPC: \n" /* find out where the hard fault happened */
" ldr r1,[r0,#24] \n" /* load program counter into R1. R1 contains address of the next instruction where the hard fault happened */
" b McuHardFault_HandlerC \n" /* decode more information. R0 contains pointer to stack frame */
);
//hw_handler(fatalerror_handler_hw_HardFault);
}

#endif


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ static void s_ipal_cfg_on_fatal_error(ipal_fatalerror_t errorcode, const char *
des->handlertype = fatalerror_handler_ipal;
des->handlererrorcode = errorcode;
des->param = NULL;
des->mpucontext = NULL;
eo_fatalerror_Restart(eo_fatalerror_GetHandle(), des);
#else
#warning DONTUSE_EOtheFatalError is defined, are you sure?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ static void s_osal_cfg_on_fatal_error(void* task, osal_fatalerror_t errorcode, c
des->handlertype = fatalerror_handler_osal;
des->handlererrorcode = errorcode;
des->param = task;
des->mpucontext = NULL;
eo_fatalerror_Restart(eo_fatalerror_GetHandle(), des);
#else
#warning DONTUSE_EOtheFatalError is defined, are you sure?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,21 +81,21 @@ extern "C" {
#define EOMTHEEMSAPPLCFG_VERSION_MAJOR (VERSION_MAJOR_OFFSET+3)
// <o> minor <0-255>
// <o> minor <0-255>
#define EOMTHEEMSAPPLCFG_VERSION_MINOR 42
#define EOMTHEEMSAPPLCFG_VERSION_MINOR 43

// </h>version

// <h> build date
// <o> year <2010-2030>
#define EOMTHEEMSAPPLCFG_BUILDDATE_YEAR 2021
// <o> month <1-12>
#define EOMTHEEMSAPPLCFG_BUILDDATE_MONTH 6
#define EOMTHEEMSAPPLCFG_BUILDDATE_MONTH 9
// <o> day <1-31>
#define EOMTHEEMSAPPLCFG_BUILDDATE_DAY 22
#define EOMTHEEMSAPPLCFG_BUILDDATE_DAY 15
// <o> hour <0-23>
#define EOMTHEEMSAPPLCFG_BUILDDATE_HOUR 10
#define EOMTHEEMSAPPLCFG_BUILDDATE_HOUR 14
// <o> minute <0-59>
#define EOMTHEEMSAPPLCFG_BUILDDATE_MIN 11
#define EOMTHEEMSAPPLCFG_BUILDDATE_MIN 37
// </h>build date
// </h>Info

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ static void s_info_standard(EOtheFatalError *p);

static void s_save_hardfault(fatal_error_descriptor_t *des);
static void s_info_hardfault(EOtheFatalError *p);
static void s_save_mpustate(fatal_error_descriptor_t *des);
static void s_info_mpustate(EOtheFatalError *p);
static void s_set_divide_by_zero_trap(void);

// --------------------------------------------------------------------------------------------------------------------
// - definition (and initialisation) of static variables
Expand All @@ -78,15 +81,16 @@ static EOtheFatalError s_eo_thefatalerror =
{
.initted = eobool_false,
.threadcount = 0,
.descriptor = {0},
.descriptor = {0, 0, 0, 0, NULL, NULL},
.tobewritten = {0},
.detectedfatalerror = {0},
.errdes = {0},
.threads =
{
{0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""},
{0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}, {0, ""}
}
},
.mpustate = {{0, {0, 0, 0}, 0}, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0}}
};

static const char s_eobj_ownname[] = "EOtheFatalError";
Expand All @@ -105,6 +109,8 @@ extern EOtheFatalError* eo_fatalerror_Initialise(void)
return(p);
}

s_set_divide_by_zero_trap();

// eo_errman_Trace(eo_errman_GetHandle(), "eo_fatalerror_Initialise() starts", s_eobj_ownname);

p->initted = eobool_true;
Expand Down Expand Up @@ -150,13 +156,31 @@ extern void eo_fatalerror_AtStartup(EOtheFatalError *p)
if(fatalerror_handler_hw_HardFault == p->detectedfatalerror.message.handlertype)
{
s_info_hardfault(p);
s_info_mpustate(p);
}
else
{
s_info_standard(p);
s_info_mpustate(p);
}
}
}
}

// test code for dive by zero
// volatile uint32_t value = 0;
// volatile uint32_t tmp = 10;
// tmp = tmp / value;
//
// value = value;

// test code for access to non existing memory
// volatile unsigned int* pp;
// volatile unsigned int n;
// pp = (unsigned int*)0xCCCCCCCC;
// n = *pp;
//
// n = n;


}

Expand All @@ -177,10 +201,12 @@ extern void eo_fatalerror_Restart(EOtheFatalError *p, fatal_error_descriptor_t *
if(fatalerror_handler_hw_HardFault == des->handlertype)
{
s_save_hardfault(des);
s_save_mpustate(des);
}
else
{
s_save_standard(des);
s_save_mpustate(des);
}


Expand Down Expand Up @@ -490,6 +516,12 @@ static void s_info_standard(EOtheFatalError *p)
eo_errman_Error(eo_errman_GetHandle(), eo_errortype_error, str, s_eobj_ownname, &p->errdes);
}

static void s_set_divide_by_zero_trap(void)
{
volatile uint32_t *pCCR = (volatile uint32_t *) 0xE000ED14;
(*pCCR) |= 0x00000010;
}

static void s_save_hardfault(fatal_error_descriptor_t *des)
{
// s_save_standard(des);
Expand Down Expand Up @@ -576,6 +608,126 @@ static void s_info_hardfault(EOtheFatalError *p)
eo_errman_Error(eo_errman_GetHandle(), eo_errortype_error, str, s_eobj_ownname, &p->errdes);
}

static void s_save_mpustate(fatal_error_descriptor_t *des)
{
volatile fatal_error_mpustate_cm4_t *pHFmore = (volatile fatal_error_mpustate_cm4_t*) 0x10000000;
volatile uint32_t * hardfault_args = (volatile uint32_t *) des->mpucontext;

pHFmore->header.signature = fatal_error_signature;
pHFmore->header.dummy[0] = 0;
pHFmore->header.dummy[1] = 1;
pHFmore->header.dummy[2] = 2;
pHFmore->header.tbd0 = 0;

if(NULL == hardfault_args)
{
pHFmore->context.r0 = pHFmore->context.r1 = pHFmore->context.r2 = pHFmore->context.r3 =
pHFmore->context.r12 = pHFmore->context.lr = pHFmore->context.pc = pHFmore->context.psr = 0;
}
else
{
pHFmore->context.r0 = hardfault_args[0];
pHFmore->context.r1 = hardfault_args[1];
pHFmore->context.r2 = hardfault_args[2];
pHFmore->context.r3 = hardfault_args[3];
pHFmore->context.r12 = hardfault_args[4];
pHFmore->context.lr = hardfault_args[5];
pHFmore->context.pc = hardfault_args[6];
pHFmore->context.psr = hardfault_args[7];
}

pHFmore->sysregs.ICSR = (*((volatile uint32_t *)(0xE000ED04)));
pHFmore->sysregs.SHCSR = (*((volatile uint32_t *)(0xE000ED24)));
pHFmore->sysregs.CFSR = (*((volatile uint32_t *)(0xE000ED28)));
pHFmore->sysregs.HFSR = (*((volatile uint32_t *)(0xE000ED2C)));
pHFmore->sysregs.DFSR = (*((volatile uint32_t *)(0xE000ED30)));
pHFmore->sysregs.MMFAR = (*((volatile uint32_t *)(0xE000ED34)));
pHFmore->sysregs.BFAR = (*((volatile uint32_t *)(0xE000ED38)));
pHFmore->sysregs.AFSR = (*((volatile uint32_t *)(0xE000ED3C)));
}

static void s_info_mpustate(EOtheFatalError *p)
{
// it is of the correct size. i use it to send a diagnostic message
uint16_t par16 = 0;
uint64_t par64 = p->detectedfatalerror.params.par64;

volatile fatal_error_mpustate_cm4_t *pHFmore = (volatile fatal_error_mpustate_cm4_t*) 0x10000000;

p->errdes.code = eoerror_code_get(eoerror_category_Debug, eoerror_value_DEB_tag00);
p->errdes.sourcedevice = eo_errman_sourcedevice_localboard;
p->errdes.sourceaddress = 0;
p->errdes.par16 = par16;
p->errdes.par64 = par64;
eo_errman_Error(eo_errman_GetHandle(), eo_errortype_error, "MORE INFO", s_eobj_ownname, &p->errdes);

// further information is in here
char str[64] = {0};

if(fatal_error_signature != pHFmore->header.signature)
{
snprintf(str, sizeof(str), "mpu state invalid sign = 0x%08x",
pHFmore->header.signature
);

eo_errman_Error(eo_errman_GetHandle(), eo_errortype_error, str, s_eobj_ownname, &p->errdes);
}
else
{
// caveat the string can be at most 48 characters

// System control registers.

snprintf(str, sizeof(str), "ICSR = 0x%08x SHCSR = 0x%08x",
pHFmore->sysregs.ICSR, pHFmore->sysregs.SHCSR
);
eo_errman_Error(eo_errman_GetHandle(), eo_errortype_error, str, s_eobj_ownname, &p->errdes);

snprintf(str, sizeof(str), "CFSR = 0x%08x HFSR = 0x%08x",
pHFmore->sysregs.CFSR, pHFmore->sysregs.HFSR
);
eo_errman_Error(eo_errman_GetHandle(), eo_errortype_error, str, s_eobj_ownname, &p->errdes);

snprintf(str, sizeof(str), "DFSR = 0x%08x MMFAR = 0x%08x",
pHFmore->sysregs.DFSR, pHFmore->sysregs.MMFAR
);
eo_errman_Error(eo_errman_GetHandle(), eo_errortype_error, str, s_eobj_ownname, &p->errdes);

snprintf(str, sizeof(str), "BFAR = 0x%08x AFSR = 0x%08x",
pHFmore->sysregs.BFAR, pHFmore->sysregs.AFSR
);
eo_errman_Error(eo_errman_GetHandle(), eo_errortype_error, str, s_eobj_ownname, &p->errdes);

// execution registers

snprintf(str, sizeof(str), "r0 = 0x%08x r1 = 0x%08x",
pHFmore->context.r0, pHFmore->context.r1
);
eo_errman_Error(eo_errman_GetHandle(), eo_errortype_error, str, s_eobj_ownname, &p->errdes);

snprintf(str, sizeof(str), "r2 = 0x%08x r3 = 0x%08x",
pHFmore->context.r2, pHFmore->context.r3
);
eo_errman_Error(eo_errman_GetHandle(), eo_errortype_error, str, s_eobj_ownname, &p->errdes);

snprintf(str, sizeof(str), "r12 = 0x%08x lr = 0x%08x",
pHFmore->context.r12, pHFmore->context.lr
);
eo_errman_Error(eo_errman_GetHandle(), eo_errortype_error, str, s_eobj_ownname, &p->errdes);

snprintf(str, sizeof(str), "pc = 0x%08x psr = 0x%08x",
pHFmore->context.pc, pHFmore->context.psr
);
eo_errman_Error(eo_errman_GetHandle(), eo_errortype_error, str, s_eobj_ownname, &p->errdes);

}

// and now i reset memory bank area
memset((fatal_error_mpustate_cm4_t *)pHFmore, 0, sizeof(fatal_error_mpustate_cm4_t));

}



// error tests

Expand Down
Loading

0 comments on commit 302b88f

Please sign in to comment.