diff options
Diffstat (limited to 'freertos/Source/include/semphr.h')
-rw-r--r-- | freertos/Source/include/semphr.h | 505 |
1 files changed, 416 insertions, 89 deletions
diff --git a/freertos/Source/include/semphr.h b/freertos/Source/include/semphr.h index 9f76072..a674b02 100644 --- a/freertos/Source/include/semphr.h +++ b/freertos/Source/include/semphr.h @@ -1,5 +1,5 @@ /* - FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd. + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. @@ -87,6 +87,10 @@ typedef QueueHandle_t SemaphoreHandle_t; * semphr. h * <pre>vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )</pre> * + * In many usage scenarios it is faster and more memory efficient to use a + * direct to task notification in place of a binary semaphore! + * http://www.freertos.org/RTOS-task-notifications.html + * * This old vSemaphoreCreateBinary() macro is now deprecated in favour of the * xSemaphoreCreateBinary() function. Note that binary semaphores created using * the vSemaphoreCreateBinary() macro are created in a state such that the @@ -128,19 +132,37 @@ typedef QueueHandle_t SemaphoreHandle_t; * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary * \ingroup Semaphores */ -#define vSemaphoreCreateBinary( xSemaphore ) \ - { \ - ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ - if( ( xSemaphore ) != NULL ) \ - { \ - ( void ) xSemaphoreGive( ( xSemaphore ) ); \ - } \ - } +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + #define vSemaphoreCreateBinary( xSemaphore ) \ + { \ + ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ + if( ( xSemaphore ) != NULL ) \ + { \ + ( void ) xSemaphoreGive( ( xSemaphore ) ); \ + } \ + } +#endif /** * semphr. h * <pre>SemaphoreHandle_t xSemaphoreCreateBinary( void )</pre> * + * Creates a new binary semaphore instance, and returns a handle by which the + * new semaphore can be referenced. + * + * In many usage scenarios it is faster and more memory efficient to use a + * direct to task notification in place of a binary semaphore! + * http://www.freertos.org/RTOS-task-notifications.html + * + * Internally, within the FreeRTOS implementation, binary semaphores use a block + * of memory, in which the semaphore structure is stored. If a binary semaphore + * is created using xSemaphoreCreateBinary() then the required memory is + * automatically dynamically allocated inside the xSemaphoreCreateBinary() + * function. (see http://www.freertos.org/a00111.html). If a binary semaphore + * is created using xSemaphoreCreateBinaryStatic() then the application writer + * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a + * binary semaphore to be created without using any dynamic memory allocation. + * * The old vSemaphoreCreateBinary() macro is now deprecated in favour of this * xSemaphoreCreateBinary() function. Note that binary semaphores created using * the vSemaphoreCreateBinary() macro are created in a state such that the @@ -148,11 +170,6 @@ typedef QueueHandle_t SemaphoreHandle_t; * created using xSemaphoreCreateBinary() are created in a state such that the * the semaphore must first be 'given' before it can be 'taken'. * - * Function that creates a semaphore by using the existing queue mechanism. - * The queue length is 1 as this is a binary semaphore. The data size is 0 - * as nothing is actually stored - all that is important is whether the queue is - * empty or full (the binary semaphore is available or not). - * * This type of semaphore can be used for pure synchronisation between tasks or * between an interrupt and a task. The semaphore need not be given back once * obtained, so one task/interrupt can continuously 'give' the semaphore while @@ -160,7 +177,8 @@ typedef QueueHandle_t SemaphoreHandle_t; * semaphore does not use a priority inheritance mechanism. For an alternative * that does use priority inheritance see xSemaphoreCreateMutex(). * - * @return Handle to the created semaphore. + * @return Handle to the created semaphore, or NULL if the memory required to + * hold the semaphore's data structures could not be allocated. * * Example usage: <pre> @@ -168,7 +186,7 @@ typedef QueueHandle_t SemaphoreHandle_t; void vATask( void * pvParameters ) { - // Semaphore cannot be used before a call to vSemaphoreCreateBinary (). + // Semaphore cannot be used before a call to xSemaphoreCreateBinary(). // This is a macro so pass the variable in directly. xSemaphore = xSemaphoreCreateBinary(); @@ -179,10 +197,71 @@ typedef QueueHandle_t SemaphoreHandle_t; } } </pre> - * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary + * \defgroup xSemaphoreCreateBinary xSemaphoreCreateBinary + * \ingroup Semaphores + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + #define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ) +#endif + +/** + * semphr. h + * <pre>SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer )</pre> + * + * Creates a new binary semaphore instance, and returns a handle by which the + * new semaphore can be referenced. + * + * NOTE: In many usage scenarios it is faster and more memory efficient to use a + * direct to task notification in place of a binary semaphore! + * http://www.freertos.org/RTOS-task-notifications.html + * + * Internally, within the FreeRTOS implementation, binary semaphores use a block + * of memory, in which the semaphore structure is stored. If a binary semaphore + * is created using xSemaphoreCreateBinary() then the required memory is + * automatically dynamically allocated inside the xSemaphoreCreateBinary() + * function. (see http://www.freertos.org/a00111.html). If a binary semaphore + * is created using xSemaphoreCreateBinaryStatic() then the application writer + * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a + * binary semaphore to be created without using any dynamic memory allocation. + * + * This type of semaphore can be used for pure synchronisation between tasks or + * between an interrupt and a task. The semaphore need not be given back once + * obtained, so one task/interrupt can continuously 'give' the semaphore while + * another continuously 'takes' the semaphore. For this reason this type of + * semaphore does not use a priority inheritance mechanism. For an alternative + * that does use priority inheritance see xSemaphoreCreateMutex(). + * + * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t, + * which will then be used to hold the semaphore's data structure, removing the + * need for the memory to be allocated dynamically. + * + * @return If the semaphore is created then a handle to the created semaphore is + * returned. If pxSemaphoreBuffer is NULL then NULL is returned. + * + * Example usage: + <pre> + SemaphoreHandle_t xSemaphore = NULL; + StaticSemaphore_t xSemaphoreBuffer; + + void vATask( void * pvParameters ) + { + // Semaphore cannot be used before a call to xSemaphoreCreateBinary(). + // The semaphore's data structures will be placed in the xSemaphoreBuffer + // variable, the address of which is passed into the function. The + // function's parameter is not NULL, so the function will not attempt any + // dynamic memory allocation, and therefore the function will not return + // return NULL. + xSemaphore = xSemaphoreCreateBinary( &xSemaphoreBuffer ); + + // Rest of task code goes here. + } + </pre> + * \defgroup xSemaphoreCreateBinaryStatic xSemaphoreCreateBinaryStatic * \ingroup Semaphores */ -#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ) +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + #define xSemaphoreCreateBinaryStatic( pxStaticSemaphore ) xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticSemaphore, queueQUEUE_TYPE_BINARY_SEMAPHORE ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ /** * semphr. h @@ -192,7 +271,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * )</pre> * * <i>Macro</i> to obtain a semaphore. The semaphore must have previously been - * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or + * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or * xSemaphoreCreateCounting(). * * @param xSemaphore A handle to the semaphore being taken - obtained when @@ -215,7 +294,7 @@ typedef QueueHandle_t SemaphoreHandle_t; void vATask( void * pvParameters ) { // Create the semaphore to guard a shared resource. - vSemaphoreCreateBinary( xSemaphore ); + xSemaphore = xSemaphoreCreateBinary(); } // A task that uses the semaphore. @@ -270,8 +349,8 @@ typedef QueueHandle_t SemaphoreHandle_t; * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex * doesn't become available again until the owner has called * xSemaphoreGiveRecursive() for each successful 'take' request. For example, - * if a task successfully 'takes' the same mutex 5 times then the mutex - * is not available to any other task until it has also 'given' the mutex back + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back * exactly five times. * * @param xMutex A handle to the mutex being obtained. This is the @@ -280,8 +359,8 @@ typedef QueueHandle_t SemaphoreHandle_t; * @param xBlockTime The time in ticks to wait for the semaphore to become * available. The macro portTICK_PERIOD_MS can be used to convert this to a * real time. A block time of zero can be used to poll the semaphore. If - * the task already owns the semaphore then xSemaphoreTakeRecursive() - * returns immediately no matter what the value of xBlockTime. + * the task already owns the semaphore then xSemaphoreTakeRecursive() will + * return immediately no matter what the value of xBlockTime. * * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime * expired without the semaphore becoming available. @@ -320,7 +399,7 @@ typedef QueueHandle_t SemaphoreHandle_t; xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); - // The mutex has now been 'taken' three times, so is not + // The mutex has now been 'taken' three times, so will not be // available to another task until it has also been given back // three times. Again it is unlikely that real code would have // these calls sequentially, but instead buried in a more complex @@ -342,29 +421,16 @@ typedef QueueHandle_t SemaphoreHandle_t; * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive * \ingroup Semaphores */ -#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) - - -/* - * xSemaphoreAltTake() is an alternative version of xSemaphoreTake(). - * - * The source code that implements the alternative (Alt) API is much - * simpler because it executes everything from within a critical section. - * This is the approach taken by many other RTOSes, but FreeRTOS.org has the - * preferred fully featured API too. The fully featured API has more - * complex code that takes longer to execute, but makes much less use of - * critical sections. Therefore the alternative API sacrifices interrupt - * responsiveness to gain execution speed, whereas the fully featured API - * sacrifices execution speed to ensure better interrupt responsiveness. - */ -#define xSemaphoreAltTake( xSemaphore, xBlockTime ) xQueueAltGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) +#if( configUSE_RECURSIVE_MUTEXES == 1 ) + #define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) +#endif /** * semphr. h * <pre>xSemaphoreGive( SemaphoreHandle_t xSemaphore )</pre> * * <i>Macro</i> to release a semaphore. The semaphore must have previously been - * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or + * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake(). * * This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for @@ -388,7 +454,7 @@ typedef QueueHandle_t SemaphoreHandle_t; void vATask( void * pvParameters ) { // Create the semaphore to guard a shared resource. - vSemaphoreCreateBinary( xSemaphore ); + xSemaphore = vSemaphoreCreateBinary(); if( xSemaphore != NULL ) { @@ -438,8 +504,8 @@ typedef QueueHandle_t SemaphoreHandle_t; * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex * doesn't become available again until the owner has called * xSemaphoreGiveRecursive() for each successful 'take' request. For example, - * if a task successfully 'takes' the same mutex 5 times then the mutex is - * not available to any other task until it has also 'given' the mutex back + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back * exactly five times. * * @param xMutex A handle to the mutex being released, or 'given'. This is the @@ -481,7 +547,7 @@ typedef QueueHandle_t SemaphoreHandle_t; xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); - // The mutex has now been 'taken' three times, so is not + // The mutex has now been 'taken' three times, so will not be // available to another task until it has also been given back // three times. Again it is unlikely that real code would have // these calls sequentially, it would be more likely that the calls @@ -504,21 +570,9 @@ typedef QueueHandle_t SemaphoreHandle_t; * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive * \ingroup Semaphores */ -#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) - -/* - * xSemaphoreAltGive() is an alternative version of xSemaphoreGive(). - * - * The source code that implements the alternative (Alt) API is much - * simpler because it executes everything from within a critical section. - * This is the approach taken by many other RTOSes, but FreeRTOS.org has the - * preferred fully featured API too. The fully featured API has more - * complex code that takes longer to execute, but makes much less use of - * critical sections. Therefore the alternative API sacrifices interrupt - * responsiveness to gain execution speed, whereas the fully featured API - * sacrifices execution speed to ensure better interrupt responsiveness. - */ -#define xSemaphoreAltGive( xSemaphore ) xQueueAltGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) +#if( configUSE_RECURSIVE_MUTEXES == 1 ) + #define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) +#endif /** * semphr. h @@ -529,7 +583,7 @@ typedef QueueHandle_t SemaphoreHandle_t; )</pre> * * <i>Macro</i> to release a semaphore. The semaphore must have previously been - * created with a call to vSemaphoreCreateBinary() or xSemaphoreCreateCounting(). + * created with a call to xSemaphoreCreateBinary() or xSemaphoreCreateCounting(). * * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) * must not be used with this macro. @@ -539,7 +593,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * @param xSemaphore A handle to the semaphore being released. This is the * handle returned when the semaphore was created. * - * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() sets + * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set * *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task * to unblock, and the unblocked task has a priority higher than the currently * running task. If xSemaphoreGiveFromISR() sets this value to pdTRUE then @@ -569,7 +623,7 @@ typedef QueueHandle_t SemaphoreHandle_t; // ... // We have finished our task. Return to the top of the loop where - // we block on the semaphore until it is time to execute + // we will block on the semaphore until it is time to execute // again. Note when using the semaphore for synchronisation with an // ISR in this manner there is no need to 'give' the semaphore back. } @@ -620,7 +674,7 @@ typedef QueueHandle_t SemaphoreHandle_t; )</pre> * * <i>Macro</i> to take a semaphore from an ISR. The semaphore must have - * previously been created with a call to vSemaphoreCreateBinary() or + * previously been created with a call to xSemaphoreCreateBinary() or * xSemaphoreCreateCounting(). * * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) @@ -634,7 +688,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * @param xSemaphore A handle to the semaphore being taken. This is the * handle returned when the semaphore was created. * - * @param pxHigherPriorityTaskWoken xSemaphoreTakeFromISR() set + * @param pxHigherPriorityTaskWoken xSemaphoreTakeFromISR() will set * *pxHigherPriorityTaskWoken to pdTRUE if taking the semaphore caused a task * to unblock, and the unblocked task has a priority higher than the currently * running task. If xSemaphoreTakeFromISR() sets this value to pdTRUE then @@ -649,12 +703,21 @@ typedef QueueHandle_t SemaphoreHandle_t; * semphr. h * <pre>SemaphoreHandle_t xSemaphoreCreateMutex( void )</pre> * - * <i>Macro</i> that implements a mutex semaphore by using the existing queue - * mechanism. + * Creates a new mutex type semaphore instance, and returns a handle by which + * the new mutex can be referenced. + * + * Internally, within the FreeRTOS implementation, mutex semaphores use a block + * of memory, in which the mutex structure is stored. If a mutex is created + * using xSemaphoreCreateMutex() then the required memory is automatically + * dynamically allocated inside the xSemaphoreCreateMutex() function. (see + * http://www.freertos.org/a00111.html). If a mutex is created using + * xSemaphoreCreateMutexStatic() then the application writer must provided the + * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created + * without using any dynamic memory allocation. * - * Mutexes created using this macro can be accessed using the xSemaphoreTake() + * Mutexes created using this function can be accessed using the xSemaphoreTake() * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and - * xSemaphoreGiveRecursive() macros should not be used. + * xSemaphoreGiveRecursive() macros must not be used. * * This type of semaphore uses a priority inheritance mechanism so a task * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the @@ -662,13 +725,14 @@ typedef QueueHandle_t SemaphoreHandle_t; * * Mutex type semaphores cannot be used from within interrupt service routines. * - * See vSemaphoreCreateBinary() for an alternative implementation that can be + * See xSemaphoreCreateBinary() for an alternative implementation that can be * used for pure synchronisation (where one task or interrupt always 'gives' the * semaphore and another always 'takes' the semaphore) and from within interrupt * service routines. * - * @return xSemaphore Handle to the created mutex semaphore. Should be of type - * SemaphoreHandle_t. + * @return If the mutex was successfully created then a handle to the created + * semaphore is returned. If there was not enough heap to allocate the mutex + * data structures then NULL is returned. * * Example usage: <pre> @@ -687,28 +751,102 @@ typedef QueueHandle_t SemaphoreHandle_t; } } </pre> - * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex + * \defgroup xSemaphoreCreateMutex xSemaphoreCreateMutex + * \ingroup Semaphores + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + #define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ) +#endif + +/** + * semphr. h + * <pre>SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer )</pre> + * + * Creates a new mutex type semaphore instance, and returns a handle by which + * the new mutex can be referenced. + * + * Internally, within the FreeRTOS implementation, mutex semaphores use a block + * of memory, in which the mutex structure is stored. If a mutex is created + * using xSemaphoreCreateMutex() then the required memory is automatically + * dynamically allocated inside the xSemaphoreCreateMutex() function. (see + * http://www.freertos.org/a00111.html). If a mutex is created using + * xSemaphoreCreateMutexStatic() then the application writer must provided the + * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created + * without using any dynamic memory allocation. + * + * Mutexes created using this function can be accessed using the xSemaphoreTake() + * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and + * xSemaphoreGiveRecursive() macros must not be used. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See xSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t, + * which will be used to hold the mutex's data structure, removing the need for + * the memory to be allocated dynamically. + * + * @return If the mutex was successfully created then a handle to the created + * mutex is returned. If pxMutexBuffer was NULL then NULL is returned. + * + * Example usage: + <pre> + SemaphoreHandle_t xSemaphore; + StaticSemaphore_t xMutexBuffer; + + void vATask( void * pvParameters ) + { + // A mutex cannot be used before it has been created. xMutexBuffer is + // into xSemaphoreCreateMutexStatic() so no dynamic memory allocation is + // attempted. + xSemaphore = xSemaphoreCreateMutexStatic( &xMutexBuffer ); + + // As no dynamic memory allocation was performed, xSemaphore cannot be NULL, + // so there is no need to check it. + } + </pre> + * \defgroup xSemaphoreCreateMutexStatic xSemaphoreCreateMutexStatic * \ingroup Semaphores */ -#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ) + #if( configSUPPORT_STATIC_ALLOCATION == 1 ) + #define xSemaphoreCreateMutexStatic( pxMutexBuffer ) xQueueCreateMutexStatic( queueQUEUE_TYPE_MUTEX, ( pxMutexBuffer ) ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ /** * semphr. h * <pre>SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )</pre> * - * <i>Macro</i> that implements a recursive mutex by using the existing queue - * mechanism. + * Creates a new recursive mutex type semaphore instance, and returns a handle + * by which the new recursive mutex can be referenced. + * + * Internally, within the FreeRTOS implementation, recursive mutexs use a block + * of memory, in which the mutex structure is stored. If a recursive mutex is + * created using xSemaphoreCreateRecursiveMutex() then the required memory is + * automatically dynamically allocated inside the + * xSemaphoreCreateRecursiveMutex() function. (see + * http://www.freertos.org/a00111.html). If a recursive mutex is created using + * xSemaphoreCreateRecursiveMutexStatic() then the application writer must + * provide the memory that will get used by the mutex. + * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to + * be created without using any dynamic memory allocation. * * Mutexes created using this macro can be accessed using the * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The - * xSemaphoreTake() and xSemaphoreGive() macros should not be used. + * xSemaphoreTake() and xSemaphoreGive() macros must not be used. * * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex * doesn't become available again until the owner has called * xSemaphoreGiveRecursive() for each successful 'take' request. For example, - * if a task successfully 'takes' the same mutex 5 times then the mutex is - * not available to any other task until it has also 'given' the mutex back + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back * exactly five times. * * This type of semaphore uses a priority inheritance mechanism so a task @@ -717,13 +855,13 @@ typedef QueueHandle_t SemaphoreHandle_t; * * Mutex type semaphores cannot be used from within interrupt service routines. * - * See vSemaphoreCreateBinary() for an alternative implementation that can be + * See xSemaphoreCreateBinary() for an alternative implementation that can be * used for pure synchronisation (where one task or interrupt always 'gives' the * semaphore and another always 'takes' the semaphore) and from within interrupt * service routines. * * @return xSemaphore Handle to the created mutex semaphore. Should be of type - * SemaphoreHandle_t. + * SemaphoreHandle_t. * * Example usage: <pre> @@ -742,25 +880,115 @@ typedef QueueHandle_t SemaphoreHandle_t; } } </pre> - * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex + * \defgroup xSemaphoreCreateRecursiveMutex xSemaphoreCreateRecursiveMutex * \ingroup Semaphores */ -#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX ) +#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) ) + #define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX ) +#endif + +/** + * semphr. h + * <pre>SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic( StaticSemaphore_t *pxMutexBuffer )</pre> + * + * Creates a new recursive mutex type semaphore instance, and returns a handle + * by which the new recursive mutex can be referenced. + * + * Internally, within the FreeRTOS implementation, recursive mutexs use a block + * of memory, in which the mutex structure is stored. If a recursive mutex is + * created using xSemaphoreCreateRecursiveMutex() then the required memory is + * automatically dynamically allocated inside the + * xSemaphoreCreateRecursiveMutex() function. (see + * http://www.freertos.org/a00111.html). If a recursive mutex is created using + * xSemaphoreCreateRecursiveMutexStatic() then the application writer must + * provide the memory that will get used by the mutex. + * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to + * be created without using any dynamic memory allocation. + * + * Mutexes created using this macro can be accessed using the + * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The + * xSemaphoreTake() and xSemaphoreGive() macros must not be used. + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See xSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t, + * which will then be used to hold the recursive mutex's data structure, + * removing the need for the memory to be allocated dynamically. + * + * @return If the recursive mutex was successfully created then a handle to the + * created recursive mutex is returned. If pxMutexBuffer was NULL then NULL is + * returned. + * + * Example usage: + <pre> + SemaphoreHandle_t xSemaphore; + StaticSemaphore_t xMutexBuffer; + + void vATask( void * pvParameters ) + { + // A recursive semaphore cannot be used before it is created. Here a + // recursive mutex is created using xSemaphoreCreateRecursiveMutexStatic(). + // The address of xMutexBuffer is passed into the function, and will hold + // the mutexes data structures - so no dynamic memory allocation will be + // attempted. + xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xMutexBuffer ); + + // As no dynamic memory allocation was performed, xSemaphore cannot be NULL, + // so there is no need to check it. + } + </pre> + * \defgroup xSemaphoreCreateRecursiveMutexStatic xSemaphoreCreateRecursiveMutexStatic + * \ingroup Semaphores + */ +#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) ) + #define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutexStatic( queueQUEUE_TYPE_RECURSIVE_MUTEX, pxStaticSemaphore ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ /** * semphr. h * <pre>SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount )</pre> * - * <i>Macro</i> that creates a counting semaphore by using the existing - * queue mechanism. + * Creates a new counting semaphore instance, and returns a handle by which the + * new counting semaphore can be referenced. + * + * In many usage scenarios it is faster and more memory efficient to use a + * direct to task notification in place of a counting semaphore! + * http://www.freertos.org/RTOS-task-notifications.html + * + * Internally, within the FreeRTOS implementation, counting semaphores use a + * block of memory, in which the counting semaphore structure is stored. If a + * counting semaphore is created using xSemaphoreCreateCounting() then the + * required memory is automatically dynamically allocated inside the + * xSemaphoreCreateCounting() function. (see + * http://www.freertos.org/a00111.html). If a counting semaphore is created + * using xSemaphoreCreateCountingStatic() then the application writer can + * instead optionally provide the memory that will get used by the counting + * semaphore. xSemaphoreCreateCountingStatic() therefore allows a counting + * semaphore to be created without using any dynamic memory allocation. * * Counting semaphores are typically used for two things: * * 1) Counting events. * - * In this usage scenario an event handler 'gives' a semaphore each time + * In this usage scenario an event handler will 'give' a semaphore each time * an event occurs (incrementing the semaphore count value), and a handler - * task 'takes' a semaphore each time it processes an event + * task will 'take' a semaphore each time it processes an event * (decrementing the semaphore count value). The count value is therefore * the difference between the number of events that have occurred and the * number that have been processed. In this case it is desirable for the @@ -808,7 +1036,94 @@ typedef QueueHandle_t SemaphoreHandle_t; * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting * \ingroup Semaphores */ -#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + #define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) +#endif + +/** + * semphr. h + * <pre>SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer )</pre> + * + * Creates a new counting semaphore instance, and returns a handle by which the + * new counting semaphore can be referenced. + * + * In many usage scenarios it is faster and more memory efficient to use a + * direct to task notification in place of a counting semaphore! + * http://www.freertos.org/RTOS-task-notifications.html + * + * Internally, within the FreeRTOS implementation, counting semaphores use a + * block of memory, in which the counting semaphore structure is stored. If a + * counting semaphore is created using xSemaphoreCreateCounting() then the + * required memory is automatically dynamically allocated inside the + * xSemaphoreCreateCounting() function. (see + * http://www.freertos.org/a00111.html). If a counting semaphore is created + * using xSemaphoreCreateCountingStatic() then the application writer must + * provide the memory. xSemaphoreCreateCountingStatic() therefore allows a + * counting semaphore to be created without using any dynamic memory allocation. + * + * Counting semaphores are typically used for two things: + * + * 1) Counting events. + * + * In this usage scenario an event handler will 'give' a semaphore each time + * an event occurs (incrementing the semaphore count value), and a handler + * task will 'take' a semaphore each time it processes an event + * (decrementing the semaphore count value). The count value is therefore + * the difference between the number of events that have occurred and the + * number that have been processed. In this case it is desirable for the + * initial count value to be zero. + * + * 2) Resource management. + * + * In this usage scenario the count value indicates the number of resources + * available. To obtain control of a resource a task must first obtain a + * semaphore - decrementing the semaphore count value. When the count value + * reaches zero there are no free resources. When a task finishes with the + * resource it 'gives' the semaphore back - incrementing the semaphore count + * value. In this case it is desirable for the initial count value to be + * equal to the maximum count value, indicating that all resources are free. + * + * @param uxMaxCount The maximum count value that can be reached. When the + * semaphore reaches this value it can no longer be 'given'. + * + * @param uxInitialCount The count value assigned to the semaphore when it is + * created. + * + * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t, + * which will then be used to hold the semaphore's data structure, removing the + * need for the memory to be allocated dynamically. + * + * @return If the counting semaphore was successfully created then a handle to + * the created counting semaphore is returned. If pxSemaphoreBuffer was NULL + * then NULL is returned. + * + * Example usage: + <pre> + SemaphoreHandle_t xSemaphore; + StaticSemaphore_t xSemaphoreBuffer; + + void vATask( void * pvParameters ) + { + SemaphoreHandle_t xSemaphore = NULL; + + // Counting semaphore cannot be used before they have been created. Create + // a counting semaphore using xSemaphoreCreateCountingStatic(). The max + // value to which the semaphore can count is 10, and the initial value + // assigned to the count will be 0. The address of xSemaphoreBuffer is + // passed in and will be used to hold the semaphore structure, so no dynamic + // memory allocation will be used. + xSemaphore = xSemaphoreCreateCounting( 10, 0, &xSemaphoreBuffer ); + + // No memory allocation was attempted so xSemaphore cannot be NULL, so there + // is no need to check its value. + } + </pre> + * \defgroup xSemaphoreCreateCountingStatic xSemaphoreCreateCountingStatic + * \ingroup Semaphores + */ +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + #define xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxSemaphoreBuffer ) xQueueCreateCountingSemaphoreStatic( ( uxMaxCount ), ( uxInitialCount ), ( pxSemaphoreBuffer ) ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ /** * semphr. h @@ -839,6 +1154,18 @@ typedef QueueHandle_t SemaphoreHandle_t; */ #define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) ) +/** + * semphr.h + * <pre>UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore );</pre> + * + * If the semaphore is a counting semaphore then uxSemaphoreGetCount() returns + * its current count value. If the semaphore is a binary semaphore then + * uxSemaphoreGetCount() returns 1 if the semaphore is available, and 0 if the + * semaphore is not available. + * + */ +#define uxSemaphoreGetCount( xSemaphore ) uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) ) + #endif /* SEMAPHORE_H */ |