Functions | |
void * | SemaphoreCreate () |
Create a semaphore. | |
int | SemaphoreTake (void *semaphore, int blockTime) |
Obtain a semaphore. | |
int | SemaphoreGive (void *semaphore) |
Release a semaphore. | |
int | SemaphoreGiveFromISR (void *semaphore, int taskWoken) |
Release a semaphore from within an ISR. |
Quite often you'll have more than one task trying to get access to the same resources. To ensure that the resource is not in some intermediate state between reading and writing, it's necessary to serialize access to it. Semaphores and mutexes provide a way to do this.
Binary semaphores and mutexes are very similar but have some subtle differences: Mutexes include a priority inheritance mechanism, binary semaphores do not. This makes binary semaphores the better choice for implementing synchronisation (between tasks or between tasks and an interrupt), and mutexes the better choice for implementing simple mutual exclusion.
A binary semaphore need not be given back once obtained, so task synchronisation can be implemented by one task/interrupt continuously 'giving' the semaphore while another continuously 'takes' the semaphore.
The priority of a task that 'takes' a mutex can potentially be raised if another task of higher priority attempts to obtain the same mutex. The task that owns the mutex 'inherits' the priority of the task attempting to 'take' the same mutex. This means the mutex must always be 'given' back - otherwise the higher priority task will never be able to obtain the mutex, and the lower priority task will never 'disinherit' the priority.
More info at http://www.freertos.org - much documentation here used from the FreeRTOS doc by Richard Barry.
void* SemaphoreCreate | ( | void | ) |
Create a semaphore.
void* mySemaphore = SemaphoreCreate( ); if( mySemaphore != NULL ) { // The semaphore was created successfully and can now be used. }
int SemaphoreGive | ( | void * | semaphore | ) |
Release a semaphore.
This must not be used from an ISR. See SemaphoreGiveFromISR( ) for an alternative which can be used from an ISR.
semaphore | The semaphore to release. |
void* mySemaphore; SemaphoreCreate( mySemaphore ); if( SemaphoreTake( mySemaphore, 1000 ) ) // wait 1000 milliseconds on this semaphore { // access the protected resources // then release the semaphore if( !SemaphoreGive( mySemaphore ) ) // then handle the error here }
int SemaphoreGiveFromISR | ( | void * | semaphore, | |
int | taskWoken | |||
) |
Release a semaphore from within an ISR.
See SemaphoreGive( ) for an alternative which can be used when not in an ISR.
semaphore | The semaphore to release. | |
taskWoken | This is included so an ISR can make multiple calls to SemaphoreGiveFromISR() from a single interrupt. The first call should always pass in 0. Subsequent calls should pass in the value returned from the previous call. |
void* mySemaphore; SemaphoreCreate( mySemaphore ); void TimerISR( ) { static int taskWoken = 0; taskWoken = SemaphoreGiveFromISR( mySemaphore, taskWoken ); // If taskWoken was set to true you may want to yield (force a switch) // here. }
int SemaphoreTake | ( | void * | semaphore, | |
int | blockTime | |||
) |
Obtain a semaphore.
The semaphore must have first been created with SemaphoreCreate( ).
semaphore | The semaphore to take. | |
blockTime | The time, in milliseconds, to wait for the semaphore to become available. |
void* mySemaphore; SemaphoreCreate( mySemaphore ); if( SemaphoreTake( mySemaphore, 100 ) ) // wait 100 milliseconds on this semaphore { // now access the protected resources }