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