Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Real time embedded FreeRTOS mailing list 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT Training




Loading

New to RTOS, understanding semaphore delays

Posted by marifca on June 11, 2014

Hi,

I am new to RTOS world. Starting with FreeRTOS. I am using Freescale Coldfire V2 microcontrollers and managed to start several tasks running on it. But I am a bit confused regarding the delay used in semaphores. I have an interrupt giving a semaphore using xSemaphoreGiveFromISR() and a task blocking this accepts it using xSemaphoreTake() as in the following example

// A task that uses the semaphore. void vAnotherTask( void * pvParameters ) { // ... Do other things.

if( xSemaphore != NULL )
{
    // See if we can obtain the semaphore.  If the semaphore is not available
    // wait 10 ticks to see if it becomes free.	
    if( xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
    {
        // We were able to obtain the semaphore and can now access the
        // shared resource.

        // ..."My Code"

        // We have finished accessing the shared resource.  Release the 
        // semaphore.
        xSemaphoreGive( xSemaphore );
    }
    else
    {
        // We could not obtain the semaphore and can therefore not access
        // the shared resource safely.
    }
}

}

My question is what does this ( TickType_t ) 10 actually means or doing here? What happens to the "My code" block in the following three cases:

1) xTicksToWait value is 0 .. is "My code" executed with every tick? Then what is the the significance of giving the semaphore from an interrupt and an event tracking mechanism? 2) xTicksToWait value is 10 .. 3) xTicksToWait value is MaxDelay (I guess 0xffffffff) and what is the difference in action between the used value of 0 and MaxDelay?

Also I would like to know what if I use

xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ); //"My Code" xSemaphoreGive( xSemaphore );

instead of the if-else structure shown above. Will it exit the task without executing "My code" if the semaphore cannot be taken? I am asking this because I have seen some code examples on a FreeRTOS book for PC showing such examples without the if( == pdTRUE) else{} statements.

Thanks in advance.


New to RTOS, understanding semaphore delays

Posted by heinbali01 on June 11, 2014

Hi Mohammad,

The meaning of the xBlockTime parameter is well explained everywhere, on freertos.org, in the book, as well as in the header files:

...

sorry, text was doubled, see response below:


New to RTOS, understanding semaphore delays

Posted by heinbali01 on June 11, 2014

Hi Mohammad,

The meaning of the xBlockTime parameter is well explained everywhere, on freertos.org, in the book, as well as in the header files:

~~~~

  • @param xBlockTime The time in ticks to wait for the semaphore to become
  • available. The macro portTICKPERIODMS can be used to convert this to a
  • real time. A block time of zero can be used to poll the semaphore. A block
  • time of portMAX_DELAY can be used to block indefinitely (provided
  • INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h).

~~~~

So you can either poll a semaphore (using zero), wait a limited time, or wait for ever.

You say that your interrupt gives the semaphore using xSemaphoreGiveFromISR() and from within vAnotherTask() you also xSemaphoreGive() the semaphore?

The use of these two functions is correct, but why would you give from both locations?

Here are two useful scenarios for a semaphore:

1) As a mutex: to protect a resource (as you say), which is shared among two or more tasks. If you really need to take the resource, you might want to wait much longer than 10 ticks. Once you've claimed the resource, be quick, don't sleep and release it. (see also 'configUSE_MUTEXES')

2) To wake up a task immediately after an interrupt has detected some situation. In that case the interrupt is "the giver", and the task is "the taker", in a one-to-one relation.

This method is very useful, because the interrupt can be kept short. It wakes up a task which can do the time-consuming things. The time between returning from the interrupt and the waking up of the task is very short, less than a ┬Ás (unless another higher-priority task is keeping the CPU busy).

If you want to wake up the task from more than once place, you might also consider using a queue and send messages to that task, so it knows who's "the giver".

~~~~

void i2cirq( ) { .... xSemaphoreGiveFromISR (i2cSemaphore, &woken); .... }

