www.freertos.org
Dependents: Nucleo freertos_test FreeRTOS_test freertos_bluetooth ... more
semphr.h
00001 /* 00002 FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd. 00003 All rights reserved 00004 00005 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. 00006 00007 *************************************************************************** 00008 * * 00009 * FreeRTOS provides completely free yet professionally developed, * 00010 * robust, strictly quality controlled, supported, and cross * 00011 * platform software that has become a de facto standard. * 00012 * * 00013 * Help yourself get started quickly and support the FreeRTOS * 00014 * project by purchasing a FreeRTOS tutorial book, reference * 00015 * manual, or both from: http://www.FreeRTOS.org/Documentation * 00016 * * 00017 * Thank you! * 00018 * * 00019 *************************************************************************** 00020 00021 This file is part of the FreeRTOS distribution. 00022 00023 FreeRTOS is free software; you can redistribute it and/or modify it under 00024 the terms of the GNU General Public License (version 2) as published by the 00025 Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. 00026 00027 >>! NOTE: The modification to the GPL is included to allow you to distribute 00028 >>! a combined work that includes FreeRTOS without being obliged to provide 00029 >>! the source code for proprietary components outside of the FreeRTOS 00030 >>! kernel. 00031 00032 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY 00033 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00034 FOR A PARTICULAR PURPOSE. Full license text is available from the following 00035 link: http://www.freertos.org/a00114.html 00036 00037 1 tab == 4 spaces! 00038 00039 *************************************************************************** 00040 * * 00041 * Having a problem? Start by reading the FAQ "My application does * 00042 * not run, what could be wrong?" * 00043 * * 00044 * http://www.FreeRTOS.org/FAQHelp.html * 00045 * * 00046 *************************************************************************** 00047 00048 http://www.FreeRTOS.org - Documentation, books, training, latest versions, 00049 license and Real Time Engineers Ltd. contact details. 00050 00051 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, 00052 including FreeRTOS+Trace - an indispensable productivity tool, a DOS 00053 compatible FAT file system, and our tiny thread aware UDP/IP stack. 00054 00055 http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High 00056 Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS 00057 licenses offer ticketed support, indemnification and middleware. 00058 00059 http://www.SafeRTOS.com - High Integrity Systems also provide a safety 00060 engineered and independently SIL3 certified version for use in safety and 00061 mission critical applications that require provable dependability. 00062 00063 1 tab == 4 spaces! 00064 */ 00065 00066 #ifndef SEMAPHORE_H 00067 #define SEMAPHORE_H 00068 00069 #ifndef INC_FREERTOS_H 00070 #error "include FreeRTOS.h" must appear in source files before "include semphr.h" 00071 #endif 00072 00073 #include "queue.h" 00074 00075 typedef xQueueHandle xSemaphoreHandle; 00076 00077 #define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( unsigned char ) 1U ) 00078 #define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned char ) 0U ) 00079 #define semGIVE_BLOCK_TIME ( ( portTickType ) 0U ) 00080 00081 00082 /** 00083 * semphr. h 00084 * <pre>vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore )</pre> 00085 * 00086 * This old vSemaphoreCreateBinary() macro is now deprecated in favour of the 00087 * xSemaphoreCreateBinary() function. Note that binary semaphores created using 00088 * the vSemaphoreCreateBinary() macro are created in a state such that the 00089 * first call to 'take' the semaphore would pass, whereas binary semaphores 00090 * created using xSemaphoreCreateBinary() are created in a state such that the 00091 * the semaphore must first be 'given' before it can be 'taken'. 00092 * 00093 * <i>Macro</i> that implements a semaphore by using the existing queue mechanism. 00094 * The queue length is 1 as this is a binary semaphore. The data size is 0 00095 * as we don't want to actually store any data - we just want to know if the 00096 * queue is empty or full. 00097 * 00098 * This type of semaphore can be used for pure synchronisation between tasks or 00099 * between an interrupt and a task. The semaphore need not be given back once 00100 * obtained, so one task/interrupt can continuously 'give' the semaphore while 00101 * another continuously 'takes' the semaphore. For this reason this type of 00102 * semaphore does not use a priority inheritance mechanism. For an alternative 00103 * that does use priority inheritance see xSemaphoreCreateMutex(). 00104 * 00105 * @param xSemaphore Handle to the created semaphore. Should be of type xSemaphoreHandle. 00106 * 00107 * Example usage: 00108 <pre> 00109 xSemaphoreHandle xSemaphore = NULL; 00110 00111 void vATask( void * pvParameters ) 00112 { 00113 // Semaphore cannot be used before a call to vSemaphoreCreateBinary (). 00114 // This is a macro so pass the variable in directly. 00115 vSemaphoreCreateBinary( xSemaphore ); 00116 00117 if( xSemaphore != NULL ) 00118 { 00119 // The semaphore was created successfully. 00120 // The semaphore can now be used. 00121 } 00122 } 00123 </pre> 00124 * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary 00125 * \ingroup Semaphores 00126 */ 00127 #define vSemaphoreCreateBinary( xSemaphore ) \ 00128 { \ 00129 ( xSemaphore ) = xQueueGenericCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ 00130 if( ( xSemaphore ) != NULL ) \ 00131 { \ 00132 ( void ) xSemaphoreGive( ( xSemaphore ) ); \ 00133 } \ 00134 } 00135 00136 /** 00137 * semphr. h 00138 * <pre>xSemaphoreHandle xSemaphoreCreateBinary( void )</pre> 00139 * 00140 * The old vSemaphoreCreateBinary() macro is now deprecated in favour of this 00141 * xSemaphoreCreateBinary() function. Note that binary semaphores created using 00142 * the vSemaphoreCreateBinary() macro are created in a state such that the 00143 * first call to 'take' the semaphore would pass, whereas binary semaphores 00144 * created using xSemaphoreCreateBinary() are created in a state such that the 00145 * the semaphore must first be 'given' before it can be 'taken'. 00146 * 00147 * Function that creates a semaphore by using the existing queue mechanism. 00148 * The queue length is 1 as this is a binary semaphore. The data size is 0 00149 * as nothing is actually stored - all that is important is whether the queue is 00150 * empty or full (the binary semaphore is available or not). 00151 * 00152 * This type of semaphore can be used for pure synchronisation between tasks or 00153 * between an interrupt and a task. The semaphore need not be given back once 00154 * obtained, so one task/interrupt can continuously 'give' the semaphore while 00155 * another continuously 'takes' the semaphore. For this reason this type of 00156 * semaphore does not use a priority inheritance mechanism. For an alternative 00157 * that does use priority inheritance see xSemaphoreCreateMutex(). 00158 * 00159 * @return Handle to the created semaphore. 00160 * 00161 * Example usage: 00162 <pre> 00163 xSemaphoreHandle xSemaphore = NULL; 00164 00165 void vATask( void * pvParameters ) 00166 { 00167 // Semaphore cannot be used before a call to vSemaphoreCreateBinary (). 00168 // This is a macro so pass the variable in directly. 00169 xSemaphore = xSemaphoreCreateBinary(); 00170 00171 if( xSemaphore != NULL ) 00172 { 00173 // The semaphore was created successfully. 00174 // The semaphore can now be used. 00175 } 00176 } 00177 </pre> 00178 * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary 00179 * \ingroup Semaphores 00180 */ 00181 #define xSemaphoreCreateBinary() xQueueGenericCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ) 00182 00183 /** 00184 * semphr. h 00185 * <pre>xSemaphoreTake( 00186 * xSemaphoreHandle xSemaphore, 00187 * portTickType xBlockTime 00188 * )</pre> 00189 * 00190 * <i>Macro</i> to obtain a semaphore. The semaphore must have previously been 00191 * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or 00192 * xSemaphoreCreateCounting(). 00193 * 00194 * @param xSemaphore A handle to the semaphore being taken - obtained when 00195 * the semaphore was created. 00196 * 00197 * @param xBlockTime The time in ticks to wait for the semaphore to become 00198 * available. The macro portTICK_RATE_MS can be used to convert this to a 00199 * real time. A block time of zero can be used to poll the semaphore. A block 00200 * time of portMAX_DELAY can be used to block indefinitely (provided 00201 * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h). 00202 * 00203 * @return pdTRUE if the semaphore was obtained. pdFALSE 00204 * if xBlockTime expired without the semaphore becoming available. 00205 * 00206 * Example usage: 00207 <pre> 00208 xSemaphoreHandle xSemaphore = NULL; 00209 00210 // A task that creates a semaphore. 00211 void vATask( void * pvParameters ) 00212 { 00213 // Create the semaphore to guard a shared resource. 00214 vSemaphoreCreateBinary( xSemaphore ); 00215 } 00216 00217 // A task that uses the semaphore. 00218 void vAnotherTask( void * pvParameters ) 00219 { 00220 // ... Do other things. 00221 00222 if( xSemaphore != NULL ) 00223 { 00224 // See if we can obtain the semaphore. If the semaphore is not available 00225 // wait 10 ticks to see if it becomes free. 00226 if( xSemaphoreTake( xSemaphore, ( portTickType ) 10 ) == pdTRUE ) 00227 { 00228 // We were able to obtain the semaphore and can now access the 00229 // shared resource. 00230 00231 // ... 00232 00233 // We have finished accessing the shared resource. Release the 00234 // semaphore. 00235 xSemaphoreGive( xSemaphore ); 00236 } 00237 else 00238 { 00239 // We could not obtain the semaphore and can therefore not access 00240 // the shared resource safely. 00241 } 00242 } 00243 } 00244 </pre> 00245 * \defgroup xSemaphoreTake xSemaphoreTake 00246 * \ingroup Semaphores 00247 */ 00248 #define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( xQueueHandle ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) 00249 00250 /** 00251 * semphr. h 00252 * xSemaphoreTakeRecursive( 00253 * xSemaphoreHandle xMutex, 00254 * portTickType xBlockTime 00255 * ) 00256 * 00257 * <i>Macro</i> to recursively obtain, or 'take', a mutex type semaphore. 00258 * The mutex must have previously been created using a call to 00259 * xSemaphoreCreateRecursiveMutex(); 00260 * 00261 * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this 00262 * macro to be available. 00263 * 00264 * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). 00265 * 00266 * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex 00267 * doesn't become available again until the owner has called 00268 * xSemaphoreGiveRecursive() for each successful 'take' request. For example, 00269 * if a task successfully 'takes' the same mutex 5 times then the mutex will 00270 * not be available to any other task until it has also 'given' the mutex back 00271 * exactly five times. 00272 * 00273 * @param xMutex A handle to the mutex being obtained. This is the 00274 * handle returned by xSemaphoreCreateRecursiveMutex(); 00275 * 00276 * @param xBlockTime The time in ticks to wait for the semaphore to become 00277 * available. The macro portTICK_RATE_MS can be used to convert this to a 00278 * real time. A block time of zero can be used to poll the semaphore. If 00279 * the task already owns the semaphore then xSemaphoreTakeRecursive() will 00280 * return immediately no matter what the value of xBlockTime. 00281 * 00282 * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime 00283 * expired without the semaphore becoming available. 00284 * 00285 * Example usage: 00286 <pre> 00287 xSemaphoreHandle xMutex = NULL; 00288 00289 // A task that creates a mutex. 00290 void vATask( void * pvParameters ) 00291 { 00292 // Create the mutex to guard a shared resource. 00293 xMutex = xSemaphoreCreateRecursiveMutex(); 00294 } 00295 00296 // A task that uses the mutex. 00297 void vAnotherTask( void * pvParameters ) 00298 { 00299 // ... Do other things. 00300 00301 if( xMutex != NULL ) 00302 { 00303 // See if we can obtain the mutex. If the mutex is not available 00304 // wait 10 ticks to see if it becomes free. 00305 if( xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 ) == pdTRUE ) 00306 { 00307 // We were able to obtain the mutex and can now access the 00308 // shared resource. 00309 00310 // ... 00311 // For some reason due to the nature of the code further calls to 00312 // xSemaphoreTakeRecursive() are made on the same mutex. In real 00313 // code these would not be just sequential calls as this would make 00314 // no sense. Instead the calls are likely to be buried inside 00315 // a more complex call structure. 00316 xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 ); 00317 xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 ); 00318 00319 // The mutex has now been 'taken' three times, so will not be 00320 // available to another task until it has also been given back 00321 // three times. Again it is unlikely that real code would have 00322 // these calls sequentially, but instead buried in a more complex 00323 // call structure. This is just for illustrative purposes. 00324 xSemaphoreGiveRecursive( xMutex ); 00325 xSemaphoreGiveRecursive( xMutex ); 00326 xSemaphoreGiveRecursive( xMutex ); 00327 00328 // Now the mutex can be taken by other tasks. 00329 } 00330 else 00331 { 00332 // We could not obtain the mutex and can therefore not access 00333 // the shared resource safely. 00334 } 00335 } 00336 } 00337 </pre> 00338 * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive 00339 * \ingroup Semaphores 00340 */ 00341 #define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) 00342 00343 00344 /* 00345 * xSemaphoreAltTake() is an alternative version of xSemaphoreTake(). 00346 * 00347 * The source code that implements the alternative (Alt) API is much 00348 * simpler because it executes everything from within a critical section. 00349 * This is the approach taken by many other RTOSes, but FreeRTOS.org has the 00350 * preferred fully featured API too. The fully featured API has more 00351 * complex code that takes longer to execute, but makes much less use of 00352 * critical sections. Therefore the alternative API sacrifices interrupt 00353 * responsiveness to gain execution speed, whereas the fully featured API 00354 * sacrifices execution speed to ensure better interrupt responsiveness. 00355 */ 00356 #define xSemaphoreAltTake( xSemaphore, xBlockTime ) xQueueAltGenericReceive( ( xQueueHandle ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) 00357 00358 /** 00359 * semphr. h 00360 * <pre>xSemaphoreGive( xSemaphoreHandle xSemaphore )</pre> 00361 * 00362 * <i>Macro</i> to release a semaphore. The semaphore must have previously been 00363 * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or 00364 * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake(). 00365 * 00366 * This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for 00367 * an alternative which can be used from an ISR. 00368 * 00369 * This macro must also not be used on semaphores created using 00370 * xSemaphoreCreateRecursiveMutex(). 00371 * 00372 * @param xSemaphore A handle to the semaphore being released. This is the 00373 * handle returned when the semaphore was created. 00374 * 00375 * @return pdTRUE if the semaphore was released. pdFALSE if an error occurred. 00376 * Semaphores are implemented using queues. An error can occur if there is 00377 * no space on the queue to post a message - indicating that the 00378 * semaphore was not first obtained correctly. 00379 * 00380 * Example usage: 00381 <pre> 00382 xSemaphoreHandle xSemaphore = NULL; 00383 00384 void vATask( void * pvParameters ) 00385 { 00386 // Create the semaphore to guard a shared resource. 00387 vSemaphoreCreateBinary( xSemaphore ); 00388 00389 if( xSemaphore != NULL ) 00390 { 00391 if( xSemaphoreGive( xSemaphore ) != pdTRUE ) 00392 { 00393 // We would expect this call to fail because we cannot give 00394 // a semaphore without first "taking" it! 00395 } 00396 00397 // Obtain the semaphore - don't block if the semaphore is not 00398 // immediately available. 00399 if( xSemaphoreTake( xSemaphore, ( portTickType ) 0 ) ) 00400 { 00401 // We now have the semaphore and can access the shared resource. 00402 00403 // ... 00404 00405 // We have finished accessing the shared resource so can free the 00406 // semaphore. 00407 if( xSemaphoreGive( xSemaphore ) != pdTRUE ) 00408 { 00409 // We would not expect this call to fail because we must have 00410 // obtained the semaphore to get here. 00411 } 00412 } 00413 } 00414 } 00415 </pre> 00416 * \defgroup xSemaphoreGive xSemaphoreGive 00417 * \ingroup Semaphores 00418 */ 00419 #define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( xQueueHandle ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) 00420 00421 /** 00422 * semphr. h 00423 * <pre>xSemaphoreGiveRecursive( xSemaphoreHandle xMutex )</pre> 00424 * 00425 * <i>Macro</i> to recursively release, or 'give', a mutex type semaphore. 00426 * The mutex must have previously been created using a call to 00427 * xSemaphoreCreateRecursiveMutex(); 00428 * 00429 * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this 00430 * macro to be available. 00431 * 00432 * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). 00433 * 00434 * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex 00435 * doesn't become available again until the owner has called 00436 * xSemaphoreGiveRecursive() for each successful 'take' request. For example, 00437 * if a task successfully 'takes' the same mutex 5 times then the mutex will 00438 * not be available to any other task until it has also 'given' the mutex back 00439 * exactly five times. 00440 * 00441 * @param xMutex A handle to the mutex being released, or 'given'. This is the 00442 * handle returned by xSemaphoreCreateMutex(); 00443 * 00444 * @return pdTRUE if the semaphore was given. 00445 * 00446 * Example usage: 00447 <pre> 00448 xSemaphoreHandle xMutex = NULL; 00449 00450 // A task that creates a mutex. 00451 void vATask( void * pvParameters ) 00452 { 00453 // Create the mutex to guard a shared resource. 00454 xMutex = xSemaphoreCreateRecursiveMutex(); 00455 } 00456 00457 // A task that uses the mutex. 00458 void vAnotherTask( void * pvParameters ) 00459 { 00460 // ... Do other things. 00461 00462 if( xMutex != NULL ) 00463 { 00464 // See if we can obtain the mutex. If the mutex is not available 00465 // wait 10 ticks to see if it becomes free. 00466 if( xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 ) == pdTRUE ) 00467 { 00468 // We were able to obtain the mutex and can now access the 00469 // shared resource. 00470 00471 // ... 00472 // For some reason due to the nature of the code further calls to 00473 // xSemaphoreTakeRecursive() are made on the same mutex. In real 00474 // code these would not be just sequential calls as this would make 00475 // no sense. Instead the calls are likely to be buried inside 00476 // a more complex call structure. 00477 xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 ); 00478 xSemaphoreTakeRecursive( xMutex, ( portTickType ) 10 ); 00479 00480 // The mutex has now been 'taken' three times, so will not be 00481 // available to another task until it has also been given back 00482 // three times. Again it is unlikely that real code would have 00483 // these calls sequentially, it would be more likely that the calls 00484 // to xSemaphoreGiveRecursive() would be called as a call stack 00485 // unwound. This is just for demonstrative purposes. 00486 xSemaphoreGiveRecursive( xMutex ); 00487 xSemaphoreGiveRecursive( xMutex ); 00488 xSemaphoreGiveRecursive( xMutex ); 00489 00490 // Now the mutex can be taken by other tasks. 00491 } 00492 else 00493 { 00494 // We could not obtain the mutex and can therefore not access 00495 // the shared resource safely. 00496 } 00497 } 00498 } 00499 </pre> 00500 * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive 00501 * \ingroup Semaphores 00502 */ 00503 #define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) 00504 00505 /* 00506 * xSemaphoreAltGive() is an alternative version of xSemaphoreGive(). 00507 * 00508 * The source code that implements the alternative (Alt) API is much 00509 * simpler because it executes everything from within a critical section. 00510 * This is the approach taken by many other RTOSes, but FreeRTOS.org has the 00511 * preferred fully featured API too. The fully featured API has more 00512 * complex code that takes longer to execute, but makes much less use of 00513 * critical sections. Therefore the alternative API sacrifices interrupt 00514 * responsiveness to gain execution speed, whereas the fully featured API 00515 * sacrifices execution speed to ensure better interrupt responsiveness. 00516 */ 00517 #define xSemaphoreAltGive( xSemaphore ) xQueueAltGenericSend( ( xQueueHandle ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) 00518 00519 /** 00520 * semphr. h 00521 * <pre> 00522 xSemaphoreGiveFromISR( 00523 xSemaphoreHandle xSemaphore, 00524 signed portBASE_TYPE *pxHigherPriorityTaskWoken 00525 )</pre> 00526 * 00527 * <i>Macro</i> to release a semaphore. The semaphore must have previously been 00528 * created with a call to vSemaphoreCreateBinary() or xSemaphoreCreateCounting(). 00529 * 00530 * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) 00531 * must not be used with this macro. 00532 * 00533 * This macro can be used from an ISR. 00534 * 00535 * @param xSemaphore A handle to the semaphore being released. This is the 00536 * handle returned when the semaphore was created. 00537 * 00538 * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set 00539 * *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task 00540 * to unblock, and the unblocked task has a priority higher than the currently 00541 * running task. If xSemaphoreGiveFromISR() sets this value to pdTRUE then 00542 * a context switch should be requested before the interrupt is exited. 00543 * 00544 * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL. 00545 * 00546 * Example usage: 00547 <pre> 00548 \#define LONG_TIME 0xffff 00549 \#define TICKS_TO_WAIT 10 00550 xSemaphoreHandle xSemaphore = NULL; 00551 00552 // Repetitive task. 00553 void vATask( void * pvParameters ) 00554 { 00555 for( ;; ) 00556 { 00557 // We want this task to run every 10 ticks of a timer. The semaphore 00558 // was created before this task was started. 00559 00560 // Block waiting for the semaphore to become available. 00561 if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE ) 00562 { 00563 // It is time to execute. 00564 00565 // ... 00566 00567 // We have finished our task. Return to the top of the loop where 00568 // we will block on the semaphore until it is time to execute 00569 // again. Note when using the semaphore for synchronisation with an 00570 // ISR in this manner there is no need to 'give' the semaphore back. 00571 } 00572 } 00573 } 00574 00575 // Timer ISR 00576 void vTimerISR( void * pvParameters ) 00577 { 00578 static unsigned char ucLocalTickCount = 0; 00579 static signed portBASE_TYPE xHigherPriorityTaskWoken; 00580 00581 // A timer tick has occurred. 00582 00583 // ... Do other time functions. 00584 00585 // Is it time for vATask () to run? 00586 xHigherPriorityTaskWoken = pdFALSE; 00587 ucLocalTickCount++; 00588 if( ucLocalTickCount >= TICKS_TO_WAIT ) 00589 { 00590 // Unblock the task by releasing the semaphore. 00591 xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken ); 00592 00593 // Reset the count so we release the semaphore again in 10 ticks time. 00594 ucLocalTickCount = 0; 00595 } 00596 00597 if( xHigherPriorityTaskWoken != pdFALSE ) 00598 { 00599 // We can force a context switch here. Context switching from an 00600 // ISR uses port specific syntax. Check the demo task for your port 00601 // to find the syntax required. 00602 } 00603 } 00604 </pre> 00605 * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR 00606 * \ingroup Semaphores 00607 */ 00608 #define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueueHandle ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) 00609 00610 /** 00611 * semphr. h 00612 * <pre> 00613 xSemaphoreTakeFromISR( 00614 xSemaphoreHandle xSemaphore, 00615 signed portBASE_TYPE *pxHigherPriorityTaskWoken 00616 )</pre> 00617 * 00618 * <i>Macro</i> to take a semaphore from an ISR. The semaphore must have 00619 * previously been created with a call to vSemaphoreCreateBinary() or 00620 * xSemaphoreCreateCounting(). 00621 * 00622 * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) 00623 * must not be used with this macro. 00624 * 00625 * This macro can be used from an ISR, however taking a semaphore from an ISR 00626 * is not a common operation. It is likely to only be useful when taking a 00627 * counting semaphore when an interrupt is obtaining an object from a resource 00628 * pool (when the semaphore count indicates the number of resources available). 00629 * 00630 * @param xSemaphore A handle to the semaphore being taken. This is the 00631 * handle returned when the semaphore was created. 00632 * 00633 * @param pxHigherPriorityTaskWoken xSemaphoreTakeFromISR() will set 00634 * *pxHigherPriorityTaskWoken to pdTRUE if taking the semaphore caused a task 00635 * to unblock, and the unblocked task has a priority higher than the currently 00636 * running task. If xSemaphoreTakeFromISR() sets this value to pdTRUE then 00637 * a context switch should be requested before the interrupt is exited. 00638 * 00639 * @return pdTRUE if the semaphore was successfully taken, otherwise 00640 * pdFALSE 00641 */ 00642 #define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( xQueueHandle ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) ) 00643 00644 /** 00645 * semphr. h 00646 * <pre>xSemaphoreHandle xSemaphoreCreateMutex( void )</pre> 00647 * 00648 * <i>Macro</i> that implements a mutex semaphore by using the existing queue 00649 * mechanism. 00650 * 00651 * Mutexes created using this macro can be accessed using the xSemaphoreTake() 00652 * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and 00653 * xSemaphoreGiveRecursive() macros should not be used. 00654 * 00655 * This type of semaphore uses a priority inheritance mechanism so a task 00656 * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the 00657 * semaphore it is no longer required. 00658 * 00659 * Mutex type semaphores cannot be used from within interrupt service routines. 00660 * 00661 * See vSemaphoreCreateBinary() for an alternative implementation that can be 00662 * used for pure synchronisation (where one task or interrupt always 'gives' the 00663 * semaphore and another always 'takes' the semaphore) and from within interrupt 00664 * service routines. 00665 * 00666 * @return xSemaphore Handle to the created mutex semaphore. Should be of type 00667 * xSemaphoreHandle. 00668 * 00669 * Example usage: 00670 <pre> 00671 xSemaphoreHandle xSemaphore; 00672 00673 void vATask( void * pvParameters ) 00674 { 00675 // Semaphore cannot be used before a call to xSemaphoreCreateMutex(). 00676 // This is a macro so pass the variable in directly. 00677 xSemaphore = xSemaphoreCreateMutex(); 00678 00679 if( xSemaphore != NULL ) 00680 { 00681 // The semaphore was created successfully. 00682 // The semaphore can now be used. 00683 } 00684 } 00685 </pre> 00686 * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex 00687 * \ingroup Semaphores 00688 */ 00689 #define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ) 00690 00691 00692 /** 00693 * semphr. h 00694 * <pre>xSemaphoreHandle xSemaphoreCreateRecursiveMutex( void )</pre> 00695 * 00696 * <i>Macro</i> that implements a recursive mutex by using the existing queue 00697 * mechanism. 00698 * 00699 * Mutexes created using this macro can be accessed using the 00700 * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The 00701 * xSemaphoreTake() and xSemaphoreGive() macros should not be used. 00702 * 00703 * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex 00704 * doesn't become available again until the owner has called 00705 * xSemaphoreGiveRecursive() for each successful 'take' request. For example, 00706 * if a task successfully 'takes' the same mutex 5 times then the mutex will 00707 * not be available to any other task until it has also 'given' the mutex back 00708 * exactly five times. 00709 * 00710 * This type of semaphore uses a priority inheritance mechanism so a task 00711 * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the 00712 * semaphore it is no longer required. 00713 * 00714 * Mutex type semaphores cannot be used from within interrupt service routines. 00715 * 00716 * See vSemaphoreCreateBinary() for an alternative implementation that can be 00717 * used for pure synchronisation (where one task or interrupt always 'gives' the 00718 * semaphore and another always 'takes' the semaphore) and from within interrupt 00719 * service routines. 00720 * 00721 * @return xSemaphore Handle to the created mutex semaphore. Should be of type 00722 * xSemaphoreHandle. 00723 * 00724 * Example usage: 00725 <pre> 00726 xSemaphoreHandle xSemaphore; 00727 00728 void vATask( void * pvParameters ) 00729 { 00730 // Semaphore cannot be used before a call to xSemaphoreCreateMutex(). 00731 // This is a macro so pass the variable in directly. 00732 xSemaphore = xSemaphoreCreateRecursiveMutex(); 00733 00734 if( xSemaphore != NULL ) 00735 { 00736 // The semaphore was created successfully. 00737 // The semaphore can now be used. 00738 } 00739 } 00740 </pre> 00741 * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex 00742 * \ingroup Semaphores 00743 */ 00744 #define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX ) 00745 00746 /** 00747 * semphr. h 00748 * <pre>xSemaphoreHandle xSemaphoreCreateCounting( unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount )</pre> 00749 * 00750 * <i>Macro</i> that creates a counting semaphore by using the existing 00751 * queue mechanism. 00752 * 00753 * Counting semaphores are typically used for two things: 00754 * 00755 * 1) Counting events. 00756 * 00757 * In this usage scenario an event handler will 'give' a semaphore each time 00758 * an event occurs (incrementing the semaphore count value), and a handler 00759 * task will 'take' a semaphore each time it processes an event 00760 * (decrementing the semaphore count value). The count value is therefore 00761 * the difference between the number of events that have occurred and the 00762 * number that have been processed. In this case it is desirable for the 00763 * initial count value to be zero. 00764 * 00765 * 2) Resource management. 00766 * 00767 * In this usage scenario the count value indicates the number of resources 00768 * available. To obtain control of a resource a task must first obtain a 00769 * semaphore - decrementing the semaphore count value. When the count value 00770 * reaches zero there are no free resources. When a task finishes with the 00771 * resource it 'gives' the semaphore back - incrementing the semaphore count 00772 * value. In this case it is desirable for the initial count value to be 00773 * equal to the maximum count value, indicating that all resources are free. 00774 * 00775 * @param uxMaxCount The maximum count value that can be reached. When the 00776 * semaphore reaches this value it can no longer be 'given'. 00777 * 00778 * @param uxInitialCount The count value assigned to the semaphore when it is 00779 * created. 00780 * 00781 * @return Handle to the created semaphore. Null if the semaphore could not be 00782 * created. 00783 * 00784 * Example usage: 00785 <pre> 00786 xSemaphoreHandle xSemaphore; 00787 00788 void vATask( void * pvParameters ) 00789 { 00790 xSemaphoreHandle xSemaphore = NULL; 00791 00792 // Semaphore cannot be used before a call to xSemaphoreCreateCounting(). 00793 // The max value to which the semaphore can count should be 10, and the 00794 // initial value assigned to the count should be 0. 00795 xSemaphore = xSemaphoreCreateCounting( 10, 0 ); 00796 00797 if( xSemaphore != NULL ) 00798 { 00799 // The semaphore was created successfully. 00800 // The semaphore can now be used. 00801 } 00802 } 00803 </pre> 00804 * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting 00805 * \ingroup Semaphores 00806 */ 00807 #define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) 00808 00809 /** 00810 * semphr. h 00811 * <pre>void vSemaphoreDelete( xSemaphoreHandle xSemaphore );</pre> 00812 * 00813 * Delete a semaphore. This function must be used with care. For example, 00814 * do not delete a mutex type semaphore if the mutex is held by a task. 00815 * 00816 * @param xSemaphore A handle to the semaphore to be deleted. 00817 * 00818 * \defgroup vSemaphoreDelete vSemaphoreDelete 00819 * \ingroup Semaphores 00820 */ 00821 #define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( xQueueHandle ) ( xSemaphore ) ) 00822 00823 /** 00824 * semphr.h 00825 * <pre>xTaskHandle xSemaphoreGetMutexHolder( xSemaphoreHandle xMutex );</pre> 00826 * 00827 * If xMutex is indeed a mutex type semaphore, return the current mutex holder. 00828 * If xMutex is not a mutex type semaphore, or the mutex is available (not held 00829 * by a task), return NULL. 00830 * 00831 * Note: This Is is a good way of determining if the calling task is the mutex 00832 * holder, but not a good way of determining the identity of the mutex holder as 00833 * the holder may change between the function exiting and the returned value 00834 * being tested. 00835 */ 00836 #define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) ) 00837 00838 #endif /* SEMAPHORE_H */ 00839 00840
Generated on Tue Jul 12 2022 11:36:40 by
![doxygen](doxygen.png)