Proper use of a semaphore

Is this the correct use of a semaphore to sync with an ISR: void aTask( void *pv ){ ____for(;;){ ________xSemaphoreTake( aSemaphore, 10 ); ________<cause ISR in a few ms > ________xSemaphoreTake( aSemaphore, 10 ); ________<rest of code> ____} } ISR( INT0_vect ) { ____xSemaphoreGiveFromISR( aSemaphore ); } Comments? Thanks, Scott

Proper use of a semaphore

This is the way it is done in some applications included in the download, and the way I do it.  The semaphore can be used to wake a high priority task to process the data obtained by the interrupt removing the need for the data to be processed in the interrupt itself. In your example I presume the interrupt is guaranteed to occur within 10 ticks, or that you handle the case when this does not happen?

Proper use of a semaphore

How can a task be suspended indefinitly until a semaphore is given?

Proper use of a semaphore

When calling xSemaphoreTake() a block time is specified.  The maximum block time that can be specified depends on the data type used for portTickType.  If portTickType is 32 bits, and the tick is set to 1KHz (too fast for most applications) then the maximum block period is 0xffffffff or equivalent to approximately 40 days. In FreeRTOS.org versions prior to V4.1.3 blocking for longer periods than this required the return value to be checked in a loop.  For example: while( xSemaphoreTake( aSemaphore, portMAX_DELAY ) != pdPASS ); would block the task indefinitely (pseudo indefinitely). From V4.1.3 the behaviour can be changed depending on the value of configINCLUDE_vTaskSuspend.  If configINCLUDE_vTaskSuspend is 0 then the behaviour is as per described above.  If configINCLUDE_vTaskSuspend is 1 then a delay period of portMAX_DEALY is taken to mean that the task should block indefinitely and the while loop is not necessary. This has not made it into the docs yet, other than the change history – sorry :-( Regards.

Proper use of a semaphore

Thanks for the suggestions.  So, just to confirm, assuming that I am using v4.1.3, I expect the following code to perform the following: 1.  Take the semaphore 2.  Cause an ISR to occur later in time 3.  Start waiting for the semaphore 4.  ISR gives the semaphore after a period of time 5.  Calling task processes the data 6.  Give the semaphore 7.  Go to 1 /* Start of file */ static xSemaphoreHandle aTaskSemaphore; void aTask( void * pv ) { ____vSemaphoreCreateBinary( aTaskSemaphore ); ____for(;;){ ________if( xSemaphoreTake( aTaskSemaphore, portMAX_DELAY ) == pdTRUE ){ ____________Trigger_ISR_Soon(); ____________if( xSemaphoreTake( aTaskSemaphore, portMAX_DELAY ) == pdTRUE ){ ________________ProcessDataFromISR(); ________________xSemaphoreGive( aTaskSemaphore ); ____________} ________} ____} } /* end aTask */ /* This is the ISR that will trigger and give the semaphore */ ISR( INT0_vect ) { ____portBASE_TYPE xTaskWoken = pdFALSE; ____if( xSemaphoreGiveFromISR( aTaskSemaphore, xTaskWoken ){ ________taskYEILD(); ____} }

Proper use of a semaphore

Which port are you using?  Some ports do not permit taskYELD() to be called directly in an ISR, and a different macro is provided for this purpose.  If this is how it is done in the demo serial port driver that came with the port then it will be ok. I’m not sure of the structure of your task, because I’m not sure what it is you are trying to do exactly.  I understand steps 2 to 5, but not the bit around it.  You seem to be synchronising with the ISR in two places.  Is this correct?  I’m also not sure about the call to xSemaphoreGive() in the task. In its simplest for, where a task wants to execute each time an ISR executes, the code would take the following structure: void vTask( void *pvParameters ) { ____for( ;; ) ____{ ________if( xSemaphoreTake( aTaskSemaphore, portMAX_DELAY ) == pdTRUE ) ________{ ____________/* Got the semaphore, the ISR must have fired.  Do the work ____________here. */ ____________ ____________/* We do not have to give the semaphore back.  The semaphore ____________is ’empty’ because of our call to xSemaphoreTake().  We go ____________back to block again waiting for it to be given again by the ____________ISR.  The task takes it, the ISR gives it. */ ________} ____} } void vISR( void ) { portBASE_TYPE xYieldRequired = pdFALSE; ____/* ISR fired.  Wake the task. */ ____if( xSemaphoreGiveFromISR( aTaskSemaphore, FALSE ) ) ____{ ________xYieldRequired = true; ____} ____ ____/* Clear the interrupt. */ ____ ____if( xYieldRequired ) ____{ ________/* Yield here using whatever macro is required by the port ________being used. */ ____} } Regards.