Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem


Loading

Proper use of a semaphore

Posted by Scott Nortman on January 8, 2007
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

RE: Proper use of a semaphore

Posted by Nobody/Anonymous on January 8, 2007
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?

RE: Proper use of a semaphore

Posted by Scott Nortman on January 8, 2007
How can a task be suspended indefinitly until a semaphore is given?

RE: Proper use of a semaphore

Posted by Richard on January 8, 2007
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.

RE: Proper use of a semaphore

Posted by Scott Nortman on January 19, 2007
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();

____}

}

RE: Proper use of a semaphore

Posted by Richard on January 20, 2007
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.


[ Back to the top ]    [ About FreeRTOS ]    [ Privacy ]    [ Sitemap ]    [ ]


Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

NXP tweet showing LPC5500 (ARMv8-M Cortex-M33) running FreeRTOS.

Meet Richard Barry and learn about running FreeRTOS on RISC-V at FOSDEM 2019

Version 10.1.1 of the FreeRTOS kernel is available for immediate download. MIT licensed.

View a recording of the "OTA Update Security and Reliability" webinar, presented by TI and AWS.


Careers

FreeRTOS and other embedded software careers at AWS.



FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Espressif ESP32

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Renesas

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS

Xilinx Microblaze and Zynq partner