ARM Cortex-M3 crashed with --use_frame_pointer

bettermanlu wrote on Friday, December 11, 2015:

Our current project includes FreeRTOS, and I added --use_frame_pointer to Keil uVision’s ARMGCC compiler option. But after loading firmware into STM32F104 chip, then runs it, it crashed. Without --use_frame_pointer, everything is OK. The hard fault handler shows that faultStackAddress is 0x40FFFFDC, which points to a reserved area. Does anyone has any idea of this error? Thanks a lot.


__asm void HardFault_Handler(void)
{
   TST lr, #4
   ITE EQ
   MRSEQ r0, MSP
   MRSNE r0, PSP
   B __cpp(Hard_Fault_Handler)
}
void Hard_Fault_Handler(uint32_t *faultStackAddress)
{

}

I stepped into each line of code, and the crash happened in below function in FreeRTOS’s port.c after I called vTaskDelete(NULL);

void vPortYieldFromISR( void )
{
    /* Set a PendSV to request a context switch. */
    portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}

But seems like this is not the root cause, because when I deleted vTaskDelete(NULL), crash still happened.

rtel wrote on Friday, December 11, 2015:

I’m afraid without reading the compiler documentation, or inspecting the changes to the generated assembler code, I don’t know why this would be. The code assumes the compiler generates ARM EABI compliant code, maybe using the frame pointer changes that? Why do you need that compiler option?

bettermanlu wrote on Monday, December 14, 2015:

We’d like to unwind ARM Cortex M3 stack when crash happened, so we need to save FP(Frame Pointer) to the stack. That’s why we add --use_frame_pointer to Keil uVision’s ARMGCC compiler option.

bettermanlu wrote on Wednesday, January 13, 2016:

I found that if I comment out the xTimerCreateTimerTask() in vTaskStartScheduler() function, the crash does not happen. Any thoughts? Thanks.

bettermanlu wrote on Wednesday, January 13, 2016:

My test code for your reference:


#include "FreeRTOSConfig.h"
#include "FreeRTOS.h"
#include "task.h"
#include <stm32f10x.h>


void crashTask(void *param)
{

    unsigned int i = 0;
    /* halt the hardware. */
    while(1)
    {
         i += 1;
    }
    vTaskDelete(NULL);
}
void testCrashTask()
{
    xTaskCreate(crashTask, (const signed char *)"crashTask",  configMINIMAL_STACK_SIZE,  NULL,  1,  NULL);    
}

void Hard_Fault_Handler(unsigned int *faultStackAddress);

/* The fault handler implementation calls a function called Hard_Fault_Handler(). */
#if defined(__CC_ARM)
__asm void HardFault_Handler(void)
{
   TST lr, #4
   ITE EQ
   MRSEQ r0, MSP
   MRSNE r0, PSP
   B __cpp(Hard_Fault_Handler)
}
#else
void HardFault_Handler(void)
{
   __asm("TST lr, #4");
   __asm("ITE EQ");
   __asm("MRSEQ r0, MSP");
   __asm("MRSNE r0, PSP");
   __asm("B Hard_Fault_Handler");
}
#endif

void Hard_Fault_Handler(unsigned int *faultStackAddress)
{
    int i = 0;
    while(1)
    {
        i += 1;
    }
}

void nvicInit(void)
{

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
	#ifdef  VECT_TAB_RAM  							
	NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);  	
	#else
	NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);  
	#endif
}



int main()
{
    nvicInit();

    testCrashTask();
    vTaskStartScheduler();
    
}

/* For now, the stack depth of IDLE has 88 left. if want add func to here, 
   you should increase it. */
void vApplicationIdleHook(void)
{	/* ATTENTION: all funcs called within here, must not be blocked */
	//workerProbe();
}

void debugSendTraceInfo(unsigned int taskNbr)
{
}

rtel wrote on Wednesday, January 13, 2016:

The timer task is a standard task, written in C, so there is nothing special about it that I am aware of. It does however give a big clue as to where you could focus your debugging. See how far you get through the function - it is actually quite small.

bettermanlu wrote on Thursday, January 14, 2016:

Seems like SP is corrupted.

Another odd thing is that if I debug it and step into the TimerTask’s portYIELD_WITHIN_API() function call, then resume the application. It does not crash. So my guess is that this might due to certain time sequence. But I could not find the root cause of it.

Any thoughts? Thanks.