Update revision to use TI's mqtt and Freertos.
Dependencies: mbed client server
Fork of cc3100_Test_mqtt_CM3 by
FreeRTOS_V8_2_1/source/include/semphr.h@3:a8c249046181, 2015-09-03 (annotated)
- Committer:
- dflet
- Date:
- Thu Sep 03 14:02:37 2015 +0000
- Revision:
- 3:a8c249046181
SPI Mode change 1 to 0
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dflet | 3:a8c249046181 | 1 | /* |
dflet | 3:a8c249046181 | 2 | FreeRTOS V8.2.1 - Copyright (C) 2015 Real Time Engineers Ltd. |
dflet | 3:a8c249046181 | 3 | All rights reserved |
dflet | 3:a8c249046181 | 4 | |
dflet | 3:a8c249046181 | 5 | VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. |
dflet | 3:a8c249046181 | 6 | |
dflet | 3:a8c249046181 | 7 | This file is part of the FreeRTOS distribution. |
dflet | 3:a8c249046181 | 8 | |
dflet | 3:a8c249046181 | 9 | FreeRTOS is free software; you can redistribute it and/or modify it under |
dflet | 3:a8c249046181 | 10 | the terms of the GNU General Public License (version 2) as published by the |
dflet | 3:a8c249046181 | 11 | Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. |
dflet | 3:a8c249046181 | 12 | |
dflet | 3:a8c249046181 | 13 | *************************************************************************** |
dflet | 3:a8c249046181 | 14 | >>! NOTE: The modification to the GPL is included to allow you to !<< |
dflet | 3:a8c249046181 | 15 | >>! distribute a combined work that includes FreeRTOS without being !<< |
dflet | 3:a8c249046181 | 16 | >>! obliged to provide the source code for proprietary components !<< |
dflet | 3:a8c249046181 | 17 | >>! outside of the FreeRTOS kernel. !<< |
dflet | 3:a8c249046181 | 18 | *************************************************************************** |
dflet | 3:a8c249046181 | 19 | |
dflet | 3:a8c249046181 | 20 | FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY |
dflet | 3:a8c249046181 | 21 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
dflet | 3:a8c249046181 | 22 | FOR A PARTICULAR PURPOSE. Full license text is available on the following |
dflet | 3:a8c249046181 | 23 | link: http://www.freertos.org/a00114.html |
dflet | 3:a8c249046181 | 24 | |
dflet | 3:a8c249046181 | 25 | *************************************************************************** |
dflet | 3:a8c249046181 | 26 | * * |
dflet | 3:a8c249046181 | 27 | * FreeRTOS provides completely free yet professionally developed, * |
dflet | 3:a8c249046181 | 28 | * robust, strictly quality controlled, supported, and cross * |
dflet | 3:a8c249046181 | 29 | * platform software that is more than just the market leader, it * |
dflet | 3:a8c249046181 | 30 | * is the industry's de facto standard. * |
dflet | 3:a8c249046181 | 31 | * * |
dflet | 3:a8c249046181 | 32 | * Help yourself get started quickly while simultaneously helping * |
dflet | 3:a8c249046181 | 33 | * to support the FreeRTOS project by purchasing a FreeRTOS * |
dflet | 3:a8c249046181 | 34 | * tutorial book, reference manual, or both: * |
dflet | 3:a8c249046181 | 35 | * http://www.FreeRTOS.org/Documentation * |
dflet | 3:a8c249046181 | 36 | * * |
dflet | 3:a8c249046181 | 37 | *************************************************************************** |
dflet | 3:a8c249046181 | 38 | |
dflet | 3:a8c249046181 | 39 | http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading |
dflet | 3:a8c249046181 | 40 | the FAQ page "My application does not run, what could be wrong?". Have you |
dflet | 3:a8c249046181 | 41 | defined configASSERT()? |
dflet | 3:a8c249046181 | 42 | |
dflet | 3:a8c249046181 | 43 | http://www.FreeRTOS.org/support - In return for receiving this top quality |
dflet | 3:a8c249046181 | 44 | embedded software for free we request you assist our global community by |
dflet | 3:a8c249046181 | 45 | participating in the support forum. |
dflet | 3:a8c249046181 | 46 | |
dflet | 3:a8c249046181 | 47 | http://www.FreeRTOS.org/training - Investing in training allows your team to |
dflet | 3:a8c249046181 | 48 | be as productive as possible as early as possible. Now you can receive |
dflet | 3:a8c249046181 | 49 | FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers |
dflet | 3:a8c249046181 | 50 | Ltd, and the world's leading authority on the world's leading RTOS. |
dflet | 3:a8c249046181 | 51 | |
dflet | 3:a8c249046181 | 52 | http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, |
dflet | 3:a8c249046181 | 53 | including FreeRTOS+Trace - an indispensable productivity tool, a DOS |
dflet | 3:a8c249046181 | 54 | compatible FAT file system, and our tiny thread aware UDP/IP stack. |
dflet | 3:a8c249046181 | 55 | |
dflet | 3:a8c249046181 | 56 | http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. |
dflet | 3:a8c249046181 | 57 | Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. |
dflet | 3:a8c249046181 | 58 | |
dflet | 3:a8c249046181 | 59 | http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High |
dflet | 3:a8c249046181 | 60 | Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS |
dflet | 3:a8c249046181 | 61 | licenses offer ticketed support, indemnification and commercial middleware. |
dflet | 3:a8c249046181 | 62 | |
dflet | 3:a8c249046181 | 63 | http://www.SafeRTOS.com - High Integrity Systems also provide a safety |
dflet | 3:a8c249046181 | 64 | engineered and independently SIL3 certified version for use in safety and |
dflet | 3:a8c249046181 | 65 | mission critical applications that require provable dependability. |
dflet | 3:a8c249046181 | 66 | |
dflet | 3:a8c249046181 | 67 | 1 tab == 4 spaces! |
dflet | 3:a8c249046181 | 68 | */ |
dflet | 3:a8c249046181 | 69 | |
dflet | 3:a8c249046181 | 70 | #ifndef SEMAPHORE_H |
dflet | 3:a8c249046181 | 71 | #define SEMAPHORE_H |
dflet | 3:a8c249046181 | 72 | |
dflet | 3:a8c249046181 | 73 | #ifndef INC_FREERTOS_H |
dflet | 3:a8c249046181 | 74 | #error "include FreeRTOS.h" must appear in source files before "include semphr.h" |
dflet | 3:a8c249046181 | 75 | #endif |
dflet | 3:a8c249046181 | 76 | |
dflet | 3:a8c249046181 | 77 | #include "queue.h" |
dflet | 3:a8c249046181 | 78 | |
dflet | 3:a8c249046181 | 79 | typedef QueueHandle_t SemaphoreHandle_t; |
dflet | 3:a8c249046181 | 80 | |
dflet | 3:a8c249046181 | 81 | #define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( uint8_t ) 1U ) |
dflet | 3:a8c249046181 | 82 | #define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( uint8_t ) 0U ) |
dflet | 3:a8c249046181 | 83 | #define semGIVE_BLOCK_TIME ( ( TickType_t ) 0U ) |
dflet | 3:a8c249046181 | 84 | |
dflet | 3:a8c249046181 | 85 | |
dflet | 3:a8c249046181 | 86 | /** |
dflet | 3:a8c249046181 | 87 | * semphr. h |
dflet | 3:a8c249046181 | 88 | * <pre>vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )</pre> |
dflet | 3:a8c249046181 | 89 | * |
dflet | 3:a8c249046181 | 90 | * This old vSemaphoreCreateBinary() macro is now deprecated in favour of the |
dflet | 3:a8c249046181 | 91 | * xSemaphoreCreateBinary() function. Note that binary semaphores created using |
dflet | 3:a8c249046181 | 92 | * the vSemaphoreCreateBinary() macro are created in a state such that the |
dflet | 3:a8c249046181 | 93 | * first call to 'take' the semaphore would pass, whereas binary semaphores |
dflet | 3:a8c249046181 | 94 | * created using xSemaphoreCreateBinary() are created in a state such that the |
dflet | 3:a8c249046181 | 95 | * the semaphore must first be 'given' before it can be 'taken'. |
dflet | 3:a8c249046181 | 96 | * |
dflet | 3:a8c249046181 | 97 | * <i>Macro</i> that implements a semaphore by using the existing queue mechanism. |
dflet | 3:a8c249046181 | 98 | * The queue length is 1 as this is a binary semaphore. The data size is 0 |
dflet | 3:a8c249046181 | 99 | * as we don't want to actually store any data - we just want to know if the |
dflet | 3:a8c249046181 | 100 | * queue is empty or full. |
dflet | 3:a8c249046181 | 101 | * |
dflet | 3:a8c249046181 | 102 | * This type of semaphore can be used for pure synchronisation between tasks or |
dflet | 3:a8c249046181 | 103 | * between an interrupt and a task. The semaphore need not be given back once |
dflet | 3:a8c249046181 | 104 | * obtained, so one task/interrupt can continuously 'give' the semaphore while |
dflet | 3:a8c249046181 | 105 | * another continuously 'takes' the semaphore. For this reason this type of |
dflet | 3:a8c249046181 | 106 | * semaphore does not use a priority inheritance mechanism. For an alternative |
dflet | 3:a8c249046181 | 107 | * that does use priority inheritance see xSemaphoreCreateMutex(). |
dflet | 3:a8c249046181 | 108 | * |
dflet | 3:a8c249046181 | 109 | * @param xSemaphore Handle to the created semaphore. Should be of type SemaphoreHandle_t. |
dflet | 3:a8c249046181 | 110 | * |
dflet | 3:a8c249046181 | 111 | * Example usage: |
dflet | 3:a8c249046181 | 112 | <pre> |
dflet | 3:a8c249046181 | 113 | SemaphoreHandle_t xSemaphore = NULL; |
dflet | 3:a8c249046181 | 114 | |
dflet | 3:a8c249046181 | 115 | void vATask( void * pvParameters ) |
dflet | 3:a8c249046181 | 116 | { |
dflet | 3:a8c249046181 | 117 | // Semaphore cannot be used before a call to vSemaphoreCreateBinary (). |
dflet | 3:a8c249046181 | 118 | // This is a macro so pass the variable in directly. |
dflet | 3:a8c249046181 | 119 | vSemaphoreCreateBinary( xSemaphore ); |
dflet | 3:a8c249046181 | 120 | |
dflet | 3:a8c249046181 | 121 | if( xSemaphore != NULL ) |
dflet | 3:a8c249046181 | 122 | { |
dflet | 3:a8c249046181 | 123 | // The semaphore was created successfully. |
dflet | 3:a8c249046181 | 124 | // The semaphore can now be used. |
dflet | 3:a8c249046181 | 125 | } |
dflet | 3:a8c249046181 | 126 | } |
dflet | 3:a8c249046181 | 127 | </pre> |
dflet | 3:a8c249046181 | 128 | * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary |
dflet | 3:a8c249046181 | 129 | * \ingroup Semaphores |
dflet | 3:a8c249046181 | 130 | */ |
dflet | 3:a8c249046181 | 131 | #define vSemaphoreCreateBinary( xSemaphore ) \ |
dflet | 3:a8c249046181 | 132 | { \ |
dflet | 3:a8c249046181 | 133 | ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ |
dflet | 3:a8c249046181 | 134 | if( ( xSemaphore ) != NULL ) \ |
dflet | 3:a8c249046181 | 135 | { \ |
dflet | 3:a8c249046181 | 136 | ( void ) xSemaphoreGive( ( xSemaphore ) ); \ |
dflet | 3:a8c249046181 | 137 | } \ |
dflet | 3:a8c249046181 | 138 | } |
dflet | 3:a8c249046181 | 139 | |
dflet | 3:a8c249046181 | 140 | /** |
dflet | 3:a8c249046181 | 141 | * semphr. h |
dflet | 3:a8c249046181 | 142 | * <pre>SemaphoreHandle_t xSemaphoreCreateBinary( void )</pre> |
dflet | 3:a8c249046181 | 143 | * |
dflet | 3:a8c249046181 | 144 | * The old vSemaphoreCreateBinary() macro is now deprecated in favour of this |
dflet | 3:a8c249046181 | 145 | * xSemaphoreCreateBinary() function. Note that binary semaphores created using |
dflet | 3:a8c249046181 | 146 | * the vSemaphoreCreateBinary() macro are created in a state such that the |
dflet | 3:a8c249046181 | 147 | * first call to 'take' the semaphore would pass, whereas binary semaphores |
dflet | 3:a8c249046181 | 148 | * created using xSemaphoreCreateBinary() are created in a state such that the |
dflet | 3:a8c249046181 | 149 | * the semaphore must first be 'given' before it can be 'taken'. |
dflet | 3:a8c249046181 | 150 | * |
dflet | 3:a8c249046181 | 151 | * Function that creates a semaphore by using the existing queue mechanism. |
dflet | 3:a8c249046181 | 152 | * The queue length is 1 as this is a binary semaphore. The data size is 0 |
dflet | 3:a8c249046181 | 153 | * as nothing is actually stored - all that is important is whether the queue is |
dflet | 3:a8c249046181 | 154 | * empty or full (the binary semaphore is available or not). |
dflet | 3:a8c249046181 | 155 | * |
dflet | 3:a8c249046181 | 156 | * This type of semaphore can be used for pure synchronisation between tasks or |
dflet | 3:a8c249046181 | 157 | * between an interrupt and a task. The semaphore need not be given back once |
dflet | 3:a8c249046181 | 158 | * obtained, so one task/interrupt can continuously 'give' the semaphore while |
dflet | 3:a8c249046181 | 159 | * another continuously 'takes' the semaphore. For this reason this type of |
dflet | 3:a8c249046181 | 160 | * semaphore does not use a priority inheritance mechanism. For an alternative |
dflet | 3:a8c249046181 | 161 | * that does use priority inheritance see xSemaphoreCreateMutex(). |
dflet | 3:a8c249046181 | 162 | * |
dflet | 3:a8c249046181 | 163 | * @return Handle to the created semaphore. |
dflet | 3:a8c249046181 | 164 | * |
dflet | 3:a8c249046181 | 165 | * Example usage: |
dflet | 3:a8c249046181 | 166 | <pre> |
dflet | 3:a8c249046181 | 167 | SemaphoreHandle_t xSemaphore = NULL; |
dflet | 3:a8c249046181 | 168 | |
dflet | 3:a8c249046181 | 169 | void vATask( void * pvParameters ) |
dflet | 3:a8c249046181 | 170 | { |
dflet | 3:a8c249046181 | 171 | // Semaphore cannot be used before a call to vSemaphoreCreateBinary (). |
dflet | 3:a8c249046181 | 172 | // This is a macro so pass the variable in directly. |
dflet | 3:a8c249046181 | 173 | xSemaphore = xSemaphoreCreateBinary(); |
dflet | 3:a8c249046181 | 174 | |
dflet | 3:a8c249046181 | 175 | if( xSemaphore != NULL ) |
dflet | 3:a8c249046181 | 176 | { |
dflet | 3:a8c249046181 | 177 | // The semaphore was created successfully. |
dflet | 3:a8c249046181 | 178 | // The semaphore can now be used. |
dflet | 3:a8c249046181 | 179 | } |
dflet | 3:a8c249046181 | 180 | } |
dflet | 3:a8c249046181 | 181 | </pre> |
dflet | 3:a8c249046181 | 182 | * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary |
dflet | 3:a8c249046181 | 183 | * \ingroup Semaphores |
dflet | 3:a8c249046181 | 184 | */ |
dflet | 3:a8c249046181 | 185 | #define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ) |
dflet | 3:a8c249046181 | 186 | |
dflet | 3:a8c249046181 | 187 | /** |
dflet | 3:a8c249046181 | 188 | * semphr. h |
dflet | 3:a8c249046181 | 189 | * <pre>xSemaphoreTake( |
dflet | 3:a8c249046181 | 190 | * SemaphoreHandle_t xSemaphore, |
dflet | 3:a8c249046181 | 191 | * TickType_t xBlockTime |
dflet | 3:a8c249046181 | 192 | * )</pre> |
dflet | 3:a8c249046181 | 193 | * |
dflet | 3:a8c249046181 | 194 | * <i>Macro</i> to obtain a semaphore. The semaphore must have previously been |
dflet | 3:a8c249046181 | 195 | * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or |
dflet | 3:a8c249046181 | 196 | * xSemaphoreCreateCounting(). |
dflet | 3:a8c249046181 | 197 | * |
dflet | 3:a8c249046181 | 198 | * @param xSemaphore A handle to the semaphore being taken - obtained when |
dflet | 3:a8c249046181 | 199 | * the semaphore was created. |
dflet | 3:a8c249046181 | 200 | * |
dflet | 3:a8c249046181 | 201 | * @param xBlockTime The time in ticks to wait for the semaphore to become |
dflet | 3:a8c249046181 | 202 | * available. The macro portTICK_PERIOD_MS can be used to convert this to a |
dflet | 3:a8c249046181 | 203 | * real time. A block time of zero can be used to poll the semaphore. A block |
dflet | 3:a8c249046181 | 204 | * time of portMAX_DELAY can be used to block indefinitely (provided |
dflet | 3:a8c249046181 | 205 | * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h). |
dflet | 3:a8c249046181 | 206 | * |
dflet | 3:a8c249046181 | 207 | * @return pdTRUE if the semaphore was obtained. pdFALSE |
dflet | 3:a8c249046181 | 208 | * if xBlockTime expired without the semaphore becoming available. |
dflet | 3:a8c249046181 | 209 | * |
dflet | 3:a8c249046181 | 210 | * Example usage: |
dflet | 3:a8c249046181 | 211 | <pre> |
dflet | 3:a8c249046181 | 212 | SemaphoreHandle_t xSemaphore = NULL; |
dflet | 3:a8c249046181 | 213 | |
dflet | 3:a8c249046181 | 214 | // A task that creates a semaphore. |
dflet | 3:a8c249046181 | 215 | void vATask( void * pvParameters ) |
dflet | 3:a8c249046181 | 216 | { |
dflet | 3:a8c249046181 | 217 | // Create the semaphore to guard a shared resource. |
dflet | 3:a8c249046181 | 218 | vSemaphoreCreateBinary( xSemaphore ); |
dflet | 3:a8c249046181 | 219 | } |
dflet | 3:a8c249046181 | 220 | |
dflet | 3:a8c249046181 | 221 | // A task that uses the semaphore. |
dflet | 3:a8c249046181 | 222 | void vAnotherTask( void * pvParameters ) |
dflet | 3:a8c249046181 | 223 | { |
dflet | 3:a8c249046181 | 224 | // ... Do other things. |
dflet | 3:a8c249046181 | 225 | |
dflet | 3:a8c249046181 | 226 | if( xSemaphore != NULL ) |
dflet | 3:a8c249046181 | 227 | { |
dflet | 3:a8c249046181 | 228 | // See if we can obtain the semaphore. If the semaphore is not available |
dflet | 3:a8c249046181 | 229 | // wait 10 ticks to see if it becomes free. |
dflet | 3:a8c249046181 | 230 | if( xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ) == pdTRUE ) |
dflet | 3:a8c249046181 | 231 | { |
dflet | 3:a8c249046181 | 232 | // We were able to obtain the semaphore and can now access the |
dflet | 3:a8c249046181 | 233 | // shared resource. |
dflet | 3:a8c249046181 | 234 | |
dflet | 3:a8c249046181 | 235 | // ... |
dflet | 3:a8c249046181 | 236 | |
dflet | 3:a8c249046181 | 237 | // We have finished accessing the shared resource. Release the |
dflet | 3:a8c249046181 | 238 | // semaphore. |
dflet | 3:a8c249046181 | 239 | xSemaphoreGive( xSemaphore ); |
dflet | 3:a8c249046181 | 240 | } |
dflet | 3:a8c249046181 | 241 | else |
dflet | 3:a8c249046181 | 242 | { |
dflet | 3:a8c249046181 | 243 | // We could not obtain the semaphore and can therefore not access |
dflet | 3:a8c249046181 | 244 | // the shared resource safely. |
dflet | 3:a8c249046181 | 245 | } |
dflet | 3:a8c249046181 | 246 | } |
dflet | 3:a8c249046181 | 247 | } |
dflet | 3:a8c249046181 | 248 | </pre> |
dflet | 3:a8c249046181 | 249 | * \defgroup xSemaphoreTake xSemaphoreTake |
dflet | 3:a8c249046181 | 250 | * \ingroup Semaphores |
dflet | 3:a8c249046181 | 251 | */ |
dflet | 3:a8c249046181 | 252 | #define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) |
dflet | 3:a8c249046181 | 253 | |
dflet | 3:a8c249046181 | 254 | /** |
dflet | 3:a8c249046181 | 255 | * semphr. h |
dflet | 3:a8c249046181 | 256 | * xSemaphoreTakeRecursive( |
dflet | 3:a8c249046181 | 257 | * SemaphoreHandle_t xMutex, |
dflet | 3:a8c249046181 | 258 | * TickType_t xBlockTime |
dflet | 3:a8c249046181 | 259 | * ) |
dflet | 3:a8c249046181 | 260 | * |
dflet | 3:a8c249046181 | 261 | * <i>Macro</i> to recursively obtain, or 'take', a mutex type semaphore. |
dflet | 3:a8c249046181 | 262 | * The mutex must have previously been created using a call to |
dflet | 3:a8c249046181 | 263 | * xSemaphoreCreateRecursiveMutex(); |
dflet | 3:a8c249046181 | 264 | * |
dflet | 3:a8c249046181 | 265 | * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this |
dflet | 3:a8c249046181 | 266 | * macro to be available. |
dflet | 3:a8c249046181 | 267 | * |
dflet | 3:a8c249046181 | 268 | * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). |
dflet | 3:a8c249046181 | 269 | * |
dflet | 3:a8c249046181 | 270 | * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex |
dflet | 3:a8c249046181 | 271 | * doesn't become available again until the owner has called |
dflet | 3:a8c249046181 | 272 | * xSemaphoreGiveRecursive() for each successful 'take' request. For example, |
dflet | 3:a8c249046181 | 273 | * if a task successfully 'takes' the same mutex 5 times then the mutex will |
dflet | 3:a8c249046181 | 274 | * not be available to any other task until it has also 'given' the mutex back |
dflet | 3:a8c249046181 | 275 | * exactly five times. |
dflet | 3:a8c249046181 | 276 | * |
dflet | 3:a8c249046181 | 277 | * @param xMutex A handle to the mutex being obtained. This is the |
dflet | 3:a8c249046181 | 278 | * handle returned by xSemaphoreCreateRecursiveMutex(); |
dflet | 3:a8c249046181 | 279 | * |
dflet | 3:a8c249046181 | 280 | * @param xBlockTime The time in ticks to wait for the semaphore to become |
dflet | 3:a8c249046181 | 281 | * available. The macro portTICK_PERIOD_MS can be used to convert this to a |
dflet | 3:a8c249046181 | 282 | * real time. A block time of zero can be used to poll the semaphore. If |
dflet | 3:a8c249046181 | 283 | * the task already owns the semaphore then xSemaphoreTakeRecursive() will |
dflet | 3:a8c249046181 | 284 | * return immediately no matter what the value of xBlockTime. |
dflet | 3:a8c249046181 | 285 | * |
dflet | 3:a8c249046181 | 286 | * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime |
dflet | 3:a8c249046181 | 287 | * expired without the semaphore becoming available. |
dflet | 3:a8c249046181 | 288 | * |
dflet | 3:a8c249046181 | 289 | * Example usage: |
dflet | 3:a8c249046181 | 290 | <pre> |
dflet | 3:a8c249046181 | 291 | SemaphoreHandle_t xMutex = NULL; |
dflet | 3:a8c249046181 | 292 | |
dflet | 3:a8c249046181 | 293 | // A task that creates a mutex. |
dflet | 3:a8c249046181 | 294 | void vATask( void * pvParameters ) |
dflet | 3:a8c249046181 | 295 | { |
dflet | 3:a8c249046181 | 296 | // Create the mutex to guard a shared resource. |
dflet | 3:a8c249046181 | 297 | xMutex = xSemaphoreCreateRecursiveMutex(); |
dflet | 3:a8c249046181 | 298 | } |
dflet | 3:a8c249046181 | 299 | |
dflet | 3:a8c249046181 | 300 | // A task that uses the mutex. |
dflet | 3:a8c249046181 | 301 | void vAnotherTask( void * pvParameters ) |
dflet | 3:a8c249046181 | 302 | { |
dflet | 3:a8c249046181 | 303 | // ... Do other things. |
dflet | 3:a8c249046181 | 304 | |
dflet | 3:a8c249046181 | 305 | if( xMutex != NULL ) |
dflet | 3:a8c249046181 | 306 | { |
dflet | 3:a8c249046181 | 307 | // See if we can obtain the mutex. If the mutex is not available |
dflet | 3:a8c249046181 | 308 | // wait 10 ticks to see if it becomes free. |
dflet | 3:a8c249046181 | 309 | if( xSemaphoreTakeRecursive( xSemaphore, ( TickType_t ) 10 ) == pdTRUE ) |
dflet | 3:a8c249046181 | 310 | { |
dflet | 3:a8c249046181 | 311 | // We were able to obtain the mutex and can now access the |
dflet | 3:a8c249046181 | 312 | // shared resource. |
dflet | 3:a8c249046181 | 313 | |
dflet | 3:a8c249046181 | 314 | // ... |
dflet | 3:a8c249046181 | 315 | // For some reason due to the nature of the code further calls to |
dflet | 3:a8c249046181 | 316 | // xSemaphoreTakeRecursive() are made on the same mutex. In real |
dflet | 3:a8c249046181 | 317 | // code these would not be just sequential calls as this would make |
dflet | 3:a8c249046181 | 318 | // no sense. Instead the calls are likely to be buried inside |
dflet | 3:a8c249046181 | 319 | // a more complex call structure. |
dflet | 3:a8c249046181 | 320 | xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); |
dflet | 3:a8c249046181 | 321 | xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); |
dflet | 3:a8c249046181 | 322 | |
dflet | 3:a8c249046181 | 323 | // The mutex has now been 'taken' three times, so will not be |
dflet | 3:a8c249046181 | 324 | // available to another task until it has also been given back |
dflet | 3:a8c249046181 | 325 | // three times. Again it is unlikely that real code would have |
dflet | 3:a8c249046181 | 326 | // these calls sequentially, but instead buried in a more complex |
dflet | 3:a8c249046181 | 327 | // call structure. This is just for illustrative purposes. |
dflet | 3:a8c249046181 | 328 | xSemaphoreGiveRecursive( xMutex ); |
dflet | 3:a8c249046181 | 329 | xSemaphoreGiveRecursive( xMutex ); |
dflet | 3:a8c249046181 | 330 | xSemaphoreGiveRecursive( xMutex ); |
dflet | 3:a8c249046181 | 331 | |
dflet | 3:a8c249046181 | 332 | // Now the mutex can be taken by other tasks. |
dflet | 3:a8c249046181 | 333 | } |
dflet | 3:a8c249046181 | 334 | else |
dflet | 3:a8c249046181 | 335 | { |
dflet | 3:a8c249046181 | 336 | // We could not obtain the mutex and can therefore not access |
dflet | 3:a8c249046181 | 337 | // the shared resource safely. |
dflet | 3:a8c249046181 | 338 | } |
dflet | 3:a8c249046181 | 339 | } |
dflet | 3:a8c249046181 | 340 | } |
dflet | 3:a8c249046181 | 341 | </pre> |
dflet | 3:a8c249046181 | 342 | * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive |
dflet | 3:a8c249046181 | 343 | * \ingroup Semaphores |
dflet | 3:a8c249046181 | 344 | */ |
dflet | 3:a8c249046181 | 345 | #define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) |
dflet | 3:a8c249046181 | 346 | |
dflet | 3:a8c249046181 | 347 | |
dflet | 3:a8c249046181 | 348 | /* |
dflet | 3:a8c249046181 | 349 | * xSemaphoreAltTake() is an alternative version of xSemaphoreTake(). |
dflet | 3:a8c249046181 | 350 | * |
dflet | 3:a8c249046181 | 351 | * The source code that implements the alternative (Alt) API is much |
dflet | 3:a8c249046181 | 352 | * simpler because it executes everything from within a critical section. |
dflet | 3:a8c249046181 | 353 | * This is the approach taken by many other RTOSes, but FreeRTOS.org has the |
dflet | 3:a8c249046181 | 354 | * preferred fully featured API too. The fully featured API has more |
dflet | 3:a8c249046181 | 355 | * complex code that takes longer to execute, but makes much less use of |
dflet | 3:a8c249046181 | 356 | * critical sections. Therefore the alternative API sacrifices interrupt |
dflet | 3:a8c249046181 | 357 | * responsiveness to gain execution speed, whereas the fully featured API |
dflet | 3:a8c249046181 | 358 | * sacrifices execution speed to ensure better interrupt responsiveness. |
dflet | 3:a8c249046181 | 359 | */ |
dflet | 3:a8c249046181 | 360 | #define xSemaphoreAltTake( xSemaphore, xBlockTime ) xQueueAltGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) |
dflet | 3:a8c249046181 | 361 | |
dflet | 3:a8c249046181 | 362 | /** |
dflet | 3:a8c249046181 | 363 | * semphr. h |
dflet | 3:a8c249046181 | 364 | * <pre>xSemaphoreGive( SemaphoreHandle_t xSemaphore )</pre> |
dflet | 3:a8c249046181 | 365 | * |
dflet | 3:a8c249046181 | 366 | * <i>Macro</i> to release a semaphore. The semaphore must have previously been |
dflet | 3:a8c249046181 | 367 | * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or |
dflet | 3:a8c249046181 | 368 | * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake(). |
dflet | 3:a8c249046181 | 369 | * |
dflet | 3:a8c249046181 | 370 | * This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for |
dflet | 3:a8c249046181 | 371 | * an alternative which can be used from an ISR. |
dflet | 3:a8c249046181 | 372 | * |
dflet | 3:a8c249046181 | 373 | * This macro must also not be used on semaphores created using |
dflet | 3:a8c249046181 | 374 | * xSemaphoreCreateRecursiveMutex(). |
dflet | 3:a8c249046181 | 375 | * |
dflet | 3:a8c249046181 | 376 | * @param xSemaphore A handle to the semaphore being released. This is the |
dflet | 3:a8c249046181 | 377 | * handle returned when the semaphore was created. |
dflet | 3:a8c249046181 | 378 | * |
dflet | 3:a8c249046181 | 379 | * @return pdTRUE if the semaphore was released. pdFALSE if an error occurred. |
dflet | 3:a8c249046181 | 380 | * Semaphores are implemented using queues. An error can occur if there is |
dflet | 3:a8c249046181 | 381 | * no space on the queue to post a message - indicating that the |
dflet | 3:a8c249046181 | 382 | * semaphore was not first obtained correctly. |
dflet | 3:a8c249046181 | 383 | * |
dflet | 3:a8c249046181 | 384 | * Example usage: |
dflet | 3:a8c249046181 | 385 | <pre> |
dflet | 3:a8c249046181 | 386 | SemaphoreHandle_t xSemaphore = NULL; |
dflet | 3:a8c249046181 | 387 | |
dflet | 3:a8c249046181 | 388 | void vATask( void * pvParameters ) |
dflet | 3:a8c249046181 | 389 | { |
dflet | 3:a8c249046181 | 390 | // Create the semaphore to guard a shared resource. |
dflet | 3:a8c249046181 | 391 | vSemaphoreCreateBinary( xSemaphore ); |
dflet | 3:a8c249046181 | 392 | |
dflet | 3:a8c249046181 | 393 | if( xSemaphore != NULL ) |
dflet | 3:a8c249046181 | 394 | { |
dflet | 3:a8c249046181 | 395 | if( xSemaphoreGive( xSemaphore ) != pdTRUE ) |
dflet | 3:a8c249046181 | 396 | { |
dflet | 3:a8c249046181 | 397 | // We would expect this call to fail because we cannot give |
dflet | 3:a8c249046181 | 398 | // a semaphore without first "taking" it! |
dflet | 3:a8c249046181 | 399 | } |
dflet | 3:a8c249046181 | 400 | |
dflet | 3:a8c249046181 | 401 | // Obtain the semaphore - don't block if the semaphore is not |
dflet | 3:a8c249046181 | 402 | // immediately available. |
dflet | 3:a8c249046181 | 403 | if( xSemaphoreTake( xSemaphore, ( TickType_t ) 0 ) ) |
dflet | 3:a8c249046181 | 404 | { |
dflet | 3:a8c249046181 | 405 | // We now have the semaphore and can access the shared resource. |
dflet | 3:a8c249046181 | 406 | |
dflet | 3:a8c249046181 | 407 | // ... |
dflet | 3:a8c249046181 | 408 | |
dflet | 3:a8c249046181 | 409 | // We have finished accessing the shared resource so can free the |
dflet | 3:a8c249046181 | 410 | // semaphore. |
dflet | 3:a8c249046181 | 411 | if( xSemaphoreGive( xSemaphore ) != pdTRUE ) |
dflet | 3:a8c249046181 | 412 | { |
dflet | 3:a8c249046181 | 413 | // We would not expect this call to fail because we must have |
dflet | 3:a8c249046181 | 414 | // obtained the semaphore to get here. |
dflet | 3:a8c249046181 | 415 | } |
dflet | 3:a8c249046181 | 416 | } |
dflet | 3:a8c249046181 | 417 | } |
dflet | 3:a8c249046181 | 418 | } |
dflet | 3:a8c249046181 | 419 | </pre> |
dflet | 3:a8c249046181 | 420 | * \defgroup xSemaphoreGive xSemaphoreGive |
dflet | 3:a8c249046181 | 421 | * \ingroup Semaphores |
dflet | 3:a8c249046181 | 422 | */ |
dflet | 3:a8c249046181 | 423 | #define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) |
dflet | 3:a8c249046181 | 424 | |
dflet | 3:a8c249046181 | 425 | /** |
dflet | 3:a8c249046181 | 426 | * semphr. h |
dflet | 3:a8c249046181 | 427 | * <pre>xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex )</pre> |
dflet | 3:a8c249046181 | 428 | * |
dflet | 3:a8c249046181 | 429 | * <i>Macro</i> to recursively release, or 'give', a mutex type semaphore. |
dflet | 3:a8c249046181 | 430 | * The mutex must have previously been created using a call to |
dflet | 3:a8c249046181 | 431 | * xSemaphoreCreateRecursiveMutex(); |
dflet | 3:a8c249046181 | 432 | * |
dflet | 3:a8c249046181 | 433 | * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this |
dflet | 3:a8c249046181 | 434 | * macro to be available. |
dflet | 3:a8c249046181 | 435 | * |
dflet | 3:a8c249046181 | 436 | * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). |
dflet | 3:a8c249046181 | 437 | * |
dflet | 3:a8c249046181 | 438 | * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex |
dflet | 3:a8c249046181 | 439 | * doesn't become available again until the owner has called |
dflet | 3:a8c249046181 | 440 | * xSemaphoreGiveRecursive() for each successful 'take' request. For example, |
dflet | 3:a8c249046181 | 441 | * if a task successfully 'takes' the same mutex 5 times then the mutex will |
dflet | 3:a8c249046181 | 442 | * not be available to any other task until it has also 'given' the mutex back |
dflet | 3:a8c249046181 | 443 | * exactly five times. |
dflet | 3:a8c249046181 | 444 | * |
dflet | 3:a8c249046181 | 445 | * @param xMutex A handle to the mutex being released, or 'given'. This is the |
dflet | 3:a8c249046181 | 446 | * handle returned by xSemaphoreCreateMutex(); |
dflet | 3:a8c249046181 | 447 | * |
dflet | 3:a8c249046181 | 448 | * @return pdTRUE if the semaphore was given. |
dflet | 3:a8c249046181 | 449 | * |
dflet | 3:a8c249046181 | 450 | * Example usage: |
dflet | 3:a8c249046181 | 451 | <pre> |
dflet | 3:a8c249046181 | 452 | SemaphoreHandle_t xMutex = NULL; |
dflet | 3:a8c249046181 | 453 | |
dflet | 3:a8c249046181 | 454 | // A task that creates a mutex. |
dflet | 3:a8c249046181 | 455 | void vATask( void * pvParameters ) |
dflet | 3:a8c249046181 | 456 | { |
dflet | 3:a8c249046181 | 457 | // Create the mutex to guard a shared resource. |
dflet | 3:a8c249046181 | 458 | xMutex = xSemaphoreCreateRecursiveMutex(); |
dflet | 3:a8c249046181 | 459 | } |
dflet | 3:a8c249046181 | 460 | |
dflet | 3:a8c249046181 | 461 | // A task that uses the mutex. |
dflet | 3:a8c249046181 | 462 | void vAnotherTask( void * pvParameters ) |
dflet | 3:a8c249046181 | 463 | { |
dflet | 3:a8c249046181 | 464 | // ... Do other things. |
dflet | 3:a8c249046181 | 465 | |
dflet | 3:a8c249046181 | 466 | if( xMutex != NULL ) |
dflet | 3:a8c249046181 | 467 | { |
dflet | 3:a8c249046181 | 468 | // See if we can obtain the mutex. If the mutex is not available |
dflet | 3:a8c249046181 | 469 | // wait 10 ticks to see if it becomes free. |
dflet | 3:a8c249046181 | 470 | if( xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ) == pdTRUE ) |
dflet | 3:a8c249046181 | 471 | { |
dflet | 3:a8c249046181 | 472 | // We were able to obtain the mutex and can now access the |
dflet | 3:a8c249046181 | 473 | // shared resource. |
dflet | 3:a8c249046181 | 474 | |
dflet | 3:a8c249046181 | 475 | // ... |
dflet | 3:a8c249046181 | 476 | // For some reason due to the nature of the code further calls to |
dflet | 3:a8c249046181 | 477 | // xSemaphoreTakeRecursive() are made on the same mutex. In real |
dflet | 3:a8c249046181 | 478 | // code these would not be just sequential calls as this would make |
dflet | 3:a8c249046181 | 479 | // no sense. Instead the calls are likely to be buried inside |
dflet | 3:a8c249046181 | 480 | // a more complex call structure. |
dflet | 3:a8c249046181 | 481 | xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); |
dflet | 3:a8c249046181 | 482 | xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); |
dflet | 3:a8c249046181 | 483 | |
dflet | 3:a8c249046181 | 484 | // The mutex has now been 'taken' three times, so will not be |
dflet | 3:a8c249046181 | 485 | // available to another task until it has also been given back |
dflet | 3:a8c249046181 | 486 | // three times. Again it is unlikely that real code would have |
dflet | 3:a8c249046181 | 487 | // these calls sequentially, it would be more likely that the calls |
dflet | 3:a8c249046181 | 488 | // to xSemaphoreGiveRecursive() would be called as a call stack |
dflet | 3:a8c249046181 | 489 | // unwound. This is just for demonstrative purposes. |
dflet | 3:a8c249046181 | 490 | xSemaphoreGiveRecursive( xMutex ); |
dflet | 3:a8c249046181 | 491 | xSemaphoreGiveRecursive( xMutex ); |
dflet | 3:a8c249046181 | 492 | xSemaphoreGiveRecursive( xMutex ); |
dflet | 3:a8c249046181 | 493 | |
dflet | 3:a8c249046181 | 494 | // Now the mutex can be taken by other tasks. |
dflet | 3:a8c249046181 | 495 | } |
dflet | 3:a8c249046181 | 496 | else |
dflet | 3:a8c249046181 | 497 | { |
dflet | 3:a8c249046181 | 498 | // We could not obtain the mutex and can therefore not access |
dflet | 3:a8c249046181 | 499 | // the shared resource safely. |
dflet | 3:a8c249046181 | 500 | } |
dflet | 3:a8c249046181 | 501 | } |
dflet | 3:a8c249046181 | 502 | } |
dflet | 3:a8c249046181 | 503 | </pre> |
dflet | 3:a8c249046181 | 504 | * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive |
dflet | 3:a8c249046181 | 505 | * \ingroup Semaphores |
dflet | 3:a8c249046181 | 506 | */ |
dflet | 3:a8c249046181 | 507 | #define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) |
dflet | 3:a8c249046181 | 508 | |
dflet | 3:a8c249046181 | 509 | /* |
dflet | 3:a8c249046181 | 510 | * xSemaphoreAltGive() is an alternative version of xSemaphoreGive(). |
dflet | 3:a8c249046181 | 511 | * |
dflet | 3:a8c249046181 | 512 | * The source code that implements the alternative (Alt) API is much |
dflet | 3:a8c249046181 | 513 | * simpler because it executes everything from within a critical section. |
dflet | 3:a8c249046181 | 514 | * This is the approach taken by many other RTOSes, but FreeRTOS.org has the |
dflet | 3:a8c249046181 | 515 | * preferred fully featured API too. The fully featured API has more |
dflet | 3:a8c249046181 | 516 | * complex code that takes longer to execute, but makes much less use of |
dflet | 3:a8c249046181 | 517 | * critical sections. Therefore the alternative API sacrifices interrupt |
dflet | 3:a8c249046181 | 518 | * responsiveness to gain execution speed, whereas the fully featured API |
dflet | 3:a8c249046181 | 519 | * sacrifices execution speed to ensure better interrupt responsiveness. |
dflet | 3:a8c249046181 | 520 | */ |
dflet | 3:a8c249046181 | 521 | #define xSemaphoreAltGive( xSemaphore ) xQueueAltGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) |
dflet | 3:a8c249046181 | 522 | |
dflet | 3:a8c249046181 | 523 | /** |
dflet | 3:a8c249046181 | 524 | * semphr. h |
dflet | 3:a8c249046181 | 525 | * <pre> |
dflet | 3:a8c249046181 | 526 | xSemaphoreGiveFromISR( |
dflet | 3:a8c249046181 | 527 | SemaphoreHandle_t xSemaphore, |
dflet | 3:a8c249046181 | 528 | BaseType_t *pxHigherPriorityTaskWoken |
dflet | 3:a8c249046181 | 529 | )</pre> |
dflet | 3:a8c249046181 | 530 | * |
dflet | 3:a8c249046181 | 531 | * <i>Macro</i> to release a semaphore. The semaphore must have previously been |
dflet | 3:a8c249046181 | 532 | * created with a call to vSemaphoreCreateBinary() or xSemaphoreCreateCounting(). |
dflet | 3:a8c249046181 | 533 | * |
dflet | 3:a8c249046181 | 534 | * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) |
dflet | 3:a8c249046181 | 535 | * must not be used with this macro. |
dflet | 3:a8c249046181 | 536 | * |
dflet | 3:a8c249046181 | 537 | * This macro can be used from an ISR. |
dflet | 3:a8c249046181 | 538 | * |
dflet | 3:a8c249046181 | 539 | * @param xSemaphore A handle to the semaphore being released. This is the |
dflet | 3:a8c249046181 | 540 | * handle returned when the semaphore was created. |
dflet | 3:a8c249046181 | 541 | * |
dflet | 3:a8c249046181 | 542 | * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set |
dflet | 3:a8c249046181 | 543 | * *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task |
dflet | 3:a8c249046181 | 544 | * to unblock, and the unblocked task has a priority higher than the currently |
dflet | 3:a8c249046181 | 545 | * running task. If xSemaphoreGiveFromISR() sets this value to pdTRUE then |
dflet | 3:a8c249046181 | 546 | * a context switch should be requested before the interrupt is exited. |
dflet | 3:a8c249046181 | 547 | * |
dflet | 3:a8c249046181 | 548 | * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL. |
dflet | 3:a8c249046181 | 549 | * |
dflet | 3:a8c249046181 | 550 | * Example usage: |
dflet | 3:a8c249046181 | 551 | <pre> |
dflet | 3:a8c249046181 | 552 | \#define LONG_TIME 0xffff |
dflet | 3:a8c249046181 | 553 | \#define TICKS_TO_WAIT 10 |
dflet | 3:a8c249046181 | 554 | SemaphoreHandle_t xSemaphore = NULL; |
dflet | 3:a8c249046181 | 555 | |
dflet | 3:a8c249046181 | 556 | // Repetitive task. |
dflet | 3:a8c249046181 | 557 | void vATask( void * pvParameters ) |
dflet | 3:a8c249046181 | 558 | { |
dflet | 3:a8c249046181 | 559 | for( ;; ) |
dflet | 3:a8c249046181 | 560 | { |
dflet | 3:a8c249046181 | 561 | // We want this task to run every 10 ticks of a timer. The semaphore |
dflet | 3:a8c249046181 | 562 | // was created before this task was started. |
dflet | 3:a8c249046181 | 563 | |
dflet | 3:a8c249046181 | 564 | // Block waiting for the semaphore to become available. |
dflet | 3:a8c249046181 | 565 | if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE ) |
dflet | 3:a8c249046181 | 566 | { |
dflet | 3:a8c249046181 | 567 | // It is time to execute. |
dflet | 3:a8c249046181 | 568 | |
dflet | 3:a8c249046181 | 569 | // ... |
dflet | 3:a8c249046181 | 570 | |
dflet | 3:a8c249046181 | 571 | // We have finished our task. Return to the top of the loop where |
dflet | 3:a8c249046181 | 572 | // we will block on the semaphore until it is time to execute |
dflet | 3:a8c249046181 | 573 | // again. Note when using the semaphore for synchronisation with an |
dflet | 3:a8c249046181 | 574 | // ISR in this manner there is no need to 'give' the semaphore back. |
dflet | 3:a8c249046181 | 575 | } |
dflet | 3:a8c249046181 | 576 | } |
dflet | 3:a8c249046181 | 577 | } |
dflet | 3:a8c249046181 | 578 | |
dflet | 3:a8c249046181 | 579 | // Timer ISR |
dflet | 3:a8c249046181 | 580 | void vTimerISR( void * pvParameters ) |
dflet | 3:a8c249046181 | 581 | { |
dflet | 3:a8c249046181 | 582 | static uint8_t ucLocalTickCount = 0; |
dflet | 3:a8c249046181 | 583 | static BaseType_t xHigherPriorityTaskWoken; |
dflet | 3:a8c249046181 | 584 | |
dflet | 3:a8c249046181 | 585 | // A timer tick has occurred. |
dflet | 3:a8c249046181 | 586 | |
dflet | 3:a8c249046181 | 587 | // ... Do other time functions. |
dflet | 3:a8c249046181 | 588 | |
dflet | 3:a8c249046181 | 589 | // Is it time for vATask () to run? |
dflet | 3:a8c249046181 | 590 | xHigherPriorityTaskWoken = pdFALSE; |
dflet | 3:a8c249046181 | 591 | ucLocalTickCount++; |
dflet | 3:a8c249046181 | 592 | if( ucLocalTickCount >= TICKS_TO_WAIT ) |
dflet | 3:a8c249046181 | 593 | { |
dflet | 3:a8c249046181 | 594 | // Unblock the task by releasing the semaphore. |
dflet | 3:a8c249046181 | 595 | xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken ); |
dflet | 3:a8c249046181 | 596 | |
dflet | 3:a8c249046181 | 597 | // Reset the count so we release the semaphore again in 10 ticks time. |
dflet | 3:a8c249046181 | 598 | ucLocalTickCount = 0; |
dflet | 3:a8c249046181 | 599 | } |
dflet | 3:a8c249046181 | 600 | |
dflet | 3:a8c249046181 | 601 | if( xHigherPriorityTaskWoken != pdFALSE ) |
dflet | 3:a8c249046181 | 602 | { |
dflet | 3:a8c249046181 | 603 | // We can force a context switch here. Context switching from an |
dflet | 3:a8c249046181 | 604 | // ISR uses port specific syntax. Check the demo task for your port |
dflet | 3:a8c249046181 | 605 | // to find the syntax required. |
dflet | 3:a8c249046181 | 606 | } |
dflet | 3:a8c249046181 | 607 | } |
dflet | 3:a8c249046181 | 608 | </pre> |
dflet | 3:a8c249046181 | 609 | * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR |
dflet | 3:a8c249046181 | 610 | * \ingroup Semaphores |
dflet | 3:a8c249046181 | 611 | */ |
dflet | 3:a8c249046181 | 612 | #define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) ) |
dflet | 3:a8c249046181 | 613 | |
dflet | 3:a8c249046181 | 614 | /** |
dflet | 3:a8c249046181 | 615 | * semphr. h |
dflet | 3:a8c249046181 | 616 | * <pre> |
dflet | 3:a8c249046181 | 617 | xSemaphoreTakeFromISR( |
dflet | 3:a8c249046181 | 618 | SemaphoreHandle_t xSemaphore, |
dflet | 3:a8c249046181 | 619 | BaseType_t *pxHigherPriorityTaskWoken |
dflet | 3:a8c249046181 | 620 | )</pre> |
dflet | 3:a8c249046181 | 621 | * |
dflet | 3:a8c249046181 | 622 | * <i>Macro</i> to take a semaphore from an ISR. The semaphore must have |
dflet | 3:a8c249046181 | 623 | * previously been created with a call to vSemaphoreCreateBinary() or |
dflet | 3:a8c249046181 | 624 | * xSemaphoreCreateCounting(). |
dflet | 3:a8c249046181 | 625 | * |
dflet | 3:a8c249046181 | 626 | * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) |
dflet | 3:a8c249046181 | 627 | * must not be used with this macro. |
dflet | 3:a8c249046181 | 628 | * |
dflet | 3:a8c249046181 | 629 | * This macro can be used from an ISR, however taking a semaphore from an ISR |
dflet | 3:a8c249046181 | 630 | * is not a common operation. It is likely to only be useful when taking a |
dflet | 3:a8c249046181 | 631 | * counting semaphore when an interrupt is obtaining an object from a resource |
dflet | 3:a8c249046181 | 632 | * pool (when the semaphore count indicates the number of resources available). |
dflet | 3:a8c249046181 | 633 | * |
dflet | 3:a8c249046181 | 634 | * @param xSemaphore A handle to the semaphore being taken. This is the |
dflet | 3:a8c249046181 | 635 | * handle returned when the semaphore was created. |
dflet | 3:a8c249046181 | 636 | * |
dflet | 3:a8c249046181 | 637 | * @param pxHigherPriorityTaskWoken xSemaphoreTakeFromISR() will set |
dflet | 3:a8c249046181 | 638 | * *pxHigherPriorityTaskWoken to pdTRUE if taking the semaphore caused a task |
dflet | 3:a8c249046181 | 639 | * to unblock, and the unblocked task has a priority higher than the currently |
dflet | 3:a8c249046181 | 640 | * running task. If xSemaphoreTakeFromISR() sets this value to pdTRUE then |
dflet | 3:a8c249046181 | 641 | * a context switch should be requested before the interrupt is exited. |
dflet | 3:a8c249046181 | 642 | * |
dflet | 3:a8c249046181 | 643 | * @return pdTRUE if the semaphore was successfully taken, otherwise |
dflet | 3:a8c249046181 | 644 | * pdFALSE |
dflet | 3:a8c249046181 | 645 | */ |
dflet | 3:a8c249046181 | 646 | #define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) ) |
dflet | 3:a8c249046181 | 647 | |
dflet | 3:a8c249046181 | 648 | /** |
dflet | 3:a8c249046181 | 649 | * semphr. h |
dflet | 3:a8c249046181 | 650 | * <pre>SemaphoreHandle_t xSemaphoreCreateMutex( void )</pre> |
dflet | 3:a8c249046181 | 651 | * |
dflet | 3:a8c249046181 | 652 | * <i>Macro</i> that implements a mutex semaphore by using the existing queue |
dflet | 3:a8c249046181 | 653 | * mechanism. |
dflet | 3:a8c249046181 | 654 | * |
dflet | 3:a8c249046181 | 655 | * Mutexes created using this macro can be accessed using the xSemaphoreTake() |
dflet | 3:a8c249046181 | 656 | * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and |
dflet | 3:a8c249046181 | 657 | * xSemaphoreGiveRecursive() macros should not be used. |
dflet | 3:a8c249046181 | 658 | * |
dflet | 3:a8c249046181 | 659 | * This type of semaphore uses a priority inheritance mechanism so a task |
dflet | 3:a8c249046181 | 660 | * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the |
dflet | 3:a8c249046181 | 661 | * semaphore it is no longer required. |
dflet | 3:a8c249046181 | 662 | * |
dflet | 3:a8c249046181 | 663 | * Mutex type semaphores cannot be used from within interrupt service routines. |
dflet | 3:a8c249046181 | 664 | * |
dflet | 3:a8c249046181 | 665 | * See vSemaphoreCreateBinary() for an alternative implementation that can be |
dflet | 3:a8c249046181 | 666 | * used for pure synchronisation (where one task or interrupt always 'gives' the |
dflet | 3:a8c249046181 | 667 | * semaphore and another always 'takes' the semaphore) and from within interrupt |
dflet | 3:a8c249046181 | 668 | * service routines. |
dflet | 3:a8c249046181 | 669 | * |
dflet | 3:a8c249046181 | 670 | * @return xSemaphore Handle to the created mutex semaphore. Should be of type |
dflet | 3:a8c249046181 | 671 | * SemaphoreHandle_t. |
dflet | 3:a8c249046181 | 672 | * |
dflet | 3:a8c249046181 | 673 | * Example usage: |
dflet | 3:a8c249046181 | 674 | <pre> |
dflet | 3:a8c249046181 | 675 | SemaphoreHandle_t xSemaphore; |
dflet | 3:a8c249046181 | 676 | |
dflet | 3:a8c249046181 | 677 | void vATask( void * pvParameters ) |
dflet | 3:a8c249046181 | 678 | { |
dflet | 3:a8c249046181 | 679 | // Semaphore cannot be used before a call to xSemaphoreCreateMutex(). |
dflet | 3:a8c249046181 | 680 | // This is a macro so pass the variable in directly. |
dflet | 3:a8c249046181 | 681 | xSemaphore = xSemaphoreCreateMutex(); |
dflet | 3:a8c249046181 | 682 | |
dflet | 3:a8c249046181 | 683 | if( xSemaphore != NULL ) |
dflet | 3:a8c249046181 | 684 | { |
dflet | 3:a8c249046181 | 685 | // The semaphore was created successfully. |
dflet | 3:a8c249046181 | 686 | // The semaphore can now be used. |
dflet | 3:a8c249046181 | 687 | } |
dflet | 3:a8c249046181 | 688 | } |
dflet | 3:a8c249046181 | 689 | </pre> |
dflet | 3:a8c249046181 | 690 | * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex |
dflet | 3:a8c249046181 | 691 | * \ingroup Semaphores |
dflet | 3:a8c249046181 | 692 | */ |
dflet | 3:a8c249046181 | 693 | #define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ) |
dflet | 3:a8c249046181 | 694 | |
dflet | 3:a8c249046181 | 695 | |
dflet | 3:a8c249046181 | 696 | /** |
dflet | 3:a8c249046181 | 697 | * semphr. h |
dflet | 3:a8c249046181 | 698 | * <pre>SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )</pre> |
dflet | 3:a8c249046181 | 699 | * |
dflet | 3:a8c249046181 | 700 | * <i>Macro</i> that implements a recursive mutex by using the existing queue |
dflet | 3:a8c249046181 | 701 | * mechanism. |
dflet | 3:a8c249046181 | 702 | * |
dflet | 3:a8c249046181 | 703 | * Mutexes created using this macro can be accessed using the |
dflet | 3:a8c249046181 | 704 | * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The |
dflet | 3:a8c249046181 | 705 | * xSemaphoreTake() and xSemaphoreGive() macros should not be used. |
dflet | 3:a8c249046181 | 706 | * |
dflet | 3:a8c249046181 | 707 | * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex |
dflet | 3:a8c249046181 | 708 | * doesn't become available again until the owner has called |
dflet | 3:a8c249046181 | 709 | * xSemaphoreGiveRecursive() for each successful 'take' request. For example, |
dflet | 3:a8c249046181 | 710 | * if a task successfully 'takes' the same mutex 5 times then the mutex will |
dflet | 3:a8c249046181 | 711 | * not be available to any other task until it has also 'given' the mutex back |
dflet | 3:a8c249046181 | 712 | * exactly five times. |
dflet | 3:a8c249046181 | 713 | * |
dflet | 3:a8c249046181 | 714 | * This type of semaphore uses a priority inheritance mechanism so a task |
dflet | 3:a8c249046181 | 715 | * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the |
dflet | 3:a8c249046181 | 716 | * semaphore it is no longer required. |
dflet | 3:a8c249046181 | 717 | * |
dflet | 3:a8c249046181 | 718 | * Mutex type semaphores cannot be used from within interrupt service routines. |
dflet | 3:a8c249046181 | 719 | * |
dflet | 3:a8c249046181 | 720 | * See vSemaphoreCreateBinary() for an alternative implementation that can be |
dflet | 3:a8c249046181 | 721 | * used for pure synchronisation (where one task or interrupt always 'gives' the |
dflet | 3:a8c249046181 | 722 | * semaphore and another always 'takes' the semaphore) and from within interrupt |
dflet | 3:a8c249046181 | 723 | * service routines. |
dflet | 3:a8c249046181 | 724 | * |
dflet | 3:a8c249046181 | 725 | * @return xSemaphore Handle to the created mutex semaphore. Should be of type |
dflet | 3:a8c249046181 | 726 | * SemaphoreHandle_t. |
dflet | 3:a8c249046181 | 727 | * |
dflet | 3:a8c249046181 | 728 | * Example usage: |
dflet | 3:a8c249046181 | 729 | <pre> |
dflet | 3:a8c249046181 | 730 | SemaphoreHandle_t xSemaphore; |
dflet | 3:a8c249046181 | 731 | |
dflet | 3:a8c249046181 | 732 | void vATask( void * pvParameters ) |
dflet | 3:a8c249046181 | 733 | { |
dflet | 3:a8c249046181 | 734 | // Semaphore cannot be used before a call to xSemaphoreCreateMutex(). |
dflet | 3:a8c249046181 | 735 | // This is a macro so pass the variable in directly. |
dflet | 3:a8c249046181 | 736 | xSemaphore = xSemaphoreCreateRecursiveMutex(); |
dflet | 3:a8c249046181 | 737 | |
dflet | 3:a8c249046181 | 738 | if( xSemaphore != NULL ) |
dflet | 3:a8c249046181 | 739 | { |
dflet | 3:a8c249046181 | 740 | // The semaphore was created successfully. |
dflet | 3:a8c249046181 | 741 | // The semaphore can now be used. |
dflet | 3:a8c249046181 | 742 | } |
dflet | 3:a8c249046181 | 743 | } |
dflet | 3:a8c249046181 | 744 | </pre> |
dflet | 3:a8c249046181 | 745 | * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex |
dflet | 3:a8c249046181 | 746 | * \ingroup Semaphores |
dflet | 3:a8c249046181 | 747 | */ |
dflet | 3:a8c249046181 | 748 | #define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX ) |
dflet | 3:a8c249046181 | 749 | |
dflet | 3:a8c249046181 | 750 | /** |
dflet | 3:a8c249046181 | 751 | * semphr. h |
dflet | 3:a8c249046181 | 752 | * <pre>SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount )</pre> |
dflet | 3:a8c249046181 | 753 | * |
dflet | 3:a8c249046181 | 754 | * <i>Macro</i> that creates a counting semaphore by using the existing |
dflet | 3:a8c249046181 | 755 | * queue mechanism. |
dflet | 3:a8c249046181 | 756 | * |
dflet | 3:a8c249046181 | 757 | * Counting semaphores are typically used for two things: |
dflet | 3:a8c249046181 | 758 | * |
dflet | 3:a8c249046181 | 759 | * 1) Counting events. |
dflet | 3:a8c249046181 | 760 | * |
dflet | 3:a8c249046181 | 761 | * In this usage scenario an event handler will 'give' a semaphore each time |
dflet | 3:a8c249046181 | 762 | * an event occurs (incrementing the semaphore count value), and a handler |
dflet | 3:a8c249046181 | 763 | * task will 'take' a semaphore each time it processes an event |
dflet | 3:a8c249046181 | 764 | * (decrementing the semaphore count value). The count value is therefore |
dflet | 3:a8c249046181 | 765 | * the difference between the number of events that have occurred and the |
dflet | 3:a8c249046181 | 766 | * number that have been processed. In this case it is desirable for the |
dflet | 3:a8c249046181 | 767 | * initial count value to be zero. |
dflet | 3:a8c249046181 | 768 | * |
dflet | 3:a8c249046181 | 769 | * 2) Resource management. |
dflet | 3:a8c249046181 | 770 | * |
dflet | 3:a8c249046181 | 771 | * In this usage scenario the count value indicates the number of resources |
dflet | 3:a8c249046181 | 772 | * available. To obtain control of a resource a task must first obtain a |
dflet | 3:a8c249046181 | 773 | * semaphore - decrementing the semaphore count value. When the count value |
dflet | 3:a8c249046181 | 774 | * reaches zero there are no free resources. When a task finishes with the |
dflet | 3:a8c249046181 | 775 | * resource it 'gives' the semaphore back - incrementing the semaphore count |
dflet | 3:a8c249046181 | 776 | * value. In this case it is desirable for the initial count value to be |
dflet | 3:a8c249046181 | 777 | * equal to the maximum count value, indicating that all resources are free. |
dflet | 3:a8c249046181 | 778 | * |
dflet | 3:a8c249046181 | 779 | * @param uxMaxCount The maximum count value that can be reached. When the |
dflet | 3:a8c249046181 | 780 | * semaphore reaches this value it can no longer be 'given'. |
dflet | 3:a8c249046181 | 781 | * |
dflet | 3:a8c249046181 | 782 | * @param uxInitialCount The count value assigned to the semaphore when it is |
dflet | 3:a8c249046181 | 783 | * created. |
dflet | 3:a8c249046181 | 784 | * |
dflet | 3:a8c249046181 | 785 | * @return Handle to the created semaphore. Null if the semaphore could not be |
dflet | 3:a8c249046181 | 786 | * created. |
dflet | 3:a8c249046181 | 787 | * |
dflet | 3:a8c249046181 | 788 | * Example usage: |
dflet | 3:a8c249046181 | 789 | <pre> |
dflet | 3:a8c249046181 | 790 | SemaphoreHandle_t xSemaphore; |
dflet | 3:a8c249046181 | 791 | |
dflet | 3:a8c249046181 | 792 | void vATask( void * pvParameters ) |
dflet | 3:a8c249046181 | 793 | { |
dflet | 3:a8c249046181 | 794 | SemaphoreHandle_t xSemaphore = NULL; |
dflet | 3:a8c249046181 | 795 | |
dflet | 3:a8c249046181 | 796 | // Semaphore cannot be used before a call to xSemaphoreCreateCounting(). |
dflet | 3:a8c249046181 | 797 | // The max value to which the semaphore can count should be 10, and the |
dflet | 3:a8c249046181 | 798 | // initial value assigned to the count should be 0. |
dflet | 3:a8c249046181 | 799 | xSemaphore = xSemaphoreCreateCounting( 10, 0 ); |
dflet | 3:a8c249046181 | 800 | |
dflet | 3:a8c249046181 | 801 | if( xSemaphore != NULL ) |
dflet | 3:a8c249046181 | 802 | { |
dflet | 3:a8c249046181 | 803 | // The semaphore was created successfully. |
dflet | 3:a8c249046181 | 804 | // The semaphore can now be used. |
dflet | 3:a8c249046181 | 805 | } |
dflet | 3:a8c249046181 | 806 | } |
dflet | 3:a8c249046181 | 807 | </pre> |
dflet | 3:a8c249046181 | 808 | * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting |
dflet | 3:a8c249046181 | 809 | * \ingroup Semaphores |
dflet | 3:a8c249046181 | 810 | */ |
dflet | 3:a8c249046181 | 811 | #define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) |
dflet | 3:a8c249046181 | 812 | |
dflet | 3:a8c249046181 | 813 | /** |
dflet | 3:a8c249046181 | 814 | * semphr. h |
dflet | 3:a8c249046181 | 815 | * <pre>void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );</pre> |
dflet | 3:a8c249046181 | 816 | * |
dflet | 3:a8c249046181 | 817 | * Delete a semaphore. This function must be used with care. For example, |
dflet | 3:a8c249046181 | 818 | * do not delete a mutex type semaphore if the mutex is held by a task. |
dflet | 3:a8c249046181 | 819 | * |
dflet | 3:a8c249046181 | 820 | * @param xSemaphore A handle to the semaphore to be deleted. |
dflet | 3:a8c249046181 | 821 | * |
dflet | 3:a8c249046181 | 822 | * \defgroup vSemaphoreDelete vSemaphoreDelete |
dflet | 3:a8c249046181 | 823 | * \ingroup Semaphores |
dflet | 3:a8c249046181 | 824 | */ |
dflet | 3:a8c249046181 | 825 | #define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) ) |
dflet | 3:a8c249046181 | 826 | |
dflet | 3:a8c249046181 | 827 | /** |
dflet | 3:a8c249046181 | 828 | * semphr.h |
dflet | 3:a8c249046181 | 829 | * <pre>TaskHandle_t xSemaphoreGetMutexHolder( SemaphoreHandle_t xMutex );</pre> |
dflet | 3:a8c249046181 | 830 | * |
dflet | 3:a8c249046181 | 831 | * If xMutex is indeed a mutex type semaphore, return the current mutex holder. |
dflet | 3:a8c249046181 | 832 | * If xMutex is not a mutex type semaphore, or the mutex is available (not held |
dflet | 3:a8c249046181 | 833 | * by a task), return NULL. |
dflet | 3:a8c249046181 | 834 | * |
dflet | 3:a8c249046181 | 835 | * Note: This is a good way of determining if the calling task is the mutex |
dflet | 3:a8c249046181 | 836 | * holder, but not a good way of determining the identity of the mutex holder as |
dflet | 3:a8c249046181 | 837 | * the holder may change between the function exiting and the returned value |
dflet | 3:a8c249046181 | 838 | * being tested. |
dflet | 3:a8c249046181 | 839 | */ |
dflet | 3:a8c249046181 | 840 | #define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) ) |
dflet | 3:a8c249046181 | 841 | |
dflet | 3:a8c249046181 | 842 | #endif /* SEMAPHORE_H */ |
dflet | 3:a8c249046181 | 843 | |
dflet | 3:a8c249046181 | 844 | |
dflet | 3:a8c249046181 | 845 |