Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: frdm_k64f_freertos_lib
src/include/semphr.h@0:62cd296ba2a7, 2017-05-31 (annotated)
- Committer:
- fep
- Date:
- Wed May 31 02:27:10 2017 +0000
- Revision:
- 0:62cd296ba2a7
FreeRTOS v9.0.0 for Cortex-M4F (FRDM-K64F and others...)
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| fep | 0:62cd296ba2a7 | 1 | /* |
| fep | 0:62cd296ba2a7 | 2 | FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. |
| fep | 0:62cd296ba2a7 | 3 | All rights reserved |
| fep | 0:62cd296ba2a7 | 4 | |
| fep | 0:62cd296ba2a7 | 5 | VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. |
| fep | 0:62cd296ba2a7 | 6 | |
| fep | 0:62cd296ba2a7 | 7 | This file is part of the FreeRTOS distribution. |
| fep | 0:62cd296ba2a7 | 8 | |
| fep | 0:62cd296ba2a7 | 9 | FreeRTOS is free software; you can redistribute it and/or modify it under |
| fep | 0:62cd296ba2a7 | 10 | the terms of the GNU General Public License (version 2) as published by the |
| fep | 0:62cd296ba2a7 | 11 | Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. |
| fep | 0:62cd296ba2a7 | 12 | |
| fep | 0:62cd296ba2a7 | 13 | *************************************************************************** |
| fep | 0:62cd296ba2a7 | 14 | >>! NOTE: The modification to the GPL is included to allow you to !<< |
| fep | 0:62cd296ba2a7 | 15 | >>! distribute a combined work that includes FreeRTOS without being !<< |
| fep | 0:62cd296ba2a7 | 16 | >>! obliged to provide the source code for proprietary components !<< |
| fep | 0:62cd296ba2a7 | 17 | >>! outside of the FreeRTOS kernel. !<< |
| fep | 0:62cd296ba2a7 | 18 | *************************************************************************** |
| fep | 0:62cd296ba2a7 | 19 | |
| fep | 0:62cd296ba2a7 | 20 | FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY |
| fep | 0:62cd296ba2a7 | 21 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| fep | 0:62cd296ba2a7 | 22 | FOR A PARTICULAR PURPOSE. Full license text is available on the following |
| fep | 0:62cd296ba2a7 | 23 | link: http://www.freertos.org/a00114.html |
| fep | 0:62cd296ba2a7 | 24 | |
| fep | 0:62cd296ba2a7 | 25 | *************************************************************************** |
| fep | 0:62cd296ba2a7 | 26 | * * |
| fep | 0:62cd296ba2a7 | 27 | * FreeRTOS provides completely free yet professionally developed, * |
| fep | 0:62cd296ba2a7 | 28 | * robust, strictly quality controlled, supported, and cross * |
| fep | 0:62cd296ba2a7 | 29 | * platform software that is more than just the market leader, it * |
| fep | 0:62cd296ba2a7 | 30 | * is the industry's de facto standard. * |
| fep | 0:62cd296ba2a7 | 31 | * * |
| fep | 0:62cd296ba2a7 | 32 | * Help yourself get started quickly while simultaneously helping * |
| fep | 0:62cd296ba2a7 | 33 | * to support the FreeRTOS project by purchasing a FreeRTOS * |
| fep | 0:62cd296ba2a7 | 34 | * tutorial book, reference manual, or both: * |
| fep | 0:62cd296ba2a7 | 35 | * http://www.FreeRTOS.org/Documentation * |
| fep | 0:62cd296ba2a7 | 36 | * * |
| fep | 0:62cd296ba2a7 | 37 | *************************************************************************** |
| fep | 0:62cd296ba2a7 | 38 | |
| fep | 0:62cd296ba2a7 | 39 | http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading |
| fep | 0:62cd296ba2a7 | 40 | the FAQ page "My application does not run, what could be wrong?". Have you |
| fep | 0:62cd296ba2a7 | 41 | defined configASSERT()? |
| fep | 0:62cd296ba2a7 | 42 | |
| fep | 0:62cd296ba2a7 | 43 | http://www.FreeRTOS.org/support - In return for receiving this top quality |
| fep | 0:62cd296ba2a7 | 44 | embedded software for free we request you assist our global community by |
| fep | 0:62cd296ba2a7 | 45 | participating in the support forum. |
| fep | 0:62cd296ba2a7 | 46 | |
| fep | 0:62cd296ba2a7 | 47 | http://www.FreeRTOS.org/training - Investing in training allows your team to |
| fep | 0:62cd296ba2a7 | 48 | be as productive as possible as early as possible. Now you can receive |
| fep | 0:62cd296ba2a7 | 49 | FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers |
| fep | 0:62cd296ba2a7 | 50 | Ltd, and the world's leading authority on the world's leading RTOS. |
| fep | 0:62cd296ba2a7 | 51 | |
| fep | 0:62cd296ba2a7 | 52 | http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, |
| fep | 0:62cd296ba2a7 | 53 | including FreeRTOS+Trace - an indispensable productivity tool, a DOS |
| fep | 0:62cd296ba2a7 | 54 | compatible FAT file system, and our tiny thread aware UDP/IP stack. |
| fep | 0:62cd296ba2a7 | 55 | |
| fep | 0:62cd296ba2a7 | 56 | http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. |
| fep | 0:62cd296ba2a7 | 57 | Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. |
| fep | 0:62cd296ba2a7 | 58 | |
| fep | 0:62cd296ba2a7 | 59 | http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High |
| fep | 0:62cd296ba2a7 | 60 | Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS |
| fep | 0:62cd296ba2a7 | 61 | licenses offer ticketed support, indemnification and commercial middleware. |
| fep | 0:62cd296ba2a7 | 62 | |
| fep | 0:62cd296ba2a7 | 63 | http://www.SafeRTOS.com - High Integrity Systems also provide a safety |
| fep | 0:62cd296ba2a7 | 64 | engineered and independently SIL3 certified version for use in safety and |
| fep | 0:62cd296ba2a7 | 65 | mission critical applications that require provable dependability. |
| fep | 0:62cd296ba2a7 | 66 | |
| fep | 0:62cd296ba2a7 | 67 | 1 tab == 4 spaces! |
| fep | 0:62cd296ba2a7 | 68 | */ |
| fep | 0:62cd296ba2a7 | 69 | |
| fep | 0:62cd296ba2a7 | 70 | #ifndef SEMAPHORE_H |
| fep | 0:62cd296ba2a7 | 71 | #define SEMAPHORE_H |
| fep | 0:62cd296ba2a7 | 72 | |
| fep | 0:62cd296ba2a7 | 73 | #ifndef INC_FREERTOS_H |
| fep | 0:62cd296ba2a7 | 74 | #error "include FreeRTOS.h" must appear in source files before "include semphr.h" |
| fep | 0:62cd296ba2a7 | 75 | #endif |
| fep | 0:62cd296ba2a7 | 76 | |
| fep | 0:62cd296ba2a7 | 77 | #include "queue.h" |
| fep | 0:62cd296ba2a7 | 78 | |
| fep | 0:62cd296ba2a7 | 79 | typedef QueueHandle_t SemaphoreHandle_t; |
| fep | 0:62cd296ba2a7 | 80 | |
| fep | 0:62cd296ba2a7 | 81 | #define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( uint8_t ) 1U ) |
| fep | 0:62cd296ba2a7 | 82 | #define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( uint8_t ) 0U ) |
| fep | 0:62cd296ba2a7 | 83 | #define semGIVE_BLOCK_TIME ( ( TickType_t ) 0U ) |
| fep | 0:62cd296ba2a7 | 84 | |
| fep | 0:62cd296ba2a7 | 85 | |
| fep | 0:62cd296ba2a7 | 86 | /** |
| fep | 0:62cd296ba2a7 | 87 | * semphr. h |
| fep | 0:62cd296ba2a7 | 88 | * <pre>vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )</pre> |
| fep | 0:62cd296ba2a7 | 89 | * |
| fep | 0:62cd296ba2a7 | 90 | * In many usage scenarios it is faster and more memory efficient to use a |
| fep | 0:62cd296ba2a7 | 91 | * direct to task notification in place of a binary semaphore! |
| fep | 0:62cd296ba2a7 | 92 | * http://www.freertos.org/RTOS-task-notifications.html |
| fep | 0:62cd296ba2a7 | 93 | * |
| fep | 0:62cd296ba2a7 | 94 | * This old vSemaphoreCreateBinary() macro is now deprecated in favour of the |
| fep | 0:62cd296ba2a7 | 95 | * xSemaphoreCreateBinary() function. Note that binary semaphores created using |
| fep | 0:62cd296ba2a7 | 96 | * the vSemaphoreCreateBinary() macro are created in a state such that the |
| fep | 0:62cd296ba2a7 | 97 | * first call to 'take' the semaphore would pass, whereas binary semaphores |
| fep | 0:62cd296ba2a7 | 98 | * created using xSemaphoreCreateBinary() are created in a state such that the |
| fep | 0:62cd296ba2a7 | 99 | * the semaphore must first be 'given' before it can be 'taken'. |
| fep | 0:62cd296ba2a7 | 100 | * |
| fep | 0:62cd296ba2a7 | 101 | * <i>Macro</i> that implements a semaphore by using the existing queue mechanism. |
| fep | 0:62cd296ba2a7 | 102 | * The queue length is 1 as this is a binary semaphore. The data size is 0 |
| fep | 0:62cd296ba2a7 | 103 | * as we don't want to actually store any data - we just want to know if the |
| fep | 0:62cd296ba2a7 | 104 | * queue is empty or full. |
| fep | 0:62cd296ba2a7 | 105 | * |
| fep | 0:62cd296ba2a7 | 106 | * This type of semaphore can be used for pure synchronisation between tasks or |
| fep | 0:62cd296ba2a7 | 107 | * between an interrupt and a task. The semaphore need not be given back once |
| fep | 0:62cd296ba2a7 | 108 | * obtained, so one task/interrupt can continuously 'give' the semaphore while |
| fep | 0:62cd296ba2a7 | 109 | * another continuously 'takes' the semaphore. For this reason this type of |
| fep | 0:62cd296ba2a7 | 110 | * semaphore does not use a priority inheritance mechanism. For an alternative |
| fep | 0:62cd296ba2a7 | 111 | * that does use priority inheritance see xSemaphoreCreateMutex(). |
| fep | 0:62cd296ba2a7 | 112 | * |
| fep | 0:62cd296ba2a7 | 113 | * @param xSemaphore Handle to the created semaphore. Should be of type SemaphoreHandle_t. |
| fep | 0:62cd296ba2a7 | 114 | * |
| fep | 0:62cd296ba2a7 | 115 | * Example usage: |
| fep | 0:62cd296ba2a7 | 116 | <pre> |
| fep | 0:62cd296ba2a7 | 117 | SemaphoreHandle_t xSemaphore = NULL; |
| fep | 0:62cd296ba2a7 | 118 | |
| fep | 0:62cd296ba2a7 | 119 | void vATask( void * pvParameters ) |
| fep | 0:62cd296ba2a7 | 120 | { |
| fep | 0:62cd296ba2a7 | 121 | // Semaphore cannot be used before a call to vSemaphoreCreateBinary (). |
| fep | 0:62cd296ba2a7 | 122 | // This is a macro so pass the variable in directly. |
| fep | 0:62cd296ba2a7 | 123 | vSemaphoreCreateBinary( xSemaphore ); |
| fep | 0:62cd296ba2a7 | 124 | |
| fep | 0:62cd296ba2a7 | 125 | if( xSemaphore != NULL ) |
| fep | 0:62cd296ba2a7 | 126 | { |
| fep | 0:62cd296ba2a7 | 127 | // The semaphore was created successfully. |
| fep | 0:62cd296ba2a7 | 128 | // The semaphore can now be used. |
| fep | 0:62cd296ba2a7 | 129 | } |
| fep | 0:62cd296ba2a7 | 130 | } |
| fep | 0:62cd296ba2a7 | 131 | </pre> |
| fep | 0:62cd296ba2a7 | 132 | * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary |
| fep | 0:62cd296ba2a7 | 133 | * \ingroup Semaphores |
| fep | 0:62cd296ba2a7 | 134 | */ |
| fep | 0:62cd296ba2a7 | 135 | #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) |
| fep | 0:62cd296ba2a7 | 136 | #define vSemaphoreCreateBinary( xSemaphore ) \ |
| fep | 0:62cd296ba2a7 | 137 | { \ |
| fep | 0:62cd296ba2a7 | 138 | ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ |
| fep | 0:62cd296ba2a7 | 139 | if( ( xSemaphore ) != NULL ) \ |
| fep | 0:62cd296ba2a7 | 140 | { \ |
| fep | 0:62cd296ba2a7 | 141 | ( void ) xSemaphoreGive( ( xSemaphore ) ); \ |
| fep | 0:62cd296ba2a7 | 142 | } \ |
| fep | 0:62cd296ba2a7 | 143 | } |
| fep | 0:62cd296ba2a7 | 144 | #endif |
| fep | 0:62cd296ba2a7 | 145 | |
| fep | 0:62cd296ba2a7 | 146 | /** |
| fep | 0:62cd296ba2a7 | 147 | * semphr. h |
| fep | 0:62cd296ba2a7 | 148 | * <pre>SemaphoreHandle_t xSemaphoreCreateBinary( void )</pre> |
| fep | 0:62cd296ba2a7 | 149 | * |
| fep | 0:62cd296ba2a7 | 150 | * Creates a new binary semaphore instance, and returns a handle by which the |
| fep | 0:62cd296ba2a7 | 151 | * new semaphore can be referenced. |
| fep | 0:62cd296ba2a7 | 152 | * |
| fep | 0:62cd296ba2a7 | 153 | * In many usage scenarios it is faster and more memory efficient to use a |
| fep | 0:62cd296ba2a7 | 154 | * direct to task notification in place of a binary semaphore! |
| fep | 0:62cd296ba2a7 | 155 | * http://www.freertos.org/RTOS-task-notifications.html |
| fep | 0:62cd296ba2a7 | 156 | * |
| fep | 0:62cd296ba2a7 | 157 | * Internally, within the FreeRTOS implementation, binary semaphores use a block |
| fep | 0:62cd296ba2a7 | 158 | * of memory, in which the semaphore structure is stored. If a binary semaphore |
| fep | 0:62cd296ba2a7 | 159 | * is created using xSemaphoreCreateBinary() then the required memory is |
| fep | 0:62cd296ba2a7 | 160 | * automatically dynamically allocated inside the xSemaphoreCreateBinary() |
| fep | 0:62cd296ba2a7 | 161 | * function. (see http://www.freertos.org/a00111.html). If a binary semaphore |
| fep | 0:62cd296ba2a7 | 162 | * is created using xSemaphoreCreateBinaryStatic() then the application writer |
| fep | 0:62cd296ba2a7 | 163 | * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a |
| fep | 0:62cd296ba2a7 | 164 | * binary semaphore to be created without using any dynamic memory allocation. |
| fep | 0:62cd296ba2a7 | 165 | * |
| fep | 0:62cd296ba2a7 | 166 | * The old vSemaphoreCreateBinary() macro is now deprecated in favour of this |
| fep | 0:62cd296ba2a7 | 167 | * xSemaphoreCreateBinary() function. Note that binary semaphores created using |
| fep | 0:62cd296ba2a7 | 168 | * the vSemaphoreCreateBinary() macro are created in a state such that the |
| fep | 0:62cd296ba2a7 | 169 | * first call to 'take' the semaphore would pass, whereas binary semaphores |
| fep | 0:62cd296ba2a7 | 170 | * created using xSemaphoreCreateBinary() are created in a state such that the |
| fep | 0:62cd296ba2a7 | 171 | * the semaphore must first be 'given' before it can be 'taken'. |
| fep | 0:62cd296ba2a7 | 172 | * |
| fep | 0:62cd296ba2a7 | 173 | * This type of semaphore can be used for pure synchronisation between tasks or |
| fep | 0:62cd296ba2a7 | 174 | * between an interrupt and a task. The semaphore need not be given back once |
| fep | 0:62cd296ba2a7 | 175 | * obtained, so one task/interrupt can continuously 'give' the semaphore while |
| fep | 0:62cd296ba2a7 | 176 | * another continuously 'takes' the semaphore. For this reason this type of |
| fep | 0:62cd296ba2a7 | 177 | * semaphore does not use a priority inheritance mechanism. For an alternative |
| fep | 0:62cd296ba2a7 | 178 | * that does use priority inheritance see xSemaphoreCreateMutex(). |
| fep | 0:62cd296ba2a7 | 179 | * |
| fep | 0:62cd296ba2a7 | 180 | * @return Handle to the created semaphore, or NULL if the memory required to |
| fep | 0:62cd296ba2a7 | 181 | * hold the semaphore's data structures could not be allocated. |
| fep | 0:62cd296ba2a7 | 182 | * |
| fep | 0:62cd296ba2a7 | 183 | * Example usage: |
| fep | 0:62cd296ba2a7 | 184 | <pre> |
| fep | 0:62cd296ba2a7 | 185 | SemaphoreHandle_t xSemaphore = NULL; |
| fep | 0:62cd296ba2a7 | 186 | |
| fep | 0:62cd296ba2a7 | 187 | void vATask( void * pvParameters ) |
| fep | 0:62cd296ba2a7 | 188 | { |
| fep | 0:62cd296ba2a7 | 189 | // Semaphore cannot be used before a call to xSemaphoreCreateBinary(). |
| fep | 0:62cd296ba2a7 | 190 | // This is a macro so pass the variable in directly. |
| fep | 0:62cd296ba2a7 | 191 | xSemaphore = xSemaphoreCreateBinary(); |
| fep | 0:62cd296ba2a7 | 192 | |
| fep | 0:62cd296ba2a7 | 193 | if( xSemaphore != NULL ) |
| fep | 0:62cd296ba2a7 | 194 | { |
| fep | 0:62cd296ba2a7 | 195 | // The semaphore was created successfully. |
| fep | 0:62cd296ba2a7 | 196 | // The semaphore can now be used. |
| fep | 0:62cd296ba2a7 | 197 | } |
| fep | 0:62cd296ba2a7 | 198 | } |
| fep | 0:62cd296ba2a7 | 199 | </pre> |
| fep | 0:62cd296ba2a7 | 200 | * \defgroup xSemaphoreCreateBinary xSemaphoreCreateBinary |
| fep | 0:62cd296ba2a7 | 201 | * \ingroup Semaphores |
| fep | 0:62cd296ba2a7 | 202 | */ |
| fep | 0:62cd296ba2a7 | 203 | #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) |
| fep | 0:62cd296ba2a7 | 204 | #define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ) |
| fep | 0:62cd296ba2a7 | 205 | #endif |
| fep | 0:62cd296ba2a7 | 206 | |
| fep | 0:62cd296ba2a7 | 207 | /** |
| fep | 0:62cd296ba2a7 | 208 | * semphr. h |
| fep | 0:62cd296ba2a7 | 209 | * <pre>SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer )</pre> |
| fep | 0:62cd296ba2a7 | 210 | * |
| fep | 0:62cd296ba2a7 | 211 | * Creates a new binary semaphore instance, and returns a handle by which the |
| fep | 0:62cd296ba2a7 | 212 | * new semaphore can be referenced. |
| fep | 0:62cd296ba2a7 | 213 | * |
| fep | 0:62cd296ba2a7 | 214 | * NOTE: In many usage scenarios it is faster and more memory efficient to use a |
| fep | 0:62cd296ba2a7 | 215 | * direct to task notification in place of a binary semaphore! |
| fep | 0:62cd296ba2a7 | 216 | * http://www.freertos.org/RTOS-task-notifications.html |
| fep | 0:62cd296ba2a7 | 217 | * |
| fep | 0:62cd296ba2a7 | 218 | * Internally, within the FreeRTOS implementation, binary semaphores use a block |
| fep | 0:62cd296ba2a7 | 219 | * of memory, in which the semaphore structure is stored. If a binary semaphore |
| fep | 0:62cd296ba2a7 | 220 | * is created using xSemaphoreCreateBinary() then the required memory is |
| fep | 0:62cd296ba2a7 | 221 | * automatically dynamically allocated inside the xSemaphoreCreateBinary() |
| fep | 0:62cd296ba2a7 | 222 | * function. (see http://www.freertos.org/a00111.html). If a binary semaphore |
| fep | 0:62cd296ba2a7 | 223 | * is created using xSemaphoreCreateBinaryStatic() then the application writer |
| fep | 0:62cd296ba2a7 | 224 | * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a |
| fep | 0:62cd296ba2a7 | 225 | * binary semaphore to be created without using any dynamic memory allocation. |
| fep | 0:62cd296ba2a7 | 226 | * |
| fep | 0:62cd296ba2a7 | 227 | * This type of semaphore can be used for pure synchronisation between tasks or |
| fep | 0:62cd296ba2a7 | 228 | * between an interrupt and a task. The semaphore need not be given back once |
| fep | 0:62cd296ba2a7 | 229 | * obtained, so one task/interrupt can continuously 'give' the semaphore while |
| fep | 0:62cd296ba2a7 | 230 | * another continuously 'takes' the semaphore. For this reason this type of |
| fep | 0:62cd296ba2a7 | 231 | * semaphore does not use a priority inheritance mechanism. For an alternative |
| fep | 0:62cd296ba2a7 | 232 | * that does use priority inheritance see xSemaphoreCreateMutex(). |
| fep | 0:62cd296ba2a7 | 233 | * |
| fep | 0:62cd296ba2a7 | 234 | * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t, |
| fep | 0:62cd296ba2a7 | 235 | * which will then be used to hold the semaphore's data structure, removing the |
| fep | 0:62cd296ba2a7 | 236 | * need for the memory to be allocated dynamically. |
| fep | 0:62cd296ba2a7 | 237 | * |
| fep | 0:62cd296ba2a7 | 238 | * @return If the semaphore is created then a handle to the created semaphore is |
| fep | 0:62cd296ba2a7 | 239 | * returned. If pxSemaphoreBuffer is NULL then NULL is returned. |
| fep | 0:62cd296ba2a7 | 240 | * |
| fep | 0:62cd296ba2a7 | 241 | * Example usage: |
| fep | 0:62cd296ba2a7 | 242 | <pre> |
| fep | 0:62cd296ba2a7 | 243 | SemaphoreHandle_t xSemaphore = NULL; |
| fep | 0:62cd296ba2a7 | 244 | StaticSemaphore_t xSemaphoreBuffer; |
| fep | 0:62cd296ba2a7 | 245 | |
| fep | 0:62cd296ba2a7 | 246 | void vATask( void * pvParameters ) |
| fep | 0:62cd296ba2a7 | 247 | { |
| fep | 0:62cd296ba2a7 | 248 | // Semaphore cannot be used before a call to xSemaphoreCreateBinary(). |
| fep | 0:62cd296ba2a7 | 249 | // The semaphore's data structures will be placed in the xSemaphoreBuffer |
| fep | 0:62cd296ba2a7 | 250 | // variable, the address of which is passed into the function. The |
| fep | 0:62cd296ba2a7 | 251 | // function's parameter is not NULL, so the function will not attempt any |
| fep | 0:62cd296ba2a7 | 252 | // dynamic memory allocation, and therefore the function will not return |
| fep | 0:62cd296ba2a7 | 253 | // return NULL. |
| fep | 0:62cd296ba2a7 | 254 | xSemaphore = xSemaphoreCreateBinary( &xSemaphoreBuffer ); |
| fep | 0:62cd296ba2a7 | 255 | |
| fep | 0:62cd296ba2a7 | 256 | // Rest of task code goes here. |
| fep | 0:62cd296ba2a7 | 257 | } |
| fep | 0:62cd296ba2a7 | 258 | </pre> |
| fep | 0:62cd296ba2a7 | 259 | * \defgroup xSemaphoreCreateBinaryStatic xSemaphoreCreateBinaryStatic |
| fep | 0:62cd296ba2a7 | 260 | * \ingroup Semaphores |
| fep | 0:62cd296ba2a7 | 261 | */ |
| fep | 0:62cd296ba2a7 | 262 | #if( configSUPPORT_STATIC_ALLOCATION == 1 ) |
| fep | 0:62cd296ba2a7 | 263 | #define xSemaphoreCreateBinaryStatic( pxStaticSemaphore ) xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticSemaphore, queueQUEUE_TYPE_BINARY_SEMAPHORE ) |
| fep | 0:62cd296ba2a7 | 264 | #endif /* configSUPPORT_STATIC_ALLOCATION */ |
| fep | 0:62cd296ba2a7 | 265 | |
| fep | 0:62cd296ba2a7 | 266 | /** |
| fep | 0:62cd296ba2a7 | 267 | * semphr. h |
| fep | 0:62cd296ba2a7 | 268 | * <pre>xSemaphoreTake( |
| fep | 0:62cd296ba2a7 | 269 | * SemaphoreHandle_t xSemaphore, |
| fep | 0:62cd296ba2a7 | 270 | * TickType_t xBlockTime |
| fep | 0:62cd296ba2a7 | 271 | * )</pre> |
| fep | 0:62cd296ba2a7 | 272 | * |
| fep | 0:62cd296ba2a7 | 273 | * <i>Macro</i> to obtain a semaphore. The semaphore must have previously been |
| fep | 0:62cd296ba2a7 | 274 | * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or |
| fep | 0:62cd296ba2a7 | 275 | * xSemaphoreCreateCounting(). |
| fep | 0:62cd296ba2a7 | 276 | * |
| fep | 0:62cd296ba2a7 | 277 | * @param xSemaphore A handle to the semaphore being taken - obtained when |
| fep | 0:62cd296ba2a7 | 278 | * the semaphore was created. |
| fep | 0:62cd296ba2a7 | 279 | * |
| fep | 0:62cd296ba2a7 | 280 | * @param xBlockTime The time in ticks to wait for the semaphore to become |
| fep | 0:62cd296ba2a7 | 281 | * available. The macro portTICK_PERIOD_MS can be used to convert this to a |
| fep | 0:62cd296ba2a7 | 282 | * real time. A block time of zero can be used to poll the semaphore. A block |
| fep | 0:62cd296ba2a7 | 283 | * time of portMAX_DELAY can be used to block indefinitely (provided |
| fep | 0:62cd296ba2a7 | 284 | * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h). |
| fep | 0:62cd296ba2a7 | 285 | * |
| fep | 0:62cd296ba2a7 | 286 | * @return pdTRUE if the semaphore was obtained. pdFALSE |
| fep | 0:62cd296ba2a7 | 287 | * if xBlockTime expired without the semaphore becoming available. |
| fep | 0:62cd296ba2a7 | 288 | * |
| fep | 0:62cd296ba2a7 | 289 | * Example usage: |
| fep | 0:62cd296ba2a7 | 290 | <pre> |
| fep | 0:62cd296ba2a7 | 291 | SemaphoreHandle_t xSemaphore = NULL; |
| fep | 0:62cd296ba2a7 | 292 | |
| fep | 0:62cd296ba2a7 | 293 | // A task that creates a semaphore. |
| fep | 0:62cd296ba2a7 | 294 | void vATask( void * pvParameters ) |
| fep | 0:62cd296ba2a7 | 295 | { |
| fep | 0:62cd296ba2a7 | 296 | // Create the semaphore to guard a shared resource. |
| fep | 0:62cd296ba2a7 | 297 | xSemaphore = xSemaphoreCreateBinary(); |
| fep | 0:62cd296ba2a7 | 298 | } |
| fep | 0:62cd296ba2a7 | 299 | |
| fep | 0:62cd296ba2a7 | 300 | // A task that uses the semaphore. |
| fep | 0:62cd296ba2a7 | 301 | void vAnotherTask( void * pvParameters ) |
| fep | 0:62cd296ba2a7 | 302 | { |
| fep | 0:62cd296ba2a7 | 303 | // ... Do other things. |
| fep | 0:62cd296ba2a7 | 304 | |
| fep | 0:62cd296ba2a7 | 305 | if( xSemaphore != NULL ) |
| fep | 0:62cd296ba2a7 | 306 | { |
| fep | 0:62cd296ba2a7 | 307 | // See if we can obtain the semaphore. If the semaphore is not available |
| fep | 0:62cd296ba2a7 | 308 | // wait 10 ticks to see if it becomes free. |
| fep | 0:62cd296ba2a7 | 309 | if( xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ) == pdTRUE ) |
| fep | 0:62cd296ba2a7 | 310 | { |
| fep | 0:62cd296ba2a7 | 311 | // We were able to obtain the semaphore and can now access the |
| fep | 0:62cd296ba2a7 | 312 | // shared resource. |
| fep | 0:62cd296ba2a7 | 313 | |
| fep | 0:62cd296ba2a7 | 314 | // ... |
| fep | 0:62cd296ba2a7 | 315 | |
| fep | 0:62cd296ba2a7 | 316 | // We have finished accessing the shared resource. Release the |
| fep | 0:62cd296ba2a7 | 317 | // semaphore. |
| fep | 0:62cd296ba2a7 | 318 | xSemaphoreGive( xSemaphore ); |
| fep | 0:62cd296ba2a7 | 319 | } |
| fep | 0:62cd296ba2a7 | 320 | else |
| fep | 0:62cd296ba2a7 | 321 | { |
| fep | 0:62cd296ba2a7 | 322 | // We could not obtain the semaphore and can therefore not access |
| fep | 0:62cd296ba2a7 | 323 | // the shared resource safely. |
| fep | 0:62cd296ba2a7 | 324 | } |
| fep | 0:62cd296ba2a7 | 325 | } |
| fep | 0:62cd296ba2a7 | 326 | } |
| fep | 0:62cd296ba2a7 | 327 | </pre> |
| fep | 0:62cd296ba2a7 | 328 | * \defgroup xSemaphoreTake xSemaphoreTake |
| fep | 0:62cd296ba2a7 | 329 | * \ingroup Semaphores |
| fep | 0:62cd296ba2a7 | 330 | */ |
| fep | 0:62cd296ba2a7 | 331 | #define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) |
| fep | 0:62cd296ba2a7 | 332 | |
| fep | 0:62cd296ba2a7 | 333 | /** |
| fep | 0:62cd296ba2a7 | 334 | * semphr. h |
| fep | 0:62cd296ba2a7 | 335 | * xSemaphoreTakeRecursive( |
| fep | 0:62cd296ba2a7 | 336 | * SemaphoreHandle_t xMutex, |
| fep | 0:62cd296ba2a7 | 337 | * TickType_t xBlockTime |
| fep | 0:62cd296ba2a7 | 338 | * ) |
| fep | 0:62cd296ba2a7 | 339 | * |
| fep | 0:62cd296ba2a7 | 340 | * <i>Macro</i> to recursively obtain, or 'take', a mutex type semaphore. |
| fep | 0:62cd296ba2a7 | 341 | * The mutex must have previously been created using a call to |
| fep | 0:62cd296ba2a7 | 342 | * xSemaphoreCreateRecursiveMutex(); |
| fep | 0:62cd296ba2a7 | 343 | * |
| fep | 0:62cd296ba2a7 | 344 | * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this |
| fep | 0:62cd296ba2a7 | 345 | * macro to be available. |
| fep | 0:62cd296ba2a7 | 346 | * |
| fep | 0:62cd296ba2a7 | 347 | * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). |
| fep | 0:62cd296ba2a7 | 348 | * |
| fep | 0:62cd296ba2a7 | 349 | * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex |
| fep | 0:62cd296ba2a7 | 350 | * doesn't become available again until the owner has called |
| fep | 0:62cd296ba2a7 | 351 | * xSemaphoreGiveRecursive() for each successful 'take' request. For example, |
| fep | 0:62cd296ba2a7 | 352 | * if a task successfully 'takes' the same mutex 5 times then the mutex will |
| fep | 0:62cd296ba2a7 | 353 | * not be available to any other task until it has also 'given' the mutex back |
| fep | 0:62cd296ba2a7 | 354 | * exactly five times. |
| fep | 0:62cd296ba2a7 | 355 | * |
| fep | 0:62cd296ba2a7 | 356 | * @param xMutex A handle to the mutex being obtained. This is the |
| fep | 0:62cd296ba2a7 | 357 | * handle returned by xSemaphoreCreateRecursiveMutex(); |
| fep | 0:62cd296ba2a7 | 358 | * |
| fep | 0:62cd296ba2a7 | 359 | * @param xBlockTime The time in ticks to wait for the semaphore to become |
| fep | 0:62cd296ba2a7 | 360 | * available. The macro portTICK_PERIOD_MS can be used to convert this to a |
| fep | 0:62cd296ba2a7 | 361 | * real time. A block time of zero can be used to poll the semaphore. If |
| fep | 0:62cd296ba2a7 | 362 | * the task already owns the semaphore then xSemaphoreTakeRecursive() will |
| fep | 0:62cd296ba2a7 | 363 | * return immediately no matter what the value of xBlockTime. |
| fep | 0:62cd296ba2a7 | 364 | * |
| fep | 0:62cd296ba2a7 | 365 | * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime |
| fep | 0:62cd296ba2a7 | 366 | * expired without the semaphore becoming available. |
| fep | 0:62cd296ba2a7 | 367 | * |
| fep | 0:62cd296ba2a7 | 368 | * Example usage: |
| fep | 0:62cd296ba2a7 | 369 | <pre> |
| fep | 0:62cd296ba2a7 | 370 | SemaphoreHandle_t xMutex = NULL; |
| fep | 0:62cd296ba2a7 | 371 | |
| fep | 0:62cd296ba2a7 | 372 | // A task that creates a mutex. |
| fep | 0:62cd296ba2a7 | 373 | void vATask( void * pvParameters ) |
| fep | 0:62cd296ba2a7 | 374 | { |
| fep | 0:62cd296ba2a7 | 375 | // Create the mutex to guard a shared resource. |
| fep | 0:62cd296ba2a7 | 376 | xMutex = xSemaphoreCreateRecursiveMutex(); |
| fep | 0:62cd296ba2a7 | 377 | } |
| fep | 0:62cd296ba2a7 | 378 | |
| fep | 0:62cd296ba2a7 | 379 | // A task that uses the mutex. |
| fep | 0:62cd296ba2a7 | 380 | void vAnotherTask( void * pvParameters ) |
| fep | 0:62cd296ba2a7 | 381 | { |
| fep | 0:62cd296ba2a7 | 382 | // ... Do other things. |
| fep | 0:62cd296ba2a7 | 383 | |
| fep | 0:62cd296ba2a7 | 384 | if( xMutex != NULL ) |
| fep | 0:62cd296ba2a7 | 385 | { |
| fep | 0:62cd296ba2a7 | 386 | // See if we can obtain the mutex. If the mutex is not available |
| fep | 0:62cd296ba2a7 | 387 | // wait 10 ticks to see if it becomes free. |
| fep | 0:62cd296ba2a7 | 388 | if( xSemaphoreTakeRecursive( xSemaphore, ( TickType_t ) 10 ) == pdTRUE ) |
| fep | 0:62cd296ba2a7 | 389 | { |
| fep | 0:62cd296ba2a7 | 390 | // We were able to obtain the mutex and can now access the |
| fep | 0:62cd296ba2a7 | 391 | // shared resource. |
| fep | 0:62cd296ba2a7 | 392 | |
| fep | 0:62cd296ba2a7 | 393 | // ... |
| fep | 0:62cd296ba2a7 | 394 | // For some reason due to the nature of the code further calls to |
| fep | 0:62cd296ba2a7 | 395 | // xSemaphoreTakeRecursive() are made on the same mutex. In real |
| fep | 0:62cd296ba2a7 | 396 | // code these would not be just sequential calls as this would make |
| fep | 0:62cd296ba2a7 | 397 | // no sense. Instead the calls are likely to be buried inside |
| fep | 0:62cd296ba2a7 | 398 | // a more complex call structure. |
| fep | 0:62cd296ba2a7 | 399 | xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); |
| fep | 0:62cd296ba2a7 | 400 | xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); |
| fep | 0:62cd296ba2a7 | 401 | |
| fep | 0:62cd296ba2a7 | 402 | // The mutex has now been 'taken' three times, so will not be |
| fep | 0:62cd296ba2a7 | 403 | // available to another task until it has also been given back |
| fep | 0:62cd296ba2a7 | 404 | // three times. Again it is unlikely that real code would have |
| fep | 0:62cd296ba2a7 | 405 | // these calls sequentially, but instead buried in a more complex |
| fep | 0:62cd296ba2a7 | 406 | // call structure. This is just for illustrative purposes. |
| fep | 0:62cd296ba2a7 | 407 | xSemaphoreGiveRecursive( xMutex ); |
| fep | 0:62cd296ba2a7 | 408 | xSemaphoreGiveRecursive( xMutex ); |
| fep | 0:62cd296ba2a7 | 409 | xSemaphoreGiveRecursive( xMutex ); |
| fep | 0:62cd296ba2a7 | 410 | |
| fep | 0:62cd296ba2a7 | 411 | // Now the mutex can be taken by other tasks. |
| fep | 0:62cd296ba2a7 | 412 | } |
| fep | 0:62cd296ba2a7 | 413 | else |
| fep | 0:62cd296ba2a7 | 414 | { |
| fep | 0:62cd296ba2a7 | 415 | // We could not obtain the mutex and can therefore not access |
| fep | 0:62cd296ba2a7 | 416 | // the shared resource safely. |
| fep | 0:62cd296ba2a7 | 417 | } |
| fep | 0:62cd296ba2a7 | 418 | } |
| fep | 0:62cd296ba2a7 | 419 | } |
| fep | 0:62cd296ba2a7 | 420 | </pre> |
| fep | 0:62cd296ba2a7 | 421 | * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive |
| fep | 0:62cd296ba2a7 | 422 | * \ingroup Semaphores |
| fep | 0:62cd296ba2a7 | 423 | */ |
| fep | 0:62cd296ba2a7 | 424 | #if( configUSE_RECURSIVE_MUTEXES == 1 ) |
| fep | 0:62cd296ba2a7 | 425 | #define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) |
| fep | 0:62cd296ba2a7 | 426 | #endif |
| fep | 0:62cd296ba2a7 | 427 | |
| fep | 0:62cd296ba2a7 | 428 | /** |
| fep | 0:62cd296ba2a7 | 429 | * semphr. h |
| fep | 0:62cd296ba2a7 | 430 | * <pre>xSemaphoreGive( SemaphoreHandle_t xSemaphore )</pre> |
| fep | 0:62cd296ba2a7 | 431 | * |
| fep | 0:62cd296ba2a7 | 432 | * <i>Macro</i> to release a semaphore. The semaphore must have previously been |
| fep | 0:62cd296ba2a7 | 433 | * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or |
| fep | 0:62cd296ba2a7 | 434 | * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake(). |
| fep | 0:62cd296ba2a7 | 435 | * |
| fep | 0:62cd296ba2a7 | 436 | * This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for |
| fep | 0:62cd296ba2a7 | 437 | * an alternative which can be used from an ISR. |
| fep | 0:62cd296ba2a7 | 438 | * |
| fep | 0:62cd296ba2a7 | 439 | * This macro must also not be used on semaphores created using |
| fep | 0:62cd296ba2a7 | 440 | * xSemaphoreCreateRecursiveMutex(). |
| fep | 0:62cd296ba2a7 | 441 | * |
| fep | 0:62cd296ba2a7 | 442 | * @param xSemaphore A handle to the semaphore being released. This is the |
| fep | 0:62cd296ba2a7 | 443 | * handle returned when the semaphore was created. |
| fep | 0:62cd296ba2a7 | 444 | * |
| fep | 0:62cd296ba2a7 | 445 | * @return pdTRUE if the semaphore was released. pdFALSE if an error occurred. |
| fep | 0:62cd296ba2a7 | 446 | * Semaphores are implemented using queues. An error can occur if there is |
| fep | 0:62cd296ba2a7 | 447 | * no space on the queue to post a message - indicating that the |
| fep | 0:62cd296ba2a7 | 448 | * semaphore was not first obtained correctly. |
| fep | 0:62cd296ba2a7 | 449 | * |
| fep | 0:62cd296ba2a7 | 450 | * Example usage: |
| fep | 0:62cd296ba2a7 | 451 | <pre> |
| fep | 0:62cd296ba2a7 | 452 | SemaphoreHandle_t xSemaphore = NULL; |
| fep | 0:62cd296ba2a7 | 453 | |
| fep | 0:62cd296ba2a7 | 454 | void vATask( void * pvParameters ) |
| fep | 0:62cd296ba2a7 | 455 | { |
| fep | 0:62cd296ba2a7 | 456 | // Create the semaphore to guard a shared resource. |
| fep | 0:62cd296ba2a7 | 457 | xSemaphore = vSemaphoreCreateBinary(); |
| fep | 0:62cd296ba2a7 | 458 | |
| fep | 0:62cd296ba2a7 | 459 | if( xSemaphore != NULL ) |
| fep | 0:62cd296ba2a7 | 460 | { |
| fep | 0:62cd296ba2a7 | 461 | if( xSemaphoreGive( xSemaphore ) != pdTRUE ) |
| fep | 0:62cd296ba2a7 | 462 | { |
| fep | 0:62cd296ba2a7 | 463 | // We would expect this call to fail because we cannot give |
| fep | 0:62cd296ba2a7 | 464 | // a semaphore without first "taking" it! |
| fep | 0:62cd296ba2a7 | 465 | } |
| fep | 0:62cd296ba2a7 | 466 | |
| fep | 0:62cd296ba2a7 | 467 | // Obtain the semaphore - don't block if the semaphore is not |
| fep | 0:62cd296ba2a7 | 468 | // immediately available. |
| fep | 0:62cd296ba2a7 | 469 | if( xSemaphoreTake( xSemaphore, ( TickType_t ) 0 ) ) |
| fep | 0:62cd296ba2a7 | 470 | { |
| fep | 0:62cd296ba2a7 | 471 | // We now have the semaphore and can access the shared resource. |
| fep | 0:62cd296ba2a7 | 472 | |
| fep | 0:62cd296ba2a7 | 473 | // ... |
| fep | 0:62cd296ba2a7 | 474 | |
| fep | 0:62cd296ba2a7 | 475 | // We have finished accessing the shared resource so can free the |
| fep | 0:62cd296ba2a7 | 476 | // semaphore. |
| fep | 0:62cd296ba2a7 | 477 | if( xSemaphoreGive( xSemaphore ) != pdTRUE ) |
| fep | 0:62cd296ba2a7 | 478 | { |
| fep | 0:62cd296ba2a7 | 479 | // We would not expect this call to fail because we must have |
| fep | 0:62cd296ba2a7 | 480 | // obtained the semaphore to get here. |
| fep | 0:62cd296ba2a7 | 481 | } |
| fep | 0:62cd296ba2a7 | 482 | } |
| fep | 0:62cd296ba2a7 | 483 | } |
| fep | 0:62cd296ba2a7 | 484 | } |
| fep | 0:62cd296ba2a7 | 485 | </pre> |
| fep | 0:62cd296ba2a7 | 486 | * \defgroup xSemaphoreGive xSemaphoreGive |
| fep | 0:62cd296ba2a7 | 487 | * \ingroup Semaphores |
| fep | 0:62cd296ba2a7 | 488 | */ |
| fep | 0:62cd296ba2a7 | 489 | #define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) |
| fep | 0:62cd296ba2a7 | 490 | |
| fep | 0:62cd296ba2a7 | 491 | /** |
| fep | 0:62cd296ba2a7 | 492 | * semphr. h |
| fep | 0:62cd296ba2a7 | 493 | * <pre>xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex )</pre> |
| fep | 0:62cd296ba2a7 | 494 | * |
| fep | 0:62cd296ba2a7 | 495 | * <i>Macro</i> to recursively release, or 'give', a mutex type semaphore. |
| fep | 0:62cd296ba2a7 | 496 | * The mutex must have previously been created using a call to |
| fep | 0:62cd296ba2a7 | 497 | * xSemaphoreCreateRecursiveMutex(); |
| fep | 0:62cd296ba2a7 | 498 | * |
| fep | 0:62cd296ba2a7 | 499 | * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this |
| fep | 0:62cd296ba2a7 | 500 | * macro to be available. |
| fep | 0:62cd296ba2a7 | 501 | * |
| fep | 0:62cd296ba2a7 | 502 | * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). |
| fep | 0:62cd296ba2a7 | 503 | * |
| fep | 0:62cd296ba2a7 | 504 | * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex |
| fep | 0:62cd296ba2a7 | 505 | * doesn't become available again until the owner has called |
| fep | 0:62cd296ba2a7 | 506 | * xSemaphoreGiveRecursive() for each successful 'take' request. For example, |
| fep | 0:62cd296ba2a7 | 507 | * if a task successfully 'takes' the same mutex 5 times then the mutex will |
| fep | 0:62cd296ba2a7 | 508 | * not be available to any other task until it has also 'given' the mutex back |
| fep | 0:62cd296ba2a7 | 509 | * exactly five times. |
| fep | 0:62cd296ba2a7 | 510 | * |
| fep | 0:62cd296ba2a7 | 511 | * @param xMutex A handle to the mutex being released, or 'given'. This is the |
| fep | 0:62cd296ba2a7 | 512 | * handle returned by xSemaphoreCreateMutex(); |
| fep | 0:62cd296ba2a7 | 513 | * |
| fep | 0:62cd296ba2a7 | 514 | * @return pdTRUE if the semaphore was given. |
| fep | 0:62cd296ba2a7 | 515 | * |
| fep | 0:62cd296ba2a7 | 516 | * Example usage: |
| fep | 0:62cd296ba2a7 | 517 | <pre> |
| fep | 0:62cd296ba2a7 | 518 | SemaphoreHandle_t xMutex = NULL; |
| fep | 0:62cd296ba2a7 | 519 | |
| fep | 0:62cd296ba2a7 | 520 | // A task that creates a mutex. |
| fep | 0:62cd296ba2a7 | 521 | void vATask( void * pvParameters ) |
| fep | 0:62cd296ba2a7 | 522 | { |
| fep | 0:62cd296ba2a7 | 523 | // Create the mutex to guard a shared resource. |
| fep | 0:62cd296ba2a7 | 524 | xMutex = xSemaphoreCreateRecursiveMutex(); |
| fep | 0:62cd296ba2a7 | 525 | } |
| fep | 0:62cd296ba2a7 | 526 | |
| fep | 0:62cd296ba2a7 | 527 | // A task that uses the mutex. |
| fep | 0:62cd296ba2a7 | 528 | void vAnotherTask( void * pvParameters ) |
| fep | 0:62cd296ba2a7 | 529 | { |
| fep | 0:62cd296ba2a7 | 530 | // ... Do other things. |
| fep | 0:62cd296ba2a7 | 531 | |
| fep | 0:62cd296ba2a7 | 532 | if( xMutex != NULL ) |
| fep | 0:62cd296ba2a7 | 533 | { |
| fep | 0:62cd296ba2a7 | 534 | // See if we can obtain the mutex. If the mutex is not available |
| fep | 0:62cd296ba2a7 | 535 | // wait 10 ticks to see if it becomes free. |
| fep | 0:62cd296ba2a7 | 536 | if( xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ) == pdTRUE ) |
| fep | 0:62cd296ba2a7 | 537 | { |
| fep | 0:62cd296ba2a7 | 538 | // We were able to obtain the mutex and can now access the |
| fep | 0:62cd296ba2a7 | 539 | // shared resource. |
| fep | 0:62cd296ba2a7 | 540 | |
| fep | 0:62cd296ba2a7 | 541 | // ... |
| fep | 0:62cd296ba2a7 | 542 | // For some reason due to the nature of the code further calls to |
| fep | 0:62cd296ba2a7 | 543 | // xSemaphoreTakeRecursive() are made on the same mutex. In real |
| fep | 0:62cd296ba2a7 | 544 | // code these would not be just sequential calls as this would make |
| fep | 0:62cd296ba2a7 | 545 | // no sense. Instead the calls are likely to be buried inside |
| fep | 0:62cd296ba2a7 | 546 | // a more complex call structure. |
| fep | 0:62cd296ba2a7 | 547 | xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); |
| fep | 0:62cd296ba2a7 | 548 | xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); |
| fep | 0:62cd296ba2a7 | 549 | |
| fep | 0:62cd296ba2a7 | 550 | // The mutex has now been 'taken' three times, so will not be |
| fep | 0:62cd296ba2a7 | 551 | // available to another task until it has also been given back |
| fep | 0:62cd296ba2a7 | 552 | // three times. Again it is unlikely that real code would have |
| fep | 0:62cd296ba2a7 | 553 | // these calls sequentially, it would be more likely that the calls |
| fep | 0:62cd296ba2a7 | 554 | // to xSemaphoreGiveRecursive() would be called as a call stack |
| fep | 0:62cd296ba2a7 | 555 | // unwound. This is just for demonstrative purposes. |
| fep | 0:62cd296ba2a7 | 556 | xSemaphoreGiveRecursive( xMutex ); |
| fep | 0:62cd296ba2a7 | 557 | xSemaphoreGiveRecursive( xMutex ); |
| fep | 0:62cd296ba2a7 | 558 | xSemaphoreGiveRecursive( xMutex ); |
| fep | 0:62cd296ba2a7 | 559 | |
| fep | 0:62cd296ba2a7 | 560 | // Now the mutex can be taken by other tasks. |
| fep | 0:62cd296ba2a7 | 561 | } |
| fep | 0:62cd296ba2a7 | 562 | else |
| fep | 0:62cd296ba2a7 | 563 | { |
| fep | 0:62cd296ba2a7 | 564 | // We could not obtain the mutex and can therefore not access |
| fep | 0:62cd296ba2a7 | 565 | // the shared resource safely. |
| fep | 0:62cd296ba2a7 | 566 | } |
| fep | 0:62cd296ba2a7 | 567 | } |
| fep | 0:62cd296ba2a7 | 568 | } |
| fep | 0:62cd296ba2a7 | 569 | </pre> |
| fep | 0:62cd296ba2a7 | 570 | * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive |
| fep | 0:62cd296ba2a7 | 571 | * \ingroup Semaphores |
| fep | 0:62cd296ba2a7 | 572 | */ |
| fep | 0:62cd296ba2a7 | 573 | #if( configUSE_RECURSIVE_MUTEXES == 1 ) |
| fep | 0:62cd296ba2a7 | 574 | #define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) |
| fep | 0:62cd296ba2a7 | 575 | #endif |
| fep | 0:62cd296ba2a7 | 576 | |
| fep | 0:62cd296ba2a7 | 577 | /** |
| fep | 0:62cd296ba2a7 | 578 | * semphr. h |
| fep | 0:62cd296ba2a7 | 579 | * <pre> |
| fep | 0:62cd296ba2a7 | 580 | xSemaphoreGiveFromISR( |
| fep | 0:62cd296ba2a7 | 581 | SemaphoreHandle_t xSemaphore, |
| fep | 0:62cd296ba2a7 | 582 | BaseType_t *pxHigherPriorityTaskWoken |
| fep | 0:62cd296ba2a7 | 583 | )</pre> |
| fep | 0:62cd296ba2a7 | 584 | * |
| fep | 0:62cd296ba2a7 | 585 | * <i>Macro</i> to release a semaphore. The semaphore must have previously been |
| fep | 0:62cd296ba2a7 | 586 | * created with a call to xSemaphoreCreateBinary() or xSemaphoreCreateCounting(). |
| fep | 0:62cd296ba2a7 | 587 | * |
| fep | 0:62cd296ba2a7 | 588 | * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) |
| fep | 0:62cd296ba2a7 | 589 | * must not be used with this macro. |
| fep | 0:62cd296ba2a7 | 590 | * |
| fep | 0:62cd296ba2a7 | 591 | * This macro can be used from an ISR. |
| fep | 0:62cd296ba2a7 | 592 | * |
| fep | 0:62cd296ba2a7 | 593 | * @param xSemaphore A handle to the semaphore being released. This is the |
| fep | 0:62cd296ba2a7 | 594 | * handle returned when the semaphore was created. |
| fep | 0:62cd296ba2a7 | 595 | * |
| fep | 0:62cd296ba2a7 | 596 | * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set |
| fep | 0:62cd296ba2a7 | 597 | * *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task |
| fep | 0:62cd296ba2a7 | 598 | * to unblock, and the unblocked task has a priority higher than the currently |
| fep | 0:62cd296ba2a7 | 599 | * running task. If xSemaphoreGiveFromISR() sets this value to pdTRUE then |
| fep | 0:62cd296ba2a7 | 600 | * a context switch should be requested before the interrupt is exited. |
| fep | 0:62cd296ba2a7 | 601 | * |
| fep | 0:62cd296ba2a7 | 602 | * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL. |
| fep | 0:62cd296ba2a7 | 603 | * |
| fep | 0:62cd296ba2a7 | 604 | * Example usage: |
| fep | 0:62cd296ba2a7 | 605 | <pre> |
| fep | 0:62cd296ba2a7 | 606 | \#define LONG_TIME 0xffff |
| fep | 0:62cd296ba2a7 | 607 | \#define TICKS_TO_WAIT 10 |
| fep | 0:62cd296ba2a7 | 608 | SemaphoreHandle_t xSemaphore = NULL; |
| fep | 0:62cd296ba2a7 | 609 | |
| fep | 0:62cd296ba2a7 | 610 | // Repetitive task. |
| fep | 0:62cd296ba2a7 | 611 | void vATask( void * pvParameters ) |
| fep | 0:62cd296ba2a7 | 612 | { |
| fep | 0:62cd296ba2a7 | 613 | for( ;; ) |
| fep | 0:62cd296ba2a7 | 614 | { |
| fep | 0:62cd296ba2a7 | 615 | // We want this task to run every 10 ticks of a timer. The semaphore |
| fep | 0:62cd296ba2a7 | 616 | // was created before this task was started. |
| fep | 0:62cd296ba2a7 | 617 | |
| fep | 0:62cd296ba2a7 | 618 | // Block waiting for the semaphore to become available. |
| fep | 0:62cd296ba2a7 | 619 | if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE ) |
| fep | 0:62cd296ba2a7 | 620 | { |
| fep | 0:62cd296ba2a7 | 621 | // It is time to execute. |
| fep | 0:62cd296ba2a7 | 622 | |
| fep | 0:62cd296ba2a7 | 623 | // ... |
| fep | 0:62cd296ba2a7 | 624 | |
| fep | 0:62cd296ba2a7 | 625 | // We have finished our task. Return to the top of the loop where |
| fep | 0:62cd296ba2a7 | 626 | // we will block on the semaphore until it is time to execute |
| fep | 0:62cd296ba2a7 | 627 | // again. Note when using the semaphore for synchronisation with an |
| fep | 0:62cd296ba2a7 | 628 | // ISR in this manner there is no need to 'give' the semaphore back. |
| fep | 0:62cd296ba2a7 | 629 | } |
| fep | 0:62cd296ba2a7 | 630 | } |
| fep | 0:62cd296ba2a7 | 631 | } |
| fep | 0:62cd296ba2a7 | 632 | |
| fep | 0:62cd296ba2a7 | 633 | // Timer ISR |
| fep | 0:62cd296ba2a7 | 634 | void vTimerISR( void * pvParameters ) |
| fep | 0:62cd296ba2a7 | 635 | { |
| fep | 0:62cd296ba2a7 | 636 | static uint8_t ucLocalTickCount = 0; |
| fep | 0:62cd296ba2a7 | 637 | static BaseType_t xHigherPriorityTaskWoken; |
| fep | 0:62cd296ba2a7 | 638 | |
| fep | 0:62cd296ba2a7 | 639 | // A timer tick has occurred. |
| fep | 0:62cd296ba2a7 | 640 | |
| fep | 0:62cd296ba2a7 | 641 | // ... Do other time functions. |
| fep | 0:62cd296ba2a7 | 642 | |
| fep | 0:62cd296ba2a7 | 643 | // Is it time for vATask () to run? |
| fep | 0:62cd296ba2a7 | 644 | xHigherPriorityTaskWoken = pdFALSE; |
| fep | 0:62cd296ba2a7 | 645 | ucLocalTickCount++; |
| fep | 0:62cd296ba2a7 | 646 | if( ucLocalTickCount >= TICKS_TO_WAIT ) |
| fep | 0:62cd296ba2a7 | 647 | { |
| fep | 0:62cd296ba2a7 | 648 | // Unblock the task by releasing the semaphore. |
| fep | 0:62cd296ba2a7 | 649 | xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken ); |
| fep | 0:62cd296ba2a7 | 650 | |
| fep | 0:62cd296ba2a7 | 651 | // Reset the count so we release the semaphore again in 10 ticks time. |
| fep | 0:62cd296ba2a7 | 652 | ucLocalTickCount = 0; |
| fep | 0:62cd296ba2a7 | 653 | } |
| fep | 0:62cd296ba2a7 | 654 | |
| fep | 0:62cd296ba2a7 | 655 | if( xHigherPriorityTaskWoken != pdFALSE ) |
| fep | 0:62cd296ba2a7 | 656 | { |
| fep | 0:62cd296ba2a7 | 657 | // We can force a context switch here. Context switching from an |
| fep | 0:62cd296ba2a7 | 658 | // ISR uses port specific syntax. Check the demo task for your port |
| fep | 0:62cd296ba2a7 | 659 | // to find the syntax required. |
| fep | 0:62cd296ba2a7 | 660 | } |
| fep | 0:62cd296ba2a7 | 661 | } |
| fep | 0:62cd296ba2a7 | 662 | </pre> |
| fep | 0:62cd296ba2a7 | 663 | * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR |
| fep | 0:62cd296ba2a7 | 664 | * \ingroup Semaphores |
| fep | 0:62cd296ba2a7 | 665 | */ |
| fep | 0:62cd296ba2a7 | 666 | #define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) ) |
| fep | 0:62cd296ba2a7 | 667 | |
| fep | 0:62cd296ba2a7 | 668 | /** |
| fep | 0:62cd296ba2a7 | 669 | * semphr. h |
| fep | 0:62cd296ba2a7 | 670 | * <pre> |
| fep | 0:62cd296ba2a7 | 671 | xSemaphoreTakeFromISR( |
| fep | 0:62cd296ba2a7 | 672 | SemaphoreHandle_t xSemaphore, |
| fep | 0:62cd296ba2a7 | 673 | BaseType_t *pxHigherPriorityTaskWoken |
| fep | 0:62cd296ba2a7 | 674 | )</pre> |
| fep | 0:62cd296ba2a7 | 675 | * |
| fep | 0:62cd296ba2a7 | 676 | * <i>Macro</i> to take a semaphore from an ISR. The semaphore must have |
| fep | 0:62cd296ba2a7 | 677 | * previously been created with a call to xSemaphoreCreateBinary() or |
| fep | 0:62cd296ba2a7 | 678 | * xSemaphoreCreateCounting(). |
| fep | 0:62cd296ba2a7 | 679 | * |
| fep | 0:62cd296ba2a7 | 680 | * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) |
| fep | 0:62cd296ba2a7 | 681 | * must not be used with this macro. |
| fep | 0:62cd296ba2a7 | 682 | * |
| fep | 0:62cd296ba2a7 | 683 | * This macro can be used from an ISR, however taking a semaphore from an ISR |
| fep | 0:62cd296ba2a7 | 684 | * is not a common operation. It is likely to only be useful when taking a |
| fep | 0:62cd296ba2a7 | 685 | * counting semaphore when an interrupt is obtaining an object from a resource |
| fep | 0:62cd296ba2a7 | 686 | * pool (when the semaphore count indicates the number of resources available). |
| fep | 0:62cd296ba2a7 | 687 | * |
| fep | 0:62cd296ba2a7 | 688 | * @param xSemaphore A handle to the semaphore being taken. This is the |
| fep | 0:62cd296ba2a7 | 689 | * handle returned when the semaphore was created. |
| fep | 0:62cd296ba2a7 | 690 | * |
| fep | 0:62cd296ba2a7 | 691 | * @param pxHigherPriorityTaskWoken xSemaphoreTakeFromISR() will set |
| fep | 0:62cd296ba2a7 | 692 | * *pxHigherPriorityTaskWoken to pdTRUE if taking the semaphore caused a task |
| fep | 0:62cd296ba2a7 | 693 | * to unblock, and the unblocked task has a priority higher than the currently |
| fep | 0:62cd296ba2a7 | 694 | * running task. If xSemaphoreTakeFromISR() sets this value to pdTRUE then |
| fep | 0:62cd296ba2a7 | 695 | * a context switch should be requested before the interrupt is exited. |
| fep | 0:62cd296ba2a7 | 696 | * |
| fep | 0:62cd296ba2a7 | 697 | * @return pdTRUE if the semaphore was successfully taken, otherwise |
| fep | 0:62cd296ba2a7 | 698 | * pdFALSE |
| fep | 0:62cd296ba2a7 | 699 | */ |
| fep | 0:62cd296ba2a7 | 700 | #define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) ) |
| fep | 0:62cd296ba2a7 | 701 | |
| fep | 0:62cd296ba2a7 | 702 | /** |
| fep | 0:62cd296ba2a7 | 703 | * semphr. h |
| fep | 0:62cd296ba2a7 | 704 | * <pre>SemaphoreHandle_t xSemaphoreCreateMutex( void )</pre> |
| fep | 0:62cd296ba2a7 | 705 | * |
| fep | 0:62cd296ba2a7 | 706 | * Creates a new mutex type semaphore instance, and returns a handle by which |
| fep | 0:62cd296ba2a7 | 707 | * the new mutex can be referenced. |
| fep | 0:62cd296ba2a7 | 708 | * |
| fep | 0:62cd296ba2a7 | 709 | * Internally, within the FreeRTOS implementation, mutex semaphores use a block |
| fep | 0:62cd296ba2a7 | 710 | * of memory, in which the mutex structure is stored. If a mutex is created |
| fep | 0:62cd296ba2a7 | 711 | * using xSemaphoreCreateMutex() then the required memory is automatically |
| fep | 0:62cd296ba2a7 | 712 | * dynamically allocated inside the xSemaphoreCreateMutex() function. (see |
| fep | 0:62cd296ba2a7 | 713 | * http://www.freertos.org/a00111.html). If a mutex is created using |
| fep | 0:62cd296ba2a7 | 714 | * xSemaphoreCreateMutexStatic() then the application writer must provided the |
| fep | 0:62cd296ba2a7 | 715 | * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created |
| fep | 0:62cd296ba2a7 | 716 | * without using any dynamic memory allocation. |
| fep | 0:62cd296ba2a7 | 717 | * |
| fep | 0:62cd296ba2a7 | 718 | * Mutexes created using this function can be accessed using the xSemaphoreTake() |
| fep | 0:62cd296ba2a7 | 719 | * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and |
| fep | 0:62cd296ba2a7 | 720 | * xSemaphoreGiveRecursive() macros must not be used. |
| fep | 0:62cd296ba2a7 | 721 | * |
| fep | 0:62cd296ba2a7 | 722 | * This type of semaphore uses a priority inheritance mechanism so a task |
| fep | 0:62cd296ba2a7 | 723 | * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the |
| fep | 0:62cd296ba2a7 | 724 | * semaphore it is no longer required. |
| fep | 0:62cd296ba2a7 | 725 | * |
| fep | 0:62cd296ba2a7 | 726 | * Mutex type semaphores cannot be used from within interrupt service routines. |
| fep | 0:62cd296ba2a7 | 727 | * |
| fep | 0:62cd296ba2a7 | 728 | * See xSemaphoreCreateBinary() for an alternative implementation that can be |
| fep | 0:62cd296ba2a7 | 729 | * used for pure synchronisation (where one task or interrupt always 'gives' the |
| fep | 0:62cd296ba2a7 | 730 | * semaphore and another always 'takes' the semaphore) and from within interrupt |
| fep | 0:62cd296ba2a7 | 731 | * service routines. |
| fep | 0:62cd296ba2a7 | 732 | * |
| fep | 0:62cd296ba2a7 | 733 | * @return If the mutex was successfully created then a handle to the created |
| fep | 0:62cd296ba2a7 | 734 | * semaphore is returned. If there was not enough heap to allocate the mutex |
| fep | 0:62cd296ba2a7 | 735 | * data structures then NULL is returned. |
| fep | 0:62cd296ba2a7 | 736 | * |
| fep | 0:62cd296ba2a7 | 737 | * Example usage: |
| fep | 0:62cd296ba2a7 | 738 | <pre> |
| fep | 0:62cd296ba2a7 | 739 | SemaphoreHandle_t xSemaphore; |
| fep | 0:62cd296ba2a7 | 740 | |
| fep | 0:62cd296ba2a7 | 741 | void vATask( void * pvParameters ) |
| fep | 0:62cd296ba2a7 | 742 | { |
| fep | 0:62cd296ba2a7 | 743 | // Semaphore cannot be used before a call to xSemaphoreCreateMutex(). |
| fep | 0:62cd296ba2a7 | 744 | // This is a macro so pass the variable in directly. |
| fep | 0:62cd296ba2a7 | 745 | xSemaphore = xSemaphoreCreateMutex(); |
| fep | 0:62cd296ba2a7 | 746 | |
| fep | 0:62cd296ba2a7 | 747 | if( xSemaphore != NULL ) |
| fep | 0:62cd296ba2a7 | 748 | { |
| fep | 0:62cd296ba2a7 | 749 | // The semaphore was created successfully. |
| fep | 0:62cd296ba2a7 | 750 | // The semaphore can now be used. |
| fep | 0:62cd296ba2a7 | 751 | } |
| fep | 0:62cd296ba2a7 | 752 | } |
| fep | 0:62cd296ba2a7 | 753 | </pre> |
| fep | 0:62cd296ba2a7 | 754 | * \defgroup xSemaphoreCreateMutex xSemaphoreCreateMutex |
| fep | 0:62cd296ba2a7 | 755 | * \ingroup Semaphores |
| fep | 0:62cd296ba2a7 | 756 | */ |
| fep | 0:62cd296ba2a7 | 757 | #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) |
| fep | 0:62cd296ba2a7 | 758 | #define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ) |
| fep | 0:62cd296ba2a7 | 759 | #endif |
| fep | 0:62cd296ba2a7 | 760 | |
| fep | 0:62cd296ba2a7 | 761 | /** |
| fep | 0:62cd296ba2a7 | 762 | * semphr. h |
| fep | 0:62cd296ba2a7 | 763 | * <pre>SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer )</pre> |
| fep | 0:62cd296ba2a7 | 764 | * |
| fep | 0:62cd296ba2a7 | 765 | * Creates a new mutex type semaphore instance, and returns a handle by which |
| fep | 0:62cd296ba2a7 | 766 | * the new mutex can be referenced. |
| fep | 0:62cd296ba2a7 | 767 | * |
| fep | 0:62cd296ba2a7 | 768 | * Internally, within the FreeRTOS implementation, mutex semaphores use a block |
| fep | 0:62cd296ba2a7 | 769 | * of memory, in which the mutex structure is stored. If a mutex is created |
| fep | 0:62cd296ba2a7 | 770 | * using xSemaphoreCreateMutex() then the required memory is automatically |
| fep | 0:62cd296ba2a7 | 771 | * dynamically allocated inside the xSemaphoreCreateMutex() function. (see |
| fep | 0:62cd296ba2a7 | 772 | * http://www.freertos.org/a00111.html). If a mutex is created using |
| fep | 0:62cd296ba2a7 | 773 | * xSemaphoreCreateMutexStatic() then the application writer must provided the |
| fep | 0:62cd296ba2a7 | 774 | * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created |
| fep | 0:62cd296ba2a7 | 775 | * without using any dynamic memory allocation. |
| fep | 0:62cd296ba2a7 | 776 | * |
| fep | 0:62cd296ba2a7 | 777 | * Mutexes created using this function can be accessed using the xSemaphoreTake() |
| fep | 0:62cd296ba2a7 | 778 | * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and |
| fep | 0:62cd296ba2a7 | 779 | * xSemaphoreGiveRecursive() macros must not be used. |
| fep | 0:62cd296ba2a7 | 780 | * |
| fep | 0:62cd296ba2a7 | 781 | * This type of semaphore uses a priority inheritance mechanism so a task |
| fep | 0:62cd296ba2a7 | 782 | * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the |
| fep | 0:62cd296ba2a7 | 783 | * semaphore it is no longer required. |
| fep | 0:62cd296ba2a7 | 784 | * |
| fep | 0:62cd296ba2a7 | 785 | * Mutex type semaphores cannot be used from within interrupt service routines. |
| fep | 0:62cd296ba2a7 | 786 | * |
| fep | 0:62cd296ba2a7 | 787 | * See xSemaphoreCreateBinary() for an alternative implementation that can be |
| fep | 0:62cd296ba2a7 | 788 | * used for pure synchronisation (where one task or interrupt always 'gives' the |
| fep | 0:62cd296ba2a7 | 789 | * semaphore and another always 'takes' the semaphore) and from within interrupt |
| fep | 0:62cd296ba2a7 | 790 | * service routines. |
| fep | 0:62cd296ba2a7 | 791 | * |
| fep | 0:62cd296ba2a7 | 792 | * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t, |
| fep | 0:62cd296ba2a7 | 793 | * which will be used to hold the mutex's data structure, removing the need for |
| fep | 0:62cd296ba2a7 | 794 | * the memory to be allocated dynamically. |
| fep | 0:62cd296ba2a7 | 795 | * |
| fep | 0:62cd296ba2a7 | 796 | * @return If the mutex was successfully created then a handle to the created |
| fep | 0:62cd296ba2a7 | 797 | * mutex is returned. If pxMutexBuffer was NULL then NULL is returned. |
| fep | 0:62cd296ba2a7 | 798 | * |
| fep | 0:62cd296ba2a7 | 799 | * Example usage: |
| fep | 0:62cd296ba2a7 | 800 | <pre> |
| fep | 0:62cd296ba2a7 | 801 | SemaphoreHandle_t xSemaphore; |
| fep | 0:62cd296ba2a7 | 802 | StaticSemaphore_t xMutexBuffer; |
| fep | 0:62cd296ba2a7 | 803 | |
| fep | 0:62cd296ba2a7 | 804 | void vATask( void * pvParameters ) |
| fep | 0:62cd296ba2a7 | 805 | { |
| fep | 0:62cd296ba2a7 | 806 | // A mutex cannot be used before it has been created. xMutexBuffer is |
| fep | 0:62cd296ba2a7 | 807 | // into xSemaphoreCreateMutexStatic() so no dynamic memory allocation is |
| fep | 0:62cd296ba2a7 | 808 | // attempted. |
| fep | 0:62cd296ba2a7 | 809 | xSemaphore = xSemaphoreCreateMutexStatic( &xMutexBuffer ); |
| fep | 0:62cd296ba2a7 | 810 | |
| fep | 0:62cd296ba2a7 | 811 | // As no dynamic memory allocation was performed, xSemaphore cannot be NULL, |
| fep | 0:62cd296ba2a7 | 812 | // so there is no need to check it. |
| fep | 0:62cd296ba2a7 | 813 | } |
| fep | 0:62cd296ba2a7 | 814 | </pre> |
| fep | 0:62cd296ba2a7 | 815 | * \defgroup xSemaphoreCreateMutexStatic xSemaphoreCreateMutexStatic |
| fep | 0:62cd296ba2a7 | 816 | * \ingroup Semaphores |
| fep | 0:62cd296ba2a7 | 817 | */ |
| fep | 0:62cd296ba2a7 | 818 | #if( configSUPPORT_STATIC_ALLOCATION == 1 ) |
| fep | 0:62cd296ba2a7 | 819 | #define xSemaphoreCreateMutexStatic( pxMutexBuffer ) xQueueCreateMutexStatic( queueQUEUE_TYPE_MUTEX, ( pxMutexBuffer ) ) |
| fep | 0:62cd296ba2a7 | 820 | #endif /* configSUPPORT_STATIC_ALLOCATION */ |
| fep | 0:62cd296ba2a7 | 821 | |
| fep | 0:62cd296ba2a7 | 822 | |
| fep | 0:62cd296ba2a7 | 823 | /** |
| fep | 0:62cd296ba2a7 | 824 | * semphr. h |
| fep | 0:62cd296ba2a7 | 825 | * <pre>SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )</pre> |
| fep | 0:62cd296ba2a7 | 826 | * |
| fep | 0:62cd296ba2a7 | 827 | * Creates a new recursive mutex type semaphore instance, and returns a handle |
| fep | 0:62cd296ba2a7 | 828 | * by which the new recursive mutex can be referenced. |
| fep | 0:62cd296ba2a7 | 829 | * |
| fep | 0:62cd296ba2a7 | 830 | * Internally, within the FreeRTOS implementation, recursive mutexs use a block |
| fep | 0:62cd296ba2a7 | 831 | * of memory, in which the mutex structure is stored. If a recursive mutex is |
| fep | 0:62cd296ba2a7 | 832 | * created using xSemaphoreCreateRecursiveMutex() then the required memory is |
| fep | 0:62cd296ba2a7 | 833 | * automatically dynamically allocated inside the |
| fep | 0:62cd296ba2a7 | 834 | * xSemaphoreCreateRecursiveMutex() function. (see |
| fep | 0:62cd296ba2a7 | 835 | * http://www.freertos.org/a00111.html). If a recursive mutex is created using |
| fep | 0:62cd296ba2a7 | 836 | * xSemaphoreCreateRecursiveMutexStatic() then the application writer must |
| fep | 0:62cd296ba2a7 | 837 | * provide the memory that will get used by the mutex. |
| fep | 0:62cd296ba2a7 | 838 | * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to |
| fep | 0:62cd296ba2a7 | 839 | * be created without using any dynamic memory allocation. |
| fep | 0:62cd296ba2a7 | 840 | * |
| fep | 0:62cd296ba2a7 | 841 | * Mutexes created using this macro can be accessed using the |
| fep | 0:62cd296ba2a7 | 842 | * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The |
| fep | 0:62cd296ba2a7 | 843 | * xSemaphoreTake() and xSemaphoreGive() macros must not be used. |
| fep | 0:62cd296ba2a7 | 844 | * |
| fep | 0:62cd296ba2a7 | 845 | * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex |
| fep | 0:62cd296ba2a7 | 846 | * doesn't become available again until the owner has called |
| fep | 0:62cd296ba2a7 | 847 | * xSemaphoreGiveRecursive() for each successful 'take' request. For example, |
| fep | 0:62cd296ba2a7 | 848 | * if a task successfully 'takes' the same mutex 5 times then the mutex will |
| fep | 0:62cd296ba2a7 | 849 | * not be available to any other task until it has also 'given' the mutex back |
| fep | 0:62cd296ba2a7 | 850 | * exactly five times. |
| fep | 0:62cd296ba2a7 | 851 | * |
| fep | 0:62cd296ba2a7 | 852 | * This type of semaphore uses a priority inheritance mechanism so a task |
| fep | 0:62cd296ba2a7 | 853 | * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the |
| fep | 0:62cd296ba2a7 | 854 | * semaphore it is no longer required. |
| fep | 0:62cd296ba2a7 | 855 | * |
| fep | 0:62cd296ba2a7 | 856 | * Mutex type semaphores cannot be used from within interrupt service routines. |
| fep | 0:62cd296ba2a7 | 857 | * |
| fep | 0:62cd296ba2a7 | 858 | * See xSemaphoreCreateBinary() for an alternative implementation that can be |
| fep | 0:62cd296ba2a7 | 859 | * used for pure synchronisation (where one task or interrupt always 'gives' the |
| fep | 0:62cd296ba2a7 | 860 | * semaphore and another always 'takes' the semaphore) and from within interrupt |
| fep | 0:62cd296ba2a7 | 861 | * service routines. |
| fep | 0:62cd296ba2a7 | 862 | * |
| fep | 0:62cd296ba2a7 | 863 | * @return xSemaphore Handle to the created mutex semaphore. Should be of type |
| fep | 0:62cd296ba2a7 | 864 | * SemaphoreHandle_t. |
| fep | 0:62cd296ba2a7 | 865 | * |
| fep | 0:62cd296ba2a7 | 866 | * Example usage: |
| fep | 0:62cd296ba2a7 | 867 | <pre> |
| fep | 0:62cd296ba2a7 | 868 | SemaphoreHandle_t xSemaphore; |
| fep | 0:62cd296ba2a7 | 869 | |
| fep | 0:62cd296ba2a7 | 870 | void vATask( void * pvParameters ) |
| fep | 0:62cd296ba2a7 | 871 | { |
| fep | 0:62cd296ba2a7 | 872 | // Semaphore cannot be used before a call to xSemaphoreCreateMutex(). |
| fep | 0:62cd296ba2a7 | 873 | // This is a macro so pass the variable in directly. |
| fep | 0:62cd296ba2a7 | 874 | xSemaphore = xSemaphoreCreateRecursiveMutex(); |
| fep | 0:62cd296ba2a7 | 875 | |
| fep | 0:62cd296ba2a7 | 876 | if( xSemaphore != NULL ) |
| fep | 0:62cd296ba2a7 | 877 | { |
| fep | 0:62cd296ba2a7 | 878 | // The semaphore was created successfully. |
| fep | 0:62cd296ba2a7 | 879 | // The semaphore can now be used. |
| fep | 0:62cd296ba2a7 | 880 | } |
| fep | 0:62cd296ba2a7 | 881 | } |
| fep | 0:62cd296ba2a7 | 882 | </pre> |
| fep | 0:62cd296ba2a7 | 883 | * \defgroup xSemaphoreCreateRecursiveMutex xSemaphoreCreateRecursiveMutex |
| fep | 0:62cd296ba2a7 | 884 | * \ingroup Semaphores |
| fep | 0:62cd296ba2a7 | 885 | */ |
| fep | 0:62cd296ba2a7 | 886 | #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) ) |
| fep | 0:62cd296ba2a7 | 887 | #define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX ) |
| fep | 0:62cd296ba2a7 | 888 | #endif |
| fep | 0:62cd296ba2a7 | 889 | |
| fep | 0:62cd296ba2a7 | 890 | /** |
| fep | 0:62cd296ba2a7 | 891 | * semphr. h |
| fep | 0:62cd296ba2a7 | 892 | * <pre>SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic( StaticSemaphore_t *pxMutexBuffer )</pre> |
| fep | 0:62cd296ba2a7 | 893 | * |
| fep | 0:62cd296ba2a7 | 894 | * Creates a new recursive mutex type semaphore instance, and returns a handle |
| fep | 0:62cd296ba2a7 | 895 | * by which the new recursive mutex can be referenced. |
| fep | 0:62cd296ba2a7 | 896 | * |
| fep | 0:62cd296ba2a7 | 897 | * Internally, within the FreeRTOS implementation, recursive mutexs use a block |
| fep | 0:62cd296ba2a7 | 898 | * of memory, in which the mutex structure is stored. If a recursive mutex is |
| fep | 0:62cd296ba2a7 | 899 | * created using xSemaphoreCreateRecursiveMutex() then the required memory is |
| fep | 0:62cd296ba2a7 | 900 | * automatically dynamically allocated inside the |
| fep | 0:62cd296ba2a7 | 901 | * xSemaphoreCreateRecursiveMutex() function. (see |
| fep | 0:62cd296ba2a7 | 902 | * http://www.freertos.org/a00111.html). If a recursive mutex is created using |
| fep | 0:62cd296ba2a7 | 903 | * xSemaphoreCreateRecursiveMutexStatic() then the application writer must |
| fep | 0:62cd296ba2a7 | 904 | * provide the memory that will get used by the mutex. |
| fep | 0:62cd296ba2a7 | 905 | * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to |
| fep | 0:62cd296ba2a7 | 906 | * be created without using any dynamic memory allocation. |
| fep | 0:62cd296ba2a7 | 907 | * |
| fep | 0:62cd296ba2a7 | 908 | * Mutexes created using this macro can be accessed using the |
| fep | 0:62cd296ba2a7 | 909 | * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The |
| fep | 0:62cd296ba2a7 | 910 | * xSemaphoreTake() and xSemaphoreGive() macros must not be used. |
| fep | 0:62cd296ba2a7 | 911 | * |
| fep | 0:62cd296ba2a7 | 912 | * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex |
| fep | 0:62cd296ba2a7 | 913 | * doesn't become available again until the owner has called |
| fep | 0:62cd296ba2a7 | 914 | * xSemaphoreGiveRecursive() for each successful 'take' request. For example, |
| fep | 0:62cd296ba2a7 | 915 | * if a task successfully 'takes' the same mutex 5 times then the mutex will |
| fep | 0:62cd296ba2a7 | 916 | * not be available to any other task until it has also 'given' the mutex back |
| fep | 0:62cd296ba2a7 | 917 | * exactly five times. |
| fep | 0:62cd296ba2a7 | 918 | * |
| fep | 0:62cd296ba2a7 | 919 | * This type of semaphore uses a priority inheritance mechanism so a task |
| fep | 0:62cd296ba2a7 | 920 | * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the |
| fep | 0:62cd296ba2a7 | 921 | * semaphore it is no longer required. |
| fep | 0:62cd296ba2a7 | 922 | * |
| fep | 0:62cd296ba2a7 | 923 | * Mutex type semaphores cannot be used from within interrupt service routines. |
| fep | 0:62cd296ba2a7 | 924 | * |
| fep | 0:62cd296ba2a7 | 925 | * See xSemaphoreCreateBinary() for an alternative implementation that can be |
| fep | 0:62cd296ba2a7 | 926 | * used for pure synchronisation (where one task or interrupt always 'gives' the |
| fep | 0:62cd296ba2a7 | 927 | * semaphore and another always 'takes' the semaphore) and from within interrupt |
| fep | 0:62cd296ba2a7 | 928 | * service routines. |
| fep | 0:62cd296ba2a7 | 929 | * |
| fep | 0:62cd296ba2a7 | 930 | * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t, |
| fep | 0:62cd296ba2a7 | 931 | * which will then be used to hold the recursive mutex's data structure, |
| fep | 0:62cd296ba2a7 | 932 | * removing the need for the memory to be allocated dynamically. |
| fep | 0:62cd296ba2a7 | 933 | * |
| fep | 0:62cd296ba2a7 | 934 | * @return If the recursive mutex was successfully created then a handle to the |
| fep | 0:62cd296ba2a7 | 935 | * created recursive mutex is returned. If pxMutexBuffer was NULL then NULL is |
| fep | 0:62cd296ba2a7 | 936 | * returned. |
| fep | 0:62cd296ba2a7 | 937 | * |
| fep | 0:62cd296ba2a7 | 938 | * Example usage: |
| fep | 0:62cd296ba2a7 | 939 | <pre> |
| fep | 0:62cd296ba2a7 | 940 | SemaphoreHandle_t xSemaphore; |
| fep | 0:62cd296ba2a7 | 941 | StaticSemaphore_t xMutexBuffer; |
| fep | 0:62cd296ba2a7 | 942 | |
| fep | 0:62cd296ba2a7 | 943 | void vATask( void * pvParameters ) |
| fep | 0:62cd296ba2a7 | 944 | { |
| fep | 0:62cd296ba2a7 | 945 | // A recursive semaphore cannot be used before it is created. Here a |
| fep | 0:62cd296ba2a7 | 946 | // recursive mutex is created using xSemaphoreCreateRecursiveMutexStatic(). |
| fep | 0:62cd296ba2a7 | 947 | // The address of xMutexBuffer is passed into the function, and will hold |
| fep | 0:62cd296ba2a7 | 948 | // the mutexes data structures - so no dynamic memory allocation will be |
| fep | 0:62cd296ba2a7 | 949 | // attempted. |
| fep | 0:62cd296ba2a7 | 950 | xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xMutexBuffer ); |
| fep | 0:62cd296ba2a7 | 951 | |
| fep | 0:62cd296ba2a7 | 952 | // As no dynamic memory allocation was performed, xSemaphore cannot be NULL, |
| fep | 0:62cd296ba2a7 | 953 | // so there is no need to check it. |
| fep | 0:62cd296ba2a7 | 954 | } |
| fep | 0:62cd296ba2a7 | 955 | </pre> |
| fep | 0:62cd296ba2a7 | 956 | * \defgroup xSemaphoreCreateRecursiveMutexStatic xSemaphoreCreateRecursiveMutexStatic |
| fep | 0:62cd296ba2a7 | 957 | * \ingroup Semaphores |
| fep | 0:62cd296ba2a7 | 958 | */ |
| fep | 0:62cd296ba2a7 | 959 | #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) ) |
| fep | 0:62cd296ba2a7 | 960 | #define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutexStatic( queueQUEUE_TYPE_RECURSIVE_MUTEX, pxStaticSemaphore ) |
| fep | 0:62cd296ba2a7 | 961 | #endif /* configSUPPORT_STATIC_ALLOCATION */ |
| fep | 0:62cd296ba2a7 | 962 | |
| fep | 0:62cd296ba2a7 | 963 | /** |
| fep | 0:62cd296ba2a7 | 964 | * semphr. h |
| fep | 0:62cd296ba2a7 | 965 | * <pre>SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount )</pre> |
| fep | 0:62cd296ba2a7 | 966 | * |
| fep | 0:62cd296ba2a7 | 967 | * Creates a new counting semaphore instance, and returns a handle by which the |
| fep | 0:62cd296ba2a7 | 968 | * new counting semaphore can be referenced. |
| fep | 0:62cd296ba2a7 | 969 | * |
| fep | 0:62cd296ba2a7 | 970 | * In many usage scenarios it is faster and more memory efficient to use a |
| fep | 0:62cd296ba2a7 | 971 | * direct to task notification in place of a counting semaphore! |
| fep | 0:62cd296ba2a7 | 972 | * http://www.freertos.org/RTOS-task-notifications.html |
| fep | 0:62cd296ba2a7 | 973 | * |
| fep | 0:62cd296ba2a7 | 974 | * Internally, within the FreeRTOS implementation, counting semaphores use a |
| fep | 0:62cd296ba2a7 | 975 | * block of memory, in which the counting semaphore structure is stored. If a |
| fep | 0:62cd296ba2a7 | 976 | * counting semaphore is created using xSemaphoreCreateCounting() then the |
| fep | 0:62cd296ba2a7 | 977 | * required memory is automatically dynamically allocated inside the |
| fep | 0:62cd296ba2a7 | 978 | * xSemaphoreCreateCounting() function. (see |
| fep | 0:62cd296ba2a7 | 979 | * http://www.freertos.org/a00111.html). If a counting semaphore is created |
| fep | 0:62cd296ba2a7 | 980 | * using xSemaphoreCreateCountingStatic() then the application writer can |
| fep | 0:62cd296ba2a7 | 981 | * instead optionally provide the memory that will get used by the counting |
| fep | 0:62cd296ba2a7 | 982 | * semaphore. xSemaphoreCreateCountingStatic() therefore allows a counting |
| fep | 0:62cd296ba2a7 | 983 | * semaphore to be created without using any dynamic memory allocation. |
| fep | 0:62cd296ba2a7 | 984 | * |
| fep | 0:62cd296ba2a7 | 985 | * Counting semaphores are typically used for two things: |
| fep | 0:62cd296ba2a7 | 986 | * |
| fep | 0:62cd296ba2a7 | 987 | * 1) Counting events. |
| fep | 0:62cd296ba2a7 | 988 | * |
| fep | 0:62cd296ba2a7 | 989 | * In this usage scenario an event handler will 'give' a semaphore each time |
| fep | 0:62cd296ba2a7 | 990 | * an event occurs (incrementing the semaphore count value), and a handler |
| fep | 0:62cd296ba2a7 | 991 | * task will 'take' a semaphore each time it processes an event |
| fep | 0:62cd296ba2a7 | 992 | * (decrementing the semaphore count value). The count value is therefore |
| fep | 0:62cd296ba2a7 | 993 | * the difference between the number of events that have occurred and the |
| fep | 0:62cd296ba2a7 | 994 | * number that have been processed. In this case it is desirable for the |
| fep | 0:62cd296ba2a7 | 995 | * initial count value to be zero. |
| fep | 0:62cd296ba2a7 | 996 | * |
| fep | 0:62cd296ba2a7 | 997 | * 2) Resource management. |
| fep | 0:62cd296ba2a7 | 998 | * |
| fep | 0:62cd296ba2a7 | 999 | * In this usage scenario the count value indicates the number of resources |
| fep | 0:62cd296ba2a7 | 1000 | * available. To obtain control of a resource a task must first obtain a |
| fep | 0:62cd296ba2a7 | 1001 | * semaphore - decrementing the semaphore count value. When the count value |
| fep | 0:62cd296ba2a7 | 1002 | * reaches zero there are no free resources. When a task finishes with the |
| fep | 0:62cd296ba2a7 | 1003 | * resource it 'gives' the semaphore back - incrementing the semaphore count |
| fep | 0:62cd296ba2a7 | 1004 | * value. In this case it is desirable for the initial count value to be |
| fep | 0:62cd296ba2a7 | 1005 | * equal to the maximum count value, indicating that all resources are free. |
| fep | 0:62cd296ba2a7 | 1006 | * |
| fep | 0:62cd296ba2a7 | 1007 | * @param uxMaxCount The maximum count value that can be reached. When the |
| fep | 0:62cd296ba2a7 | 1008 | * semaphore reaches this value it can no longer be 'given'. |
| fep | 0:62cd296ba2a7 | 1009 | * |
| fep | 0:62cd296ba2a7 | 1010 | * @param uxInitialCount The count value assigned to the semaphore when it is |
| fep | 0:62cd296ba2a7 | 1011 | * created. |
| fep | 0:62cd296ba2a7 | 1012 | * |
| fep | 0:62cd296ba2a7 | 1013 | * @return Handle to the created semaphore. Null if the semaphore could not be |
| fep | 0:62cd296ba2a7 | 1014 | * created. |
| fep | 0:62cd296ba2a7 | 1015 | * |
| fep | 0:62cd296ba2a7 | 1016 | * Example usage: |
| fep | 0:62cd296ba2a7 | 1017 | <pre> |
| fep | 0:62cd296ba2a7 | 1018 | SemaphoreHandle_t xSemaphore; |
| fep | 0:62cd296ba2a7 | 1019 | |
| fep | 0:62cd296ba2a7 | 1020 | void vATask( void * pvParameters ) |
| fep | 0:62cd296ba2a7 | 1021 | { |
| fep | 0:62cd296ba2a7 | 1022 | SemaphoreHandle_t xSemaphore = NULL; |
| fep | 0:62cd296ba2a7 | 1023 | |
| fep | 0:62cd296ba2a7 | 1024 | // Semaphore cannot be used before a call to xSemaphoreCreateCounting(). |
| fep | 0:62cd296ba2a7 | 1025 | // The max value to which the semaphore can count should be 10, and the |
| fep | 0:62cd296ba2a7 | 1026 | // initial value assigned to the count should be 0. |
| fep | 0:62cd296ba2a7 | 1027 | xSemaphore = xSemaphoreCreateCounting( 10, 0 ); |
| fep | 0:62cd296ba2a7 | 1028 | |
| fep | 0:62cd296ba2a7 | 1029 | if( xSemaphore != NULL ) |
| fep | 0:62cd296ba2a7 | 1030 | { |
| fep | 0:62cd296ba2a7 | 1031 | // The semaphore was created successfully. |
| fep | 0:62cd296ba2a7 | 1032 | // The semaphore can now be used. |
| fep | 0:62cd296ba2a7 | 1033 | } |
| fep | 0:62cd296ba2a7 | 1034 | } |
| fep | 0:62cd296ba2a7 | 1035 | </pre> |
| fep | 0:62cd296ba2a7 | 1036 | * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting |
| fep | 0:62cd296ba2a7 | 1037 | * \ingroup Semaphores |
| fep | 0:62cd296ba2a7 | 1038 | */ |
| fep | 0:62cd296ba2a7 | 1039 | #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) |
| fep | 0:62cd296ba2a7 | 1040 | #define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) |
| fep | 0:62cd296ba2a7 | 1041 | #endif |
| fep | 0:62cd296ba2a7 | 1042 | |
| fep | 0:62cd296ba2a7 | 1043 | /** |
| fep | 0:62cd296ba2a7 | 1044 | * semphr. h |
| fep | 0:62cd296ba2a7 | 1045 | * <pre>SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer )</pre> |
| fep | 0:62cd296ba2a7 | 1046 | * |
| fep | 0:62cd296ba2a7 | 1047 | * Creates a new counting semaphore instance, and returns a handle by which the |
| fep | 0:62cd296ba2a7 | 1048 | * new counting semaphore can be referenced. |
| fep | 0:62cd296ba2a7 | 1049 | * |
| fep | 0:62cd296ba2a7 | 1050 | * In many usage scenarios it is faster and more memory efficient to use a |
| fep | 0:62cd296ba2a7 | 1051 | * direct to task notification in place of a counting semaphore! |
| fep | 0:62cd296ba2a7 | 1052 | * http://www.freertos.org/RTOS-task-notifications.html |
| fep | 0:62cd296ba2a7 | 1053 | * |
| fep | 0:62cd296ba2a7 | 1054 | * Internally, within the FreeRTOS implementation, counting semaphores use a |
| fep | 0:62cd296ba2a7 | 1055 | * block of memory, in which the counting semaphore structure is stored. If a |
| fep | 0:62cd296ba2a7 | 1056 | * counting semaphore is created using xSemaphoreCreateCounting() then the |
| fep | 0:62cd296ba2a7 | 1057 | * required memory is automatically dynamically allocated inside the |
| fep | 0:62cd296ba2a7 | 1058 | * xSemaphoreCreateCounting() function. (see |
| fep | 0:62cd296ba2a7 | 1059 | * http://www.freertos.org/a00111.html). If a counting semaphore is created |
| fep | 0:62cd296ba2a7 | 1060 | * using xSemaphoreCreateCountingStatic() then the application writer must |
| fep | 0:62cd296ba2a7 | 1061 | * provide the memory. xSemaphoreCreateCountingStatic() therefore allows a |
| fep | 0:62cd296ba2a7 | 1062 | * counting semaphore to be created without using any dynamic memory allocation. |
| fep | 0:62cd296ba2a7 | 1063 | * |
| fep | 0:62cd296ba2a7 | 1064 | * Counting semaphores are typically used for two things: |
| fep | 0:62cd296ba2a7 | 1065 | * |
| fep | 0:62cd296ba2a7 | 1066 | * 1) Counting events. |
| fep | 0:62cd296ba2a7 | 1067 | * |
| fep | 0:62cd296ba2a7 | 1068 | * In this usage scenario an event handler will 'give' a semaphore each time |
| fep | 0:62cd296ba2a7 | 1069 | * an event occurs (incrementing the semaphore count value), and a handler |
| fep | 0:62cd296ba2a7 | 1070 | * task will 'take' a semaphore each time it processes an event |
| fep | 0:62cd296ba2a7 | 1071 | * (decrementing the semaphore count value). The count value is therefore |
| fep | 0:62cd296ba2a7 | 1072 | * the difference between the number of events that have occurred and the |
| fep | 0:62cd296ba2a7 | 1073 | * number that have been processed. In this case it is desirable for the |
| fep | 0:62cd296ba2a7 | 1074 | * initial count value to be zero. |
| fep | 0:62cd296ba2a7 | 1075 | * |
| fep | 0:62cd296ba2a7 | 1076 | * 2) Resource management. |
| fep | 0:62cd296ba2a7 | 1077 | * |
| fep | 0:62cd296ba2a7 | 1078 | * In this usage scenario the count value indicates the number of resources |
| fep | 0:62cd296ba2a7 | 1079 | * available. To obtain control of a resource a task must first obtain a |
| fep | 0:62cd296ba2a7 | 1080 | * semaphore - decrementing the semaphore count value. When the count value |
| fep | 0:62cd296ba2a7 | 1081 | * reaches zero there are no free resources. When a task finishes with the |
| fep | 0:62cd296ba2a7 | 1082 | * resource it 'gives' the semaphore back - incrementing the semaphore count |
| fep | 0:62cd296ba2a7 | 1083 | * value. In this case it is desirable for the initial count value to be |
| fep | 0:62cd296ba2a7 | 1084 | * equal to the maximum count value, indicating that all resources are free. |
| fep | 0:62cd296ba2a7 | 1085 | * |
| fep | 0:62cd296ba2a7 | 1086 | * @param uxMaxCount The maximum count value that can be reached. When the |
| fep | 0:62cd296ba2a7 | 1087 | * semaphore reaches this value it can no longer be 'given'. |
| fep | 0:62cd296ba2a7 | 1088 | * |
| fep | 0:62cd296ba2a7 | 1089 | * @param uxInitialCount The count value assigned to the semaphore when it is |
| fep | 0:62cd296ba2a7 | 1090 | * created. |
| fep | 0:62cd296ba2a7 | 1091 | * |
| fep | 0:62cd296ba2a7 | 1092 | * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t, |
| fep | 0:62cd296ba2a7 | 1093 | * which will then be used to hold the semaphore's data structure, removing the |
| fep | 0:62cd296ba2a7 | 1094 | * need for the memory to be allocated dynamically. |
| fep | 0:62cd296ba2a7 | 1095 | * |
| fep | 0:62cd296ba2a7 | 1096 | * @return If the counting semaphore was successfully created then a handle to |
| fep | 0:62cd296ba2a7 | 1097 | * the created counting semaphore is returned. If pxSemaphoreBuffer was NULL |
| fep | 0:62cd296ba2a7 | 1098 | * then NULL is returned. |
| fep | 0:62cd296ba2a7 | 1099 | * |
| fep | 0:62cd296ba2a7 | 1100 | * Example usage: |
| fep | 0:62cd296ba2a7 | 1101 | <pre> |
| fep | 0:62cd296ba2a7 | 1102 | SemaphoreHandle_t xSemaphore; |
| fep | 0:62cd296ba2a7 | 1103 | StaticSemaphore_t xSemaphoreBuffer; |
| fep | 0:62cd296ba2a7 | 1104 | |
| fep | 0:62cd296ba2a7 | 1105 | void vATask( void * pvParameters ) |
| fep | 0:62cd296ba2a7 | 1106 | { |
| fep | 0:62cd296ba2a7 | 1107 | SemaphoreHandle_t xSemaphore = NULL; |
| fep | 0:62cd296ba2a7 | 1108 | |
| fep | 0:62cd296ba2a7 | 1109 | // Counting semaphore cannot be used before they have been created. Create |
| fep | 0:62cd296ba2a7 | 1110 | // a counting semaphore using xSemaphoreCreateCountingStatic(). The max |
| fep | 0:62cd296ba2a7 | 1111 | // value to which the semaphore can count is 10, and the initial value |
| fep | 0:62cd296ba2a7 | 1112 | // assigned to the count will be 0. The address of xSemaphoreBuffer is |
| fep | 0:62cd296ba2a7 | 1113 | // passed in and will be used to hold the semaphore structure, so no dynamic |
| fep | 0:62cd296ba2a7 | 1114 | // memory allocation will be used. |
| fep | 0:62cd296ba2a7 | 1115 | xSemaphore = xSemaphoreCreateCounting( 10, 0, &xSemaphoreBuffer ); |
| fep | 0:62cd296ba2a7 | 1116 | |
| fep | 0:62cd296ba2a7 | 1117 | // No memory allocation was attempted so xSemaphore cannot be NULL, so there |
| fep | 0:62cd296ba2a7 | 1118 | // is no need to check its value. |
| fep | 0:62cd296ba2a7 | 1119 | } |
| fep | 0:62cd296ba2a7 | 1120 | </pre> |
| fep | 0:62cd296ba2a7 | 1121 | * \defgroup xSemaphoreCreateCountingStatic xSemaphoreCreateCountingStatic |
| fep | 0:62cd296ba2a7 | 1122 | * \ingroup Semaphores |
| fep | 0:62cd296ba2a7 | 1123 | */ |
| fep | 0:62cd296ba2a7 | 1124 | #if( configSUPPORT_STATIC_ALLOCATION == 1 ) |
| fep | 0:62cd296ba2a7 | 1125 | #define xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxSemaphoreBuffer ) xQueueCreateCountingSemaphoreStatic( ( uxMaxCount ), ( uxInitialCount ), ( pxSemaphoreBuffer ) ) |
| fep | 0:62cd296ba2a7 | 1126 | #endif /* configSUPPORT_STATIC_ALLOCATION */ |
| fep | 0:62cd296ba2a7 | 1127 | |
| fep | 0:62cd296ba2a7 | 1128 | /** |
| fep | 0:62cd296ba2a7 | 1129 | * semphr. h |
| fep | 0:62cd296ba2a7 | 1130 | * <pre>void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );</pre> |
| fep | 0:62cd296ba2a7 | 1131 | * |
| fep | 0:62cd296ba2a7 | 1132 | * Delete a semaphore. This function must be used with care. For example, |
| fep | 0:62cd296ba2a7 | 1133 | * do not delete a mutex type semaphore if the mutex is held by a task. |
| fep | 0:62cd296ba2a7 | 1134 | * |
| fep | 0:62cd296ba2a7 | 1135 | * @param xSemaphore A handle to the semaphore to be deleted. |
| fep | 0:62cd296ba2a7 | 1136 | * |
| fep | 0:62cd296ba2a7 | 1137 | * \defgroup vSemaphoreDelete vSemaphoreDelete |
| fep | 0:62cd296ba2a7 | 1138 | * \ingroup Semaphores |
| fep | 0:62cd296ba2a7 | 1139 | */ |
| fep | 0:62cd296ba2a7 | 1140 | #define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) ) |
| fep | 0:62cd296ba2a7 | 1141 | |
| fep | 0:62cd296ba2a7 | 1142 | /** |
| fep | 0:62cd296ba2a7 | 1143 | * semphr.h |
| fep | 0:62cd296ba2a7 | 1144 | * <pre>TaskHandle_t xSemaphoreGetMutexHolder( SemaphoreHandle_t xMutex );</pre> |
| fep | 0:62cd296ba2a7 | 1145 | * |
| fep | 0:62cd296ba2a7 | 1146 | * If xMutex is indeed a mutex type semaphore, return the current mutex holder. |
| fep | 0:62cd296ba2a7 | 1147 | * If xMutex is not a mutex type semaphore, or the mutex is available (not held |
| fep | 0:62cd296ba2a7 | 1148 | * by a task), return NULL. |
| fep | 0:62cd296ba2a7 | 1149 | * |
| fep | 0:62cd296ba2a7 | 1150 | * Note: This is a good way of determining if the calling task is the mutex |
| fep | 0:62cd296ba2a7 | 1151 | * holder, but not a good way of determining the identity of the mutex holder as |
| fep | 0:62cd296ba2a7 | 1152 | * the holder may change between the function exiting and the returned value |
| fep | 0:62cd296ba2a7 | 1153 | * being tested. |
| fep | 0:62cd296ba2a7 | 1154 | */ |
| fep | 0:62cd296ba2a7 | 1155 | #define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) ) |
| fep | 0:62cd296ba2a7 | 1156 | |
| fep | 0:62cd296ba2a7 | 1157 | /** |
| fep | 0:62cd296ba2a7 | 1158 | * semphr.h |
| fep | 0:62cd296ba2a7 | 1159 | * <pre>UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore );</pre> |
| fep | 0:62cd296ba2a7 | 1160 | * |
| fep | 0:62cd296ba2a7 | 1161 | * If the semaphore is a counting semaphore then uxSemaphoreGetCount() returns |
| fep | 0:62cd296ba2a7 | 1162 | * its current count value. If the semaphore is a binary semaphore then |
| fep | 0:62cd296ba2a7 | 1163 | * uxSemaphoreGetCount() returns 1 if the semaphore is available, and 0 if the |
| fep | 0:62cd296ba2a7 | 1164 | * semaphore is not available. |
| fep | 0:62cd296ba2a7 | 1165 | * |
| fep | 0:62cd296ba2a7 | 1166 | */ |
| fep | 0:62cd296ba2a7 | 1167 | #define uxSemaphoreGetCount( xSemaphore ) uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) ) |
| fep | 0:62cd296ba2a7 | 1168 | |
| fep | 0:62cd296ba2a7 | 1169 | #endif /* SEMAPHORE_H */ |
| fep | 0:62cd296ba2a7 | 1170 | |
| fep | 0:62cd296ba2a7 | 1171 | |
| fep | 0:62cd296ba2a7 | 1172 |