void vAnotherTask( void * pvParameters ) { for( ; ; ) { if( xSemaphoreTake( i2cSemaphore, ( TickTypet ) 1000 ) == pdTRUE ) { // The i2c interrupt woke up this task // don't xSemaphoreGive() it back } } }

~~~~

You had another question:

~~~~ for( ; ; ) { xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ); //"My Code" xSemaphoreGive( xSemaphore ); } ~~~~

This is not very meaningful: the result of xSemaphoreTake() should be tested before you may assume that you have acquired the shared resource. Suppose that another task has taken the resource for a time longer than 10 ticks, the above task might also start using it after a short time out.

A last example of the use of a semaphore, with taking only:

~~~~ void msdelay( TickTypet millisec ) { // Wait for a number of milliseconds TickType_t ticks; // Here delaySemaphore is never given, only taken // until a timeout occurs

ticks = millisec / portTICK_PERIOD_MS;

// Or in case your clock is faster than 1000 Hz
ticks = ( configTICK_RATE_HZ * milisec + 500 ) /
    1000;

xSemaphoreTake( delaySemaphore, ticks );

} ~~~~

Did this answer all your questions?

Regards, Hein


New to RTOS, understanding semaphore delays

Posted by marifca on June 11, 2014

Thanks Hein for your replies.

void vAnotherTask( void * pvParameters ){} was copied from the FreeRTOS example on the web and not from my code. There is no xSemaphoreGive( xSemaphore ) in the task of my own code. Sorry for making it confusing.

So, now let me clarify my doubts regarding "So you can either poll a semaphore (using zero), wait a limited time, or wait for ever." this line. I would like to know the underlying mechanism of this.

In the interrupt handling situation should I wait forever or should I poll the semaphore in the interrupt handler to make the interrupt latency as little as possible considering the interrupt handler has the highest priority? If I wait forever on the semaphore, does it not make the semaphore inactive? I have seen "wait forever" works in the interrupt handling situations in my code but did not understand how.

Or in other words, could you please give some example of when to use 0 (polling) delay on the semaphore and when to use "wait forever" and also what will be the consequence of waiting for a limited time in that example. An interrupt handler example would be appreciated.

Regards, Arif


New to RTOS, understanding semaphore delays

Posted by heinbali01 on June 11, 2014

Hi Arif,

The underlying mechanism of blocking versus polling a semaphore or queue?

Polling (timeout == 0): the call will only try to take the semaphore and return pdTRUE (non-zero) if it was successfully taken, otherwise pdFALSE (zero).

Blocking (timeout > 0): the call will also try to take the semaphore and if it succeeds, it will return immediately. If it can not be taken, then the timeout parameter determines the maximum number of clock ticks before waiting will be given up. While waiting, it will not consume any CPU time, whereas the polling method does take CPU time.

portMAX_DELAY (e.g. 0xffff) is a so-called sentinel value, it doesn't mean 65535 clock-ticks, but it is treated as "for ever".

In the interrupt handling situation should I wait forever or should I poll the semaphore in the interrupt handler to make the interrupt latency as little as possible considering the interrupt handler has the highest priority?

The interrupt latency, i.e. the time between the interrupt (hardware) signal and the time that your IRQ handler becomes active, is not really influenced by your coding style. The latency depends on other competing interrupts, except when you use critical sections like here:

~~~~~~ extern volatile uint32t ulCounterIRQ; { taskENTERCRITICAL(); // Execution of IRQ's is temporarily disabled // work safely with variables which can also be accessed // by your IRQ handler taskEXIT_CRITICAL(); } ~~~~~~

If you think well about your design, the use of critical sections can often be avoided. There are many locking mechanisms, other than disabling interrupts.

If I wait forever on the semaphore, does it not make the semaphore inactive?

No, why? Your call will return as soon as the semaphore can be taken by your task, even if it has to wait for a year :-)

Personally, I would not use the "for ever" option. I would rather use a 1 sec timeout so that I can see that a task is still alive. It is hard to distinguish a permanently blocked task from a task that has got blocked because of stack corruption.

In a big embedded application, you might have many events from different sources. It would be expensive to create a new task with a new semaphore for every event. In stead you could make a task which receives commands, in stead of waiting for a semaphore:

~~~~~~

QueueHandle_t xServerQueue;

void serverTask (void *pvParameters) {

// Create a queue capable of containing 10 uint32_t values.
xServerQueue = xQueueCreate( 10, sizeof( uint32_t ) );
for ( ; ; )
{
    uint32_t ulCommand;
    if( xQueueReceive( xServerQueue, &ulCommand, 1000 ) )
    {
        switch( ulCommand )
        {
		case eCMD_AAA:
		case eCMD_BBB:
        }
    }
}

} ~~~~~~

Now every other task and every interrupt may send messages to the above task, using either QueueSend() or xQueueSendFromISR().

If you want to read more about FreeRTOS and the above subjects, you can find a really great manual/tutorial on http://shop.freertos.org

Regards, Hein


New to RTOS, understanding semaphore delays

Posted by marifca on June 11, 2014

Thanks a lot Hein. Appreciate your explanation.

Regards, Arif


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




Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd.. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.

Latest News:

FreeRTOS V9.0.0 is now available for download.


Free TCP/IP and file system demos for the RTOS


Sponsored Links

⇓ Now With No Code Size Limit! ⇓
⇑ Free Download Without Registering ⇑


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Renesas Electronics Gold Alliance RTOS Partner.jpg

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Atmel RTOS partner supporting ARM Cortex-M3 and AVR32 microcontrollers

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

Xilinx Microblaze and Zynq partner

Silicon Labs low power RTOS partner

Altera RTOS partner for Nios II and Cortex-A9 SoC

Freescale Alliance RTOS Member supporting ARM and ColdFire microcontrollers

Infineon ARM Cortex-M microcontrollers

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

Cypress RTOS partner supporting ARM Cortex-M3

Fujitsu RTOS partner supporting ARM Cortex-M3 and FM3

Microsemi (previously Actel) RTOS partner supporting ARM Cortex-M3

Atollic Partner

IAR Partner

Keil ARM Partner

Embedded Artists