CortexM3/PSoC-5LP : Trouble identifying the task which caused an MPU exception
Hello,
I’m implementing a “blue screen of death” for a PSoC-5LP (ARM Cortex M3 core) based product, and I’ve encountered a problem identifying which task was the offender that caused the stack overflow or other memory protection exception that I’m reporting in my BSoD. I’m using FreeRTOS v7.2.0 .
Right now, I’m catching stack overflows and other memory errors based on a two-tiered approach: I have a vApplicationStackOverflowHook() function implemented (with configCHECKFORSTACK_OVERFLOW set to 2 in FreeRTOSConfig.h) so that the RTOS can do its stack size and stack canary checks when each task is swapped out, and I have an interrupt handler set up for the MPU exception interrupt (position 3 in the interrupt vector) to catch MPU exceptions (“hard faults”).
The MPU exception interrupt handler triggers reliably, but I can’t get it to identify the offending task properly. I’m using xTaskGetCurrentTaskHandle() and pcGetTaskName() to spit the task name to the display, and manually triggering faults for testing purposes by reducing the task stack of a selected task to something tiny (eg. 10 words for a task whose stack usage is around 320 words) which is sure to cause a fault. The problem is the task name I get never matches the task that I intentionally made to overflow its stack, and sometimes is gibberish (which I assume means either that xTaskGetCurrentTaskHandle returned the handle for the idle task, which doesn’t have a valid task name string pointer in its tcb, or that the tcb for the task which overflowed its stack has been corrupted). Nb. the vApplicationStackOverflowHook function never seems to be called at all, even when I purposefully trigger a much smaller stack overflow (eg 4 bytes) which “shouldn’t” make the MPU angry – it’s always the interrupt handler triggered by an MPU exception that gets called.
I’ve got a few speculative ideas as to what might be going on (along the lines of “the mis-sized stack for TaskA is really causing TaskB to access memory in a region it can’t”), but I haven’t dug into the guts of the RTOS to the point where I’m confident my mental model of what’s going on is right in this case, and the debugger that Cypress ships with the IDE is nearly worthless. Does anyone have an idea as to what else might be causing my problem? Thanks.
CortexM3/PSoC-5LP : Trouble identifying the task which caused an MPU exception
Hi,
I working on M4 MPU (the same apply to the M3) and I wrote some fonction
to help me. I use GDB so the debugging is probably better than cypress I
don’t know.
My function was inspired from others and my reading on the hardfault to
get an I dea of what is going on when we hit the fault.
//// code here /////
void printErrorMsg(const char * errMsg);
void printUsageErrorMsg(uint32t CFSRValue);
void printBusFaultErrorMsg(uint32t CFSRValue);
void printMemoryManagementErrorMsg(uint32t CFSRValue);
void stackDump(uint32t stack[]);
void HardFaultmpudump(void)
{
static char msg[200];
int i = 0;
uint32t *mpurnr = (uint32t *) 0xE000ED98;
uint32t *mpu_base = (uint32_t *) 0xE000ED9C;
uint32_t *mpu_attr = (uint32_t *) 0xE000EDA0;
//First disable the UART interrupt
printErrorMsg("-------MPU------rn");
printErrorMsg("Privileged default memory map is ");
if(MPU->CTRL & 0x01 == 0x01)
printErrorMsg("Enabledrn");
else
printErrorMsg("Disabledrn");
for (i = 0; i < 8; i++)
{
*mpu_rnr = i;
if (*mpu_attr & 0x1) //If region is activated
{
sprintk(msg,"b:0x%08p - 0x%08p, sz:2**%d (%d), attr",
mpu_base & 0xFFFFFFE0,
(mpubase & 0xFFFFFFE0) + (1 << ((*mpuattr & 0x3E) >> 1) + 1),
((mpu_attr & 0x3E) >> 1) + 1, 1 << ((mpuattr & 0x3E) >> 1) + 1);
printErrorMsg(msg);
if(((*mpuattr) & 0x07000000)== portMPUREGIONREADWRITE)
{
printErrorMsg(“: P-RW, U-RW”);
}
else if(((*mpuattr) & 0x07000000)==
portMPUREGIONPRIVILEGEDREADWRITEUSERREADONLY)
{
printErrorMsg(“: P-RW, U-RO”);
}
else if(((*mpuattr) & 0x07000000) ==
portMPUREGIONPRIVILEGEDREADONLY)
{
printErrorMsg(“: P+RO”);
}
else if(((mpu_attr) & 0x07000000) == portMPU_REGION_READ_ONLY)
{
printErrorMsg(“: P-RO, U-RO”);
}
else if(((mpuattr) & 0x07000000) ==
portMPUREGIONPRIVILEGEDREAD_WRITE)
{
printErrorMsg(“: P-RW”);
}
printErrorMsg(“rn”);
}
}
}
void HardFaultHandler(uint32_t stack[])
{
static char msg[80];
printErrorMsg(“x1B[2J”);
printErrorMsg("In Hard Fault Handlerrn");
sprintk(msg, "SCB->HFSR = 0x%08xrn", SCB->HFSR);
printErrorMsg(msg);
if ((SCB->HFSR & (1 << 30)) != 0)
{
printErrorMsg("Forced Hard Faultrn");
}
sprintf(msg, "SCB->CFSR = 0x%08xrn", SCB->CFSR );
printErrorMsg(msg);
if((SCB->CFSR & 0xFFFF0000) != 0) {
printUsageErrorMsg(SCB->CFSR);
}
if((SCB->CFSR & 0xFF00) != 0) {
printBusFaultErrorMsg(SCB->CFSR);
}
if((SCB->CFSR & 0xFF) != 0) {
printMemoryManagementErrorMsg(SCB->CFSR);
}
stackDump(stack);
HardFault_mpu_dump();
__asm("BKPT #0rn") ; // Break into the debugger
while(1);
}
void printErrorMsg(const char * errMsg)
{
while(errMsg != ‘