Hardfault Handler called due to RTOS Call in ISR

Hello,

I am struggling with a hardfault handler issue, which occurs when I have freertos call in an interrupt.

Setup
I am using freertos version 10.5.1 on the SAM4E platform using the gcc compiler.

It is configured for cooperative mode.

Code
The interrupt in question can be seen below:


void fpga_handler(uint32_t id, uint32_t mask)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
BaseType_t xResult = pdFALSE;

if(PIN_FPGA_DRDY_ID == id && PIN_FPGA_DRDY_MASK == mask)
{
    xResult = xEventGroupSetBitsFromISR(xDigitalSensorFlag, 1, xHigherPriorityTaskWoken);
    if( xResult != pdFAIL )
	{
		//analogue_acquisition_handler_xfer();
		/* If xHigherPriorityTaskWoken is now set to pdTRUE then a context
		switch should be requested.  The macro used is port specific and will
		be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to
		the documentation page for the port being used. */
		portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
	}		
}

}

Things Ive Tried

Interrupt Priority
Note that the fpga_handler is given a numerical priority of 6:
pio_handler_set_priority(PIN_FPGA_DRDY_PIO,(IRQn_Type)PIN_FPGA_DRDY_ID, 6);

Which is higher than:
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2

If I make it lower it causes CONFIG ASSERT to be called so I’m fairly confident I have it the right way around.

Silly code by me
Can’t see any NULLs or anything that has not been initialised. i.e the xDigitalSensorFlag is the same address as its creation and structure members look good.

Reason why I’ve come here for help
The reason I think its in the FreeRTOS Kernel is that:

  1. If I comment out the xEventGroupSetBitsFromISR no hardfault issue occurs.
  2. The hardfault does not occur straight away. Stepping through it seems to happen when I next context switch which differs every time.
  3. When I use the FreeRTOS viewer to see the state of the tasks its always running the “Tmr Svc”. Which is FreeRTOS’ internal task.

Any advice of what to try or any pointers would be appreciated.

Cheers,
Dyfan

Because xEventGroupSetBitsFromISR might need to walk a list to wake multiple tasks it doesn’t do the operation inside the ISR, but sends a message to the TmrSvc Task to have it do the operation as a task.

It might be that you have done something to make that task not work correctly, perhaps not giving it enough stack or having done something to corrupt some memory it is using.

Shouldn’t you be using the & operator with xHigherPriorityTaskWoken here?

Good spot, it is in my code, somehow got rid of it when it was copied over :upside_down_face:

Can you share your definition of that variable? Can you exclude the possibility that it is unassigned yet when the ISR is called the first time?

EventGroupHandle_t xDigitalSensorFlag;

I can see this being created correctly and given reasonable memory allocations, and two minutes later the interrupt fires and the variable contents are the same during the interrupt as it is on creation.

One thought I’ve had is that the receiving task (i.e where my xEventGroupWaitBits function is called) is called a fair bit (i.e quite an aggressive schedule) and could the interrupt and the task have some sort of collision? I don’t think the xDigitalSensorFlag needs a mutex protection but maybe something like that is the cause?

No, should not… Another thing to check for is the size of the startup stack which FreeRTOS reuses to run its ISRs on once the OS is launched. Maybe the stack is too small (I believe Richard Damon suggested something similar)? Normally the startup stack size is defined in your linker command file.

1 Like

Thanks for the suggestion, I wouldn’t have thought about that. I have increased the stack and no difference but I’ll investigate other things to negate the TmrSvc as the cause of the issue.

Yeah good point I’ve already played with that, I think we all mean the variable" stack_size" and its currently set to a good size of 0x4000.

So it looks like the issue may have been solved through increasing the stack size of the Receiving task (i.e where my xEventGroupWaitBits function is called).

Maybe it worked before as the stack corruption occurred but the TmrSvc code wasn’t called. But now with an fromISR function executed. The TmrSvc now executes a few more co-routines (this is what Richard mentions) and uses the corrupted area.

Or increasing the stack size has just moved the problem elsewhere.

Either way its a stack issue and not a freertos issue, so I would like to thank you both for your help.

Cheers,
Dyfan

Feel free to close this ticket! :smiley: