uc-sdk
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
queue.c
Go to the documentation of this file.
1 /*
2  FreeRTOS V7.5.3 - Copyright (C) 2013 Real Time Engineers Ltd.
3  All rights reserved
4 
5  VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
6 
7  ***************************************************************************
8  * *
9  * FreeRTOS provides completely free yet professionally developed, *
10  * robust, strictly quality controlled, supported, and cross *
11  * platform software that has become a de facto standard. *
12  * *
13  * Help yourself get started quickly and support the FreeRTOS *
14  * project by purchasing a FreeRTOS tutorial book, reference *
15  * manual, or both from: http://www.FreeRTOS.org/Documentation *
16  * *
17  * Thank you! *
18  * *
19  ***************************************************************************
20 
21  This file is part of the FreeRTOS distribution.
22 
23  FreeRTOS is free software; you can redistribute it and/or modify it under
24  the terms of the GNU General Public License (version 2) as published by the
25  Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
26 
27  >>! NOTE: The modification to the GPL is included to allow you to distribute
28  >>! a combined work that includes FreeRTOS without being obliged to provide
29  >>! the source code for proprietary components outside of the FreeRTOS
30  >>! kernel.
31 
32  FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
33  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
34  FOR A PARTICULAR PURPOSE. Full license text is available from the following
35  link: http://www.freertos.org/a00114.html
36 
37  1 tab == 4 spaces!
38 
39  ***************************************************************************
40  * *
41  * Having a problem? Start by reading the FAQ "My application does *
42  * not run, what could be wrong?" *
43  * *
44  * http://www.FreeRTOS.org/FAQHelp.html *
45  * *
46  ***************************************************************************
47 
48  http://www.FreeRTOS.org - Documentation, books, training, latest versions,
49  license and Real Time Engineers Ltd. contact details.
50 
51  http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
52  including FreeRTOS+Trace - an indispensable productivity tool, a DOS
53  compatible FAT file system, and our tiny thread aware UDP/IP stack.
54 
55  http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
56  Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
57  licenses offer ticketed support, indemnification and middleware.
58 
59  http://www.SafeRTOS.com - High Integrity Systems also provide a safety
60  engineered and independently SIL3 certified version for use in safety and
61  mission critical applications that require provable dependability.
62 
63  1 tab == 4 spaces!
64 */
65 
66 #include <stdlib.h>
67 #include <string.h>
68 
69 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
70 all the API functions to use the MPU wrappers. That should only be done when
71 task.h is included from an application file. */
72 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
73 
74 #include "FreeRTOS.h"
75 #include "task.h"
76 #include "queue.h"
77 
78 #if ( configUSE_CO_ROUTINES == 1 )
79  #include "croutine.h"
80 #endif
81 
82 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the
83 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
84 header files above, but not in this file, in order to generate the correct
85 privileged Vs unprivileged linkage and placement. */
86 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
87 
88 
89 /* Constants used with the cRxLock and xTxLock structure members. */
90 #define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 )
91 #define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 )
92 
93 /* When the xQUEUE structure is used to represent a base queue its pcHead and
94 pcTail members are used as pointers into the queue storage area. When the
95 xQUEUE structure is used to represent a mutex pcHead and pcTail pointers are
96 not necessary, and the pcHead pointer is set to NULL to indicate that the
97 pcTail pointer actually points to the mutex holder (if any). Map alternative
98 names to the pcHead and pcTail structure members to ensure the readability of
99 the code is maintained despite this dual use of two structure members. An
100 alternative implementation would be to use a union, but use of a union is
101 against the coding standard (although an exception to the standard has been
102 permitted where the dual use also significantly changes the type of the
103 structure member). */
104 #define pxMutexHolder pcTail
105 #define uxQueueType pcHead
106 #define queueQUEUE_IS_MUTEX NULL
107 
108 /* Semaphores do not actually store or copy data, so have an item size of
109 zero. */
110 #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portBASE_TYPE ) 0 )
111 #define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0U )
112 
113 
114 /*
115  * Definition of the queue used by the scheduler.
116  * Items are queued by copy, not reference.
117  */
118 typedef struct QueueDefinition
119 {
120  signed char *pcHead; /*< Points to the beginning of the queue storage area. */
121  signed char *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. */
122 
123  signed char *pcWriteTo; /*< Points to the free next place in the storage area. */
124 
125  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). */
126  {
127  signed char *pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */
128  unsigned portBASE_TYPE uxRecursiveCallCount;/*< Maintains a count of the numebr of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */
129  } u;
130 
131  xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */
132  xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */
133 
134  volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */
135  unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
136  unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */
137 
138  volatile signed portBASE_TYPE xRxLock; /*< 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. */
139  volatile signed portBASE_TYPE xTxLock; /*< 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. */
140 
141  #if ( configUSE_TRACE_FACILITY == 1 )
142  unsigned char ucQueueNumber;
143  unsigned char ucQueueType;
144  #endif
145 
146  #if ( configUSE_QUEUE_SETS == 1 )
147  struct QueueDefinition *pxQueueSetContainer;
148  #endif
149 
150 } xQUEUE;
151 /*-----------------------------------------------------------*/
152 
153 /*
154  * The queue registry is just a means for kernel aware debuggers to locate
155  * queue structures. It has no other purpose so is an optional component.
156  */
157 #if ( configQUEUE_REGISTRY_SIZE > 0 )
158 
159  /* The type stored within the queue registry array. This allows a name
160  to be assigned to each queue making kernel aware debugging a little
161  more user friendly. */
162  typedef struct QUEUE_REGISTRY_ITEM
163  {
164  signed char *pcQueueName;
165  xQueueHandle xHandle;
166  } xQueueRegistryItem;
167 
168  /* The queue registry is simply an array of xQueueRegistryItem structures.
169  The pcQueueName member of a structure being NULL is indicative of the
170  array position being vacant. */
171  xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
172 
173 #endif /* configQUEUE_REGISTRY_SIZE */
174 
175 /*
176  * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not
177  * prevent an ISR from adding or removing items to the queue, but does prevent
178  * an ISR from removing tasks from the queue event lists. If an ISR finds a
179  * queue is locked it will instead increment the appropriate queue lock count
180  * to indicate that a task may require unblocking. When the queue in unlocked
181  * these lock counts are inspected, and the appropriate action taken.
182  */
183 static void prvUnlockQueue( xQUEUE *pxQueue ) PRIVILEGED_FUNCTION;
184 
185 /*
186  * Uses a critical section to determine if there is any data in a queue.
187  *
188  * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
189  */
190 static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue ) PRIVILEGED_FUNCTION;
191 
192 /*
193  * Uses a critical section to determine if there is any space in a queue.
194  *
195  * @return pdTRUE if there is no space, otherwise pdFALSE;
196  */
197 static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue ) PRIVILEGED_FUNCTION;
198 
199 /*
200  * Copies an item into the queue, either at the front of the queue or the
201  * back of the queue.
202  */
203 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION;
204 
205 /*
206  * Copies an item out of a queue.
207  */
208 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void * const pvBuffer ) PRIVILEGED_FUNCTION;
209 
210 #if ( configUSE_QUEUE_SETS == 1 )
211  /*
212  * Checks to see if a queue is a member of a queue set, and if so, notifies
213  * the queue set that the queue contains data.
214  */
215  static portBASE_TYPE prvNotifyQueueSetContainer( const xQUEUE * const pxQueue, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
216 #endif
217 
218 /*-----------------------------------------------------------*/
219 
220 /*
221  * Macro to mark a queue as locked. Locking a queue prevents an ISR from
222  * accessing the queue event lists.
223  */
224 #define prvLockQueue( pxQueue ) \
225  taskENTER_CRITICAL(); \
226  { \
227  if( ( pxQueue )->xRxLock == queueUNLOCKED ) \
228  { \
229  ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED; \
230  } \
231  if( ( pxQueue )->xTxLock == queueUNLOCKED ) \
232  { \
233  ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED; \
234  } \
235  } \
236  taskEXIT_CRITICAL()
237 /*-----------------------------------------------------------*/
238 
240 {
241 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
242 
243  configASSERT( pxQueue );
244 
246  {
247  pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize );
248  pxQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
249  pxQueue->pcWriteTo = pxQueue->pcHead;
250  pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( unsigned portBASE_TYPE ) 1U ) * pxQueue->uxItemSize );
251  pxQueue->xRxLock = queueUNLOCKED;
252  pxQueue->xTxLock = queueUNLOCKED;
253 
254  if( xNewQueue == pdFALSE )
255  {
256  /* If there are tasks blocked waiting to read from the queue, then
257  the tasks will remain blocked as after this function exits the queue
258  will still be empty. If there are tasks blocked waiting to write to
259  the queue, then one should be unblocked as after this function exits
260  it will be possible to write to it. */
261  if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
262  {
263  if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
264  {
266  }
267  }
268  }
269  else
270  {
271  /* Ensure the event queues start in the correct state. */
272  vListInitialise( &( pxQueue->xTasksWaitingToSend ) );
273  vListInitialise( &( pxQueue->xTasksWaitingToReceive ) );
274  }
275  }
277 
278  /* A value is returned for calling semantic consistency with previous
279  versions. */
280  return pdPASS;
281 }
282 /*-----------------------------------------------------------*/
283 
284 xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType )
285 {
286 xQUEUE *pxNewQueue;
287 size_t xQueueSizeInBytes;
288 xQueueHandle xReturn = NULL;
289 
290  /* Remove compiler warnings about unused parameters should
291  configUSE_TRACE_FACILITY not be set to 1. */
292  ( void ) ucQueueType;
293 
294  /* Allocate the new queue structure. */
295  if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )
296  {
297  pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
298  if( pxNewQueue != NULL )
299  {
300  /* Create the list of pointers to queue items. The queue is one byte
301  longer than asked for to make wrap checking easier/faster. */
302  xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
303 
304  pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes );
305  if( pxNewQueue->pcHead != NULL )
306  {
307  /* Initialise the queue members as described above where the
308  queue type is defined. */
309  pxNewQueue->uxLength = uxQueueLength;
310  pxNewQueue->uxItemSize = uxItemSize;
311  ( void ) xQueueGenericReset( pxNewQueue, pdTRUE );
312 
313  #if ( configUSE_TRACE_FACILITY == 1 )
314  {
315  pxNewQueue->ucQueueType = ucQueueType;
316  }
317  #endif /* configUSE_TRACE_FACILITY */
318 
319  #if( configUSE_QUEUE_SETS == 1 )
320  {
321  pxNewQueue->pxQueueSetContainer = NULL;
322  }
323  #endif /* configUSE_QUEUE_SETS */
324 
325  traceQUEUE_CREATE( pxNewQueue );
326  xReturn = pxNewQueue;
327  }
328  else
329  {
330  traceQUEUE_CREATE_FAILED( ucQueueType );
331  vPortFree( pxNewQueue );
332  }
333  }
334  }
335 
336  configASSERT( xReturn );
337 
338  return xReturn;
339 }
340 /*-----------------------------------------------------------*/
341 
342 #if ( configUSE_MUTEXES == 1 )
343 
344  xQueueHandle xQueueCreateMutex( unsigned char ucQueueType )
345  {
346  xQUEUE *pxNewQueue;
347 
348  /* Prevent compiler warnings about unused parameters if
349  configUSE_TRACE_FACILITY does not equal 1. */
350  ( void ) ucQueueType;
351 
352  /* Allocate the new queue structure. */
353  pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
354  if( pxNewQueue != NULL )
355  {
356  /* Information required for priority inheritance. */
357  pxNewQueue->pxMutexHolder = NULL;
358  pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
359 
360  /* Queues used as a mutex no data is actually copied into or out
361  of the queue. */
362  pxNewQueue->pcWriteTo = NULL;
363  pxNewQueue->u.pcReadFrom = NULL;
364 
365  /* Each mutex has a length of 1 (like a binary semaphore) and
366  an item size of 0 as nothing is actually copied into or out
367  of the mutex. */
368  pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
369  pxNewQueue->uxLength = ( unsigned portBASE_TYPE ) 1U;
370  pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 0U;
371  pxNewQueue->xRxLock = queueUNLOCKED;
372  pxNewQueue->xTxLock = queueUNLOCKED;
373 
374  #if ( configUSE_TRACE_FACILITY == 1 )
375  {
376  pxNewQueue->ucQueueType = ucQueueType;
377  }
378  #endif
379 
380  #if ( configUSE_QUEUE_SETS == 1 )
381  {
382  pxNewQueue->pxQueueSetContainer = NULL;
383  }
384  #endif
385 
386  /* Ensure the event queues start with the correct state. */
387  vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
388  vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
389 
390  traceCREATE_MUTEX( pxNewQueue );
391 
392  /* Start with the semaphore in the expected state. */
393  ( void ) xQueueGenericSend( pxNewQueue, NULL, ( portTickType ) 0U, queueSEND_TO_BACK );
394  }
395  else
396  {
398  }
399 
400  configASSERT( pxNewQueue );
401  return pxNewQueue;
402  }
403 
404 #endif /* configUSE_MUTEXES */
405 /*-----------------------------------------------------------*/
406 
407 #if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
408 
409  void* xQueueGetMutexHolder( xQueueHandle xSemaphore )
410  {
411  void *pxReturn;
412 
413  /* This function is called by xSemaphoreGetMutexHolder(), and should not
414  be called directly. Note: This is is a good way of determining if the
415  calling task is the mutex holder, but not a good way of determining the
416  identity of the mutex holder, as the holder may change between the
417  following critical section exiting and the function returning. */
419  {
420  if( ( ( xQUEUE * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX )
421  {
422  pxReturn = ( void * ) ( ( xQUEUE * ) xSemaphore )->pxMutexHolder;
423  }
424  else
425  {
426  pxReturn = NULL;
427  }
428  }
430 
431  return pxReturn;
432  }
433 
434 #endif
435 /*-----------------------------------------------------------*/
436 
437 #if ( configUSE_RECURSIVE_MUTEXES == 1 )
438 
440  {
441  portBASE_TYPE xReturn;
442  xQUEUE * const pxMutex = ( xQUEUE * ) xMutex;
443 
444  configASSERT( pxMutex );
445 
446  /* If this is the task that holds the mutex then pxMutexHolder will not
447  change outside of this task. If this task does not hold the mutex then
448  pxMutexHolder can never coincidentally equal the tasks handle, and as
449  this is the only condition we are interested in it does not matter if
450  pxMutexHolder is accessed simultaneously by another task. Therefore no
451  mutual exclusion is required to test the pxMutexHolder variable. */
452  if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Not a redundant cast as xTaskHandle is a typedef. */
453  {
454  traceGIVE_MUTEX_RECURSIVE( pxMutex );
455 
456  /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to
457  the task handle, therefore no underflow check is required. Also,
458  uxRecursiveCallCount is only modified by the mutex holder, and as
459  there can only be one, no mutual exclusion is required to modify the
460  uxRecursiveCallCount member. */
461  ( pxMutex->u.uxRecursiveCallCount )--;
462 
463  /* Have we unwound the call count? */
464  if( pxMutex->u.uxRecursiveCallCount == ( unsigned portBASE_TYPE ) 0 )
465  {
466  /* Return the mutex. This will automatically unblock any other
467  task that might be waiting to access the mutex. */
469  }
470 
471  xReturn = pdPASS;
472  }
473  else
474  {
475  /* We cannot give the mutex because we are not the holder. */
476  xReturn = pdFAIL;
477 
479  }
480 
481  return xReturn;
482  }
483 
484 #endif /* configUSE_RECURSIVE_MUTEXES */
485 /*-----------------------------------------------------------*/
486 
487 #if ( configUSE_RECURSIVE_MUTEXES == 1 )
488 
490  {
491  portBASE_TYPE xReturn;
492  xQUEUE * const pxMutex = ( xQUEUE * ) xMutex;
493 
494  configASSERT( pxMutex );
495 
496  /* Comments regarding mutual exclusion as per those within
497  xQueueGiveMutexRecursive(). */
498 
499  traceTAKE_MUTEX_RECURSIVE( pxMutex );
500 
501  if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Cast is not redundant as xTaskHandle is a typedef. */
502  {
503  ( pxMutex->u.uxRecursiveCallCount )++;
504  xReturn = pdPASS;
505  }
506  else
507  {
508  xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );
509 
510  /* pdPASS will only be returned if we successfully obtained the mutex,
511  we may have blocked to reach here. */
512  if( xReturn == pdPASS )
513  {
514  ( pxMutex->u.uxRecursiveCallCount )++;
515  }
516  else
517  {
519  }
520  }
521 
522  return xReturn;
523  }
524 
525 #endif /* configUSE_RECURSIVE_MUTEXES */
526 /*-----------------------------------------------------------*/
527 
528 #if ( configUSE_COUNTING_SEMAPHORES == 1 )
529 
530  xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount )
531  {
532  xQueueHandle xHandle;
533 
535 
536  if( xHandle != NULL )
537  {
538  ( ( xQUEUE * ) xHandle )->uxMessagesWaiting = uxInitialCount;
539 
541  }
542  else
543  {
545  }
546 
547  configASSERT( xHandle );
548  return xHandle;
549  }
550 
551 #endif /* configUSE_COUNTING_SEMAPHORES */
552 /*-----------------------------------------------------------*/
553 
554 signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
555 {
556 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
557 xTimeOutType xTimeOut;
558 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
559 
560  configASSERT( pxQueue );
561  configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
562  configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
563 
564  /* This function relaxes the coding standard somewhat to allow return
565  statements within the function itself. This is done in the interest
566  of execution time efficiency. */
567  for( ;; )
568  {
570  {
571  /* Is there room on the queue now? The running task must be
572  the highest priority task wanting to access the queue. If
573  the head item in the queue is to be overwritten then it does
574  not matter if the queue is full. */
575  if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
576  {
577  traceQUEUE_SEND( pxQueue );
578  prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
579 
580  #if ( configUSE_QUEUE_SETS == 1 )
581  {
582  if( pxQueue->pxQueueSetContainer != NULL )
583  {
584  if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )
585  {
586  /* The queue is a member of a queue set, and posting
587  to the queue set caused a higher priority task to
588  unblock. A context switch is required. */
590  }
591  }
592  else
593  {
594  /* If there was a task waiting for data to arrive on the
595  queue then unblock it now. */
596  if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
597  {
598  if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
599  {
600  /* The unblocked task has a priority higher than
601  our own so yield immediately. Yes it is ok to
602  do this from within the critical section - the
603  kernel takes care of that. */
605  }
606  }
607  }
608  }
609  #else /* configUSE_QUEUE_SETS */
610  {
611  /* If there was a task waiting for data to arrive on the
612  queue then unblock it now. */
613  if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
614  {
615  if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
616  {
617  /* The unblocked task has a priority higher than
618  our own so yield immediately. Yes it is ok to do
619  this from within the critical section - the kernel
620  takes care of that. */
622  }
623  }
624  }
625  #endif /* configUSE_QUEUE_SETS */
626 
628 
629  /* Return to the original privilege level before exiting the
630  function. */
631  return pdPASS;
632  }
633  else
634  {
635  if( xTicksToWait == ( portTickType ) 0 )
636  {
637  /* The queue was full and no block time is specified (or
638  the block time has expired) so leave now. */
640 
641  /* Return to the original privilege level before exiting
642  the function. */
643  traceQUEUE_SEND_FAILED( pxQueue );
644  return errQUEUE_FULL;
645  }
646  else if( xEntryTimeSet == pdFALSE )
647  {
648  /* The queue was full and a block time was specified so
649  configure the timeout structure. */
650  vTaskSetTimeOutState( &xTimeOut );
651  xEntryTimeSet = pdTRUE;
652  }
653  else
654  {
655  /* Entry time was already set. */
656  }
657  }
658  }
660 
661  /* Interrupts and other tasks can send to and receive from the queue
662  now the critical section has been exited. */
663 
664  vTaskSuspendAll();
665  prvLockQueue( pxQueue );
666 
667  /* Update the timeout state to see if it has expired yet. */
668  if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
669  {
670  if( prvIsQueueFull( pxQueue ) != pdFALSE )
671  {
672  traceBLOCKING_ON_QUEUE_SEND( pxQueue );
673  vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
674 
675  /* Unlocking the queue means queue events can effect the
676  event list. It is possible that interrupts occurring now
677  remove this task from the event list again - but as the
678  scheduler is suspended the task will go onto the pending
679  ready last instead of the actual ready list. */
680  prvUnlockQueue( pxQueue );
681 
682  /* Resuming the scheduler will move tasks from the pending
683  ready list into the ready list - so it is feasible that this
684  task is already in a ready list before it yields - in which
685  case the yield will not cause a context switch unless there
686  is also a higher priority task in the pending ready list. */
687  if( xTaskResumeAll() == pdFALSE )
688  {
690  }
691  }
692  else
693  {
694  /* Try again. */
695  prvUnlockQueue( pxQueue );
696  ( void ) xTaskResumeAll();
697  }
698  }
699  else
700  {
701  /* The timeout has expired. */
702  prvUnlockQueue( pxQueue );
703  ( void ) xTaskResumeAll();
704 
705  /* Return to the original privilege level before exiting the
706  function. */
707  traceQUEUE_SEND_FAILED( pxQueue );
708  return errQUEUE_FULL;
709  }
710  }
711 }
712 /*-----------------------------------------------------------*/
713 
714 #if ( configUSE_ALTERNATIVE_API == 1 )
715 
716  signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
717  {
718  signed portBASE_TYPE xEntryTimeSet = pdFALSE;
719  xTimeOutType xTimeOut;
720  xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
721 
722  configASSERT( pxQueue );
723  configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
724 
725  for( ;; )
726  {
728  {
729  /* Is there room on the queue now? To be running we must be
730  the highest priority task wanting to access the queue. */
731  if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
732  {
733  traceQUEUE_SEND( pxQueue );
734  prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
735 
736  /* If there was a task waiting for data to arrive on the
737  queue then unblock it now. */
738  if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
739  {
740  if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
741  {
742  /* The unblocked task has a priority higher than
743  our own so yield immediately. */
745  }
746  }
747 
749  return pdPASS;
750  }
751  else
752  {
753  if( xTicksToWait == ( portTickType ) 0 )
754  {
756  return errQUEUE_FULL;
757  }
758  else if( xEntryTimeSet == pdFALSE )
759  {
760  vTaskSetTimeOutState( &xTimeOut );
761  xEntryTimeSet = pdTRUE;
762  }
763  }
764  }
766 
768  {
769  if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
770  {
771  if( prvIsQueueFull( pxQueue ) != pdFALSE )
772  {
773  traceBLOCKING_ON_QUEUE_SEND( pxQueue );
774  vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
776  }
777  }
778  else
779  {
781  traceQUEUE_SEND_FAILED( pxQueue );
782  return errQUEUE_FULL;
783  }
784  }
786  }
787  }
788 
789 #endif /* configUSE_ALTERNATIVE_API */
790 /*-----------------------------------------------------------*/
791 
792 #if ( configUSE_ALTERNATIVE_API == 1 )
793 
794  signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
795  {
796  signed portBASE_TYPE xEntryTimeSet = pdFALSE;
797  xTimeOutType xTimeOut;
798  signed char *pcOriginalReadPosition;
799  xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
800 
801  configASSERT( pxQueue );
802  configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
803 
804  for( ;; )
805  {
807  {
808  if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
809  {
810  /* Remember our read position in case we are just peeking. */
811  pcOriginalReadPosition = pxQueue->u.pcReadFrom;
812 
813  prvCopyDataFromQueue( pxQueue, pvBuffer );
814 
815  if( xJustPeeking == pdFALSE )
816  {
817  traceQUEUE_RECEIVE( pxQueue );
818 
819  /* Data is actually being removed (not just peeked). */
820  --( pxQueue->uxMessagesWaiting );
821 
822  #if ( configUSE_MUTEXES == 1 )
823  {
824  if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
825  {
826  /* Record the information required to implement
827  priority inheritance should it become necessary. */
828  pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle();
829  }
830  }
831  #endif
832 
833  if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
834  {
835  if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
836  {
838  }
839  }
840  }
841  else
842  {
843  traceQUEUE_PEEK( pxQueue );
844 
845  /* We are not removing the data, so reset our read
846  pointer. */
847  pxQueue->u.pcReadFrom = pcOriginalReadPosition;
848 
849  /* The data is being left in the queue, so see if there are
850  any other tasks waiting for the data. */
851  if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
852  {
853  /* Tasks that are removed from the event list will get added to
854  the pending ready list as the scheduler is still suspended. */
856  {
857  /* The task waiting has a higher priority than this task. */
859  }
860  }
861 
862  }
863 
865  return pdPASS;
866  }
867  else
868  {
869  if( xTicksToWait == ( portTickType ) 0 )
870  {
872  traceQUEUE_RECEIVE_FAILED( pxQueue );
873  return errQUEUE_EMPTY;
874  }
875  else if( xEntryTimeSet == pdFALSE )
876  {
877  vTaskSetTimeOutState( &xTimeOut );
878  xEntryTimeSet = pdTRUE;
879  }
880  }
881  }
883 
885  {
886  if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
887  {
888  if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
889  {
891 
892  #if ( configUSE_MUTEXES == 1 )
893  {
894  if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
895  {
897  {
898  vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
899  }
901  }
902  }
903  #endif
904 
905  vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
907  }
908  }
909  else
910  {
912  traceQUEUE_RECEIVE_FAILED( pxQueue );
913  return errQUEUE_EMPTY;
914  }
915  }
917  }
918  }
919 
920 
921 #endif /* configUSE_ALTERNATIVE_API */
922 /*-----------------------------------------------------------*/
923 
924 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )
925 {
926 signed portBASE_TYPE xReturn;
927 unsigned portBASE_TYPE uxSavedInterruptStatus;
928 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
929 
930  configASSERT( pxQueue );
931  configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
932  configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
933 
934  /* RTOS ports that support interrupt nesting have the concept of a maximum
935  system call (or maximum API call) interrupt priority. Interrupts that are
936  above the maximum system call priority are keep permanently enabled, even
937  when the RTOS kernel is in a critical section, but cannot make any calls to
938  FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
939  then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
940  failure if a FreeRTOS API function is called from an interrupt that has been
941  assigned a priority above the configured maximum system call priority.
942  Only FreeRTOS functions that end in FromISR can be called from interrupts
943  that have been assigned a priority at or (logically) below the maximum
944  system call interrupt priority. FreeRTOS maintains a separate interrupt
945  safe API to ensure interrupt entry is as fast and as simple as possible.
946  More information (albeit Cortex-M specific) is provided on the following
947  link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
949 
950  /* Similar to xQueueGenericSend, except we don't block if there is no room
951  in the queue. Also we don't directly wake a task that was blocked on a
952  queue read, instead we return a flag to say whether a context switch is
953  required or not (i.e. has a task with a higher priority than us been woken
954  by this post). */
955  uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
956  {
957  if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
958  {
959  traceQUEUE_SEND_FROM_ISR( pxQueue );
960 
961  prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
962 
963  /* If the queue is locked we do not alter the event list. This will
964  be done when the queue is unlocked later. */
965  if( pxQueue->xTxLock == queueUNLOCKED )
966  {
967  #if ( configUSE_QUEUE_SETS == 1 )
968  {
969  if( pxQueue->pxQueueSetContainer != NULL )
970  {
971  if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )
972  {
973  /* The queue is a member of a queue set, and posting
974  to the queue set caused a higher priority task to
975  unblock. A context switch is required. */
976  if( pxHigherPriorityTaskWoken != NULL )
977  {
978  *pxHigherPriorityTaskWoken = pdTRUE;
979  }
980  }
981  }
982  else
983  {
984  if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
985  {
987  {
988  /* The task waiting has a higher priority so record that a
989  context switch is required. */
990  if( pxHigherPriorityTaskWoken != NULL )
991  {
992  *pxHigherPriorityTaskWoken = pdTRUE;
993  }
994  }
995  }
996  }
997  }
998  #else /* configUSE_QUEUE_SETS */
999  {
1000  if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
1001  {
1002  if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
1003  {
1004  /* The task waiting has a higher priority so record that a
1005  context switch is required. */
1006  if( pxHigherPriorityTaskWoken != NULL )
1007  {
1008  *pxHigherPriorityTaskWoken = pdTRUE;
1009  }
1010  }
1011  }
1012  }
1013  #endif /* configUSE_QUEUE_SETS */
1014  }
1015  else
1016  {
1017  /* Increment the lock count so the task that unlocks the queue
1018  knows that data was posted while it was locked. */
1019  ++( pxQueue->xTxLock );
1020  }
1021 
1022  xReturn = pdPASS;
1023  }
1024  else
1025  {
1027  xReturn = errQUEUE_FULL;
1028  }
1029  }
1030  portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
1031 
1032  return xReturn;
1033 }
1034 /*-----------------------------------------------------------*/
1035 
1036 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
1037 {
1038 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
1039 xTimeOutType xTimeOut;
1040 signed char *pcOriginalReadPosition;
1041 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
1042 
1043  configASSERT( pxQueue );
1044  configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
1045 
1046  /* This function relaxes the coding standard somewhat to allow return
1047  statements within the function itself. This is done in the interest
1048  of execution time efficiency. */
1049 
1050  for( ;; )
1051  {
1053  {
1054  /* Is there data in the queue now? To be running we must be
1055  the highest priority task wanting to access the queue. */
1056  if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
1057  {
1058  /* Remember the read position in case the queue is only being
1059  peeked. */
1060  pcOriginalReadPosition = pxQueue->u.pcReadFrom;
1061 
1062  prvCopyDataFromQueue( pxQueue, pvBuffer );
1063 
1064  if( xJustPeeking == pdFALSE )
1065  {
1066  traceQUEUE_RECEIVE( pxQueue );
1067 
1068  /* Actually removing data, not just peeking. */
1069  --( pxQueue->uxMessagesWaiting );
1070 
1071  #if ( configUSE_MUTEXES == 1 )
1072  {
1073  if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
1074  {
1075  /* Record the information required to implement
1076  priority inheritance should it become necessary. */
1077  pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle(); /*lint !e961 Cast is not redundant as xTaskHandle is a typedef. */
1078  }
1079  }
1080  #endif
1081 
1082  if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
1083  {
1084  if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
1085  {
1087  }
1088  }
1089  }
1090  else
1091  {
1092  traceQUEUE_PEEK( pxQueue );
1093 
1094  /* The data is not being removed, so reset the read
1095  pointer. */
1096  pxQueue->u.pcReadFrom = pcOriginalReadPosition;
1097 
1098  /* The data is being left in the queue, so see if there are
1099  any other tasks waiting for the data. */
1100  if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
1101  {
1102  /* Tasks that are removed from the event list will get added to
1103  the pending ready list as the scheduler is still suspended. */
1104  if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
1105  {
1106  /* The task waiting has a higher priority than this task. */
1108  }
1109  }
1110  }
1111 
1113  return pdPASS;
1114  }
1115  else
1116  {
1117  if( xTicksToWait == ( portTickType ) 0 )
1118  {
1119  /* The queue was empty and no block time is specified (or
1120  the block time has expired) so leave now. */
1122  traceQUEUE_RECEIVE_FAILED( pxQueue );
1123  return errQUEUE_EMPTY;
1124  }
1125  else if( xEntryTimeSet == pdFALSE )
1126  {
1127  /* The queue was empty and a block time was specified so
1128  configure the timeout structure. */
1129  vTaskSetTimeOutState( &xTimeOut );
1130  xEntryTimeSet = pdTRUE;
1131  }
1132  else
1133  {
1134  /* Entry time was already set. */
1135  }
1136  }
1137  }
1139 
1140  /* Interrupts and other tasks can send to and receive from the queue
1141  now the critical section has been exited. */
1142 
1143  vTaskSuspendAll();
1144  prvLockQueue( pxQueue );
1145 
1146  /* Update the timeout state to see if it has expired yet. */
1147  if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
1148  {
1149  if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
1150  {
1151  traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
1152 
1153  #if ( configUSE_MUTEXES == 1 )
1154  {
1155  if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
1156  {
1158  {
1159  vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
1160  }
1162  }
1163  }
1164  #endif
1165 
1166  vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
1167  prvUnlockQueue( pxQueue );
1168  if( xTaskResumeAll() == pdFALSE )
1169  {
1171  }
1172  }
1173  else
1174  {
1175  /* Try again. */
1176  prvUnlockQueue( pxQueue );
1177  ( void ) xTaskResumeAll();
1178  }
1179  }
1180  else
1181  {
1182  prvUnlockQueue( pxQueue );
1183  ( void ) xTaskResumeAll();
1184  traceQUEUE_RECEIVE_FAILED( pxQueue );
1185  return errQUEUE_EMPTY;
1186  }
1187  }
1188 }
1189 /*-----------------------------------------------------------*/
1190 
1191 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle xQueue, const void * const pvBuffer, signed portBASE_TYPE *pxHigherPriorityTaskWoken )
1192 {
1193 signed portBASE_TYPE xReturn;
1194 unsigned portBASE_TYPE uxSavedInterruptStatus;
1195 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
1196 
1197  configASSERT( pxQueue );
1198  configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
1199 
1200  /* RTOS ports that support interrupt nesting have the concept of a maximum
1201  system call (or maximum API call) interrupt priority. Interrupts that are
1202  above the maximum system call priority are keep permanently enabled, even
1203  when the RTOS kernel is in a critical section, but cannot make any calls to
1204  FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
1205  then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
1206  failure if a FreeRTOS API function is called from an interrupt that has been
1207  assigned a priority above the configured maximum system call priority.
1208  Only FreeRTOS functions that end in FromISR can be called from interrupts
1209  that have been assigned a priority at or (logically) below the maximum
1210  system call interrupt priority. FreeRTOS maintains a separate interrupt
1211  safe API to ensure interrupt entry is as fast and as simple as possible.
1212  More information (albeit Cortex-M specific) is provided on the following
1213  link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
1215 
1216  uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
1217  {
1218  /* Cannot block in an ISR, so check there is data available. */
1219  if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
1220  {
1221  traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
1222 
1223  prvCopyDataFromQueue( pxQueue, pvBuffer );
1224  --( pxQueue->uxMessagesWaiting );
1225 
1226  /* If the queue is locked the event list will not be modified.
1227  Instead update the lock count so the task that unlocks the queue
1228  will know that an ISR has removed data while the queue was
1229  locked. */
1230  if( pxQueue->xRxLock == queueUNLOCKED )
1231  {
1232  if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
1233  {
1234  if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
1235  {
1236  /* The task waiting has a higher priority than us so
1237  force a context switch. */
1238  if( pxHigherPriorityTaskWoken != NULL )
1239  {
1240  *pxHigherPriorityTaskWoken = pdTRUE;
1241  }
1242  }
1243  }
1244  }
1245  else
1246  {
1247  /* Increment the lock count so the task that unlocks the queue
1248  knows that data was removed while it was locked. */
1249  ++( pxQueue->xRxLock );
1250  }
1251 
1252  xReturn = pdPASS;
1253  }
1254  else
1255  {
1256  xReturn = pdFAIL;
1258  }
1259  }
1260  portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
1261 
1262  return xReturn;
1263 }
1264 /*-----------------------------------------------------------*/
1265 
1266 signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, const void * const pvBuffer )
1267 {
1268 signed portBASE_TYPE xReturn;
1269 unsigned portBASE_TYPE uxSavedInterruptStatus;
1270 signed char *pcOriginalReadPosition;
1271 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
1272 
1273  configASSERT( pxQueue );
1274  configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
1275 
1276  /* RTOS ports that support interrupt nesting have the concept of a maximum
1277  system call (or maximum API call) interrupt priority. Interrupts that are
1278  above the maximum system call priority are keep permanently enabled, even
1279  when the RTOS kernel is in a critical section, but cannot make any calls to
1280  FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
1281  then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
1282  failure if a FreeRTOS API function is called from an interrupt that has been
1283  assigned a priority above the configured maximum system call priority.
1284  Only FreeRTOS functions that end in FromISR can be called from interrupts
1285  that have been assigned a priority at or (logically) below the maximum
1286  system call interrupt priority. FreeRTOS maintains a separate interrupt
1287  safe API to ensure interrupt entry is as fast and as simple as possible.
1288  More information (albeit Cortex-M specific) is provided on the following
1289  link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
1291 
1292  uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
1293  {
1294  /* Cannot block in an ISR, so check there is data available. */
1295  if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
1296  {
1297  traceQUEUE_PEEK_FROM_ISR( pxQueue );
1298 
1299  /* Remember the read position so it can be reset as nothing is
1300  actually being removed from the queue. */
1301  pcOriginalReadPosition = pxQueue->u.pcReadFrom;
1302  prvCopyDataFromQueue( pxQueue, pvBuffer );
1303  pxQueue->u.pcReadFrom = pcOriginalReadPosition;
1304 
1305  xReturn = pdPASS;
1306  }
1307  else
1308  {
1309  xReturn = pdFAIL;
1311  }
1312  }
1313  portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
1314 
1315  return xReturn;
1316 }
1317 /*-----------------------------------------------------------*/
1318 
1319 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue )
1320 {
1321 unsigned portBASE_TYPE uxReturn;
1322 
1323  configASSERT( xQueue );
1324 
1326  uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting;
1328 
1329  return uxReturn;
1330 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
1331 /*-----------------------------------------------------------*/
1332 
1333 unsigned portBASE_TYPE uxQueueSpacesAvailable( const xQueueHandle xQueue )
1334 {
1335 unsigned portBASE_TYPE uxReturn;
1336 xQUEUE *pxQueue;
1337 
1338  pxQueue = ( xQUEUE * ) xQueue;
1339  configASSERT( pxQueue );
1340 
1342  uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting;
1344 
1345  return uxReturn;
1346 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
1347 /*-----------------------------------------------------------*/
1348 
1349 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle xQueue )
1350 {
1351 unsigned portBASE_TYPE uxReturn;
1352 
1353  configASSERT( xQueue );
1354 
1355  uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting;
1356 
1357  return uxReturn;
1358 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
1359 /*-----------------------------------------------------------*/
1360 
1362 {
1363 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
1364 
1365  configASSERT( pxQueue );
1366 
1367  traceQUEUE_DELETE( pxQueue );
1368  #if ( configQUEUE_REGISTRY_SIZE > 0 )
1369  {
1370  vQueueUnregisterQueue( pxQueue );
1371  }
1372  #endif
1373  vPortFree( pxQueue->pcHead );
1374  vPortFree( pxQueue );
1375 }
1376 /*-----------------------------------------------------------*/
1377 
1378 #if ( configUSE_TRACE_FACILITY == 1 )
1379 
1380  unsigned char ucQueueGetQueueNumber( xQueueHandle xQueue )
1381  {
1382  return ( ( xQUEUE * ) xQueue )->ucQueueNumber;
1383  }
1384 
1385 #endif /* configUSE_TRACE_FACILITY */
1386 /*-----------------------------------------------------------*/
1387 
1388 #if ( configUSE_TRACE_FACILITY == 1 )
1389 
1390  void vQueueSetQueueNumber( xQueueHandle xQueue, unsigned char ucQueueNumber )
1391  {
1392  ( ( xQUEUE * ) xQueue )->ucQueueNumber = ucQueueNumber;
1393  }
1394 
1395 #endif /* configUSE_TRACE_FACILITY */
1396 /*-----------------------------------------------------------*/
1397 
1398 #if ( configUSE_TRACE_FACILITY == 1 )
1399 
1400  unsigned char ucQueueGetQueueType( xQueueHandle xQueue )
1401  {
1402  return ( ( xQUEUE * ) xQueue )->ucQueueType;
1403  }
1404 
1405 #endif /* configUSE_TRACE_FACILITY */
1406 /*-----------------------------------------------------------*/
1407 
1408 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )
1409 {
1410  if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )
1411  {
1412  #if ( configUSE_MUTEXES == 1 )
1413  {
1414  if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
1415  {
1416  /* The mutex is no longer being held. */
1417  vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
1418  pxQueue->pxMutexHolder = NULL;
1419  }
1420  }
1421  #endif /* configUSE_MUTEXES */
1422  }
1423  else if( xPosition == queueSEND_TO_BACK )
1424  {
1425  ( 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. */
1426  pxQueue->pcWriteTo += pxQueue->uxItemSize;
1427  if( pxQueue->pcWriteTo >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */
1428  {
1429  pxQueue->pcWriteTo = pxQueue->pcHead;
1430  }
1431  }
1432  else
1433  {
1434  ( void ) memcpy( ( void * ) pxQueue->u.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
1435  pxQueue->u.pcReadFrom -= pxQueue->uxItemSize;
1436  if( pxQueue->u.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */
1437  {
1438  pxQueue->u.pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
1439  }
1440 
1441  if( xPosition == queueOVERWRITE )
1442  {
1443  if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
1444  {
1445  /* An item is not being added but overwritten, so subtract
1446  one from the recorded number of items in the queue so when
1447  one is added again below the number of recorded items remains
1448  correct. */
1449  --( pxQueue->uxMessagesWaiting );
1450  }
1451  }
1452  }
1453 
1454  ++( pxQueue->uxMessagesWaiting );
1455 }
1456 /*-----------------------------------------------------------*/
1457 
1458 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void * const pvBuffer )
1459 {
1460  if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
1461  {
1462  pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
1463  if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */
1464  {
1465  pxQueue->u.pcReadFrom = pxQueue->pcHead;
1466  }
1467  ( 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. */
1468  }
1469 }
1470 /*-----------------------------------------------------------*/
1471 
1472 static void prvUnlockQueue( xQUEUE *pxQueue )
1473 {
1474  /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
1475 
1476  /* The lock counts contains the number of extra data items placed or
1477  removed from the queue while the queue was locked. When a queue is
1478  locked items can be added or removed, but the event lists cannot be
1479  updated. */
1481  {
1482  /* See if data was added to the queue while it was locked. */
1483  while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )
1484  {
1485  /* Data was posted while the queue was locked. Are any tasks
1486  blocked waiting for data to become available? */
1487  #if ( configUSE_QUEUE_SETS == 1 )
1488  {
1489  if( pxQueue->pxQueueSetContainer != NULL )
1490  {
1491  if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) == pdTRUE )
1492  {
1493  /* The queue is a member of a queue set, and posting to
1494  the queue set caused a higher priority task to unblock.
1495  A context switch is required. */
1496  vTaskMissedYield();
1497  }
1498  }
1499  else
1500  {
1501  /* Tasks that are removed from the event list will get added to
1502  the pending ready list as the scheduler is still suspended. */
1503  if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
1504  {
1505  if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
1506  {
1507  /* The task waiting has a higher priority so record that a
1508  context switch is required. */
1509  vTaskMissedYield();
1510  }
1511  }
1512  else
1513  {
1514  break;
1515  }
1516  }
1517  }
1518  #else /* configUSE_QUEUE_SETS */
1519  {
1520  /* Tasks that are removed from the event list will get added to
1521  the pending ready list as the scheduler is still suspended. */
1522  if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
1523  {
1524  if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
1525  {
1526  /* The task waiting has a higher priority so record that a
1527  context switch is required. */
1528  vTaskMissedYield();
1529  }
1530  }
1531  else
1532  {
1533  break;
1534  }
1535  }
1536  #endif /* configUSE_QUEUE_SETS */
1537 
1538  --( pxQueue->xTxLock );
1539  }
1540 
1541  pxQueue->xTxLock = queueUNLOCKED;
1542  }
1544 
1545  /* Do the same for the Rx lock. */
1547  {
1548  while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )
1549  {
1550  if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
1551  {
1552  if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
1553  {
1554  vTaskMissedYield();
1555  }
1556 
1557  --( pxQueue->xRxLock );
1558  }
1559  else
1560  {
1561  break;
1562  }
1563  }
1564 
1565  pxQueue->xRxLock = queueUNLOCKED;
1566  }
1568 }
1569 /*-----------------------------------------------------------*/
1570 
1571 static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue )
1572 {
1573 signed portBASE_TYPE xReturn;
1574 
1576  {
1577  if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
1578  {
1579  xReturn = pdTRUE;
1580  }
1581  else
1582  {
1583  xReturn = pdFALSE;
1584  }
1585  }
1587 
1588  return xReturn;
1589 }
1590 /*-----------------------------------------------------------*/
1591 
1592 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle xQueue )
1593 {
1594 signed portBASE_TYPE xReturn;
1595 
1596  configASSERT( xQueue );
1597  if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
1598  {
1599  xReturn = pdTRUE;
1600  }
1601  else
1602  {
1603  xReturn = pdFALSE;
1604  }
1605 
1606  return xReturn;
1607 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
1608 /*-----------------------------------------------------------*/
1609 
1610 static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue )
1611 {
1612 signed portBASE_TYPE xReturn;
1613 
1615  {
1616  if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )
1617  {
1618  xReturn = pdTRUE;
1619  }
1620  else
1621  {
1622  xReturn = pdFALSE;
1623  }
1624  }
1626 
1627  return xReturn;
1628 }
1629 /*-----------------------------------------------------------*/
1630 
1631 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle xQueue )
1632 {
1633 signed portBASE_TYPE xReturn;
1634 
1635  configASSERT( xQueue );
1636  if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( ( xQUEUE * ) xQueue )->uxLength )
1637  {
1638  xReturn = pdTRUE;
1639  }
1640  else
1641  {
1642  xReturn = pdFALSE;
1643  }
1644 
1645  return xReturn;
1646 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
1647 /*-----------------------------------------------------------*/
1648 
1649 #if ( configUSE_CO_ROUTINES == 1 )
1650 
1651  signed portBASE_TYPE xQueueCRSend( xQueueHandle xQueue, const void *pvItemToQueue, portTickType xTicksToWait )
1652  {
1653  signed portBASE_TYPE xReturn;
1654  xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
1655 
1656  /* If the queue is already full we may have to block. A critical section
1657  is required to prevent an interrupt removing something from the queue
1658  between the check to see if the queue is full and blocking on the queue. */
1660  {
1661  if( prvIsQueueFull( pxQueue ) != pdFALSE )
1662  {
1663  /* The queue is full - do we want to block or just leave without
1664  posting? */
1665  if( xTicksToWait > ( portTickType ) 0 )
1666  {
1667  /* As this is called from a coroutine we cannot block directly, but
1668  return indicating that we need to block. */
1669  vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
1671  return errQUEUE_BLOCKED;
1672  }
1673  else
1674  {
1676  return errQUEUE_FULL;
1677  }
1678  }
1679  }
1681 
1683  {
1684  if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
1685  {
1686  /* There is room in the queue, copy the data into the queue. */
1687  prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
1688  xReturn = pdPASS;
1689 
1690  /* Were any co-routines waiting for data to become available? */
1691  if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
1692  {
1693  /* In this instance the co-routine could be placed directly
1694  into the ready list as we are within a critical section.
1695  Instead the same pending ready list mechanism is used as if
1696  the event were caused from within an interrupt. */
1698  {
1699  /* The co-routine waiting has a higher priority so record
1700  that a yield might be appropriate. */
1701  xReturn = errQUEUE_YIELD;
1702  }
1703  }
1704  }
1705  else
1706  {
1707  xReturn = errQUEUE_FULL;
1708  }
1709  }
1711 
1712  return xReturn;
1713  }
1714 
1715 #endif /* configUSE_CO_ROUTINES */
1716 /*-----------------------------------------------------------*/
1717 
1718 #if ( configUSE_CO_ROUTINES == 1 )
1719 
1720  signed portBASE_TYPE xQueueCRReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait )
1721  {
1722  signed portBASE_TYPE xReturn;
1723  xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
1724 
1725  /* If the queue is already empty we may have to block. A critical section
1726  is required to prevent an interrupt adding something to the queue
1727  between the check to see if the queue is empty and blocking on the queue. */
1729  {
1730  if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
1731  {
1732  /* There are no messages in the queue, do we want to block or just
1733  leave with nothing? */
1734  if( xTicksToWait > ( portTickType ) 0 )
1735  {
1736  /* As this is a co-routine we cannot block directly, but return
1737  indicating that we need to block. */
1738  vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
1740  return errQUEUE_BLOCKED;
1741  }
1742  else
1743  {
1745  return errQUEUE_FULL;
1746  }
1747  }
1748  }
1750 
1752  {
1753  if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
1754  {
1755  /* Data is available from the queue. */
1756  pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
1757  if( pxQueue->u.pcReadFrom >= pxQueue->pcTail )
1758  {
1759  pxQueue->u.pcReadFrom = pxQueue->pcHead;
1760  }
1761  --( pxQueue->uxMessagesWaiting );
1762  ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
1763 
1764  xReturn = pdPASS;
1765 
1766  /* Were any co-routines waiting for space to become available? */
1767  if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
1768  {
1769  /* In this instance the co-routine could be placed directly
1770  into the ready list as we are within a critical section.
1771  Instead the same pending ready list mechanism is used as if
1772  the event were caused from within an interrupt. */
1774  {
1775  xReturn = errQUEUE_YIELD;
1776  }
1777  }
1778  }
1779  else
1780  {
1781  xReturn = pdFAIL;
1782  }
1783  }
1785 
1786  return xReturn;
1787  }
1788 
1789 #endif /* configUSE_CO_ROUTINES */
1790 /*-----------------------------------------------------------*/
1791 
1792 #if ( configUSE_CO_ROUTINES == 1 )
1793 
1794  signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
1795  {
1796  xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
1797 
1798  /* Cannot block within an ISR so if there is no space on the queue then
1799  exit without doing anything. */
1800  if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
1801  {
1802  prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
1803 
1804  /* We only want to wake one co-routine per ISR, so check that a
1805  co-routine has not already been woken. */
1806  if( xCoRoutinePreviouslyWoken == pdFALSE )
1807  {
1808  if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
1809  {
1811  {
1812  return pdTRUE;
1813  }
1814  }
1815  }
1816  }
1817 
1818  return xCoRoutinePreviouslyWoken;
1819  }
1820 
1821 #endif /* configUSE_CO_ROUTINES */
1822 /*-----------------------------------------------------------*/
1823 
1824 #if ( configUSE_CO_ROUTINES == 1 )
1825 
1826  signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle xQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )
1827  {
1828  signed portBASE_TYPE xReturn;
1829  xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
1830 
1831  /* We cannot block from an ISR, so check there is data available. If
1832  not then just leave without doing anything. */
1833  if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
1834  {
1835  /* Copy the data from the queue. */
1836  pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
1837  if( pxQueue->u.pcReadFrom >= pxQueue->pcTail )
1838  {
1839  pxQueue->u.pcReadFrom = pxQueue->pcHead;
1840  }
1841  --( pxQueue->uxMessagesWaiting );
1842  ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
1843 
1844  if( ( *pxCoRoutineWoken ) == pdFALSE )
1845  {
1846  if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
1847  {
1849  {
1850  *pxCoRoutineWoken = pdTRUE;
1851  }
1852  }
1853  }
1854 
1855  xReturn = pdPASS;
1856  }
1857  else
1858  {
1859  xReturn = pdFAIL;
1860  }
1861 
1862  return xReturn;
1863  }
1864 
1865 #endif /* configUSE_CO_ROUTINES */
1866 /*-----------------------------------------------------------*/
1867 
1868 #if ( configQUEUE_REGISTRY_SIZE > 0 )
1869 
1870  void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )
1871  {
1872  unsigned portBASE_TYPE ux;
1873 
1874  /* See if there is an empty space in the registry. A NULL name denotes
1875  a free slot. */
1876  for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
1877  {
1878  if( xQueueRegistry[ ux ].pcQueueName == NULL )
1879  {
1880  /* Store the information on this queue. */
1881  xQueueRegistry[ ux ].pcQueueName = pcQueueName;
1882  xQueueRegistry[ ux ].xHandle = xQueue;
1883  break;
1884  }
1885  }
1886  }
1887 
1888 #endif /* configQUEUE_REGISTRY_SIZE */
1889 /*-----------------------------------------------------------*/
1890 
1891 #if ( configQUEUE_REGISTRY_SIZE > 0 )
1892 
1893  void vQueueUnregisterQueue( xQueueHandle xQueue )
1894  {
1895  unsigned portBASE_TYPE ux;
1896 
1897  /* See if the handle of the queue being unregistered in actually in the
1898  registry. */
1899  for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
1900  {
1901  if( xQueueRegistry[ ux ].xHandle == xQueue )
1902  {
1903  /* Set the name to NULL to show that this slot if free again. */
1904  xQueueRegistry[ ux ].pcQueueName = NULL;
1905  break;
1906  }
1907  }
1908 
1909  } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
1910 
1911 #endif /* configQUEUE_REGISTRY_SIZE */
1912 /*-----------------------------------------------------------*/
1913 
1914 #if ( configUSE_TIMERS == 1 )
1915 
1916  void vQueueWaitForMessageRestricted( xQueueHandle xQueue, portTickType xTicksToWait )
1917  {
1918  xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
1919 
1920  /* This function should not be called by application code hence the
1921  'Restricted' in its name. It is not part of the public API. It is
1922  designed for use by kernel code, and has special calling requirements.
1923  It can result in vListInsert() being called on a list that can only
1924  possibly ever have one item in it, so the list will be fast, but even
1925  so it should be called with the scheduler locked and not from a critical
1926  section. */
1927 
1928  /* Only do anything if there are no messages in the queue. This function
1929  will not actually cause the task to block, just place it on a blocked
1930  list. It will not block until the scheduler is unlocked - at which
1931  time a yield will be performed. If an item is added to the queue while
1932  the queue is locked, and the calling task blocks on the queue, then the
1933  calling task will be immediately unblocked when the queue is unlocked. */
1934  prvLockQueue( pxQueue );
1935  if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U )
1936  {
1937  /* There is nothing in the queue, block for the specified period. */
1938  vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
1939  }
1940  prvUnlockQueue( pxQueue );
1941  }
1942 
1943 #endif /* configUSE_TIMERS */
1944 /*-----------------------------------------------------------*/
1945 
1946 #if ( configUSE_QUEUE_SETS == 1 )
1947 
1948  xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength )
1949  {
1950  xQueueSetHandle pxQueue;
1951 
1952  pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( xQUEUE * ), queueQUEUE_TYPE_SET );
1953 
1954  return pxQueue;
1955  }
1956 
1957 #endif /* configUSE_QUEUE_SETS */
1958 /*-----------------------------------------------------------*/
1959 
1960 #if ( configUSE_QUEUE_SETS == 1 )
1961 
1962  portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )
1963  {
1964  portBASE_TYPE xReturn;
1965 
1966  if( ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )
1967  {
1968  /* Cannot add a queue/semaphore to more than one queue set. */
1969  xReturn = pdFAIL;
1970  }
1971  else if( ( ( xQUEUE * ) xQueueOrSemaphore )->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 )
1972  {
1973  /* Cannot add a queue/semaphore to a queue set if there are already
1974  items in the queue/semaphore. */
1975  xReturn = pdFAIL;
1976  }
1977  else
1978  {
1980  {
1981  ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet;
1982  }
1984  xReturn = pdPASS;
1985  }
1986 
1987  return xReturn;
1988  }
1989 
1990 #endif /* configUSE_QUEUE_SETS */
1991 /*-----------------------------------------------------------*/
1992 
1993 #if ( configUSE_QUEUE_SETS == 1 )
1994 
1995  portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )
1996  {
1997  portBASE_TYPE xReturn;
1998  xQUEUE * const pxQueueOrSemaphore = ( xQUEUE * ) xQueueOrSemaphore;
1999 
2000  if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet )
2001  {
2002  /* The queue was not a member of the set. */
2003  xReturn = pdFAIL;
2004  }
2005  else if( pxQueueOrSemaphore->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 )
2006  {
2007  /* It is dangerous to remove a queue from a set when the queue is
2008  not empty because the queue set will still hold pending events for
2009  the queue. */
2010  xReturn = pdFAIL;
2011  }
2012  else
2013  {
2015  {
2016  /* The queue is no longer contained in the set. */
2017  pxQueueOrSemaphore->pxQueueSetContainer = NULL;
2018  }
2020  xReturn = pdPASS;
2021  }
2022 
2023  return xReturn;
2024  } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */
2025 
2026 #endif /* configUSE_QUEUE_SETS */
2027 /*-----------------------------------------------------------*/
2028 
2029 #if ( configUSE_QUEUE_SETS == 1 )
2030 
2032  {
2033  xQueueSetMemberHandle xReturn = NULL;
2034 
2035  ( void ) xQueueGenericReceive( ( xQueueHandle ) xQueueSet, &xReturn, xBlockTimeTicks, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */
2036  return xReturn;
2037  }
2038 
2039 #endif /* configUSE_QUEUE_SETS */
2040 /*-----------------------------------------------------------*/
2041 
2042 #if ( configUSE_QUEUE_SETS == 1 )
2043 
2045  {
2046  xQueueSetMemberHandle xReturn = NULL;
2047 
2048  ( void ) xQueueReceiveFromISR( ( xQueueHandle ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */
2049  return xReturn;
2050  }
2051 
2052 #endif /* configUSE_QUEUE_SETS */
2053 /*-----------------------------------------------------------*/
2054 
2055 #if ( configUSE_QUEUE_SETS == 1 )
2056 
2057  static portBASE_TYPE prvNotifyQueueSetContainer( const xQUEUE * const pxQueue, portBASE_TYPE xCopyPosition )
2058  {
2059  xQUEUE *pxQueueSetContainer = pxQueue->pxQueueSetContainer;
2060  portBASE_TYPE xReturn = pdFALSE;
2061 
2062  configASSERT( pxQueueSetContainer );
2063  configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );
2064 
2065  if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )
2066  {
2067  traceQUEUE_SEND( pxQueueSetContainer );
2068  /* The data copies is the handle of the queue that contains data. */
2069  prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition );
2070  if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE )
2071  {
2072  if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE )
2073  {
2074  /* The task waiting has a higher priority */
2075  xReturn = pdTRUE;
2076  }
2077  }
2078  }
2079 
2080  return xReturn;
2081  }
2082 
2083 #endif /* configUSE_QUEUE_SETS */
2084