Issue in xSemaphoreGiveFromISR

sareenakp wrote on Friday, December 20, 2013:

Hi,

I am facing an issue with xSemaphoreGiveFromISR . It is not unblocking the task that is waiting on a xSemaphoreTake. I am working on ARM Cortex™-M3 core.
I use the xSemaphoreGiveFromISR in the ISR, and this interrupt is fired fast.

I have ensured that the interrupt is fired with an LED, as well as the call to xSemaphoreGiveFromISR is executed.
The firmware is blocked at this instance.
Please provide your inputs.

The priority of the interrupt is 7.
configMAX_SYSCALL_INTERRUPT_PRIORITY is kept as 4.

gxSem_CntlessIntAvl is a binary semaphore.

The code is as below

ISR -->

void EXTI9_5_IRQHandler (void)
{

#if (configUSE_TRACE_FACILITY == 1)
	portENTER_CRITICAL(); // Required if nested ISRs are allowed
    vTraceStoreISRBegin(ID_CLESS);
    portEXIT_CRITICAL();
#endif


static portBASE_TYPE xTaskWoken = pdFALSE;
portBASE_TYPE xStatus = pdFALSE;


if(EXTI_GetFlagStatus(EXTI_Line5) == SET)
{

	EXTI_ClearFlag(EXTI_Line5);

	if (NULL != gxSem_CntlessIntAvl)
	{
		if (xQueueIsQueueFullFromISR(gxSem_CntlessIntAvl))
		{
                        // Queue is full
		}
		else
		{

    			xStatus = xSemaphoreGiveFromISR (gxSem_CntlessIntAvl,        
                                    &xTaskWoken );
                        

                            if (xTaskWoken == pdTRUE)
                            {
                                //Force a context switch here not at all necessary
                                portYIELD_FROM_ISR (xTaskWoken );
                            }


		}
	}
}


#if (configUSE_TRACE_FACILITY == 1)
    portENTER_CRITICAL(); // Required if nested ISRs are allowed
    vTraceStoreISREnd();
    portEXIT_CRITICAL();
#endif

}

TASK -->

while (TRUE)
{

if (pdFALSE == xSemaphoreTake (gxSem_CntlessIntAvl, gwStmTimeout/portTICK_RATE_MS))
{
	PC_CL ('+');
	byRetVal = ERROR_TIMEOUT;
	break;
}
... 

//Continue to process the interrupt.

}

edwards3 wrote on Friday, December 20, 2013:

portENTER_CRITICAL();

You can’t call that from an interrupt because it does not end in FromISR. Step into xSemaphoreGiveFromISR() to see how it creates a critical section from an interrupt. There is nothing else obviously wrong in your code assuming the trace function calls are ok.

Are you using the latest FreeRTOS version 7.6.0 with configASSERT() defined? That helps trap quite a lot more config errors than older versions.

sareenakp wrote on Monday, December 23, 2013:

I am using FreeRTOS V7.5.2.

Even RTOS API’s uses the portENTER_CRITICAL function internally.
There are no portENTER_CRITICALFromIsr functions defined in this RTOS version.

I feel the issue is in xSemaphoreTake, as the semaphore is given successfully from ISR ( confirmed with LED toggling.)
The xSemaphoreTake should have atleast timed out.

The issue is seen when the xSemaphoreTake has entered its waiting loop and then the ISR gives the semaphore.

Its all fine , when the ISR has given the semaphore before the xSemaphoreTake enters its waiting loop in the RTOS.

Another issue I am facing is that , the FreeRTOS+ TRace is not able to capture any log past the xSemaphoreGiveFromISR call. It always stops at the first call to xSemaphoreGiveFromISR .
Can anything be done about this?

rtel wrote on Monday, December 23, 2013:

Even RTOS API’s uses the portENTER_CRITICAL function internally.

No they don’t.

There are no portENTER_CRITICALFromIsr functions defined in this RTOS version.

Yes there are.

Look at the implementation of xQueueGenericSendFromISR() in queue.c to see how it uses the portSET_INTERRUPT_MASK_FROM_ISR() macro, and also read the FAQ “My application does not run what could be wrong” to ensure you understand which functions can be called from interrupts. FreeRTOS - Open Source RTOS Kernel for small embedded systems

Can anything be done about this?

Please also use V7.6.0 and define configASSERT() as already suggested then report back if the asserts have trapped the problem or not as you are describing a situation that will occur if the configuration is not correct - and the asserts are there to trap that for you. If not we can look into the issue further.

Regards.