www.freertos.org

Dependents:   mbed_freeRTOS_send

Fork of FreeRTOS by Rohit Grover

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?

UserRevisionLine numberNew 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