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