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