]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/queue.c
Added traceQUEUE_CREATE_FAILED() trace macros into the queue create functions.
[freertos] / FreeRTOS / Source / queue.c
1 /*\r
2     FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     This file is part of the FreeRTOS distribution.\r
8 \r
9     FreeRTOS is free software; you can redistribute it and/or modify it under\r
10     the terms of the GNU General Public License (version 2) as published by the\r
11     Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
12 \r
13     ***************************************************************************\r
14     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
15     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
16     >>!   obliged to provide the source code for proprietary components     !<<\r
17     >>!   outside of the FreeRTOS kernel.                                   !<<\r
18     ***************************************************************************\r
19 \r
20     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
21     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
22     FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
23     link: http://www.freertos.org/a00114.html\r
24 \r
25     ***************************************************************************\r
26      *                                                                       *\r
27      *    FreeRTOS provides completely free yet professionally developed,    *\r
28      *    robust, strictly quality controlled, supported, and cross          *\r
29      *    platform software that is more than just the market leader, it     *\r
30      *    is the industry's de facto standard.                               *\r
31      *                                                                       *\r
32      *    Help yourself get started quickly while simultaneously helping     *\r
33      *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
34      *    tutorial book, reference manual, or both:                          *\r
35      *    http://www.FreeRTOS.org/Documentation                              *\r
36      *                                                                       *\r
37     ***************************************************************************\r
38 \r
39     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
40     the FAQ page "My application does not run, what could be wrong?".  Have you\r
41     defined configASSERT()?\r
42 \r
43     http://www.FreeRTOS.org/support - In return for receiving this top quality\r
44     embedded software for free we request you assist our global community by\r
45     participating in the support forum.\r
46 \r
47     http://www.FreeRTOS.org/training - Investing in training allows your team to\r
48     be as productive as possible as early as possible.  Now you can receive\r
49     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
50     Ltd, and the world's leading authority on the world's leading RTOS.\r
51 \r
52     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
53     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
54     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
55 \r
56     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
57     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
58 \r
59     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
60     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
61     licenses offer ticketed support, indemnification and commercial middleware.\r
62 \r
63     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
64     engineered and independently SIL3 certified version for use in safety and\r
65     mission critical applications that require provable dependability.\r
66 \r
67     1 tab == 4 spaces!\r
68 */\r
69 \r
70 #include <stdlib.h>\r
71 #include <string.h>\r
72 \r
73 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining\r
74 all the API functions to use the MPU wrappers.  That should only be done when\r
75 task.h is included from an application file. */\r
76 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
77 \r
78 #include "FreeRTOS.h"\r
79 #include "task.h"\r
80 #include "queue.h"\r
81 \r
82 #if ( configUSE_CO_ROUTINES == 1 )\r
83         #include "croutine.h"\r
84 #endif\r
85 \r
86 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the\r
87 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the\r
88 header files above, but not in this file, in order to generate the correct\r
89 privileged Vs unprivileged linkage and placement. */\r
90 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */\r
91 \r
92 \r
93 /* Constants used with the cRxLock and cTxLock structure members. */\r
94 #define queueUNLOCKED                                   ( ( int8_t ) -1 )\r
95 #define queueLOCKED_UNMODIFIED                  ( ( int8_t ) 0 )\r
96 \r
97 /* When the Queue_t structure is used to represent a base queue its pcHead and\r
98 pcTail members are used as pointers into the queue storage area.  When the\r
99 Queue_t structure is used to represent a mutex pcHead and pcTail pointers are\r
100 not necessary, and the pcHead pointer is set to NULL to indicate that the\r
101 pcTail pointer actually points to the mutex holder (if any).  Map alternative\r
102 names to the pcHead and pcTail structure members to ensure the readability of\r
103 the code is maintained despite this dual use of two structure members.  An\r
104 alternative implementation would be to use a union, but use of a union is\r
105 against the coding standard (although an exception to the standard has been\r
106 permitted where the dual use also significantly changes the type of the\r
107 structure member). */\r
108 #define pxMutexHolder                                   pcTail\r
109 #define uxQueueType                                             pcHead\r
110 #define queueQUEUE_IS_MUTEX                             NULL\r
111 \r
112 /* Semaphores do not actually store or copy data, so have an item size of\r
113 zero. */\r
114 #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( UBaseType_t ) 0 )\r
115 #define queueMUTEX_GIVE_BLOCK_TIME               ( ( TickType_t ) 0U )\r
116 \r
117 #if( configUSE_PREEMPTION == 0 )\r
118         /* If the cooperative scheduler is being used then a yield should not be\r
119         performed just because a higher priority task has been woken. */\r
120         #define queueYIELD_IF_USING_PREEMPTION()\r
121 #else\r
122         #define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()\r
123 #endif\r
124 \r
125 /*\r
126  * Definition of the queue used by the scheduler.\r
127  * Items are queued by copy, not reference.  See the following link for the\r
128  * rationale: http://www.freertos.org/Embedded-RTOS-Queues.html\r
129  */\r
130 typedef struct QueueDefinition\r
131 {\r
132         int8_t *pcHead;                                 /*< Points to the beginning of the queue storage area. */\r
133         int8_t *pcTail;                                 /*< Points to the byte at the end of the queue storage area.  Once more byte is allocated than necessary to store the queue items, this is used as a marker. */\r
134         int8_t *pcWriteTo;                              /*< Points to the free next place in the storage area. */\r
135 \r
136         union                                                   /* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */\r
137         {\r
138                 int8_t *pcReadFrom;                     /*< Points to the last place that a queued item was read from when the structure is used as a queue. */\r
139                 UBaseType_t uxRecursiveCallCount;/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */\r
140         } u;\r
141 \r
142         List_t xTasksWaitingToSend;             /*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */\r
143         List_t xTasksWaitingToReceive;  /*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */\r
144 \r
145         volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */\r
146         UBaseType_t uxLength;                   /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */\r
147         UBaseType_t uxItemSize;                 /*< The size of each items that the queue will hold. */\r
148 \r
149         volatile int8_t cRxLock;                /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */\r
150         volatile int8_t cTxLock;                /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked.  Set to queueUNLOCKED when the queue is not locked. */\r
151 \r
152         #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )\r
153                 uint8_t ucStaticallyAllocated;  /*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */\r
154         #endif\r
155 \r
156         #if ( configUSE_QUEUE_SETS == 1 )\r
157                 struct QueueDefinition *pxQueueSetContainer;\r
158         #endif\r
159 \r
160         #if ( configUSE_TRACE_FACILITY == 1 )\r
161                 UBaseType_t uxQueueNumber;\r
162                 uint8_t ucQueueType;\r
163         #endif\r
164 \r
165 } xQUEUE;\r
166 \r
167 /* The old xQUEUE name is maintained above then typedefed to the new Queue_t\r
168 name below to enable the use of older kernel aware debuggers. */\r
169 typedef xQUEUE Queue_t;\r
170 \r
171 /*-----------------------------------------------------------*/\r
172 \r
173 /*\r
174  * The queue registry is just a means for kernel aware debuggers to locate\r
175  * queue structures.  It has no other purpose so is an optional component.\r
176  */\r
177 #if ( configQUEUE_REGISTRY_SIZE > 0 )\r
178 \r
179         /* The type stored within the queue registry array.  This allows a name\r
180         to be assigned to each queue making kernel aware debugging a little\r
181         more user friendly. */\r
182         typedef struct QUEUE_REGISTRY_ITEM\r
183         {\r
184                 const char *pcQueueName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
185                 QueueHandle_t xHandle;\r
186         } xQueueRegistryItem;\r
187 \r
188         /* The old xQueueRegistryItem name is maintained above then typedefed to the\r
189         new xQueueRegistryItem name below to enable the use of older kernel aware\r
190         debuggers. */\r
191         typedef xQueueRegistryItem QueueRegistryItem_t;\r
192 \r
193         /* The queue registry is simply an array of QueueRegistryItem_t structures.\r
194         The pcQueueName member of a structure being NULL is indicative of the\r
195         array position being vacant. */\r
196         PRIVILEGED_DATA QueueRegistryItem_t xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];\r
197 \r
198 #endif /* configQUEUE_REGISTRY_SIZE */\r
199 \r
200 /*\r
201  * Unlocks a queue locked by a call to prvLockQueue.  Locking a queue does not\r
202  * prevent an ISR from adding or removing items to the queue, but does prevent\r
203  * an ISR from removing tasks from the queue event lists.  If an ISR finds a\r
204  * queue is locked it will instead increment the appropriate queue lock count\r
205  * to indicate that a task may require unblocking.  When the queue in unlocked\r
206  * these lock counts are inspected, and the appropriate action taken.\r
207  */\r
208 static void prvUnlockQueue( Queue_t * const pxQueue ) PRIVILEGED_FUNCTION;\r
209 \r
210 /*\r
211  * Uses a critical section to determine if there is any data in a queue.\r
212  *\r
213  * @return pdTRUE if the queue contains no items, otherwise pdFALSE.\r
214  */\r
215 static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue ) PRIVILEGED_FUNCTION;\r
216 \r
217 /*\r
218  * Uses a critical section to determine if there is any space in a queue.\r
219  *\r
220  * @return pdTRUE if there is no space, otherwise pdFALSE;\r
221  */\r
222 static BaseType_t prvIsQueueFull( const Queue_t *pxQueue ) PRIVILEGED_FUNCTION;\r
223 \r
224 /*\r
225  * Copies an item into the queue, either at the front of the queue or the\r
226  * back of the queue.\r
227  */\r
228 static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) PRIVILEGED_FUNCTION;\r
229 \r
230 /*\r
231  * Copies an item out of a queue.\r
232  */\r
233 static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION;\r
234 \r
235 #if ( configUSE_QUEUE_SETS == 1 )\r
236         /*\r
237          * Checks to see if a queue is a member of a queue set, and if so, notifies\r
238          * the queue set that the queue contains data.\r
239          */\r
240         static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION;\r
241 #endif\r
242 \r
243 /*\r
244  * Called after a Queue_t structure has been allocated either statically or\r
245  * dynamically to fill in the structure's members.\r
246  */\r
247 static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION;\r
248 \r
249 /*\r
250  * Mutexes are a special type of queue.  When a mutex is created, first the\r
251  * queue is created, then prvInitialiseMutex() is called to configure the queue\r
252  * as a mutex.\r
253  */\r
254 #if( configUSE_MUTEXES == 1 )\r
255         static void prvInitialiseMutex( Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION;\r
256 #endif\r
257 \r
258 #if( configUSE_MUTEXES == 1 )\r
259         /*\r
260          * If a task waiting for a mutex causes the mutex holder to inherit a\r
261          * priority, but the waiting task times out, then the holder should\r
262          * disinherit the priority - but only down to the highest priority of any\r
263          * other tasks that are waiting for the same mutex.  This function returns\r
264          * that priority.\r
265          */\r
266         static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION;\r
267 #endif\r
268 /*-----------------------------------------------------------*/\r
269 \r
270 /*\r
271  * Macro to mark a queue as locked.  Locking a queue prevents an ISR from\r
272  * accessing the queue event lists.\r
273  */\r
274 #define prvLockQueue( pxQueue )                                                         \\r
275         taskENTER_CRITICAL();                                                                   \\r
276         {                                                                                                               \\r
277                 if( ( pxQueue )->cRxLock == queueUNLOCKED )                     \\r
278                 {                                                                                                       \\r
279                         ( pxQueue )->cRxLock = queueLOCKED_UNMODIFIED;  \\r
280                 }                                                                                                       \\r
281                 if( ( pxQueue )->cTxLock == queueUNLOCKED )                     \\r
282                 {                                                                                                       \\r
283                         ( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED;  \\r
284                 }                                                                                                       \\r
285         }                                                                                                               \\r
286         taskEXIT_CRITICAL()\r
287 /*-----------------------------------------------------------*/\r
288 \r
289 BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue )\r
290 {\r
291 Queue_t * const pxQueue = ( Queue_t * ) xQueue;\r
292 \r
293         configASSERT( pxQueue );\r
294 \r
295         taskENTER_CRITICAL();\r
296         {\r
297                 pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize );\r
298                 pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U;\r
299                 pxQueue->pcWriteTo = pxQueue->pcHead;\r
300                 pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( UBaseType_t ) 1U ) * pxQueue->uxItemSize );\r
301                 pxQueue->cRxLock = queueUNLOCKED;\r
302                 pxQueue->cTxLock = queueUNLOCKED;\r
303 \r
304                 if( xNewQueue == pdFALSE )\r
305                 {\r
306                         /* If there are tasks blocked waiting to read from the queue, then\r
307                         the tasks will remain blocked as after this function exits the queue\r
308                         will still be empty.  If there are tasks blocked waiting to write to\r
309                         the queue, then one should be unblocked as after this function exits\r
310                         it will be possible to write to it. */\r
311                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
312                         {\r
313                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
314                                 {\r
315                                         queueYIELD_IF_USING_PREEMPTION();\r
316                                 }\r
317                                 else\r
318                                 {\r
319                                         mtCOVERAGE_TEST_MARKER();\r
320                                 }\r
321                         }\r
322                         else\r
323                         {\r
324                                 mtCOVERAGE_TEST_MARKER();\r
325                         }\r
326                 }\r
327                 else\r
328                 {\r
329                         /* Ensure the event queues start in the correct state. */\r
330                         vListInitialise( &( pxQueue->xTasksWaitingToSend ) );\r
331                         vListInitialise( &( pxQueue->xTasksWaitingToReceive ) );\r
332                 }\r
333         }\r
334         taskEXIT_CRITICAL();\r
335 \r
336         /* A value is returned for calling semantic consistency with previous\r
337         versions. */\r
338         return pdPASS;\r
339 }\r
340 /*-----------------------------------------------------------*/\r
341 \r
342 #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
343 \r
344         QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType )\r
345         {\r
346         Queue_t *pxNewQueue;\r
347 \r
348                 configASSERT( uxQueueLength > ( UBaseType_t ) 0 );\r
349 \r
350                 /* The StaticQueue_t structure and the queue storage area must be\r
351                 supplied. */\r
352                 configASSERT( pxStaticQueue != NULL );\r
353 \r
354                 /* A queue storage area should be provided if the item size is not 0, and\r
355                 should not be provided if the item size is 0. */\r
356                 configASSERT( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) );\r
357                 configASSERT( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) );\r
358 \r
359                 #if( configASSERT_DEFINED == 1 )\r
360                 {\r
361                         /* Sanity check that the size of the structure used to declare a\r
362                         variable of type StaticQueue_t or StaticSemaphore_t equals the size of\r
363                         the real queue and semaphore structures. */\r
364                         volatile size_t xSize = sizeof( StaticQueue_t );\r
365                         configASSERT( xSize == sizeof( Queue_t ) );\r
366                 }\r
367                 #endif /* configASSERT_DEFINED */\r
368 \r
369                 /* The address of a statically allocated queue was passed in, use it.\r
370                 The address of a statically allocated storage area was also passed in\r
371                 but is already set. */\r
372                 pxNewQueue = ( Queue_t * ) pxStaticQueue; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */\r
373 \r
374                 if( pxNewQueue != NULL )\r
375                 {\r
376                         #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
377                         {\r
378                                 /* Queues can be allocated wither statically or dynamically, so\r
379                                 note this queue was allocated statically in case the queue is\r
380                                 later deleted. */\r
381                                 pxNewQueue->ucStaticallyAllocated = pdTRUE;\r
382                         }\r
383                         #endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
384 \r
385                         prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );\r
386                 }\r
387                 else\r
388                 {\r
389                         traceQUEUE_CREATE_FAILED( ucQueueType );\r
390                 }\r
391 \r
392                 return pxNewQueue;\r
393         }\r
394 \r
395 #endif /* configSUPPORT_STATIC_ALLOCATION */\r
396 /*-----------------------------------------------------------*/\r
397 \r
398 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
399 \r
400         QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType )\r
401         {\r
402         Queue_t *pxNewQueue;\r
403         size_t xQueueSizeInBytes;\r
404         uint8_t *pucQueueStorage;\r
405 \r
406                 configASSERT( uxQueueLength > ( UBaseType_t ) 0 );\r
407 \r
408                 if( uxItemSize == ( UBaseType_t ) 0 )\r
409                 {\r
410                         /* There is not going to be a queue storage area. */\r
411                         xQueueSizeInBytes = ( size_t ) 0;\r
412                 }\r
413                 else\r
414                 {\r
415                         /* Allocate enough space to hold the maximum number of items that\r
416                         can be in the queue at any time. */\r
417                         xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
418                 }\r
419 \r
420                 pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );\r
421 \r
422                 if( pxNewQueue != NULL )\r
423                 {\r
424                         /* Jump past the queue structure to find the location of the queue\r
425                         storage area. */\r
426                         pucQueueStorage = ( ( uint8_t * ) pxNewQueue ) + sizeof( Queue_t );\r
427 \r
428                         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
429                         {\r
430                                 /* Queues can be created either statically or dynamically, so\r
431                                 note this task was created dynamically in case it is later\r
432                                 deleted. */\r
433                                 pxNewQueue->ucStaticallyAllocated = pdFALSE;\r
434                         }\r
435                         #endif /* configSUPPORT_STATIC_ALLOCATION */\r
436 \r
437                         prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );\r
438                 }\r
439                 else\r
440                 {\r
441                         traceQUEUE_CREATE_FAILED( ucQueueType );\r
442                 }\r
443 \r
444                 return pxNewQueue;\r
445         }\r
446 \r
447 #endif /* configSUPPORT_STATIC_ALLOCATION */\r
448 /*-----------------------------------------------------------*/\r
449 \r
450 static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue )\r
451 {\r
452         /* Remove compiler warnings about unused parameters should\r
453         configUSE_TRACE_FACILITY not be set to 1. */\r
454         ( void ) ucQueueType;\r
455 \r
456         if( uxItemSize == ( UBaseType_t ) 0 )\r
457         {\r
458                 /* No RAM was allocated for the queue storage area, but PC head cannot\r
459                 be set to NULL because NULL is used as a key to say the queue is used as\r
460                 a mutex.  Therefore just set pcHead to point to the queue as a benign\r
461                 value that is known to be within the memory map. */\r
462                 pxNewQueue->pcHead = ( int8_t * ) pxNewQueue;\r
463         }\r
464         else\r
465         {\r
466                 /* Set the head to the start of the queue storage area. */\r
467                 pxNewQueue->pcHead = ( int8_t * ) pucQueueStorage;\r
468         }\r
469 \r
470         /* Initialise the queue members as described where the queue type is\r
471         defined. */\r
472         pxNewQueue->uxLength = uxQueueLength;\r
473         pxNewQueue->uxItemSize = uxItemSize;\r
474         ( void ) xQueueGenericReset( pxNewQueue, pdTRUE );\r
475 \r
476         #if ( configUSE_TRACE_FACILITY == 1 )\r
477         {\r
478                 pxNewQueue->ucQueueType = ucQueueType;\r
479         }\r
480         #endif /* configUSE_TRACE_FACILITY */\r
481 \r
482         #if( configUSE_QUEUE_SETS == 1 )\r
483         {\r
484                 pxNewQueue->pxQueueSetContainer = NULL;\r
485         }\r
486         #endif /* configUSE_QUEUE_SETS */\r
487 \r
488         traceQUEUE_CREATE( pxNewQueue );\r
489 }\r
490 /*-----------------------------------------------------------*/\r
491 \r
492 #if( configUSE_MUTEXES == 1 )\r
493 \r
494         static void prvInitialiseMutex( Queue_t *pxNewQueue )\r
495         {\r
496                 if( pxNewQueue != NULL )\r
497                 {\r
498                         /* The queue create function will set all the queue structure members\r
499                         correctly for a generic queue, but this function is creating a\r
500                         mutex.  Overwrite those members that need to be set differently -\r
501                         in particular the information required for priority inheritance. */\r
502                         pxNewQueue->pxMutexHolder = NULL;\r
503                         pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;\r
504 \r
505                         /* In case this is a recursive mutex. */\r
506                         pxNewQueue->u.uxRecursiveCallCount = 0;\r
507 \r
508                         traceCREATE_MUTEX( pxNewQueue );\r
509 \r
510                         /* Start with the semaphore in the expected state. */\r
511                         ( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK );\r
512                 }\r
513                 else\r
514                 {\r
515                         traceCREATE_MUTEX_FAILED();\r
516                 }\r
517         }\r
518 \r
519 #endif /* configUSE_MUTEXES */\r
520 /*-----------------------------------------------------------*/\r
521 \r
522 #if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )\r
523 \r
524         QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )\r
525         {\r
526         Queue_t *pxNewQueue;\r
527         const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;\r
528 \r
529                 pxNewQueue = ( Queue_t * ) xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType );\r
530                 prvInitialiseMutex( pxNewQueue );\r
531 \r
532                 return pxNewQueue;\r
533         }\r
534 \r
535 #endif /* configUSE_MUTEXES */\r
536 /*-----------------------------------------------------------*/\r
537 \r
538 #if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )\r
539 \r
540         QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue )\r
541         {\r
542         Queue_t *pxNewQueue;\r
543         const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;\r
544 \r
545                 /* Prevent compiler warnings about unused parameters if\r
546                 configUSE_TRACE_FACILITY does not equal 1. */\r
547                 ( void ) ucQueueType;\r
548 \r
549                 pxNewQueue = ( Queue_t * ) xQueueGenericCreateStatic( uxMutexLength, uxMutexSize, NULL, pxStaticQueue, ucQueueType );\r
550                 prvInitialiseMutex( pxNewQueue );\r
551 \r
552                 return pxNewQueue;\r
553         }\r
554 \r
555 #endif /* configUSE_MUTEXES */\r
556 /*-----------------------------------------------------------*/\r
557 \r
558 #if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )\r
559 \r
560         void* xQueueGetMutexHolder( QueueHandle_t xSemaphore )\r
561         {\r
562         void *pxReturn;\r
563 \r
564                 /* This function is called by xSemaphoreGetMutexHolder(), and should not\r
565                 be called directly.  Note:  This is a good way of determining if the\r
566                 calling task is the mutex holder, but not a good way of determining the\r
567                 identity of the mutex holder, as the holder may change between the\r
568                 following critical section exiting and the function returning. */\r
569                 taskENTER_CRITICAL();\r
570                 {\r
571                         if( ( ( Queue_t * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX )\r
572                         {\r
573                                 pxReturn = ( void * ) ( ( Queue_t * ) xSemaphore )->pxMutexHolder;\r
574                         }\r
575                         else\r
576                         {\r
577                                 pxReturn = NULL;\r
578                         }\r
579                 }\r
580                 taskEXIT_CRITICAL();\r
581 \r
582                 return pxReturn;\r
583         } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */\r
584 \r
585 #endif\r
586 /*-----------------------------------------------------------*/\r
587 \r
588 #if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )\r
589 \r
590         void* xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore )\r
591         {\r
592         void *pxReturn;\r
593 \r
594                 configASSERT( xSemaphore );\r
595 \r
596                 /* Mutexes cannot be used in interrupt service routines, so the mutex\r
597                 holder should not change in an ISR, and therefore a critical section is\r
598                 not required here. */\r
599                 if( ( ( Queue_t * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX )\r
600                 {\r
601                         pxReturn = ( void * ) ( ( Queue_t * ) xSemaphore )->pxMutexHolder;\r
602                 }\r
603                 else\r
604                 {\r
605                         pxReturn = NULL;\r
606                 }\r
607 \r
608                 return pxReturn;\r
609         } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */\r
610 \r
611 #endif\r
612 /*-----------------------------------------------------------*/\r
613 \r
614 #if ( configUSE_RECURSIVE_MUTEXES == 1 )\r
615 \r
616         BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex )\r
617         {\r
618         BaseType_t xReturn;\r
619         Queue_t * const pxMutex = ( Queue_t * ) xMutex;\r
620 \r
621                 configASSERT( pxMutex );\r
622 \r
623                 /* If this is the task that holds the mutex then pxMutexHolder will not\r
624                 change outside of this task.  If this task does not hold the mutex then\r
625                 pxMutexHolder can never coincidentally equal the tasks handle, and as\r
626                 this is the only condition we are interested in it does not matter if\r
627                 pxMutexHolder is accessed simultaneously by another task.  Therefore no\r
628                 mutual exclusion is required to test the pxMutexHolder variable. */\r
629                 if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Not a redundant cast as TaskHandle_t is a typedef. */\r
630                 {\r
631                         traceGIVE_MUTEX_RECURSIVE( pxMutex );\r
632 \r
633                         /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to\r
634                         the task handle, therefore no underflow check is required.  Also,\r
635                         uxRecursiveCallCount is only modified by the mutex holder, and as\r
636                         there can only be one, no mutual exclusion is required to modify the\r
637                         uxRecursiveCallCount member. */\r
638                         ( pxMutex->u.uxRecursiveCallCount )--;\r
639 \r
640                         /* Has the recursive call count unwound to 0? */\r
641                         if( pxMutex->u.uxRecursiveCallCount == ( UBaseType_t ) 0 )\r
642                         {\r
643                                 /* Return the mutex.  This will automatically unblock any other\r
644                                 task that might be waiting to access the mutex. */\r
645                                 ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );\r
646                         }\r
647                         else\r
648                         {\r
649                                 mtCOVERAGE_TEST_MARKER();\r
650                         }\r
651 \r
652                         xReturn = pdPASS;\r
653                 }\r
654                 else\r
655                 {\r
656                         /* The mutex cannot be given because the calling task is not the\r
657                         holder. */\r
658                         xReturn = pdFAIL;\r
659 \r
660                         traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );\r
661                 }\r
662 \r
663                 return xReturn;\r
664         }\r
665 \r
666 #endif /* configUSE_RECURSIVE_MUTEXES */\r
667 /*-----------------------------------------------------------*/\r
668 \r
669 #if ( configUSE_RECURSIVE_MUTEXES == 1 )\r
670 \r
671         BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait )\r
672         {\r
673         BaseType_t xReturn;\r
674         Queue_t * const pxMutex = ( Queue_t * ) xMutex;\r
675 \r
676                 configASSERT( pxMutex );\r
677 \r
678                 /* Comments regarding mutual exclusion as per those within\r
679                 xQueueGiveMutexRecursive(). */\r
680 \r
681                 traceTAKE_MUTEX_RECURSIVE( pxMutex );\r
682 \r
683                 if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */\r
684                 {\r
685                         ( pxMutex->u.uxRecursiveCallCount )++;\r
686                         xReturn = pdPASS;\r
687                 }\r
688                 else\r
689                 {\r
690                         xReturn = xQueueSemaphoreTake( pxMutex, xTicksToWait );\r
691 \r
692                         /* pdPASS will only be returned if the mutex was successfully\r
693                         obtained.  The calling task may have entered the Blocked state\r
694                         before reaching here. */\r
695                         if( xReturn != pdFAIL )\r
696                         {\r
697                                 ( pxMutex->u.uxRecursiveCallCount )++;\r
698                         }\r
699                         else\r
700                         {\r
701                                 traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );\r
702                         }\r
703                 }\r
704 \r
705                 return xReturn;\r
706         }\r
707 \r
708 #endif /* configUSE_RECURSIVE_MUTEXES */\r
709 /*-----------------------------------------------------------*/\r
710 \r
711 #if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )\r
712 \r
713         QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue )\r
714         {\r
715         QueueHandle_t xHandle;\r
716 \r
717                 configASSERT( uxMaxCount != 0 );\r
718                 configASSERT( uxInitialCount <= uxMaxCount );\r
719 \r
720                 xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE );\r
721 \r
722                 if( xHandle != NULL )\r
723                 {\r
724                         ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;\r
725 \r
726                         traceCREATE_COUNTING_SEMAPHORE();\r
727                 }\r
728                 else\r
729                 {\r
730                         traceCREATE_COUNTING_SEMAPHORE_FAILED();\r
731                 }\r
732 \r
733                 return xHandle;\r
734         }\r
735 \r
736 #endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */\r
737 /*-----------------------------------------------------------*/\r
738 \r
739 #if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )\r
740 \r
741         QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount )\r
742         {\r
743         QueueHandle_t xHandle;\r
744 \r
745                 configASSERT( uxMaxCount != 0 );\r
746                 configASSERT( uxInitialCount <= uxMaxCount );\r
747 \r
748                 xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );\r
749 \r
750                 if( xHandle != NULL )\r
751                 {\r
752                         ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount;\r
753 \r
754                         traceCREATE_COUNTING_SEMAPHORE();\r
755                 }\r
756                 else\r
757                 {\r
758                         traceCREATE_COUNTING_SEMAPHORE_FAILED();\r
759                 }\r
760 \r
761                 return xHandle;\r
762         }\r
763 \r
764 #endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */\r
765 /*-----------------------------------------------------------*/\r
766 \r
767 BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition )\r
768 {\r
769 BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired;\r
770 TimeOut_t xTimeOut;\r
771 Queue_t * const pxQueue = ( Queue_t * ) xQueue;\r
772 \r
773         configASSERT( pxQueue );\r
774         configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );\r
775         configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );\r
776         #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )\r
777         {\r
778                 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );\r
779         }\r
780         #endif\r
781 \r
782 \r
783         /* This function relaxes the coding standard somewhat to allow return\r
784         statements within the function itself.  This is done in the interest\r
785         of execution time efficiency. */\r
786         for( ;; )\r
787         {\r
788                 taskENTER_CRITICAL();\r
789                 {\r
790                         /* Is there room on the queue now?  The running task must be the\r
791                         highest priority task wanting to access the queue.  If the head item\r
792                         in the queue is to be overwritten then it does not matter if the\r
793                         queue is full. */\r
794                         if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )\r
795                         {\r
796                                 traceQUEUE_SEND( pxQueue );\r
797                                 xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
798 \r
799                                 #if ( configUSE_QUEUE_SETS == 1 )\r
800                                 {\r
801                                         if( pxQueue->pxQueueSetContainer != NULL )\r
802                                         {\r
803                                                 if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE )\r
804                                                 {\r
805                                                         /* The queue is a member of a queue set, and posting\r
806                                                         to the queue set caused a higher priority task to\r
807                                                         unblock. A context switch is required. */\r
808                                                         queueYIELD_IF_USING_PREEMPTION();\r
809                                                 }\r
810                                                 else\r
811                                                 {\r
812                                                         mtCOVERAGE_TEST_MARKER();\r
813                                                 }\r
814                                         }\r
815                                         else\r
816                                         {\r
817                                                 /* If there was a task waiting for data to arrive on the\r
818                                                 queue then unblock it now. */\r
819                                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
820                                                 {\r
821                                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
822                                                         {\r
823                                                                 /* The unblocked task has a priority higher than\r
824                                                                 our own so yield immediately.  Yes it is ok to\r
825                                                                 do this from within the critical section - the\r
826                                                                 kernel takes care of that. */\r
827                                                                 queueYIELD_IF_USING_PREEMPTION();\r
828                                                         }\r
829                                                         else\r
830                                                         {\r
831                                                                 mtCOVERAGE_TEST_MARKER();\r
832                                                         }\r
833                                                 }\r
834                                                 else if( xYieldRequired != pdFALSE )\r
835                                                 {\r
836                                                         /* This path is a special case that will only get\r
837                                                         executed if the task was holding multiple mutexes\r
838                                                         and the mutexes were given back in an order that is\r
839                                                         different to that in which they were taken. */\r
840                                                         queueYIELD_IF_USING_PREEMPTION();\r
841                                                 }\r
842                                                 else\r
843                                                 {\r
844                                                         mtCOVERAGE_TEST_MARKER();\r
845                                                 }\r
846                                         }\r
847                                 }\r
848                                 #else /* configUSE_QUEUE_SETS */\r
849                                 {\r
850                                         /* If there was a task waiting for data to arrive on the\r
851                                         queue then unblock it now. */\r
852                                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
853                                         {\r
854                                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
855                                                 {\r
856                                                         /* The unblocked task has a priority higher than\r
857                                                         our own so yield immediately.  Yes it is ok to do\r
858                                                         this from within the critical section - the kernel\r
859                                                         takes care of that. */\r
860                                                         queueYIELD_IF_USING_PREEMPTION();\r
861                                                 }\r
862                                                 else\r
863                                                 {\r
864                                                         mtCOVERAGE_TEST_MARKER();\r
865                                                 }\r
866                                         }\r
867                                         else if( xYieldRequired != pdFALSE )\r
868                                         {\r
869                                                 /* This path is a special case that will only get\r
870                                                 executed if the task was holding multiple mutexes and\r
871                                                 the mutexes were given back in an order that is\r
872                                                 different to that in which they were taken. */\r
873                                                 queueYIELD_IF_USING_PREEMPTION();\r
874                                         }\r
875                                         else\r
876                                         {\r
877                                                 mtCOVERAGE_TEST_MARKER();\r
878                                         }\r
879                                 }\r
880                                 #endif /* configUSE_QUEUE_SETS */\r
881 \r
882                                 taskEXIT_CRITICAL();\r
883                                 return pdPASS;\r
884                         }\r
885                         else\r
886                         {\r
887                                 if( xTicksToWait == ( TickType_t ) 0 )\r
888                                 {\r
889                                         /* The queue was full and no block time is specified (or\r
890                                         the block time has expired) so leave now. */\r
891                                         taskEXIT_CRITICAL();\r
892 \r
893                                         /* Return to the original privilege level before exiting\r
894                                         the function. */\r
895                                         traceQUEUE_SEND_FAILED( pxQueue );\r
896                                         return errQUEUE_FULL;\r
897                                 }\r
898                                 else if( xEntryTimeSet == pdFALSE )\r
899                                 {\r
900                                         /* The queue was full and a block time was specified so\r
901                                         configure the timeout structure. */\r
902                                         vTaskInternalSetTimeOutState( &xTimeOut );\r
903                                         xEntryTimeSet = pdTRUE;\r
904                                 }\r
905                                 else\r
906                                 {\r
907                                         /* Entry time was already set. */\r
908                                         mtCOVERAGE_TEST_MARKER();\r
909                                 }\r
910                         }\r
911                 }\r
912                 taskEXIT_CRITICAL();\r
913 \r
914                 /* Interrupts and other tasks can send to and receive from the queue\r
915                 now the critical section has been exited. */\r
916 \r
917                 vTaskSuspendAll();\r
918                 prvLockQueue( pxQueue );\r
919 \r
920                 /* Update the timeout state to see if it has expired yet. */\r
921                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
922                 {\r
923                         if( prvIsQueueFull( pxQueue ) != pdFALSE )\r
924                         {\r
925                                 traceBLOCKING_ON_QUEUE_SEND( pxQueue );\r
926                                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );\r
927 \r
928                                 /* Unlocking the queue means queue events can effect the\r
929                                 event list.  It is possible     that interrupts occurring now\r
930                                 remove this task from the event list again - but as the\r
931                                 scheduler is suspended the task will go onto the pending\r
932                                 ready last instead of the actual ready list. */\r
933                                 prvUnlockQueue( pxQueue );\r
934 \r
935                                 /* Resuming the scheduler will move tasks from the pending\r
936                                 ready list into the ready list - so it is feasible that this\r
937                                 task is already in a ready list before it yields - in which\r
938                                 case the yield will not cause a context switch unless there\r
939                                 is also a higher priority task in the pending ready list. */\r
940                                 if( xTaskResumeAll() == pdFALSE )\r
941                                 {\r
942                                         portYIELD_WITHIN_API();\r
943                                 }\r
944                         }\r
945                         else\r
946                         {\r
947                                 /* Try again. */\r
948                                 prvUnlockQueue( pxQueue );\r
949                                 ( void ) xTaskResumeAll();\r
950                         }\r
951                 }\r
952                 else\r
953                 {\r
954                         /* The timeout has expired. */\r
955                         prvUnlockQueue( pxQueue );\r
956                         ( void ) xTaskResumeAll();\r
957 \r
958                         traceQUEUE_SEND_FAILED( pxQueue );\r
959                         return errQUEUE_FULL;\r
960                 }\r
961         }\r
962 }\r
963 /*-----------------------------------------------------------*/\r
964 \r
965 BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition )\r
966 {\r
967 BaseType_t xReturn;\r
968 UBaseType_t uxSavedInterruptStatus;\r
969 Queue_t * const pxQueue = ( Queue_t * ) xQueue;\r
970 \r
971         configASSERT( pxQueue );\r
972         configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );\r
973         configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );\r
974 \r
975         /* RTOS ports that support interrupt nesting have the concept of a maximum\r
976         system call (or maximum API call) interrupt priority.  Interrupts that are\r
977         above the maximum system call priority are kept permanently enabled, even\r
978         when the RTOS kernel is in a critical section, but cannot make any calls to\r
979         FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h\r
980         then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
981         failure if a FreeRTOS API function is called from an interrupt that has been\r
982         assigned a priority above the configured maximum system call priority.\r
983         Only FreeRTOS functions that end in FromISR can be called from interrupts\r
984         that have been assigned a priority at or (logically) below the maximum\r
985         system call     interrupt priority.  FreeRTOS maintains a separate interrupt\r
986         safe API to ensure interrupt entry is as fast and as simple as possible.\r
987         More information (albeit Cortex-M specific) is provided on the following\r
988         link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
989         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
990 \r
991         /* Similar to xQueueGenericSend, except without blocking if there is no room\r
992         in the queue.  Also don't directly wake a task that was blocked on a queue\r
993         read, instead return a flag to say whether a context switch is required or\r
994         not (i.e. has a task with a higher priority than us been woken by this\r
995         post). */\r
996         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
997         {\r
998                 if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )\r
999                 {\r
1000                         const int8_t cTxLock = pxQueue->cTxLock;\r
1001 \r
1002                         traceQUEUE_SEND_FROM_ISR( pxQueue );\r
1003 \r
1004                         /* Semaphores use xQueueGiveFromISR(), so pxQueue will not be a\r
1005                         semaphore or mutex.  That means prvCopyDataToQueue() cannot result\r
1006                         in a task disinheriting a priority and prvCopyDataToQueue() can be\r
1007                         called here even though the disinherit function does not check if\r
1008                         the scheduler is suspended before accessing the ready lists. */\r
1009                         ( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );\r
1010 \r
1011                         /* The event list is not altered if the queue is locked.  This will\r
1012                         be done when the queue is unlocked later. */\r
1013                         if( cTxLock == queueUNLOCKED )\r
1014                         {\r
1015                                 #if ( configUSE_QUEUE_SETS == 1 )\r
1016                                 {\r
1017                                         if( pxQueue->pxQueueSetContainer != NULL )\r
1018                                         {\r
1019                                                 if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE )\r
1020                                                 {\r
1021                                                         /* The queue is a member of a queue set, and posting\r
1022                                                         to the queue set caused a higher priority task to\r
1023                                                         unblock.  A context switch is required. */\r
1024                                                         if( pxHigherPriorityTaskWoken != NULL )\r
1025                                                         {\r
1026                                                                 *pxHigherPriorityTaskWoken = pdTRUE;\r
1027                                                         }\r
1028                                                         else\r
1029                                                         {\r
1030                                                                 mtCOVERAGE_TEST_MARKER();\r
1031                                                         }\r
1032                                                 }\r
1033                                                 else\r
1034                                                 {\r
1035                                                         mtCOVERAGE_TEST_MARKER();\r
1036                                                 }\r
1037                                         }\r
1038                                         else\r
1039                                         {\r
1040                                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1041                                                 {\r
1042                                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1043                                                         {\r
1044                                                                 /* The task waiting has a higher priority so\r
1045                                                                 record that a context switch is required. */\r
1046                                                                 if( pxHigherPriorityTaskWoken != NULL )\r
1047                                                                 {\r
1048                                                                         *pxHigherPriorityTaskWoken = pdTRUE;\r
1049                                                                 }\r
1050                                                                 else\r
1051                                                                 {\r
1052                                                                         mtCOVERAGE_TEST_MARKER();\r
1053                                                                 }\r
1054                                                         }\r
1055                                                         else\r
1056                                                         {\r
1057                                                                 mtCOVERAGE_TEST_MARKER();\r
1058                                                         }\r
1059                                                 }\r
1060                                                 else\r
1061                                                 {\r
1062                                                         mtCOVERAGE_TEST_MARKER();\r
1063                                                 }\r
1064                                         }\r
1065                                 }\r
1066                                 #else /* configUSE_QUEUE_SETS */\r
1067                                 {\r
1068                                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1069                                         {\r
1070                                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1071                                                 {\r
1072                                                         /* The task waiting has a higher priority so record that a\r
1073                                                         context switch is required. */\r
1074                                                         if( pxHigherPriorityTaskWoken != NULL )\r
1075                                                         {\r
1076                                                                 *pxHigherPriorityTaskWoken = pdTRUE;\r
1077                                                         }\r
1078                                                         else\r
1079                                                         {\r
1080                                                                 mtCOVERAGE_TEST_MARKER();\r
1081                                                         }\r
1082                                                 }\r
1083                                                 else\r
1084                                                 {\r
1085                                                         mtCOVERAGE_TEST_MARKER();\r
1086                                                 }\r
1087                                         }\r
1088                                         else\r
1089                                         {\r
1090                                                 mtCOVERAGE_TEST_MARKER();\r
1091                                         }\r
1092                                 }\r
1093                                 #endif /* configUSE_QUEUE_SETS */\r
1094                         }\r
1095                         else\r
1096                         {\r
1097                                 /* Increment the lock count so the task that unlocks the queue\r
1098                                 knows that data was posted while it was locked. */\r
1099                                 pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 );\r
1100                         }\r
1101 \r
1102                         xReturn = pdPASS;\r
1103                 }\r
1104                 else\r
1105                 {\r
1106                         traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );\r
1107                         xReturn = errQUEUE_FULL;\r
1108                 }\r
1109         }\r
1110         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
1111 \r
1112         return xReturn;\r
1113 }\r
1114 /*-----------------------------------------------------------*/\r
1115 \r
1116 BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken )\r
1117 {\r
1118 BaseType_t xReturn;\r
1119 UBaseType_t uxSavedInterruptStatus;\r
1120 Queue_t * const pxQueue = ( Queue_t * ) xQueue;\r
1121 \r
1122         /* Similar to xQueueGenericSendFromISR() but used with semaphores where the\r
1123         item size is 0.  Don't directly wake a task that was blocked on a queue\r
1124         read, instead return a flag to say whether a context switch is required or\r
1125         not (i.e. has a task with a higher priority than us been woken by this\r
1126         post). */\r
1127 \r
1128         configASSERT( pxQueue );\r
1129 \r
1130         /* xQueueGenericSendFromISR() should be used instead of xQueueGiveFromISR()\r
1131         if the item size is not 0. */\r
1132         configASSERT( pxQueue->uxItemSize == 0 );\r
1133 \r
1134         /* Normally a mutex would not be given from an interrupt, especially if\r
1135         there is a mutex holder, as priority inheritance makes no sense for an\r
1136         interrupts, only tasks. */\r
1137         configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->pxMutexHolder != NULL ) ) );\r
1138 \r
1139         /* RTOS ports that support interrupt nesting have the concept of a maximum\r
1140         system call (or maximum API call) interrupt priority.  Interrupts that are\r
1141         above the maximum system call priority are kept permanently enabled, even\r
1142         when the RTOS kernel is in a critical section, but cannot make any calls to\r
1143         FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h\r
1144         then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
1145         failure if a FreeRTOS API function is called from an interrupt that has been\r
1146         assigned a priority above the configured maximum system call priority.\r
1147         Only FreeRTOS functions that end in FromISR can be called from interrupts\r
1148         that have been assigned a priority at or (logically) below the maximum\r
1149         system call     interrupt priority.  FreeRTOS maintains a separate interrupt\r
1150         safe API to ensure interrupt entry is as fast and as simple as possible.\r
1151         More information (albeit Cortex-M specific) is provided on the following\r
1152         link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
1153         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
1154 \r
1155         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
1156         {\r
1157                 const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;\r
1158 \r
1159                 /* When the queue is used to implement a semaphore no data is ever\r
1160                 moved through the queue but it is still valid to see if the queue 'has\r
1161                 space'. */\r
1162                 if( uxMessagesWaiting < pxQueue->uxLength )\r
1163                 {\r
1164                         const int8_t cTxLock = pxQueue->cTxLock;\r
1165 \r
1166                         traceQUEUE_SEND_FROM_ISR( pxQueue );\r
1167 \r
1168                         /* A task can only have an inherited priority if it is a mutex\r
1169                         holder - and if there is a mutex holder then the mutex cannot be\r
1170                         given from an ISR.  As this is the ISR version of the function it\r
1171                         can be assumed there is no mutex holder and no need to determine if\r
1172                         priority disinheritance is needed.  Simply increase the count of\r
1173                         messages (semaphores) available. */\r
1174                         pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1;\r
1175 \r
1176                         /* The event list is not altered if the queue is locked.  This will\r
1177                         be done when the queue is unlocked later. */\r
1178                         if( cTxLock == queueUNLOCKED )\r
1179                         {\r
1180                                 #if ( configUSE_QUEUE_SETS == 1 )\r
1181                                 {\r
1182                                         if( pxQueue->pxQueueSetContainer != NULL )\r
1183                                         {\r
1184                                                 if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) != pdFALSE )\r
1185                                                 {\r
1186                                                         /* The semaphore is a member of a queue set, and\r
1187                                                         posting to the queue set caused a higher priority\r
1188                                                         task to unblock.  A context switch is required. */\r
1189                                                         if( pxHigherPriorityTaskWoken != NULL )\r
1190                                                         {\r
1191                                                                 *pxHigherPriorityTaskWoken = pdTRUE;\r
1192                                                         }\r
1193                                                         else\r
1194                                                         {\r
1195                                                                 mtCOVERAGE_TEST_MARKER();\r
1196                                                         }\r
1197                                                 }\r
1198                                                 else\r
1199                                                 {\r
1200                                                         mtCOVERAGE_TEST_MARKER();\r
1201                                                 }\r
1202                                         }\r
1203                                         else\r
1204                                         {\r
1205                                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1206                                                 {\r
1207                                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1208                                                         {\r
1209                                                                 /* The task waiting has a higher priority so\r
1210                                                                 record that a context switch is required. */\r
1211                                                                 if( pxHigherPriorityTaskWoken != NULL )\r
1212                                                                 {\r
1213                                                                         *pxHigherPriorityTaskWoken = pdTRUE;\r
1214                                                                 }\r
1215                                                                 else\r
1216                                                                 {\r
1217                                                                         mtCOVERAGE_TEST_MARKER();\r
1218                                                                 }\r
1219                                                         }\r
1220                                                         else\r
1221                                                         {\r
1222                                                                 mtCOVERAGE_TEST_MARKER();\r
1223                                                         }\r
1224                                                 }\r
1225                                                 else\r
1226                                                 {\r
1227                                                         mtCOVERAGE_TEST_MARKER();\r
1228                                                 }\r
1229                                         }\r
1230                                 }\r
1231                                 #else /* configUSE_QUEUE_SETS */\r
1232                                 {\r
1233                                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1234                                         {\r
1235                                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1236                                                 {\r
1237                                                         /* The task waiting has a higher priority so record that a\r
1238                                                         context switch is required. */\r
1239                                                         if( pxHigherPriorityTaskWoken != NULL )\r
1240                                                         {\r
1241                                                                 *pxHigherPriorityTaskWoken = pdTRUE;\r
1242                                                         }\r
1243                                                         else\r
1244                                                         {\r
1245                                                                 mtCOVERAGE_TEST_MARKER();\r
1246                                                         }\r
1247                                                 }\r
1248                                                 else\r
1249                                                 {\r
1250                                                         mtCOVERAGE_TEST_MARKER();\r
1251                                                 }\r
1252                                         }\r
1253                                         else\r
1254                                         {\r
1255                                                 mtCOVERAGE_TEST_MARKER();\r
1256                                         }\r
1257                                 }\r
1258                                 #endif /* configUSE_QUEUE_SETS */\r
1259                         }\r
1260                         else\r
1261                         {\r
1262                                 /* Increment the lock count so the task that unlocks the queue\r
1263                                 knows that data was posted while it was locked. */\r
1264                                 pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 );\r
1265                         }\r
1266 \r
1267                         xReturn = pdPASS;\r
1268                 }\r
1269                 else\r
1270                 {\r
1271                         traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );\r
1272                         xReturn = errQUEUE_FULL;\r
1273                 }\r
1274         }\r
1275         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
1276 \r
1277         return xReturn;\r
1278 }\r
1279 /*-----------------------------------------------------------*/\r
1280 \r
1281 BaseType_t xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait )\r
1282 {\r
1283 BaseType_t xEntryTimeSet = pdFALSE;\r
1284 TimeOut_t xTimeOut;\r
1285 Queue_t * const pxQueue = ( Queue_t * ) xQueue;\r
1286 \r
1287         /* Check the pointer is not NULL. */\r
1288         configASSERT( ( pxQueue ) );\r
1289 \r
1290         /* The buffer into which data is received can only be NULL if the data size\r
1291         is zero (so no data is copied into the buffer. */\r
1292         configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) );\r
1293 \r
1294         /* Cannot block if the scheduler is suspended. */\r
1295         #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )\r
1296         {\r
1297                 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );\r
1298         }\r
1299         #endif\r
1300 \r
1301 \r
1302         /* This function relaxes the coding standard somewhat to allow return\r
1303         statements within the function itself.  This is done in the interest\r
1304         of execution time efficiency. */\r
1305 \r
1306         for( ;; )\r
1307         {\r
1308                 taskENTER_CRITICAL();\r
1309                 {\r
1310                         const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;\r
1311 \r
1312                         /* Is there data in the queue now?  To be running the calling task\r
1313                         must be the highest priority task wanting to access the queue. */\r
1314                         if( uxMessagesWaiting > ( UBaseType_t ) 0 )\r
1315                         {\r
1316                                 /* Data available, remove one item. */\r
1317                                 prvCopyDataFromQueue( pxQueue, pvBuffer );\r
1318                                 traceQUEUE_RECEIVE( pxQueue );\r
1319                                 pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1;\r
1320 \r
1321                                 /* There is now space in the queue, were any tasks waiting to\r
1322                                 post to the queue?  If so, unblock the highest priority waiting\r
1323                                 task. */\r
1324                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
1325                                 {\r
1326                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
1327                                         {\r
1328                                                 queueYIELD_IF_USING_PREEMPTION();\r
1329                                         }\r
1330                                         else\r
1331                                         {\r
1332                                                 mtCOVERAGE_TEST_MARKER();\r
1333                                         }\r
1334                                 }\r
1335                                 else\r
1336                                 {\r
1337                                         mtCOVERAGE_TEST_MARKER();\r
1338                                 }\r
1339 \r
1340                                 taskEXIT_CRITICAL();\r
1341                                 return pdPASS;\r
1342                         }\r
1343                         else\r
1344                         {\r
1345                                 if( xTicksToWait == ( TickType_t ) 0 )\r
1346                                 {\r
1347                                         /* The queue was empty and no block time is specified (or\r
1348                                         the block time has expired) so leave now. */\r
1349                                         taskEXIT_CRITICAL();\r
1350                                         traceQUEUE_RECEIVE_FAILED( pxQueue );\r
1351                                         return errQUEUE_EMPTY;\r
1352                                 }\r
1353                                 else if( xEntryTimeSet == pdFALSE )\r
1354                                 {\r
1355                                         /* The queue was empty and a block time was specified so\r
1356                                         configure the timeout structure. */\r
1357                                         vTaskInternalSetTimeOutState( &xTimeOut );\r
1358                                         xEntryTimeSet = pdTRUE;\r
1359                                 }\r
1360                                 else\r
1361                                 {\r
1362                                         /* Entry time was already set. */\r
1363                                         mtCOVERAGE_TEST_MARKER();\r
1364                                 }\r
1365                         }\r
1366                 }\r
1367                 taskEXIT_CRITICAL();\r
1368 \r
1369                 /* Interrupts and other tasks can send to and receive from the queue\r
1370                 now the critical section has been exited. */\r
1371 \r
1372                 vTaskSuspendAll();\r
1373                 prvLockQueue( pxQueue );\r
1374 \r
1375                 /* Update the timeout state to see if it has expired yet. */\r
1376                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
1377                 {\r
1378                         /* The timeout has not expired.  If the queue is still empty place\r
1379                         the task on the list of tasks waiting to receive from the queue. */\r
1380                         if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
1381                         {\r
1382                                 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );\r
1383                                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
1384                                 prvUnlockQueue( pxQueue );\r
1385                                 if( xTaskResumeAll() == pdFALSE )\r
1386                                 {\r
1387                                         portYIELD_WITHIN_API();\r
1388                                 }\r
1389                                 else\r
1390                                 {\r
1391                                         mtCOVERAGE_TEST_MARKER();\r
1392                                 }\r
1393                         }\r
1394                         else\r
1395                         {\r
1396                                 /* The queue contains data again.  Loop back to try and read the\r
1397                                 data. */\r
1398                                 prvUnlockQueue( pxQueue );\r
1399                                 ( void ) xTaskResumeAll();\r
1400                         }\r
1401                 }\r
1402                 else\r
1403                 {\r
1404                         /* Timed out.  If there is no data in the queue exit, otherwise loop\r
1405                         back and attempt to read the data. */\r
1406                         prvUnlockQueue( pxQueue );\r
1407                         ( void ) xTaskResumeAll();\r
1408 \r
1409                         if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
1410                         {\r
1411                                 traceQUEUE_RECEIVE_FAILED( pxQueue );\r
1412                                 return errQUEUE_EMPTY;\r
1413                         }\r
1414                         else\r
1415                         {\r
1416                                 mtCOVERAGE_TEST_MARKER();\r
1417                         }\r
1418                 }\r
1419         }\r
1420 }\r
1421 /*-----------------------------------------------------------*/\r
1422 \r
1423 BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait )\r
1424 {\r
1425 BaseType_t xEntryTimeSet = pdFALSE;\r
1426 TimeOut_t xTimeOut;\r
1427 Queue_t * const pxQueue = ( Queue_t * ) xQueue;\r
1428 \r
1429 #if( configUSE_MUTEXES == 1 )\r
1430         BaseType_t xInheritanceOccurred = pdFALSE;\r
1431 #endif\r
1432 \r
1433         /* Check the queue pointer is not NULL. */\r
1434         configASSERT( ( pxQueue ) );\r
1435 \r
1436         /* Check this really is a semaphore, in which case the item size will be\r
1437         0. */\r
1438         configASSERT( pxQueue->uxItemSize == 0 );\r
1439 \r
1440         /* Cannot block if the scheduler is suspended. */\r
1441         #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )\r
1442         {\r
1443                 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );\r
1444         }\r
1445         #endif\r
1446 \r
1447 \r
1448         /* This function relaxes the coding standard somewhat to allow return\r
1449         statements within the function itself.  This is done in the interest\r
1450         of execution time efficiency. */\r
1451 \r
1452         for( ;; )\r
1453         {\r
1454                 taskENTER_CRITICAL();\r
1455                 {\r
1456                         /* Semaphores are queues with an item size of 0, and where the\r
1457                         number of messages in the queue is the semaphore's count value. */\r
1458                         const UBaseType_t uxSemaphoreCount = pxQueue->uxMessagesWaiting;\r
1459 \r
1460                         /* Is there data in the queue now?  To be running the calling task\r
1461                         must be the highest priority task wanting to access the queue. */\r
1462                         if( uxSemaphoreCount > ( UBaseType_t ) 0 )\r
1463                         {\r
1464                                 traceQUEUE_RECEIVE( pxQueue );\r
1465 \r
1466                                 /* Semaphores are queues with a data size of zero and where the\r
1467                                 messages waiting is the semaphore's count.  Reduce the count. */\r
1468                                 pxQueue->uxMessagesWaiting = uxSemaphoreCount - ( UBaseType_t ) 1;\r
1469 \r
1470                                 #if ( configUSE_MUTEXES == 1 )\r
1471                                 {\r
1472                                         if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
1473                                         {\r
1474                                                 /* Record the information required to implement\r
1475                                                 priority inheritance should it become necessary. */\r
1476                                                 pxQueue->pxMutexHolder = ( int8_t * ) pvTaskIncrementMutexHeldCount(); /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */\r
1477                                         }\r
1478                                         else\r
1479                                         {\r
1480                                                 mtCOVERAGE_TEST_MARKER();\r
1481                                         }\r
1482                                 }\r
1483                                 #endif /* configUSE_MUTEXES */\r
1484 \r
1485                                 /* Check to see if other tasks are blocked waiting to give the\r
1486                                 semaphore, and if so, unblock the highest priority such task. */\r
1487                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
1488                                 {\r
1489                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
1490                                         {\r
1491                                                 queueYIELD_IF_USING_PREEMPTION();\r
1492                                         }\r
1493                                         else\r
1494                                         {\r
1495                                                 mtCOVERAGE_TEST_MARKER();\r
1496                                         }\r
1497                                 }\r
1498                                 else\r
1499                                 {\r
1500                                         mtCOVERAGE_TEST_MARKER();\r
1501                                 }\r
1502 \r
1503                                 taskEXIT_CRITICAL();\r
1504                                 return pdPASS;\r
1505                         }\r
1506                         else\r
1507                         {\r
1508                                 if( xTicksToWait == ( TickType_t ) 0 )\r
1509                                 {\r
1510                                         /* For inheritance to have occurred there must have been an\r
1511                                         initial timeout, and an adjusted timeout cannot become 0, as\r
1512                                         if it were 0 the function would have exited. */\r
1513                                         #if( configUSE_MUTEXES == 1 )\r
1514                                         {\r
1515                                                 configASSERT( xInheritanceOccurred == pdFALSE );\r
1516                                         }\r
1517                                         #endif /* configUSE_MUTEXES */\r
1518 \r
1519                                         /* The semaphore count was 0 and no block time is specified\r
1520                                         (or the block time has expired) so exit now. */\r
1521                                         taskEXIT_CRITICAL();\r
1522                                         traceQUEUE_RECEIVE_FAILED( pxQueue );\r
1523                                         return errQUEUE_EMPTY;\r
1524                                 }\r
1525                                 else if( xEntryTimeSet == pdFALSE )\r
1526                                 {\r
1527                                         /* The semaphore count was 0 and a block time was specified\r
1528                                         so configure the timeout structure ready to block. */\r
1529                                         vTaskInternalSetTimeOutState( &xTimeOut );\r
1530                                         xEntryTimeSet = pdTRUE;\r
1531                                 }\r
1532                                 else\r
1533                                 {\r
1534                                         /* Entry time was already set. */\r
1535                                         mtCOVERAGE_TEST_MARKER();\r
1536                                 }\r
1537                         }\r
1538                 }\r
1539                 taskEXIT_CRITICAL();\r
1540 \r
1541                 /* Interrupts and other tasks can give to and take from the semaphore\r
1542                 now the critical section has been exited. */\r
1543 \r
1544                 vTaskSuspendAll();\r
1545                 prvLockQueue( pxQueue );\r
1546 \r
1547                 /* Update the timeout state to see if it has expired yet. */\r
1548                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
1549                 {\r
1550                         /* A block time is specified and not expired.  If the semaphore\r
1551                         count is 0 then enter the Blocked state to wait for a semaphore to\r
1552                         become available.  As semaphores are implemented with queues the\r
1553                         queue being empty is equivalent to the semaphore count being 0. */\r
1554                         if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
1555                         {\r
1556                                 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );\r
1557 \r
1558                                 #if ( configUSE_MUTEXES == 1 )\r
1559                                 {\r
1560                                         if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
1561                                         {\r
1562                                                 taskENTER_CRITICAL();\r
1563                                                 {\r
1564                                                         xInheritanceOccurred = xTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );\r
1565                                                 }\r
1566                                                 taskEXIT_CRITICAL();\r
1567                                         }\r
1568                                         else\r
1569                                         {\r
1570                                                 mtCOVERAGE_TEST_MARKER();\r
1571                                         }\r
1572                                 }\r
1573                                 #endif\r
1574 \r
1575                                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
1576                                 prvUnlockQueue( pxQueue );\r
1577                                 if( xTaskResumeAll() == pdFALSE )\r
1578                                 {\r
1579                                         portYIELD_WITHIN_API();\r
1580                                 }\r
1581                                 else\r
1582                                 {\r
1583                                         mtCOVERAGE_TEST_MARKER();\r
1584                                 }\r
1585                         }\r
1586                         else\r
1587                         {\r
1588                                 /* There was no timeout and the semaphore count was not 0, so\r
1589                                 attempt to take the semaphore again. */\r
1590                                 prvUnlockQueue( pxQueue );\r
1591                                 ( void ) xTaskResumeAll();\r
1592                         }\r
1593                 }\r
1594                 else\r
1595                 {\r
1596                         /* Timed out. */\r
1597                         prvUnlockQueue( pxQueue );\r
1598                         ( void ) xTaskResumeAll();\r
1599 \r
1600                         /* If the semaphore count is 0 exit now as the timeout has\r
1601                         expired.  Otherwise return to attempt to take the semaphore that is\r
1602                         known to be available.  As semaphores are implemented by queues the\r
1603                         queue being empty is equivalent to the semaphore count being 0. */\r
1604                         if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
1605                         {\r
1606                                 #if ( configUSE_MUTEXES == 1 )\r
1607                                 {\r
1608                                         /* xInheritanceOccurred could only have be set if\r
1609                                         pxQueue->uxQueueType == queueQUEUE_IS_MUTEX so no need to\r
1610                                         test the mutex type again to check it is actually a mutex. */\r
1611                                         if( xInheritanceOccurred != pdFALSE )\r
1612                                         {\r
1613                                                 taskENTER_CRITICAL();\r
1614                                                 {\r
1615                                                         UBaseType_t uxHighestWaitingPriority;\r
1616 \r
1617                                                         /* This task blocking on the mutex caused another\r
1618                                                         task to inherit this task's priority.  Now this task\r
1619                                                         has timed out the priority should be disinherited\r
1620                                                         again, but only as low as the next highest priority\r
1621                                                         task that is waiting for the same mutex. */\r
1622                                                         uxHighestWaitingPriority = prvGetDisinheritPriorityAfterTimeout( pxQueue );\r
1623                                                         vTaskPriorityDisinheritAfterTimeout( ( void * ) pxQueue->pxMutexHolder, uxHighestWaitingPriority );\r
1624                                                 }\r
1625                                                 taskEXIT_CRITICAL();\r
1626                                         }\r
1627                                 }\r
1628                                 #endif /* configUSE_MUTEXES */\r
1629 \r
1630                                 traceQUEUE_RECEIVE_FAILED( pxQueue );\r
1631                                 return errQUEUE_EMPTY;\r
1632                         }\r
1633                         else\r
1634                         {\r
1635                                 mtCOVERAGE_TEST_MARKER();\r
1636                         }\r
1637                 }\r
1638         }\r
1639 }\r
1640 /*-----------------------------------------------------------*/\r
1641 \r
1642 BaseType_t xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait )\r
1643 {\r
1644 BaseType_t xEntryTimeSet = pdFALSE;\r
1645 TimeOut_t xTimeOut;\r
1646 int8_t *pcOriginalReadPosition;\r
1647 Queue_t * const pxQueue = ( Queue_t * ) xQueue;\r
1648 \r
1649         /* Check the pointer is not NULL. */\r
1650         configASSERT( ( pxQueue ) );\r
1651 \r
1652         /* The buffer into which data is received can only be NULL if the data size\r
1653         is zero (so no data is copied into the buffer. */\r
1654         configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) );\r
1655 \r
1656         /* Cannot block if the scheduler is suspended. */\r
1657         #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )\r
1658         {\r
1659                 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );\r
1660         }\r
1661         #endif\r
1662 \r
1663 \r
1664         /* This function relaxes the coding standard somewhat to allow return\r
1665         statements within the function itself.  This is done in the interest\r
1666         of execution time efficiency. */\r
1667 \r
1668         for( ;; )\r
1669         {\r
1670                 taskENTER_CRITICAL();\r
1671                 {\r
1672                         const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;\r
1673 \r
1674                         /* Is there data in the queue now?  To be running the calling task\r
1675                         must be the highest priority task wanting to access the queue. */\r
1676                         if( uxMessagesWaiting > ( UBaseType_t ) 0 )\r
1677                         {\r
1678                                 /* Remember the read position so it can be reset after the data\r
1679                                 is read from the queue as this function is only peeking the\r
1680                                 data, not removing it. */\r
1681                                 pcOriginalReadPosition = pxQueue->u.pcReadFrom;\r
1682 \r
1683                                 prvCopyDataFromQueue( pxQueue, pvBuffer );\r
1684                                 traceQUEUE_PEEK( pxQueue );\r
1685 \r
1686                                 /* The data is not being removed, so reset the read pointer. */\r
1687                                 pxQueue->u.pcReadFrom = pcOriginalReadPosition;\r
1688 \r
1689                                 /* The data is being left in the queue, so see if there are\r
1690                                 any other tasks waiting for the data. */\r
1691                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
1692                                 {\r
1693                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
1694                                         {\r
1695                                                 /* The task waiting has a higher priority than this task. */\r
1696                                                 queueYIELD_IF_USING_PREEMPTION();\r
1697                                         }\r
1698                                         else\r
1699                                         {\r
1700                                                 mtCOVERAGE_TEST_MARKER();\r
1701                                         }\r
1702                                 }\r
1703                                 else\r
1704                                 {\r
1705                                         mtCOVERAGE_TEST_MARKER();\r
1706                                 }\r
1707 \r
1708                                 taskEXIT_CRITICAL();\r
1709                                 return pdPASS;\r
1710                         }\r
1711                         else\r
1712                         {\r
1713                                 if( xTicksToWait == ( TickType_t ) 0 )\r
1714                                 {\r
1715                                         /* The queue was empty and no block time is specified (or\r
1716                                         the block time has expired) so leave now. */\r
1717                                         taskEXIT_CRITICAL();\r
1718                                         traceQUEUE_RECEIVE_FAILED( pxQueue );\r
1719                                         return errQUEUE_EMPTY;\r
1720                                 }\r
1721                                 else if( xEntryTimeSet == pdFALSE )\r
1722                                 {\r
1723                                         /* The queue was empty and a block time was specified so\r
1724                                         configure the timeout structure ready to enter the blocked\r
1725                                         state. */\r
1726                                         vTaskInternalSetTimeOutState( &xTimeOut );\r
1727                                         xEntryTimeSet = pdTRUE;\r
1728                                 }\r
1729                                 else\r
1730                                 {\r
1731                                         /* Entry time was already set. */\r
1732                                         mtCOVERAGE_TEST_MARKER();\r
1733                                 }\r
1734                         }\r
1735                 }\r
1736                 taskEXIT_CRITICAL();\r
1737 \r
1738                 /* Interrupts and other tasks can send to and receive from the queue\r
1739                 now the critical section has been exited. */\r
1740 \r
1741                 vTaskSuspendAll();\r
1742                 prvLockQueue( pxQueue );\r
1743 \r
1744                 /* Update the timeout state to see if it has expired yet. */\r
1745                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )\r
1746                 {\r
1747                         /* Timeout has not expired yet, check to see if there is data in the\r
1748                         queue now, and if not enter the Blocked state to wait for data. */\r
1749                         if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
1750                         {\r
1751                                 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );\r
1752                                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );\r
1753                                 prvUnlockQueue( pxQueue );\r
1754                                 if( xTaskResumeAll() == pdFALSE )\r
1755                                 {\r
1756                                         portYIELD_WITHIN_API();\r
1757                                 }\r
1758                                 else\r
1759                                 {\r
1760                                         mtCOVERAGE_TEST_MARKER();\r
1761                                 }\r
1762                         }\r
1763                         else\r
1764                         {\r
1765                                 /* There is data in the queue now, so don't enter the blocked\r
1766                                 state, instead return to try and obtain the data. */\r
1767                                 prvUnlockQueue( pxQueue );\r
1768                                 ( void ) xTaskResumeAll();\r
1769                         }\r
1770                 }\r
1771                 else\r
1772                 {\r
1773                         /* The timeout has expired.  If there is still no data in the queue\r
1774                         exit, otherwise go back and try to read the data again. */\r
1775                         prvUnlockQueue( pxQueue );\r
1776                         ( void ) xTaskResumeAll();\r
1777 \r
1778                         if( prvIsQueueEmpty( pxQueue ) != pdFALSE )\r
1779                         {\r
1780                                 traceQUEUE_RECEIVE_FAILED( pxQueue );\r
1781                                 return errQUEUE_EMPTY;\r
1782                         }\r
1783                         else\r
1784                         {\r
1785                                 mtCOVERAGE_TEST_MARKER();\r
1786                         }\r
1787                 }\r
1788         }\r
1789 }\r
1790 /*-----------------------------------------------------------*/\r
1791 \r
1792 BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken )\r
1793 {\r
1794 BaseType_t xReturn;\r
1795 UBaseType_t uxSavedInterruptStatus;\r
1796 Queue_t * const pxQueue = ( Queue_t * ) xQueue;\r
1797 \r
1798         configASSERT( pxQueue );\r
1799         configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );\r
1800 \r
1801         /* RTOS ports that support interrupt nesting have the concept of a maximum\r
1802         system call (or maximum API call) interrupt priority.  Interrupts that are\r
1803         above the maximum system call priority are kept permanently enabled, even\r
1804         when the RTOS kernel is in a critical section, but cannot make any calls to\r
1805         FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h\r
1806         then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
1807         failure if a FreeRTOS API function is called from an interrupt that has been\r
1808         assigned a priority above the configured maximum system call priority.\r
1809         Only FreeRTOS functions that end in FromISR can be called from interrupts\r
1810         that have been assigned a priority at or (logically) below the maximum\r
1811         system call     interrupt priority.  FreeRTOS maintains a separate interrupt\r
1812         safe API to ensure interrupt entry is as fast and as simple as possible.\r
1813         More information (albeit Cortex-M specific) is provided on the following\r
1814         link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
1815         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
1816 \r
1817         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
1818         {\r
1819                 const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;\r
1820 \r
1821                 /* Cannot block in an ISR, so check there is data available. */\r
1822                 if( uxMessagesWaiting > ( UBaseType_t ) 0 )\r
1823                 {\r
1824                         const int8_t cRxLock = pxQueue->cRxLock;\r
1825 \r
1826                         traceQUEUE_RECEIVE_FROM_ISR( pxQueue );\r
1827 \r
1828                         prvCopyDataFromQueue( pxQueue, pvBuffer );\r
1829                         pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1;\r
1830 \r
1831                         /* If the queue is locked the event list will not be modified.\r
1832                         Instead update the lock count so the task that unlocks the queue\r
1833                         will know that an ISR has removed data while the queue was\r
1834                         locked. */\r
1835                         if( cRxLock == queueUNLOCKED )\r
1836                         {\r
1837                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
1838                                 {\r
1839                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
1840                                         {\r
1841                                                 /* The task waiting has a higher priority than us so\r
1842                                                 force a context switch. */\r
1843                                                 if( pxHigherPriorityTaskWoken != NULL )\r
1844                                                 {\r
1845                                                         *pxHigherPriorityTaskWoken = pdTRUE;\r
1846                                                 }\r
1847                                                 else\r
1848                                                 {\r
1849                                                         mtCOVERAGE_TEST_MARKER();\r
1850                                                 }\r
1851                                         }\r
1852                                         else\r
1853                                         {\r
1854                                                 mtCOVERAGE_TEST_MARKER();\r
1855                                         }\r
1856                                 }\r
1857                                 else\r
1858                                 {\r
1859                                         mtCOVERAGE_TEST_MARKER();\r
1860                                 }\r
1861                         }\r
1862                         else\r
1863                         {\r
1864                                 /* Increment the lock count so the task that unlocks the queue\r
1865                                 knows that data was removed while it was locked. */\r
1866                                 pxQueue->cRxLock = ( int8_t ) ( cRxLock + 1 );\r
1867                         }\r
1868 \r
1869                         xReturn = pdPASS;\r
1870                 }\r
1871                 else\r
1872                 {\r
1873                         xReturn = pdFAIL;\r
1874                         traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );\r
1875                 }\r
1876         }\r
1877         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
1878 \r
1879         return xReturn;\r
1880 }\r
1881 /*-----------------------------------------------------------*/\r
1882 \r
1883 BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue,  void * const pvBuffer )\r
1884 {\r
1885 BaseType_t xReturn;\r
1886 UBaseType_t uxSavedInterruptStatus;\r
1887 int8_t *pcOriginalReadPosition;\r
1888 Queue_t * const pxQueue = ( Queue_t * ) xQueue;\r
1889 \r
1890         configASSERT( pxQueue );\r
1891         configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );\r
1892         configASSERT( pxQueue->uxItemSize != 0 ); /* Can't peek a semaphore. */\r
1893 \r
1894         /* RTOS ports that support interrupt nesting have the concept of a maximum\r
1895         system call (or maximum API call) interrupt priority.  Interrupts that are\r
1896         above the maximum system call priority are kept permanently enabled, even\r
1897         when the RTOS kernel is in a critical section, but cannot make any calls to\r
1898         FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h\r
1899         then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
1900         failure if a FreeRTOS API function is called from an interrupt that has been\r
1901         assigned a priority above the configured maximum system call priority.\r
1902         Only FreeRTOS functions that end in FromISR can be called from interrupts\r
1903         that have been assigned a priority at or (logically) below the maximum\r
1904         system call     interrupt priority.  FreeRTOS maintains a separate interrupt\r
1905         safe API to ensure interrupt entry is as fast and as simple as possible.\r
1906         More information (albeit Cortex-M specific) is provided on the following\r
1907         link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
1908         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
1909 \r
1910         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
1911         {\r
1912                 /* Cannot block in an ISR, so check there is data available. */\r
1913                 if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )\r
1914                 {\r
1915                         traceQUEUE_PEEK_FROM_ISR( pxQueue );\r
1916 \r
1917                         /* Remember the read position so it can be reset as nothing is\r
1918                         actually being removed from the queue. */\r
1919                         pcOriginalReadPosition = pxQueue->u.pcReadFrom;\r
1920                         prvCopyDataFromQueue( pxQueue, pvBuffer );\r
1921                         pxQueue->u.pcReadFrom = pcOriginalReadPosition;\r
1922 \r
1923                         xReturn = pdPASS;\r
1924                 }\r
1925                 else\r
1926                 {\r
1927                         xReturn = pdFAIL;\r
1928                         traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue );\r
1929                 }\r
1930         }\r
1931         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
1932 \r
1933         return xReturn;\r
1934 }\r
1935 /*-----------------------------------------------------------*/\r
1936 \r
1937 UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue )\r
1938 {\r
1939 UBaseType_t uxReturn;\r
1940 \r
1941         configASSERT( xQueue );\r
1942 \r
1943         taskENTER_CRITICAL();\r
1944         {\r
1945                 uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting;\r
1946         }\r
1947         taskEXIT_CRITICAL();\r
1948 \r
1949         return uxReturn;\r
1950 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */\r
1951 /*-----------------------------------------------------------*/\r
1952 \r
1953 UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue )\r
1954 {\r
1955 UBaseType_t uxReturn;\r
1956 Queue_t *pxQueue;\r
1957 \r
1958         pxQueue = ( Queue_t * ) xQueue;\r
1959         configASSERT( pxQueue );\r
1960 \r
1961         taskENTER_CRITICAL();\r
1962         {\r
1963                 uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting;\r
1964         }\r
1965         taskEXIT_CRITICAL();\r
1966 \r
1967         return uxReturn;\r
1968 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */\r
1969 /*-----------------------------------------------------------*/\r
1970 \r
1971 UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue )\r
1972 {\r
1973 UBaseType_t uxReturn;\r
1974 \r
1975         configASSERT( xQueue );\r
1976 \r
1977         uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting;\r
1978 \r
1979         return uxReturn;\r
1980 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */\r
1981 /*-----------------------------------------------------------*/\r
1982 \r
1983 void vQueueDelete( QueueHandle_t xQueue )\r
1984 {\r
1985 Queue_t * const pxQueue = ( Queue_t * ) xQueue;\r
1986 \r
1987         configASSERT( pxQueue );\r
1988         traceQUEUE_DELETE( pxQueue );\r
1989 \r
1990         #if ( configQUEUE_REGISTRY_SIZE > 0 )\r
1991         {\r
1992                 vQueueUnregisterQueue( pxQueue );\r
1993         }\r
1994         #endif\r
1995 \r
1996         #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )\r
1997         {\r
1998                 /* The queue can only have been allocated dynamically - free it\r
1999                 again. */\r
2000                 vPortFree( pxQueue );\r
2001         }\r
2002         #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )\r
2003         {\r
2004                 /* The queue could have been allocated statically or dynamically, so\r
2005                 check before attempting to free the memory. */\r
2006                 if( pxQueue->ucStaticallyAllocated == ( uint8_t ) pdFALSE )\r
2007                 {\r
2008                         vPortFree( pxQueue );\r
2009                 }\r
2010                 else\r
2011                 {\r
2012                         mtCOVERAGE_TEST_MARKER();\r
2013                 }\r
2014         }\r
2015         #else\r
2016         {\r
2017                 /* The queue must have been statically allocated, so is not going to be\r
2018                 deleted.  Avoid compiler warnings about the unused parameter. */\r
2019                 ( void ) pxQueue;\r
2020         }\r
2021         #endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
2022 }\r
2023 /*-----------------------------------------------------------*/\r
2024 \r
2025 #if ( configUSE_TRACE_FACILITY == 1 )\r
2026 \r
2027         UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue )\r
2028         {\r
2029                 return ( ( Queue_t * ) xQueue )->uxQueueNumber;\r
2030         }\r
2031 \r
2032 #endif /* configUSE_TRACE_FACILITY */\r
2033 /*-----------------------------------------------------------*/\r
2034 \r
2035 #if ( configUSE_TRACE_FACILITY == 1 )\r
2036 \r
2037         void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber )\r
2038         {\r
2039                 ( ( Queue_t * ) xQueue )->uxQueueNumber = uxQueueNumber;\r
2040         }\r
2041 \r
2042 #endif /* configUSE_TRACE_FACILITY */\r
2043 /*-----------------------------------------------------------*/\r
2044 \r
2045 #if ( configUSE_TRACE_FACILITY == 1 )\r
2046 \r
2047         uint8_t ucQueueGetQueueType( QueueHandle_t xQueue )\r
2048         {\r
2049                 return ( ( Queue_t * ) xQueue )->ucQueueType;\r
2050         }\r
2051 \r
2052 #endif /* configUSE_TRACE_FACILITY */\r
2053 /*-----------------------------------------------------------*/\r
2054 \r
2055 #if( configUSE_MUTEXES == 1 )\r
2056 \r
2057         static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue )\r
2058         {\r
2059         UBaseType_t uxHighestPriorityOfWaitingTasks;\r
2060 \r
2061                 /* If a task waiting for a mutex causes the mutex holder to inherit a\r
2062                 priority, but the waiting task times out, then the holder should\r
2063                 disinherit the priority - but only down to the highest priority of any\r
2064                 other tasks that are waiting for the same mutex.  For this purpose,\r
2065                 return the priority of the highest priority task that is waiting for the\r
2066                 mutex. */\r
2067                 if( listCURRENT_LIST_LENGTH( &( pxQueue->xTasksWaitingToReceive ) ) > 0 )\r
2068                 {\r
2069                         uxHighestPriorityOfWaitingTasks = configMAX_PRIORITIES - listGET_ITEM_VALUE_OF_HEAD_ENTRY( &( pxQueue->xTasksWaitingToReceive ) );\r
2070                 }\r
2071                 else\r
2072                 {\r
2073                         uxHighestPriorityOfWaitingTasks = tskIDLE_PRIORITY;\r
2074                 }\r
2075 \r
2076                 return uxHighestPriorityOfWaitingTasks;\r
2077         }\r
2078 \r
2079 #endif /* configUSE_MUTEXES */\r
2080 /*-----------------------------------------------------------*/\r
2081 \r
2082 static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition )\r
2083 {\r
2084 BaseType_t xReturn = pdFALSE;\r
2085 UBaseType_t uxMessagesWaiting;\r
2086 \r
2087         /* This function is called from a critical section. */\r
2088 \r
2089         uxMessagesWaiting = pxQueue->uxMessagesWaiting;\r
2090 \r
2091         if( pxQueue->uxItemSize == ( UBaseType_t ) 0 )\r
2092         {\r
2093                 #if ( configUSE_MUTEXES == 1 )\r
2094                 {\r
2095                         if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )\r
2096                         {\r
2097                                 /* The mutex is no longer being held. */\r
2098                                 xReturn = xTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );\r
2099                                 pxQueue->pxMutexHolder = NULL;\r
2100                         }\r
2101                         else\r
2102                         {\r
2103                                 mtCOVERAGE_TEST_MARKER();\r
2104                         }\r
2105                 }\r
2106                 #endif /* configUSE_MUTEXES */\r
2107         }\r
2108         else if( xPosition == queueSEND_TO_BACK )\r
2109         {\r
2110                 ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. */\r
2111                 pxQueue->pcWriteTo += pxQueue->uxItemSize;\r
2112                 if( pxQueue->pcWriteTo >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */\r
2113                 {\r
2114                         pxQueue->pcWriteTo = pxQueue->pcHead;\r
2115                 }\r
2116                 else\r
2117                 {\r
2118                         mtCOVERAGE_TEST_MARKER();\r
2119                 }\r
2120         }\r
2121         else\r
2122         {\r
2123                 ( void ) memcpy( ( void * ) pxQueue->u.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
2124                 pxQueue->u.pcReadFrom -= pxQueue->uxItemSize;\r
2125                 if( pxQueue->u.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */\r
2126                 {\r
2127                         pxQueue->u.pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );\r
2128                 }\r
2129                 else\r
2130                 {\r
2131                         mtCOVERAGE_TEST_MARKER();\r
2132                 }\r
2133 \r
2134                 if( xPosition == queueOVERWRITE )\r
2135                 {\r
2136                         if( uxMessagesWaiting > ( UBaseType_t ) 0 )\r
2137                         {\r
2138                                 /* An item is not being added but overwritten, so subtract\r
2139                                 one from the recorded number of items in the queue so when\r
2140                                 one is added again below the number of recorded items remains\r
2141                                 correct. */\r
2142                                 --uxMessagesWaiting;\r
2143                         }\r
2144                         else\r
2145                         {\r
2146                                 mtCOVERAGE_TEST_MARKER();\r
2147                         }\r
2148                 }\r
2149                 else\r
2150                 {\r
2151                         mtCOVERAGE_TEST_MARKER();\r
2152                 }\r
2153         }\r
2154 \r
2155         pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1;\r
2156 \r
2157         return xReturn;\r
2158 }\r
2159 /*-----------------------------------------------------------*/\r
2160 \r
2161 static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer )\r
2162 {\r
2163         if( pxQueue->uxItemSize != ( UBaseType_t ) 0 )\r
2164         {\r
2165                 pxQueue->u.pcReadFrom += pxQueue->uxItemSize;\r
2166                 if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */\r
2167                 {\r
2168                         pxQueue->u.pcReadFrom = pxQueue->pcHead;\r
2169                 }\r
2170                 else\r
2171                 {\r
2172                         mtCOVERAGE_TEST_MARKER();\r
2173                 }\r
2174                 ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports.  Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. */\r
2175         }\r
2176 }\r
2177 /*-----------------------------------------------------------*/\r
2178 \r
2179 static void prvUnlockQueue( Queue_t * const pxQueue )\r
2180 {\r
2181         /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */\r
2182 \r
2183         /* The lock counts contains the number of extra data items placed or\r
2184         removed from the queue while the queue was locked.  When a queue is\r
2185         locked items can be added or removed, but the event lists cannot be\r
2186         updated. */\r
2187         taskENTER_CRITICAL();\r
2188         {\r
2189                 int8_t cTxLock = pxQueue->cTxLock;\r
2190 \r
2191                 /* See if data was added to the queue while it was locked. */\r
2192                 while( cTxLock > queueLOCKED_UNMODIFIED )\r
2193                 {\r
2194                         /* Data was posted while the queue was locked.  Are any tasks\r
2195                         blocked waiting for data to become available? */\r
2196                         #if ( configUSE_QUEUE_SETS == 1 )\r
2197                         {\r
2198                                 if( pxQueue->pxQueueSetContainer != NULL )\r
2199                                 {\r
2200                                         if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) != pdFALSE )\r
2201                                         {\r
2202                                                 /* The queue is a member of a queue set, and posting to\r
2203                                                 the queue set caused a higher priority task to unblock.\r
2204                                                 A context switch is required. */\r
2205                                                 vTaskMissedYield();\r
2206                                         }\r
2207                                         else\r
2208                                         {\r
2209                                                 mtCOVERAGE_TEST_MARKER();\r
2210                                         }\r
2211                                 }\r
2212                                 else\r
2213                                 {\r
2214                                         /* Tasks that are removed from the event list will get\r
2215                                         added to the pending ready list as the scheduler is still\r
2216                                         suspended. */\r
2217                                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
2218                                         {\r
2219                                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
2220                                                 {\r
2221                                                         /* The task waiting has a higher priority so record that a\r
2222                                                         context switch is required. */\r
2223                                                         vTaskMissedYield();\r
2224                                                 }\r
2225                                                 else\r
2226                                                 {\r
2227                                                         mtCOVERAGE_TEST_MARKER();\r
2228                                                 }\r
2229                                         }\r
2230                                         else\r
2231                                         {\r
2232                                                 break;\r
2233                                         }\r
2234                                 }\r
2235                         }\r
2236                         #else /* configUSE_QUEUE_SETS */\r
2237                         {\r
2238                                 /* Tasks that are removed from the event list will get added to\r
2239                                 the pending ready list as the scheduler is still suspended. */\r
2240                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
2241                                 {\r
2242                                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
2243                                         {\r
2244                                                 /* The task waiting has a higher priority so record that\r
2245                                                 a context switch is required. */\r
2246                                                 vTaskMissedYield();\r
2247                                         }\r
2248                                         else\r
2249                                         {\r
2250                                                 mtCOVERAGE_TEST_MARKER();\r
2251                                         }\r
2252                                 }\r
2253                                 else\r
2254                                 {\r
2255                                         break;\r
2256                                 }\r
2257                         }\r
2258                         #endif /* configUSE_QUEUE_SETS */\r
2259 \r
2260                         --cTxLock;\r
2261                 }\r
2262 \r
2263                 pxQueue->cTxLock = queueUNLOCKED;\r
2264         }\r
2265         taskEXIT_CRITICAL();\r
2266 \r
2267         /* Do the same for the Rx lock. */\r
2268         taskENTER_CRITICAL();\r
2269         {\r
2270                 int8_t cRxLock = pxQueue->cRxLock;\r
2271 \r
2272                 while( cRxLock > queueLOCKED_UNMODIFIED )\r
2273                 {\r
2274                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
2275                         {\r
2276                                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
2277                                 {\r
2278                                         vTaskMissedYield();\r
2279                                 }\r
2280                                 else\r
2281                                 {\r
2282                                         mtCOVERAGE_TEST_MARKER();\r
2283                                 }\r
2284 \r
2285                                 --cRxLock;\r
2286                         }\r
2287                         else\r
2288                         {\r
2289                                 break;\r
2290                         }\r
2291                 }\r
2292 \r
2293                 pxQueue->cRxLock = queueUNLOCKED;\r
2294         }\r
2295         taskEXIT_CRITICAL();\r
2296 }\r
2297 /*-----------------------------------------------------------*/\r
2298 \r
2299 static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue )\r
2300 {\r
2301 BaseType_t xReturn;\r
2302 \r
2303         taskENTER_CRITICAL();\r
2304         {\r
2305                 if( pxQueue->uxMessagesWaiting == ( UBaseType_t )  0 )\r
2306                 {\r
2307                         xReturn = pdTRUE;\r
2308                 }\r
2309                 else\r
2310                 {\r
2311                         xReturn = pdFALSE;\r
2312                 }\r
2313         }\r
2314         taskEXIT_CRITICAL();\r
2315 \r
2316         return xReturn;\r
2317 }\r
2318 /*-----------------------------------------------------------*/\r
2319 \r
2320 BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue )\r
2321 {\r
2322 BaseType_t xReturn;\r
2323 \r
2324         configASSERT( xQueue );\r
2325         if( ( ( Queue_t * ) xQueue )->uxMessagesWaiting == ( UBaseType_t ) 0 )\r
2326         {\r
2327                 xReturn = pdTRUE;\r
2328         }\r
2329         else\r
2330         {\r
2331                 xReturn = pdFALSE;\r
2332         }\r
2333 \r
2334         return xReturn;\r
2335 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */\r
2336 /*-----------------------------------------------------------*/\r
2337 \r
2338 static BaseType_t prvIsQueueFull( const Queue_t *pxQueue )\r
2339 {\r
2340 BaseType_t xReturn;\r
2341 \r
2342         taskENTER_CRITICAL();\r
2343         {\r
2344                 if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )\r
2345                 {\r
2346                         xReturn = pdTRUE;\r
2347                 }\r
2348                 else\r
2349                 {\r
2350                         xReturn = pdFALSE;\r
2351                 }\r
2352         }\r
2353         taskEXIT_CRITICAL();\r
2354 \r
2355         return xReturn;\r
2356 }\r
2357 /*-----------------------------------------------------------*/\r
2358 \r
2359 BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue )\r
2360 {\r
2361 BaseType_t xReturn;\r
2362 \r
2363         configASSERT( xQueue );\r
2364         if( ( ( Queue_t * ) xQueue )->uxMessagesWaiting == ( ( Queue_t * ) xQueue )->uxLength )\r
2365         {\r
2366                 xReturn = pdTRUE;\r
2367         }\r
2368         else\r
2369         {\r
2370                 xReturn = pdFALSE;\r
2371         }\r
2372 \r
2373         return xReturn;\r
2374 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */\r
2375 /*-----------------------------------------------------------*/\r
2376 \r
2377 #if ( configUSE_CO_ROUTINES == 1 )\r
2378 \r
2379         BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait )\r
2380         {\r
2381         BaseType_t xReturn;\r
2382         Queue_t * const pxQueue = ( Queue_t * ) xQueue;\r
2383 \r
2384                 /* If the queue is already full we may have to block.  A critical section\r
2385                 is required to prevent an interrupt removing something from the queue\r
2386                 between the check to see if the queue is full and blocking on the queue. */\r
2387                 portDISABLE_INTERRUPTS();\r
2388                 {\r
2389                         if( prvIsQueueFull( pxQueue ) != pdFALSE )\r
2390                         {\r
2391                                 /* The queue is full - do we want to block or just leave without\r
2392                                 posting? */\r
2393                                 if( xTicksToWait > ( TickType_t ) 0 )\r
2394                                 {\r
2395                                         /* As this is called from a coroutine we cannot block directly, but\r
2396                                         return indicating that we need to block. */\r
2397                                         vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );\r
2398                                         portENABLE_INTERRUPTS();\r
2399                                         return errQUEUE_BLOCKED;\r
2400                                 }\r
2401                                 else\r
2402                                 {\r
2403                                         portENABLE_INTERRUPTS();\r
2404                                         return errQUEUE_FULL;\r
2405                                 }\r
2406                         }\r
2407                 }\r
2408                 portENABLE_INTERRUPTS();\r
2409 \r
2410                 portDISABLE_INTERRUPTS();\r
2411                 {\r
2412                         if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
2413                         {\r
2414                                 /* There is room in the queue, copy the data into the queue. */\r
2415                                 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );\r
2416                                 xReturn = pdPASS;\r
2417 \r
2418                                 /* Were any co-routines waiting for data to become available? */\r
2419                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
2420                                 {\r
2421                                         /* In this instance the co-routine could be placed directly\r
2422                                         into the ready list as we are within a critical section.\r
2423                                         Instead the same pending ready list mechanism is used as if\r
2424                                         the event were caused from within an interrupt. */\r
2425                                         if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
2426                                         {\r
2427                                                 /* The co-routine waiting has a higher priority so record\r
2428                                                 that a yield might be appropriate. */\r
2429                                                 xReturn = errQUEUE_YIELD;\r
2430                                         }\r
2431                                         else\r
2432                                         {\r
2433                                                 mtCOVERAGE_TEST_MARKER();\r
2434                                         }\r
2435                                 }\r
2436                                 else\r
2437                                 {\r
2438                                         mtCOVERAGE_TEST_MARKER();\r
2439                                 }\r
2440                         }\r
2441                         else\r
2442                         {\r
2443                                 xReturn = errQUEUE_FULL;\r
2444                         }\r
2445                 }\r
2446                 portENABLE_INTERRUPTS();\r
2447 \r
2448                 return xReturn;\r
2449         }\r
2450 \r
2451 #endif /* configUSE_CO_ROUTINES */\r
2452 /*-----------------------------------------------------------*/\r
2453 \r
2454 #if ( configUSE_CO_ROUTINES == 1 )\r
2455 \r
2456         BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait )\r
2457         {\r
2458         BaseType_t xReturn;\r
2459         Queue_t * const pxQueue = ( Queue_t * ) xQueue;\r
2460 \r
2461                 /* If the queue is already empty we may have to block.  A critical section\r
2462                 is required to prevent an interrupt adding something to the queue\r
2463                 between the check to see if the queue is empty and blocking on the queue. */\r
2464                 portDISABLE_INTERRUPTS();\r
2465                 {\r
2466                         if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 )\r
2467                         {\r
2468                                 /* There are no messages in the queue, do we want to block or just\r
2469                                 leave with nothing? */\r
2470                                 if( xTicksToWait > ( TickType_t ) 0 )\r
2471                                 {\r
2472                                         /* As this is a co-routine we cannot block directly, but return\r
2473                                         indicating that we need to block. */\r
2474                                         vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );\r
2475                                         portENABLE_INTERRUPTS();\r
2476                                         return errQUEUE_BLOCKED;\r
2477                                 }\r
2478                                 else\r
2479                                 {\r
2480                                         portENABLE_INTERRUPTS();\r
2481                                         return errQUEUE_FULL;\r
2482                                 }\r
2483                         }\r
2484                         else\r
2485                         {\r
2486                                 mtCOVERAGE_TEST_MARKER();\r
2487                         }\r
2488                 }\r
2489                 portENABLE_INTERRUPTS();\r
2490 \r
2491                 portDISABLE_INTERRUPTS();\r
2492                 {\r
2493                         if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )\r
2494                         {\r
2495                                 /* Data is available from the queue. */\r
2496                                 pxQueue->u.pcReadFrom += pxQueue->uxItemSize;\r
2497                                 if( pxQueue->u.pcReadFrom >= pxQueue->pcTail )\r
2498                                 {\r
2499                                         pxQueue->u.pcReadFrom = pxQueue->pcHead;\r
2500                                 }\r
2501                                 else\r
2502                                 {\r
2503                                         mtCOVERAGE_TEST_MARKER();\r
2504                                 }\r
2505                                 --( pxQueue->uxMessagesWaiting );\r
2506                                 ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
2507 \r
2508                                 xReturn = pdPASS;\r
2509 \r
2510                                 /* Were any co-routines waiting for space to become available? */\r
2511                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
2512                                 {\r
2513                                         /* In this instance the co-routine could be placed directly\r
2514                                         into the ready list as we are within a critical section.\r
2515                                         Instead the same pending ready list mechanism is used as if\r
2516                                         the event were caused from within an interrupt. */\r
2517                                         if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
2518                                         {\r
2519                                                 xReturn = errQUEUE_YIELD;\r
2520                                         }\r
2521                                         else\r
2522                                         {\r
2523                                                 mtCOVERAGE_TEST_MARKER();\r
2524                                         }\r
2525                                 }\r
2526                                 else\r
2527                                 {\r
2528                                         mtCOVERAGE_TEST_MARKER();\r
2529                                 }\r
2530                         }\r
2531                         else\r
2532                         {\r
2533                                 xReturn = pdFAIL;\r
2534                         }\r
2535                 }\r
2536                 portENABLE_INTERRUPTS();\r
2537 \r
2538                 return xReturn;\r
2539         }\r
2540 \r
2541 #endif /* configUSE_CO_ROUTINES */\r
2542 /*-----------------------------------------------------------*/\r
2543 \r
2544 #if ( configUSE_CO_ROUTINES == 1 )\r
2545 \r
2546         BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken )\r
2547         {\r
2548         Queue_t * const pxQueue = ( Queue_t * ) xQueue;\r
2549 \r
2550                 /* Cannot block within an ISR so if there is no space on the queue then\r
2551                 exit without doing anything. */\r
2552                 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )\r
2553                 {\r
2554                         prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );\r
2555 \r
2556                         /* We only want to wake one co-routine per ISR, so check that a\r
2557                         co-routine has not already been woken. */\r
2558                         if( xCoRoutinePreviouslyWoken == pdFALSE )\r
2559                         {\r
2560                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )\r
2561                                 {\r
2562                                         if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )\r
2563                                         {\r
2564                                                 return pdTRUE;\r
2565                                         }\r
2566                                         else\r
2567                                         {\r
2568                                                 mtCOVERAGE_TEST_MARKER();\r
2569                                         }\r
2570                                 }\r
2571                                 else\r
2572                                 {\r
2573                                         mtCOVERAGE_TEST_MARKER();\r
2574                                 }\r
2575                         }\r
2576                         else\r
2577                         {\r
2578                                 mtCOVERAGE_TEST_MARKER();\r
2579                         }\r
2580                 }\r
2581                 else\r
2582                 {\r
2583                         mtCOVERAGE_TEST_MARKER();\r
2584                 }\r
2585 \r
2586                 return xCoRoutinePreviouslyWoken;\r
2587         }\r
2588 \r
2589 #endif /* configUSE_CO_ROUTINES */\r
2590 /*-----------------------------------------------------------*/\r
2591 \r
2592 #if ( configUSE_CO_ROUTINES == 1 )\r
2593 \r
2594         BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxCoRoutineWoken )\r
2595         {\r
2596         BaseType_t xReturn;\r
2597         Queue_t * const pxQueue = ( Queue_t * ) xQueue;\r
2598 \r
2599                 /* We cannot block from an ISR, so check there is data available. If\r
2600                 not then just leave without doing anything. */\r
2601                 if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 )\r
2602                 {\r
2603                         /* Copy the data from the queue. */\r
2604                         pxQueue->u.pcReadFrom += pxQueue->uxItemSize;\r
2605                         if( pxQueue->u.pcReadFrom >= pxQueue->pcTail )\r
2606                         {\r
2607                                 pxQueue->u.pcReadFrom = pxQueue->pcHead;\r
2608                         }\r
2609                         else\r
2610                         {\r
2611                                 mtCOVERAGE_TEST_MARKER();\r
2612                         }\r
2613                         --( pxQueue->uxMessagesWaiting );\r
2614                         ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );\r
2615 \r
2616                         if( ( *pxCoRoutineWoken ) == pdFALSE )\r
2617                         {\r
2618                                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )\r
2619                                 {\r
2620                                         if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )\r
2621                                         {\r
2622                                                 *pxCoRoutineWoken = pdTRUE;\r
2623                                         }\r
2624                                         else\r
2625                                         {\r
2626                                                 mtCOVERAGE_TEST_MARKER();\r
2627                                         }\r
2628                                 }\r
2629                                 else\r
2630                                 {\r
2631                                         mtCOVERAGE_TEST_MARKER();\r
2632                                 }\r
2633                         }\r
2634                         else\r
2635                         {\r
2636                                 mtCOVERAGE_TEST_MARKER();\r
2637                         }\r
2638 \r
2639                         xReturn = pdPASS;\r
2640                 }\r
2641                 else\r
2642                 {\r
2643                         xReturn = pdFAIL;\r
2644                 }\r
2645 \r
2646                 return xReturn;\r
2647         }\r
2648 \r
2649 #endif /* configUSE_CO_ROUTINES */\r
2650 /*-----------------------------------------------------------*/\r
2651 \r
2652 #if ( configQUEUE_REGISTRY_SIZE > 0 )\r
2653 \r
2654         void vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcQueueName ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
2655         {\r
2656         UBaseType_t ux;\r
2657 \r
2658                 /* See if there is an empty space in the registry.  A NULL name denotes\r
2659                 a free slot. */\r
2660                 for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ )\r
2661                 {\r
2662                         if( xQueueRegistry[ ux ].pcQueueName == NULL )\r
2663                         {\r
2664                                 /* Store the information on this queue. */\r
2665                                 xQueueRegistry[ ux ].pcQueueName = pcQueueName;\r
2666                                 xQueueRegistry[ ux ].xHandle = xQueue;\r
2667 \r
2668                                 traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName );\r
2669                                 break;\r
2670                         }\r
2671                         else\r
2672                         {\r
2673                                 mtCOVERAGE_TEST_MARKER();\r
2674                         }\r
2675                 }\r
2676         }\r
2677 \r
2678 #endif /* configQUEUE_REGISTRY_SIZE */\r
2679 /*-----------------------------------------------------------*/\r
2680 \r
2681 #if ( configQUEUE_REGISTRY_SIZE > 0 )\r
2682 \r
2683         const char *pcQueueGetName( QueueHandle_t xQueue ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
2684         {\r
2685         UBaseType_t ux;\r
2686         const char *pcReturn = NULL; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
2687 \r
2688                 /* Note there is nothing here to protect against another task adding or\r
2689                 removing entries from the registry while it is being searched. */\r
2690                 for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ )\r
2691                 {\r
2692                         if( xQueueRegistry[ ux ].xHandle == xQueue )\r
2693                         {\r
2694                                 pcReturn = xQueueRegistry[ ux ].pcQueueName;\r
2695                                 break;\r
2696                         }\r
2697                         else\r
2698                         {\r
2699                                 mtCOVERAGE_TEST_MARKER();\r
2700                         }\r
2701                 }\r
2702 \r
2703                 return pcReturn;\r
2704         } /*lint !e818 xQueue cannot be a pointer to const because it is a typedef. */\r
2705 \r
2706 #endif /* configQUEUE_REGISTRY_SIZE */\r
2707 /*-----------------------------------------------------------*/\r
2708 \r
2709 #if ( configQUEUE_REGISTRY_SIZE > 0 )\r
2710 \r
2711         void vQueueUnregisterQueue( QueueHandle_t xQueue )\r
2712         {\r
2713         UBaseType_t ux;\r
2714 \r
2715                 /* See if the handle of the queue being unregistered in actually in the\r
2716                 registry. */\r
2717                 for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ )\r
2718                 {\r
2719                         if( xQueueRegistry[ ux ].xHandle == xQueue )\r
2720                         {\r
2721                                 /* Set the name to NULL to show that this slot if free again. */\r
2722                                 xQueueRegistry[ ux ].pcQueueName = NULL;\r
2723 \r
2724                                 /* Set the handle to NULL to ensure the same queue handle cannot\r
2725                                 appear in the registry twice if it is added, removed, then\r
2726                                 added again. */\r
2727                                 xQueueRegistry[ ux ].xHandle = ( QueueHandle_t ) 0;\r
2728                                 break;\r
2729                         }\r
2730                         else\r
2731                         {\r
2732                                 mtCOVERAGE_TEST_MARKER();\r
2733                         }\r
2734                 }\r
2735 \r
2736         } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */\r
2737 \r
2738 #endif /* configQUEUE_REGISTRY_SIZE */\r
2739 /*-----------------------------------------------------------*/\r
2740 \r
2741 #if ( configUSE_TIMERS == 1 )\r
2742 \r
2743         void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely )\r
2744         {\r
2745         Queue_t * const pxQueue = ( Queue_t * ) xQueue;\r
2746 \r
2747                 /* This function should not be called by application code hence the\r
2748                 'Restricted' in its name.  It is not part of the public API.  It is\r
2749                 designed for use by kernel code, and has special calling requirements.\r
2750                 It can result in vListInsert() being called on a list that can only\r
2751                 possibly ever have one item in it, so the list will be fast, but even\r
2752                 so it should be called with the scheduler locked and not from a critical\r
2753                 section. */\r
2754 \r
2755                 /* Only do anything if there are no messages in the queue.  This function\r
2756                 will not actually cause the task to block, just place it on a blocked\r
2757                 list.  It will not block until the scheduler is unlocked - at which\r
2758                 time a yield will be performed.  If an item is added to the queue while\r
2759                 the queue is locked, and the calling task blocks on the queue, then the\r
2760                 calling task will be immediately unblocked when the queue is unlocked. */\r
2761                 prvLockQueue( pxQueue );\r
2762                 if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0U )\r
2763                 {\r
2764                         /* There is nothing in the queue, block for the specified period. */\r
2765                         vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait, xWaitIndefinitely );\r
2766                 }\r
2767                 else\r
2768                 {\r
2769                         mtCOVERAGE_TEST_MARKER();\r
2770                 }\r
2771                 prvUnlockQueue( pxQueue );\r
2772         }\r
2773 \r
2774 #endif /* configUSE_TIMERS */\r
2775 /*-----------------------------------------------------------*/\r
2776 \r
2777 #if( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )\r
2778 \r
2779         QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength )\r
2780         {\r
2781         QueueSetHandle_t pxQueue;\r
2782 \r
2783                 pxQueue = xQueueGenericCreate( uxEventQueueLength, ( UBaseType_t ) sizeof( Queue_t * ), queueQUEUE_TYPE_SET );\r
2784 \r
2785                 return pxQueue;\r
2786         }\r
2787 \r
2788 #endif /* configUSE_QUEUE_SETS */\r
2789 /*-----------------------------------------------------------*/\r
2790 \r
2791 #if ( configUSE_QUEUE_SETS == 1 )\r
2792 \r
2793         BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet )\r
2794         {\r
2795         BaseType_t xReturn;\r
2796 \r
2797                 taskENTER_CRITICAL();\r
2798                 {\r
2799                         if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )\r
2800                         {\r
2801                                 /* Cannot add a queue/semaphore to more than one queue set. */\r
2802                                 xReturn = pdFAIL;\r
2803                         }\r
2804                         else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting != ( UBaseType_t ) 0 )\r
2805                         {\r
2806                                 /* Cannot add a queue/semaphore to a queue set if there are already\r
2807                                 items in the queue/semaphore. */\r
2808                                 xReturn = pdFAIL;\r
2809                         }\r
2810                         else\r
2811                         {\r
2812                                 ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet;\r
2813                                 xReturn = pdPASS;\r
2814                         }\r
2815                 }\r
2816                 taskEXIT_CRITICAL();\r
2817 \r
2818                 return xReturn;\r
2819         }\r
2820 \r
2821 #endif /* configUSE_QUEUE_SETS */\r
2822 /*-----------------------------------------------------------*/\r
2823 \r
2824 #if ( configUSE_QUEUE_SETS == 1 )\r
2825 \r
2826         BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet )\r
2827         {\r
2828         BaseType_t xReturn;\r
2829         Queue_t * const pxQueueOrSemaphore = ( Queue_t * ) xQueueOrSemaphore;\r
2830 \r
2831                 if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet )\r
2832                 {\r
2833                         /* The queue was not a member of the set. */\r
2834                         xReturn = pdFAIL;\r
2835                 }\r
2836                 else if( pxQueueOrSemaphore->uxMessagesWaiting != ( UBaseType_t ) 0 )\r
2837                 {\r
2838                         /* It is dangerous to remove a queue from a set when the queue is\r
2839                         not empty because the queue set will still hold pending events for\r
2840                         the queue. */\r
2841                         xReturn = pdFAIL;\r
2842                 }\r
2843                 else\r
2844                 {\r
2845                         taskENTER_CRITICAL();\r
2846                         {\r
2847                                 /* The queue is no longer contained in the set. */\r
2848                                 pxQueueOrSemaphore->pxQueueSetContainer = NULL;\r
2849                         }\r
2850                         taskEXIT_CRITICAL();\r
2851                         xReturn = pdPASS;\r
2852                 }\r
2853 \r
2854                 return xReturn;\r
2855         } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */\r
2856 \r
2857 #endif /* configUSE_QUEUE_SETS */\r
2858 /*-----------------------------------------------------------*/\r
2859 \r
2860 #if ( configUSE_QUEUE_SETS == 1 )\r
2861 \r
2862         QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t const xTicksToWait )\r
2863         {\r
2864         QueueSetMemberHandle_t xReturn = NULL;\r
2865 \r
2866                 ( void ) xQueueReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait ); /*lint !e961 Casting from one typedef to another is not redundant. */\r
2867                 return xReturn;\r
2868         }\r
2869 \r
2870 #endif /* configUSE_QUEUE_SETS */\r
2871 /*-----------------------------------------------------------*/\r
2872 \r
2873 #if ( configUSE_QUEUE_SETS == 1 )\r
2874 \r
2875         QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet )\r
2876         {\r
2877         QueueSetMemberHandle_t xReturn = NULL;\r
2878 \r
2879                 ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */\r
2880                 return xReturn;\r
2881         }\r
2882 \r
2883 #endif /* configUSE_QUEUE_SETS */\r
2884 /*-----------------------------------------------------------*/\r
2885 \r
2886 #if ( configUSE_QUEUE_SETS == 1 )\r
2887 \r
2888         static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition )\r
2889         {\r
2890         Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer;\r
2891         BaseType_t xReturn = pdFALSE;\r
2892 \r
2893                 /* This function must be called form a critical section. */\r
2894 \r
2895                 configASSERT( pxQueueSetContainer );\r
2896                 configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );\r
2897 \r
2898                 if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )\r
2899                 {\r
2900                         const int8_t cTxLock = pxQueueSetContainer->cTxLock;\r
2901 \r
2902                         traceQUEUE_SEND( pxQueueSetContainer );\r
2903 \r
2904                         /* The data copied is the handle of the queue that contains data. */\r
2905                         xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition );\r
2906 \r
2907                         if( cTxLock == queueUNLOCKED )\r
2908                         {\r
2909                                 if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE )\r
2910                                 {\r
2911                                         if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE )\r
2912                                         {\r
2913                                                 /* The task waiting has a higher priority. */\r
2914                                                 xReturn = pdTRUE;\r
2915                                         }\r
2916                                         else\r
2917                                         {\r
2918                                                 mtCOVERAGE_TEST_MARKER();\r
2919                                         }\r
2920                                 }\r
2921                                 else\r
2922                                 {\r
2923                                         mtCOVERAGE_TEST_MARKER();\r
2924                                 }\r
2925                         }\r
2926                         else\r
2927                         {\r
2928                                 pxQueueSetContainer->cTxLock = ( int8_t ) ( cTxLock + 1 );\r
2929                         }\r
2930                 }\r
2931                 else\r
2932                 {\r
2933                         mtCOVERAGE_TEST_MARKER();\r
2934                 }\r
2935 \r
2936                 return xReturn;\r
2937         }\r
2938 \r
2939 #endif /* configUSE_QUEUE_SETS */\r
2940 \r
2941 \r
2942 \r
2943 \r
2944 \r
2945 \r
2946 \r
2947 \r
2948 \r
2949 \r
2950 \r
2951 \r