2 FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.
\r
5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
7 ***************************************************************************
\r
9 * FreeRTOS provides completely free yet professionally developed, *
\r
10 * robust, strictly quality controlled, supported, and cross *
\r
11 * platform software that has become a de facto standard. *
\r
13 * Help yourself get started quickly and support the FreeRTOS *
\r
14 * project by purchasing a FreeRTOS tutorial book, reference *
\r
15 * manual, or both from: http://www.FreeRTOS.org/Documentation *
\r
19 ***************************************************************************
\r
21 This file is part of the FreeRTOS distribution.
\r
23 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
24 the terms of the GNU General Public License (version 2) as published by the
\r
25 Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
\r
27 >>! NOTE: The modification to the GPL is included to allow you to distribute
\r
28 >>! a combined work that includes FreeRTOS without being obliged to provide
\r
29 >>! the source code for proprietary components outside of the FreeRTOS
\r
32 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
33 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
34 FOR A PARTICULAR PURPOSE. Full license text is available from the following
\r
35 link: http://www.freertos.org/a00114.html
\r
39 ***************************************************************************
\r
41 * Having a problem? Start by reading the FAQ "My application does *
\r
42 * not run, what could be wrong?" *
\r
44 * http://www.FreeRTOS.org/FAQHelp.html *
\r
46 ***************************************************************************
\r
48 http://www.FreeRTOS.org - Documentation, books, training, latest versions,
\r
49 license and Real Time Engineers Ltd. contact details.
\r
51 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
52 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
\r
53 compatible FAT file system, and our tiny thread aware UDP/IP stack.
\r
55 http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
\r
56 Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
\r
57 licenses offer ticketed support, indemnification and middleware.
\r
59 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
60 engineered and independently SIL3 certified version for use in safety and
\r
61 mission critical applications that require provable dependability.
\r
69 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
\r
70 all the API functions to use the MPU wrappers. That should only be done when
\r
71 task.h is included from an application file. */
\r
72 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
74 #include "FreeRTOS.h"
\r
78 #if ( configUSE_CO_ROUTINES == 1 )
\r
79 #include "croutine.h"
\r
82 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the
\r
83 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
\r
84 header files above, but not in this file, in order to generate the correct
\r
85 privileged Vs unprivileged linkage and placement. */
\r
86 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
\r
89 /* Constants used with the cRxLock and xTxLock structure members. */
\r
90 #define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 )
\r
91 #define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 )
\r
93 /* When the xQUEUE structure is used to represent a base queue its pcHead and
\r
94 pcTail members are used as pointers into the queue storage area. When the
\r
95 xQUEUE structure is used to represent a mutex pcHead and pcTail pointers are
\r
96 not necessary, and the pcHead pointer is set to NULL to indicate that the
\r
97 pcTail pointer actually points to the mutex holder (if any). Map alternative
\r
98 names to the pcHead and pcTail structure members to ensure the readability of
\r
99 the code is maintained despite this dual use of two structure members. An
\r
100 alternative implementation would be to use a union, but use of a union is
\r
101 against the coding standard (although an exception to the standard has been
\r
102 permitted where the dual use also significantly changes the type of the
\r
103 structure member). */
\r
104 #define pxMutexHolder pcTail
\r
105 #define uxQueueType pcHead
\r
106 #define queueQUEUE_IS_MUTEX NULL
\r
108 /* Semaphores do not actually store or copy data, so have an item size of
\r
110 #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portBASE_TYPE ) 0 )
\r
111 #define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0U )
\r
113 #if( configUSE_PREEMPTION == 0 )
\r
114 /* If the cooperative scheduler is being used then a yield should not be
\r
115 performed just because a higher priority task has been woken. */
\r
116 #define queueYIELD_IF_USING_PREEMPTION()
\r
118 #define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
\r
122 * Definition of the queue used by the scheduler.
\r
123 * Items are queued by copy, not reference.
\r
125 typedef struct QueueDefinition
\r
127 signed char *pcHead; /*< Points to the beginning of the queue storage area. */
\r
128 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. */
\r
130 signed char *pcWriteTo; /*< Points to the free next place in the storage area. */
\r
132 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
134 signed char *pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */
\r
135 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. */
\r
138 xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */
\r
139 xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */
\r
141 volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */
\r
142 unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
\r
143 unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */
\r
145 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. */
\r
146 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. */
\r
148 #if ( configUSE_TRACE_FACILITY == 1 )
\r
149 unsigned char ucQueueNumber;
\r
150 unsigned char ucQueueType;
\r
153 #if ( configUSE_QUEUE_SETS == 1 )
\r
154 struct QueueDefinition *pxQueueSetContainer;
\r
158 /*-----------------------------------------------------------*/
\r
161 * The queue registry is just a means for kernel aware debuggers to locate
\r
162 * queue structures. It has no other purpose so is an optional component.
\r
164 #if ( configQUEUE_REGISTRY_SIZE > 0 )
\r
166 /* The type stored within the queue registry array. This allows a name
\r
167 to be assigned to each queue making kernel aware debugging a little
\r
168 more user friendly. */
\r
169 typedef struct QUEUE_REGISTRY_ITEM
\r
171 signed char *pcQueueName;
\r
172 xQueueHandle xHandle;
\r
173 } xQueueRegistryItem;
\r
175 /* The queue registry is simply an array of xQueueRegistryItem structures.
\r
176 The pcQueueName member of a structure being NULL is indicative of the
\r
177 array position being vacant. */
\r
178 xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
\r
180 #endif /* configQUEUE_REGISTRY_SIZE */
\r
183 * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not
\r
184 * prevent an ISR from adding or removing items to the queue, but does prevent
\r
185 * an ISR from removing tasks from the queue event lists. If an ISR finds a
\r
186 * queue is locked it will instead increment the appropriate queue lock count
\r
187 * to indicate that a task may require unblocking. When the queue in unlocked
\r
188 * these lock counts are inspected, and the appropriate action taken.
\r
190 static void prvUnlockQueue( xQUEUE *pxQueue ) PRIVILEGED_FUNCTION;
\r
193 * Uses a critical section to determine if there is any data in a queue.
\r
195 * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
\r
197 static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue ) PRIVILEGED_FUNCTION;
\r
200 * Uses a critical section to determine if there is any space in a queue.
\r
202 * @return pdTRUE if there is no space, otherwise pdFALSE;
\r
204 static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue ) PRIVILEGED_FUNCTION;
\r
207 * Copies an item into the queue, either at the front of the queue or the
\r
208 * back of the queue.
\r
210 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION;
\r
213 * Copies an item out of a queue.
\r
215 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION;
\r
217 #if ( configUSE_QUEUE_SETS == 1 )
\r
219 * Checks to see if a queue is a member of a queue set, and if so, notifies
\r
220 * the queue set that the queue contains data.
\r
222 static portBASE_TYPE prvNotifyQueueSetContainer( const xQUEUE * const pxQueue, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
\r
225 /*-----------------------------------------------------------*/
\r
228 * Macro to mark a queue as locked. Locking a queue prevents an ISR from
\r
229 * accessing the queue event lists.
\r
231 #define prvLockQueue( pxQueue ) \
\r
232 taskENTER_CRITICAL(); \
\r
234 if( ( pxQueue )->xRxLock == queueUNLOCKED ) \
\r
236 ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED; \
\r
238 if( ( pxQueue )->xTxLock == queueUNLOCKED ) \
\r
240 ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED; \
\r
243 taskEXIT_CRITICAL()
\r
244 /*-----------------------------------------------------------*/
\r
246 portBASE_TYPE xQueueGenericReset( xQueueHandle xQueue, portBASE_TYPE xNewQueue )
\r
248 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
250 configASSERT( pxQueue );
\r
252 taskENTER_CRITICAL();
\r
254 pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize );
\r
255 pxQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
\r
256 pxQueue->pcWriteTo = pxQueue->pcHead;
\r
257 pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( unsigned portBASE_TYPE ) 1U ) * pxQueue->uxItemSize );
\r
258 pxQueue->xRxLock = queueUNLOCKED;
\r
259 pxQueue->xTxLock = queueUNLOCKED;
\r
261 if( xNewQueue == pdFALSE )
\r
263 /* If there are tasks blocked waiting to read from the queue, then
\r
264 the tasks will remain blocked as after this function exits the queue
\r
265 will still be empty. If there are tasks blocked waiting to write to
\r
266 the queue, then one should be unblocked as after this function exits
\r
267 it will be possible to write to it. */
\r
268 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
270 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
272 queueYIELD_IF_USING_PREEMPTION();
\r
278 /* Ensure the event queues start in the correct state. */
\r
279 vListInitialise( &( pxQueue->xTasksWaitingToSend ) );
\r
280 vListInitialise( &( pxQueue->xTasksWaitingToReceive ) );
\r
283 taskEXIT_CRITICAL();
\r
285 /* A value is returned for calling semantic consistency with previous
\r
289 /*-----------------------------------------------------------*/
\r
291 xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType )
\r
293 xQUEUE *pxNewQueue;
\r
294 size_t xQueueSizeInBytes;
\r
295 xQueueHandle xReturn = NULL;
\r
297 /* Remove compiler warnings about unused parameters should
\r
298 configUSE_TRACE_FACILITY not be set to 1. */
\r
299 ( void ) ucQueueType;
\r
301 /* Allocate the new queue structure. */
\r
302 if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )
\r
304 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
\r
305 if( pxNewQueue != NULL )
\r
307 /* Create the list of pointers to queue items. The queue is one byte
\r
308 longer than asked for to make wrap checking easier/faster. */
\r
309 xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
311 pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes );
\r
312 if( pxNewQueue->pcHead != NULL )
\r
314 /* Initialise the queue members as described above where the
\r
315 queue type is defined. */
\r
316 pxNewQueue->uxLength = uxQueueLength;
\r
317 pxNewQueue->uxItemSize = uxItemSize;
\r
318 ( void ) xQueueGenericReset( pxNewQueue, pdTRUE );
\r
320 #if ( configUSE_TRACE_FACILITY == 1 )
\r
322 pxNewQueue->ucQueueType = ucQueueType;
\r
324 #endif /* configUSE_TRACE_FACILITY */
\r
326 #if( configUSE_QUEUE_SETS == 1 )
\r
328 pxNewQueue->pxQueueSetContainer = NULL;
\r
330 #endif /* configUSE_QUEUE_SETS */
\r
332 traceQUEUE_CREATE( pxNewQueue );
\r
333 xReturn = pxNewQueue;
\r
337 traceQUEUE_CREATE_FAILED( ucQueueType );
\r
338 vPortFree( pxNewQueue );
\r
343 configASSERT( xReturn );
\r
347 /*-----------------------------------------------------------*/
\r
349 #if ( configUSE_MUTEXES == 1 )
\r
351 xQueueHandle xQueueCreateMutex( unsigned char ucQueueType )
\r
353 xQUEUE *pxNewQueue;
\r
355 /* Prevent compiler warnings about unused parameters if
\r
356 configUSE_TRACE_FACILITY does not equal 1. */
\r
357 ( void ) ucQueueType;
\r
359 /* Allocate the new queue structure. */
\r
360 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
\r
361 if( pxNewQueue != NULL )
\r
363 /* Information required for priority inheritance. */
\r
364 pxNewQueue->pxMutexHolder = NULL;
\r
365 pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
\r
367 /* Queues used as a mutex no data is actually copied into or out
\r
369 pxNewQueue->pcWriteTo = NULL;
\r
370 pxNewQueue->u.pcReadFrom = NULL;
\r
372 /* Each mutex has a length of 1 (like a binary semaphore) and
\r
373 an item size of 0 as nothing is actually copied into or out
\r
375 pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
\r
376 pxNewQueue->uxLength = ( unsigned portBASE_TYPE ) 1U;
\r
377 pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 0U;
\r
378 pxNewQueue->xRxLock = queueUNLOCKED;
\r
379 pxNewQueue->xTxLock = queueUNLOCKED;
\r
381 #if ( configUSE_TRACE_FACILITY == 1 )
\r
383 pxNewQueue->ucQueueType = ucQueueType;
\r
387 #if ( configUSE_QUEUE_SETS == 1 )
\r
389 pxNewQueue->pxQueueSetContainer = NULL;
\r
393 /* Ensure the event queues start with the correct state. */
\r
394 vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
\r
395 vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
\r
397 traceCREATE_MUTEX( pxNewQueue );
\r
399 /* Start with the semaphore in the expected state. */
\r
400 ( void ) xQueueGenericSend( pxNewQueue, NULL, ( portTickType ) 0U, queueSEND_TO_BACK );
\r
404 traceCREATE_MUTEX_FAILED();
\r
407 configASSERT( pxNewQueue );
\r
411 #endif /* configUSE_MUTEXES */
\r
412 /*-----------------------------------------------------------*/
\r
414 #if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
\r
416 void* xQueueGetMutexHolder( xQueueHandle xSemaphore )
\r
420 /* This function is called by xSemaphoreGetMutexHolder(), and should not
\r
421 be called directly. Note: This is is a good way of determining if the
\r
422 calling task is the mutex holder, but not a good way of determining the
\r
423 identity of the mutex holder, as the holder may change between the
\r
424 following critical section exiting and the function returning. */
\r
425 taskENTER_CRITICAL();
\r
427 if( ( ( xQUEUE * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX )
\r
429 pxReturn = ( void * ) ( ( xQUEUE * ) xSemaphore )->pxMutexHolder;
\r
436 taskEXIT_CRITICAL();
\r
442 /*-----------------------------------------------------------*/
\r
444 #if ( configUSE_RECURSIVE_MUTEXES == 1 )
\r
446 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex )
\r
448 portBASE_TYPE xReturn;
\r
449 xQUEUE * const pxMutex = ( xQUEUE * ) xMutex;
\r
451 configASSERT( pxMutex );
\r
453 /* If this is the task that holds the mutex then pxMutexHolder will not
\r
454 change outside of this task. If this task does not hold the mutex then
\r
455 pxMutexHolder can never coincidentally equal the tasks handle, and as
\r
456 this is the only condition we are interested in it does not matter if
\r
457 pxMutexHolder is accessed simultaneously by another task. Therefore no
\r
458 mutual exclusion is required to test the pxMutexHolder variable. */
\r
459 if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Not a redundant cast as xTaskHandle is a typedef. */
\r
461 traceGIVE_MUTEX_RECURSIVE( pxMutex );
\r
463 /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to
\r
464 the task handle, therefore no underflow check is required. Also,
\r
465 uxRecursiveCallCount is only modified by the mutex holder, and as
\r
466 there can only be one, no mutual exclusion is required to modify the
\r
467 uxRecursiveCallCount member. */
\r
468 ( pxMutex->u.uxRecursiveCallCount )--;
\r
470 /* Have we unwound the call count? */
\r
471 if( pxMutex->u.uxRecursiveCallCount == ( unsigned portBASE_TYPE ) 0 )
\r
473 /* Return the mutex. This will automatically unblock any other
\r
474 task that might be waiting to access the mutex. */
\r
475 ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
\r
482 /* We cannot give the mutex because we are not the holder. */
\r
485 traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
\r
491 #endif /* configUSE_RECURSIVE_MUTEXES */
\r
492 /*-----------------------------------------------------------*/
\r
494 #if ( configUSE_RECURSIVE_MUTEXES == 1 )
\r
496 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime )
\r
498 portBASE_TYPE xReturn;
\r
499 xQUEUE * const pxMutex = ( xQUEUE * ) xMutex;
\r
501 configASSERT( pxMutex );
\r
503 /* Comments regarding mutual exclusion as per those within
\r
504 xQueueGiveMutexRecursive(). */
\r
506 traceTAKE_MUTEX_RECURSIVE( pxMutex );
\r
508 if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Cast is not redundant as xTaskHandle is a typedef. */
\r
510 ( pxMutex->u.uxRecursiveCallCount )++;
\r
515 xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );
\r
517 /* pdPASS will only be returned if we successfully obtained the mutex,
\r
518 we may have blocked to reach here. */
\r
519 if( xReturn == pdPASS )
\r
521 ( pxMutex->u.uxRecursiveCallCount )++;
\r
525 traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );
\r
532 #endif /* configUSE_RECURSIVE_MUTEXES */
\r
533 /*-----------------------------------------------------------*/
\r
535 #if ( configUSE_COUNTING_SEMAPHORES == 1 )
\r
537 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount )
\r
539 xQueueHandle xHandle;
\r
541 configASSERT( uxMaxCount != 0 );
\r
542 configASSERT( uxInitialCount <= uxMaxCount );
\r
544 xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
\r
546 if( xHandle != NULL )
\r
548 ( ( xQUEUE * ) xHandle )->uxMessagesWaiting = uxInitialCount;
\r
550 traceCREATE_COUNTING_SEMAPHORE();
\r
554 traceCREATE_COUNTING_SEMAPHORE_FAILED();
\r
557 configASSERT( xHandle );
\r
561 #endif /* configUSE_COUNTING_SEMAPHORES */
\r
562 /*-----------------------------------------------------------*/
\r
564 signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
\r
566 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
567 xTimeOutType xTimeOut;
\r
568 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
570 configASSERT( pxQueue );
\r
571 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
572 configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
\r
574 /* This function relaxes the coding standard somewhat to allow return
\r
575 statements within the function itself. This is done in the interest
\r
576 of execution time efficiency. */
\r
579 taskENTER_CRITICAL();
\r
581 /* Is there room on the queue now? The running task must be
\r
582 the highest priority task wanting to access the queue. If
\r
583 the head item in the queue is to be overwritten then it does
\r
584 not matter if the queue is full. */
\r
585 if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
\r
587 traceQUEUE_SEND( pxQueue );
\r
588 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
590 #if ( configUSE_QUEUE_SETS == 1 )
\r
592 if( pxQueue->pxQueueSetContainer != NULL )
\r
594 if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )
\r
596 /* The queue is a member of a queue set, and posting
\r
597 to the queue set caused a higher priority task to
\r
598 unblock. A context switch is required. */
\r
599 queueYIELD_IF_USING_PREEMPTION();
\r
604 /* If there was a task waiting for data to arrive on the
\r
605 queue then unblock it now. */
\r
606 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
608 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
610 /* The unblocked task has a priority higher than
\r
611 our own so yield immediately. Yes it is ok to
\r
612 do this from within the critical section - the
\r
613 kernel takes care of that. */
\r
614 queueYIELD_IF_USING_PREEMPTION();
\r
619 #else /* configUSE_QUEUE_SETS */
\r
621 /* If there was a task waiting for data to arrive on the
\r
622 queue then unblock it now. */
\r
623 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
625 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
627 /* The unblocked task has a priority higher than
\r
628 our own so yield immediately. Yes it is ok to do
\r
629 this from within the critical section - the kernel
\r
630 takes care of that. */
\r
631 queueYIELD_IF_USING_PREEMPTION();
\r
635 #endif /* configUSE_QUEUE_SETS */
\r
637 taskEXIT_CRITICAL();
\r
639 /* Return to the original privilege level before exiting the
\r
645 if( xTicksToWait == ( portTickType ) 0 )
\r
647 /* The queue was full and no block time is specified (or
\r
648 the block time has expired) so leave now. */
\r
649 taskEXIT_CRITICAL();
\r
651 /* Return to the original privilege level before exiting
\r
653 traceQUEUE_SEND_FAILED( pxQueue );
\r
654 return errQUEUE_FULL;
\r
656 else if( xEntryTimeSet == pdFALSE )
\r
658 /* The queue was full and a block time was specified so
\r
659 configure the timeout structure. */
\r
660 vTaskSetTimeOutState( &xTimeOut );
\r
661 xEntryTimeSet = pdTRUE;
\r
665 /* Entry time was already set. */
\r
669 taskEXIT_CRITICAL();
\r
671 /* Interrupts and other tasks can send to and receive from the queue
\r
672 now the critical section has been exited. */
\r
675 prvLockQueue( pxQueue );
\r
677 /* Update the timeout state to see if it has expired yet. */
\r
678 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
680 if( prvIsQueueFull( pxQueue ) != pdFALSE )
\r
682 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
\r
683 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
\r
685 /* Unlocking the queue means queue events can effect the
\r
686 event list. It is possible that interrupts occurring now
\r
687 remove this task from the event list again - but as the
\r
688 scheduler is suspended the task will go onto the pending
\r
689 ready last instead of the actual ready list. */
\r
690 prvUnlockQueue( pxQueue );
\r
692 /* Resuming the scheduler will move tasks from the pending
\r
693 ready list into the ready list - so it is feasible that this
\r
694 task is already in a ready list before it yields - in which
\r
695 case the yield will not cause a context switch unless there
\r
696 is also a higher priority task in the pending ready list. */
\r
697 if( xTaskResumeAll() == pdFALSE )
\r
699 portYIELD_WITHIN_API();
\r
705 prvUnlockQueue( pxQueue );
\r
706 ( void ) xTaskResumeAll();
\r
711 /* The timeout has expired. */
\r
712 prvUnlockQueue( pxQueue );
\r
713 ( void ) xTaskResumeAll();
\r
715 /* Return to the original privilege level before exiting the
\r
717 traceQUEUE_SEND_FAILED( pxQueue );
\r
718 return errQUEUE_FULL;
\r
722 /*-----------------------------------------------------------*/
\r
724 #if ( configUSE_ALTERNATIVE_API == 1 )
\r
726 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
\r
728 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
729 xTimeOutType xTimeOut;
\r
730 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
732 configASSERT( pxQueue );
\r
733 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
737 taskENTER_CRITICAL();
\r
739 /* Is there room on the queue now? To be running we must be
\r
740 the highest priority task wanting to access the queue. */
\r
741 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
743 traceQUEUE_SEND( pxQueue );
\r
744 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
746 /* If there was a task waiting for data to arrive on the
\r
747 queue then unblock it now. */
\r
748 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
750 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
752 /* The unblocked task has a priority higher than
\r
753 our own so yield immediately. */
\r
754 portYIELD_WITHIN_API();
\r
758 taskEXIT_CRITICAL();
\r
763 if( xTicksToWait == ( portTickType ) 0 )
\r
765 taskEXIT_CRITICAL();
\r
766 return errQUEUE_FULL;
\r
768 else if( xEntryTimeSet == pdFALSE )
\r
770 vTaskSetTimeOutState( &xTimeOut );
\r
771 xEntryTimeSet = pdTRUE;
\r
775 taskEXIT_CRITICAL();
\r
777 taskENTER_CRITICAL();
\r
779 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
781 if( prvIsQueueFull( pxQueue ) != pdFALSE )
\r
783 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
\r
784 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
\r
785 portYIELD_WITHIN_API();
\r
790 taskEXIT_CRITICAL();
\r
791 traceQUEUE_SEND_FAILED( pxQueue );
\r
792 return errQUEUE_FULL;
\r
795 taskEXIT_CRITICAL();
\r
799 #endif /* configUSE_ALTERNATIVE_API */
\r
800 /*-----------------------------------------------------------*/
\r
802 #if ( configUSE_ALTERNATIVE_API == 1 )
\r
804 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
\r
806 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
807 xTimeOutType xTimeOut;
\r
808 signed char *pcOriginalReadPosition;
\r
809 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
811 configASSERT( pxQueue );
\r
812 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
816 taskENTER_CRITICAL();
\r
818 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
820 /* Remember our read position in case we are just peeking. */
\r
821 pcOriginalReadPosition = pxQueue->u.pcReadFrom;
\r
823 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
825 if( xJustPeeking == pdFALSE )
\r
827 traceQUEUE_RECEIVE( pxQueue );
\r
829 /* Data is actually being removed (not just peeked). */
\r
830 --( pxQueue->uxMessagesWaiting );
\r
832 #if ( configUSE_MUTEXES == 1 )
\r
834 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
836 /* Record the information required to implement
\r
837 priority inheritance should it become necessary. */
\r
838 pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle();
\r
843 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
845 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
847 portYIELD_WITHIN_API();
\r
853 traceQUEUE_PEEK( pxQueue );
\r
855 /* We are not removing the data, so reset our read
\r
857 pxQueue->u.pcReadFrom = pcOriginalReadPosition;
\r
859 /* The data is being left in the queue, so see if there are
\r
860 any other tasks waiting for the data. */
\r
861 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
863 /* Tasks that are removed from the event list will get added to
\r
864 the pending ready list as the scheduler is still suspended. */
\r
865 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
867 /* The task waiting has a higher priority than this task. */
\r
868 portYIELD_WITHIN_API();
\r
874 taskEXIT_CRITICAL();
\r
879 if( xTicksToWait == ( portTickType ) 0 )
\r
881 taskEXIT_CRITICAL();
\r
882 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
883 return errQUEUE_EMPTY;
\r
885 else if( xEntryTimeSet == pdFALSE )
\r
887 vTaskSetTimeOutState( &xTimeOut );
\r
888 xEntryTimeSet = pdTRUE;
\r
892 taskEXIT_CRITICAL();
\r
894 taskENTER_CRITICAL();
\r
896 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
898 if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
\r
900 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
\r
902 #if ( configUSE_MUTEXES == 1 )
\r
904 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
906 portENTER_CRITICAL();
\r
908 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
\r
910 portEXIT_CRITICAL();
\r
915 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
916 portYIELD_WITHIN_API();
\r
921 taskEXIT_CRITICAL();
\r
922 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
923 return errQUEUE_EMPTY;
\r
926 taskEXIT_CRITICAL();
\r
931 #endif /* configUSE_ALTERNATIVE_API */
\r
932 /*-----------------------------------------------------------*/
\r
934 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )
\r
936 signed portBASE_TYPE xReturn;
\r
937 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
938 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
940 configASSERT( pxQueue );
\r
941 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
942 configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
\r
944 /* RTOS ports that support interrupt nesting have the concept of a maximum
\r
945 system call (or maximum API call) interrupt priority. Interrupts that are
\r
946 above the maximum system call priority are keep permanently enabled, even
\r
947 when the RTOS kernel is in a critical section, but cannot make any calls to
\r
948 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
\r
949 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
950 failure if a FreeRTOS API function is called from an interrupt that has been
\r
951 assigned a priority above the configured maximum system call priority.
\r
952 Only FreeRTOS functions that end in FromISR can be called from interrupts
\r
953 that have been assigned a priority at or (logically) below the maximum
\r
954 system call interrupt priority. FreeRTOS maintains a separate interrupt
\r
955 safe API to ensure interrupt entry is as fast and as simple as possible.
\r
956 More information (albeit Cortex-M specific) is provided on the following
\r
957 link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
958 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
960 /* Similar to xQueueGenericSend, except we don't block if there is no room
\r
961 in the queue. Also we don't directly wake a task that was blocked on a
\r
962 queue read, instead we return a flag to say whether a context switch is
\r
963 required or not (i.e. has a task with a higher priority than us been woken
\r
965 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
967 if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
\r
969 traceQUEUE_SEND_FROM_ISR( pxQueue );
\r
971 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
973 /* If the queue is locked we do not alter the event list. This will
\r
974 be done when the queue is unlocked later. */
\r
975 if( pxQueue->xTxLock == queueUNLOCKED )
\r
977 #if ( configUSE_QUEUE_SETS == 1 )
\r
979 if( pxQueue->pxQueueSetContainer != NULL )
\r
981 if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )
\r
983 /* The queue is a member of a queue set, and posting
\r
984 to the queue set caused a higher priority task to
\r
985 unblock. A context switch is required. */
\r
986 if( pxHigherPriorityTaskWoken != NULL )
\r
988 *pxHigherPriorityTaskWoken = pdTRUE;
\r
994 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
996 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
998 /* The task waiting has a higher priority so record that a
\r
999 context switch is required. */
\r
1000 if( pxHigherPriorityTaskWoken != NULL )
\r
1002 *pxHigherPriorityTaskWoken = pdTRUE;
\r
1008 #else /* configUSE_QUEUE_SETS */
\r
1010 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1012 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1014 /* The task waiting has a higher priority so record that a
\r
1015 context switch is required. */
\r
1016 if( pxHigherPriorityTaskWoken != NULL )
\r
1018 *pxHigherPriorityTaskWoken = pdTRUE;
\r
1023 #endif /* configUSE_QUEUE_SETS */
\r
1027 /* Increment the lock count so the task that unlocks the queue
\r
1028 knows that data was posted while it was locked. */
\r
1029 ++( pxQueue->xTxLock );
\r
1036 traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
\r
1037 xReturn = errQUEUE_FULL;
\r
1040 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1044 /*-----------------------------------------------------------*/
\r
1046 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
\r
1048 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
1049 xTimeOutType xTimeOut;
\r
1050 signed char *pcOriginalReadPosition;
\r
1051 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
1053 configASSERT( pxQueue );
\r
1054 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
1056 /* This function relaxes the coding standard somewhat to allow return
\r
1057 statements within the function itself. This is done in the interest
\r
1058 of execution time efficiency. */
\r
1062 taskENTER_CRITICAL();
\r
1064 /* Is there data in the queue now? To be running we must be
\r
1065 the highest priority task wanting to access the queue. */
\r
1066 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1068 /* Remember the read position in case the queue is only being
\r
1070 pcOriginalReadPosition = pxQueue->u.pcReadFrom;
\r
1072 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
1074 if( xJustPeeking == pdFALSE )
\r
1076 traceQUEUE_RECEIVE( pxQueue );
\r
1078 /* Actually removing data, not just peeking. */
\r
1079 --( pxQueue->uxMessagesWaiting );
\r
1081 #if ( configUSE_MUTEXES == 1 )
\r
1083 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
1085 /* Record the information required to implement
\r
1086 priority inheritance should it become necessary. */
\r
1087 pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle(); /*lint !e961 Cast is not redundant as xTaskHandle is a typedef. */
\r
1092 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1094 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
1096 queueYIELD_IF_USING_PREEMPTION();
\r
1102 traceQUEUE_PEEK( pxQueue );
\r
1104 /* The data is not being removed, so reset the read
\r
1106 pxQueue->u.pcReadFrom = pcOriginalReadPosition;
\r
1108 /* The data is being left in the queue, so see if there are
\r
1109 any other tasks waiting for the data. */
\r
1110 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1112 /* Tasks that are removed from the event list will get added to
\r
1113 the pending ready list as the scheduler is still suspended. */
\r
1114 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1116 /* The task waiting has a higher priority than this task. */
\r
1117 queueYIELD_IF_USING_PREEMPTION();
\r
1122 taskEXIT_CRITICAL();
\r
1127 if( xTicksToWait == ( portTickType ) 0 )
\r
1129 /* The queue was empty and no block time is specified (or
\r
1130 the block time has expired) so leave now. */
\r
1131 taskEXIT_CRITICAL();
\r
1132 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
1133 return errQUEUE_EMPTY;
\r
1135 else if( xEntryTimeSet == pdFALSE )
\r
1137 /* The queue was empty and a block time was specified so
\r
1138 configure the timeout structure. */
\r
1139 vTaskSetTimeOutState( &xTimeOut );
\r
1140 xEntryTimeSet = pdTRUE;
\r
1144 /* Entry time was already set. */
\r
1148 taskEXIT_CRITICAL();
\r
1150 /* Interrupts and other tasks can send to and receive from the queue
\r
1151 now the critical section has been exited. */
\r
1153 vTaskSuspendAll();
\r
1154 prvLockQueue( pxQueue );
\r
1156 /* Update the timeout state to see if it has expired yet. */
\r
1157 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
1159 if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
\r
1161 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
\r
1163 #if ( configUSE_MUTEXES == 1 )
\r
1165 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
1167 portENTER_CRITICAL();
\r
1169 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
\r
1171 portEXIT_CRITICAL();
\r
1176 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
1177 prvUnlockQueue( pxQueue );
\r
1178 if( xTaskResumeAll() == pdFALSE )
\r
1180 portYIELD_WITHIN_API();
\r
1186 prvUnlockQueue( pxQueue );
\r
1187 ( void ) xTaskResumeAll();
\r
1192 prvUnlockQueue( pxQueue );
\r
1193 ( void ) xTaskResumeAll();
\r
1194 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
1195 return errQUEUE_EMPTY;
\r
1199 /*-----------------------------------------------------------*/
\r
1201 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle xQueue, void * const pvBuffer, signed portBASE_TYPE *pxHigherPriorityTaskWoken )
\r
1203 signed portBASE_TYPE xReturn;
\r
1204 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
1205 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
1207 configASSERT( pxQueue );
\r
1208 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
1210 /* RTOS ports that support interrupt nesting have the concept of a maximum
\r
1211 system call (or maximum API call) interrupt priority. Interrupts that are
\r
1212 above the maximum system call priority are keep permanently enabled, even
\r
1213 when the RTOS kernel is in a critical section, but cannot make any calls to
\r
1214 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
\r
1215 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1216 failure if a FreeRTOS API function is called from an interrupt that has been
\r
1217 assigned a priority above the configured maximum system call priority.
\r
1218 Only FreeRTOS functions that end in FromISR can be called from interrupts
\r
1219 that have been assigned a priority at or (logically) below the maximum
\r
1220 system call interrupt priority. FreeRTOS maintains a separate interrupt
\r
1221 safe API to ensure interrupt entry is as fast and as simple as possible.
\r
1222 More information (albeit Cortex-M specific) is provided on the following
\r
1223 link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1224 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1226 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1228 /* Cannot block in an ISR, so check there is data available. */
\r
1229 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1231 traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
\r
1233 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
1234 --( pxQueue->uxMessagesWaiting );
\r
1236 /* If the queue is locked the event list will not be modified.
\r
1237 Instead update the lock count so the task that unlocks the queue
\r
1238 will know that an ISR has removed data while the queue was
\r
1240 if( pxQueue->xRxLock == queueUNLOCKED )
\r
1242 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1244 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1246 /* The task waiting has a higher priority than us so
\r
1247 force a context switch. */
\r
1248 if( pxHigherPriorityTaskWoken != NULL )
\r
1250 *pxHigherPriorityTaskWoken = pdTRUE;
\r
1257 /* Increment the lock count so the task that unlocks the queue
\r
1258 knows that data was removed while it was locked. */
\r
1259 ++( pxQueue->xRxLock );
\r
1267 traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
\r
1270 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1274 /*-----------------------------------------------------------*/
\r
1276 signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, void * const pvBuffer )
\r
1278 signed portBASE_TYPE xReturn;
\r
1279 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
1280 signed char *pcOriginalReadPosition;
\r
1281 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
1283 configASSERT( pxQueue );
\r
1284 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
1286 /* RTOS ports that support interrupt nesting have the concept of a maximum
\r
1287 system call (or maximum API call) interrupt priority. Interrupts that are
\r
1288 above the maximum system call priority are keep permanently enabled, even
\r
1289 when the RTOS kernel is in a critical section, but cannot make any calls to
\r
1290 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
\r
1291 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1292 failure if a FreeRTOS API function is called from an interrupt that has been
\r
1293 assigned a priority above the configured maximum system call priority.
\r
1294 Only FreeRTOS functions that end in FromISR can be called from interrupts
\r
1295 that have been assigned a priority at or (logically) below the maximum
\r
1296 system call interrupt priority. FreeRTOS maintains a separate interrupt
\r
1297 safe API to ensure interrupt entry is as fast and as simple as possible.
\r
1298 More information (albeit Cortex-M specific) is provided on the following
\r
1299 link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1300 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1302 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1304 /* Cannot block in an ISR, so check there is data available. */
\r
1305 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1307 traceQUEUE_PEEK_FROM_ISR( pxQueue );
\r
1309 /* Remember the read position so it can be reset as nothing is
\r
1310 actually being removed from the queue. */
\r
1311 pcOriginalReadPosition = pxQueue->u.pcReadFrom;
\r
1312 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
1313 pxQueue->u.pcReadFrom = pcOriginalReadPosition;
\r
1320 traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue );
\r
1323 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1327 /*-----------------------------------------------------------*/
\r
1329 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue )
\r
1331 unsigned portBASE_TYPE uxReturn;
\r
1333 configASSERT( xQueue );
\r
1335 taskENTER_CRITICAL();
\r
1336 uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting;
\r
1337 taskEXIT_CRITICAL();
\r
1340 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
\r
1341 /*-----------------------------------------------------------*/
\r
1343 unsigned portBASE_TYPE uxQueueSpacesAvailable( const xQueueHandle xQueue )
\r
1345 unsigned portBASE_TYPE uxReturn;
\r
1348 pxQueue = ( xQUEUE * ) xQueue;
\r
1349 configASSERT( pxQueue );
\r
1351 taskENTER_CRITICAL();
\r
1352 uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting;
\r
1353 taskEXIT_CRITICAL();
\r
1356 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
\r
1357 /*-----------------------------------------------------------*/
\r
1359 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle xQueue )
\r
1361 unsigned portBASE_TYPE uxReturn;
\r
1363 configASSERT( xQueue );
\r
1365 uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting;
\r
1368 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
\r
1369 /*-----------------------------------------------------------*/
\r
1371 void vQueueDelete( xQueueHandle xQueue )
\r
1373 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
1375 configASSERT( pxQueue );
\r
1377 traceQUEUE_DELETE( pxQueue );
\r
1378 #if ( configQUEUE_REGISTRY_SIZE > 0 )
\r
1380 vQueueUnregisterQueue( pxQueue );
\r
1383 vPortFree( pxQueue->pcHead );
\r
1384 vPortFree( pxQueue );
\r
1386 /*-----------------------------------------------------------*/
\r
1388 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1390 unsigned char ucQueueGetQueueNumber( xQueueHandle xQueue )
\r
1392 return ( ( xQUEUE * ) xQueue )->ucQueueNumber;
\r
1395 #endif /* configUSE_TRACE_FACILITY */
\r
1396 /*-----------------------------------------------------------*/
\r
1398 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1400 void vQueueSetQueueNumber( xQueueHandle xQueue, unsigned char ucQueueNumber )
\r
1402 ( ( xQUEUE * ) xQueue )->ucQueueNumber = ucQueueNumber;
\r
1405 #endif /* configUSE_TRACE_FACILITY */
\r
1406 /*-----------------------------------------------------------*/
\r
1408 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1410 unsigned char ucQueueGetQueueType( xQueueHandle xQueue )
\r
1412 return ( ( xQUEUE * ) xQueue )->ucQueueType;
\r
1415 #endif /* configUSE_TRACE_FACILITY */
\r
1416 /*-----------------------------------------------------------*/
\r
1418 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )
\r
1420 if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )
\r
1422 #if ( configUSE_MUTEXES == 1 )
\r
1424 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
1426 /* The mutex is no longer being held. */
\r
1427 vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
\r
1428 pxQueue->pxMutexHolder = NULL;
\r
1431 #endif /* configUSE_MUTEXES */
\r
1433 else if( xPosition == queueSEND_TO_BACK )
\r
1435 ( 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
1436 pxQueue->pcWriteTo += pxQueue->uxItemSize;
\r
1437 if( pxQueue->pcWriteTo >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */
\r
1439 pxQueue->pcWriteTo = pxQueue->pcHead;
\r
1444 ( 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
1445 pxQueue->u.pcReadFrom -= pxQueue->uxItemSize;
\r
1446 if( pxQueue->u.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */
\r
1448 pxQueue->u.pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
\r
1451 if( xPosition == queueOVERWRITE )
\r
1453 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1455 /* An item is not being added but overwritten, so subtract
\r
1456 one from the recorded number of items in the queue so when
\r
1457 one is added again below the number of recorded items remains
\r
1459 --( pxQueue->uxMessagesWaiting );
\r
1464 ++( pxQueue->uxMessagesWaiting );
\r
1466 /*-----------------------------------------------------------*/
\r
1468 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, void * const pvBuffer )
\r
1470 if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
\r
1472 pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
\r
1473 if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */
\r
1475 pxQueue->u.pcReadFrom = pxQueue->pcHead;
\r
1477 ( 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
1480 /*-----------------------------------------------------------*/
\r
1482 static void prvUnlockQueue( xQUEUE *pxQueue )
\r
1484 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
\r
1486 /* The lock counts contains the number of extra data items placed or
\r
1487 removed from the queue while the queue was locked. When a queue is
\r
1488 locked items can be added or removed, but the event lists cannot be
\r
1490 taskENTER_CRITICAL();
\r
1492 /* See if data was added to the queue while it was locked. */
\r
1493 while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )
\r
1495 /* Data was posted while the queue was locked. Are any tasks
\r
1496 blocked waiting for data to become available? */
\r
1497 #if ( configUSE_QUEUE_SETS == 1 )
\r
1499 if( pxQueue->pxQueueSetContainer != NULL )
\r
1501 if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) == pdTRUE )
\r
1503 /* The queue is a member of a queue set, and posting to
\r
1504 the queue set caused a higher priority task to unblock.
\r
1505 A context switch is required. */
\r
1506 vTaskMissedYield();
\r
1511 /* Tasks that are removed from the event list will get added to
\r
1512 the pending ready list as the scheduler is still suspended. */
\r
1513 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1515 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1517 /* The task waiting has a higher priority so record that a
\r
1518 context switch is required. */
\r
1519 vTaskMissedYield();
\r
1528 #else /* configUSE_QUEUE_SETS */
\r
1530 /* Tasks that are removed from the event list will get added to
\r
1531 the pending ready list as the scheduler is still suspended. */
\r
1532 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1534 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1536 /* The task waiting has a higher priority so record that a
\r
1537 context switch is required. */
\r
1538 vTaskMissedYield();
\r
1546 #endif /* configUSE_QUEUE_SETS */
\r
1548 --( pxQueue->xTxLock );
\r
1551 pxQueue->xTxLock = queueUNLOCKED;
\r
1553 taskEXIT_CRITICAL();
\r
1555 /* Do the same for the Rx lock. */
\r
1556 taskENTER_CRITICAL();
\r
1558 while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )
\r
1560 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1562 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1564 vTaskMissedYield();
\r
1567 --( pxQueue->xRxLock );
\r
1575 pxQueue->xRxLock = queueUNLOCKED;
\r
1577 taskEXIT_CRITICAL();
\r
1579 /*-----------------------------------------------------------*/
\r
1581 static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue )
\r
1583 signed portBASE_TYPE xReturn;
\r
1585 taskENTER_CRITICAL();
\r
1587 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
\r
1593 xReturn = pdFALSE;
\r
1596 taskEXIT_CRITICAL();
\r
1600 /*-----------------------------------------------------------*/
\r
1602 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle xQueue )
\r
1604 signed portBASE_TYPE xReturn;
\r
1606 configASSERT( xQueue );
\r
1607 if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
\r
1613 xReturn = pdFALSE;
\r
1617 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
\r
1618 /*-----------------------------------------------------------*/
\r
1620 static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue )
\r
1622 signed portBASE_TYPE xReturn;
\r
1624 taskENTER_CRITICAL();
\r
1626 if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )
\r
1632 xReturn = pdFALSE;
\r
1635 taskEXIT_CRITICAL();
\r
1639 /*-----------------------------------------------------------*/
\r
1641 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle xQueue )
\r
1643 signed portBASE_TYPE xReturn;
\r
1645 configASSERT( xQueue );
\r
1646 if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( ( xQUEUE * ) xQueue )->uxLength )
\r
1652 xReturn = pdFALSE;
\r
1656 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
\r
1657 /*-----------------------------------------------------------*/
\r
1659 #if ( configUSE_CO_ROUTINES == 1 )
\r
1661 signed portBASE_TYPE xQueueCRSend( xQueueHandle xQueue, const void *pvItemToQueue, portTickType xTicksToWait )
\r
1663 signed portBASE_TYPE xReturn;
\r
1664 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
1666 /* If the queue is already full we may have to block. A critical section
\r
1667 is required to prevent an interrupt removing something from the queue
\r
1668 between the check to see if the queue is full and blocking on the queue. */
\r
1669 portDISABLE_INTERRUPTS();
\r
1671 if( prvIsQueueFull( pxQueue ) != pdFALSE )
\r
1673 /* The queue is full - do we want to block or just leave without
\r
1675 if( xTicksToWait > ( portTickType ) 0 )
\r
1677 /* As this is called from a coroutine we cannot block directly, but
\r
1678 return indicating that we need to block. */
\r
1679 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
\r
1680 portENABLE_INTERRUPTS();
\r
1681 return errQUEUE_BLOCKED;
\r
1685 portENABLE_INTERRUPTS();
\r
1686 return errQUEUE_FULL;
\r
1690 portENABLE_INTERRUPTS();
\r
1692 portDISABLE_INTERRUPTS();
\r
1694 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
1696 /* There is room in the queue, copy the data into the queue. */
\r
1697 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
\r
1700 /* Were any co-routines waiting for data to become available? */
\r
1701 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1703 /* In this instance the co-routine could be placed directly
\r
1704 into the ready list as we are within a critical section.
\r
1705 Instead the same pending ready list mechanism is used as if
\r
1706 the event were caused from within an interrupt. */
\r
1707 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1709 /* The co-routine waiting has a higher priority so record
\r
1710 that a yield might be appropriate. */
\r
1711 xReturn = errQUEUE_YIELD;
\r
1717 xReturn = errQUEUE_FULL;
\r
1720 portENABLE_INTERRUPTS();
\r
1725 #endif /* configUSE_CO_ROUTINES */
\r
1726 /*-----------------------------------------------------------*/
\r
1728 #if ( configUSE_CO_ROUTINES == 1 )
\r
1730 signed portBASE_TYPE xQueueCRReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait )
\r
1732 signed portBASE_TYPE xReturn;
\r
1733 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
1735 /* If the queue is already empty we may have to block. A critical section
\r
1736 is required to prevent an interrupt adding something to the queue
\r
1737 between the check to see if the queue is empty and blocking on the queue. */
\r
1738 portDISABLE_INTERRUPTS();
\r
1740 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
\r
1742 /* There are no messages in the queue, do we want to block or just
\r
1743 leave with nothing? */
\r
1744 if( xTicksToWait > ( portTickType ) 0 )
\r
1746 /* As this is a co-routine we cannot block directly, but return
\r
1747 indicating that we need to block. */
\r
1748 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
\r
1749 portENABLE_INTERRUPTS();
\r
1750 return errQUEUE_BLOCKED;
\r
1754 portENABLE_INTERRUPTS();
\r
1755 return errQUEUE_FULL;
\r
1759 portENABLE_INTERRUPTS();
\r
1761 portDISABLE_INTERRUPTS();
\r
1763 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1765 /* Data is available from the queue. */
\r
1766 pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
\r
1767 if( pxQueue->u.pcReadFrom >= pxQueue->pcTail )
\r
1769 pxQueue->u.pcReadFrom = pxQueue->pcHead;
\r
1771 --( pxQueue->uxMessagesWaiting );
\r
1772 ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1776 /* Were any co-routines waiting for space to become available? */
\r
1777 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1779 /* In this instance the co-routine could be placed directly
\r
1780 into the ready list as we are within a critical section.
\r
1781 Instead the same pending ready list mechanism is used as if
\r
1782 the event were caused from within an interrupt. */
\r
1783 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1785 xReturn = errQUEUE_YIELD;
\r
1794 portENABLE_INTERRUPTS();
\r
1799 #endif /* configUSE_CO_ROUTINES */
\r
1800 /*-----------------------------------------------------------*/
\r
1802 #if ( configUSE_CO_ROUTINES == 1 )
\r
1804 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
\r
1806 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
1808 /* Cannot block within an ISR so if there is no space on the queue then
\r
1809 exit without doing anything. */
\r
1810 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
1812 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
\r
1814 /* We only want to wake one co-routine per ISR, so check that a
\r
1815 co-routine has not already been woken. */
\r
1816 if( xCoRoutinePreviouslyWoken == pdFALSE )
\r
1818 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1820 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1828 return xCoRoutinePreviouslyWoken;
\r
1831 #endif /* configUSE_CO_ROUTINES */
\r
1832 /*-----------------------------------------------------------*/
\r
1834 #if ( configUSE_CO_ROUTINES == 1 )
\r
1836 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle xQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )
\r
1838 signed portBASE_TYPE xReturn;
\r
1839 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
1841 /* We cannot block from an ISR, so check there is data available. If
\r
1842 not then just leave without doing anything. */
\r
1843 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1845 /* Copy the data from the queue. */
\r
1846 pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
\r
1847 if( pxQueue->u.pcReadFrom >= pxQueue->pcTail )
\r
1849 pxQueue->u.pcReadFrom = pxQueue->pcHead;
\r
1851 --( pxQueue->uxMessagesWaiting );
\r
1852 ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1854 if( ( *pxCoRoutineWoken ) == pdFALSE )
\r
1856 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1858 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1860 *pxCoRoutineWoken = pdTRUE;
\r
1875 #endif /* configUSE_CO_ROUTINES */
\r
1876 /*-----------------------------------------------------------*/
\r
1878 #if ( configQUEUE_REGISTRY_SIZE > 0 )
\r
1880 void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )
\r
1882 unsigned portBASE_TYPE ux;
\r
1884 /* See if there is an empty space in the registry. A NULL name denotes
\r
1886 for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
\r
1888 if( xQueueRegistry[ ux ].pcQueueName == NULL )
\r
1890 /* Store the information on this queue. */
\r
1891 xQueueRegistry[ ux ].pcQueueName = pcQueueName;
\r
1892 xQueueRegistry[ ux ].xHandle = xQueue;
\r
1898 #endif /* configQUEUE_REGISTRY_SIZE */
\r
1899 /*-----------------------------------------------------------*/
\r
1901 #if ( configQUEUE_REGISTRY_SIZE > 0 )
\r
1903 void vQueueUnregisterQueue( xQueueHandle xQueue )
\r
1905 unsigned portBASE_TYPE ux;
\r
1907 /* See if the handle of the queue being unregistered in actually in the
\r
1909 for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
\r
1911 if( xQueueRegistry[ ux ].xHandle == xQueue )
\r
1913 /* Set the name to NULL to show that this slot if free again. */
\r
1914 xQueueRegistry[ ux ].pcQueueName = NULL;
\r
1919 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
\r
1921 #endif /* configQUEUE_REGISTRY_SIZE */
\r
1922 /*-----------------------------------------------------------*/
\r
1924 #if ( configUSE_TIMERS == 1 )
\r
1926 void vQueueWaitForMessageRestricted( xQueueHandle xQueue, portTickType xTicksToWait )
\r
1928 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
1930 /* This function should not be called by application code hence the
\r
1931 'Restricted' in its name. It is not part of the public API. It is
\r
1932 designed for use by kernel code, and has special calling requirements.
\r
1933 It can result in vListInsert() being called on a list that can only
\r
1934 possibly ever have one item in it, so the list will be fast, but even
\r
1935 so it should be called with the scheduler locked and not from a critical
\r
1938 /* Only do anything if there are no messages in the queue. This function
\r
1939 will not actually cause the task to block, just place it on a blocked
\r
1940 list. It will not block until the scheduler is unlocked - at which
\r
1941 time a yield will be performed. If an item is added to the queue while
\r
1942 the queue is locked, and the calling task blocks on the queue, then the
\r
1943 calling task will be immediately unblocked when the queue is unlocked. */
\r
1944 prvLockQueue( pxQueue );
\r
1945 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U )
\r
1947 /* There is nothing in the queue, block for the specified period. */
\r
1948 vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
1950 prvUnlockQueue( pxQueue );
\r
1953 #endif /* configUSE_TIMERS */
\r
1954 /*-----------------------------------------------------------*/
\r
1956 #if ( configUSE_QUEUE_SETS == 1 )
\r
1958 xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength )
\r
1960 xQueueSetHandle pxQueue;
\r
1962 pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( xQUEUE * ), queueQUEUE_TYPE_SET );
\r
1967 #endif /* configUSE_QUEUE_SETS */
\r
1968 /*-----------------------------------------------------------*/
\r
1970 #if ( configUSE_QUEUE_SETS == 1 )
\r
1972 portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )
\r
1974 portBASE_TYPE xReturn;
\r
1976 if( ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )
\r
1978 /* Cannot add a queue/semaphore to more than one queue set. */
\r
1981 else if( ( ( xQUEUE * ) xQueueOrSemaphore )->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 )
\r
1983 /* Cannot add a queue/semaphore to a queue set if there are already
\r
1984 items in the queue/semaphore. */
\r
1989 taskENTER_CRITICAL();
\r
1991 ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet;
\r
1993 taskEXIT_CRITICAL();
\r
2000 #endif /* configUSE_QUEUE_SETS */
\r
2001 /*-----------------------------------------------------------*/
\r
2003 #if ( configUSE_QUEUE_SETS == 1 )
\r
2005 portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )
\r
2007 portBASE_TYPE xReturn;
\r
2008 xQUEUE * const pxQueueOrSemaphore = ( xQUEUE * ) xQueueOrSemaphore;
\r
2010 if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet )
\r
2012 /* The queue was not a member of the set. */
\r
2015 else if( pxQueueOrSemaphore->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 )
\r
2017 /* It is dangerous to remove a queue from a set when the queue is
\r
2018 not empty because the queue set will still hold pending events for
\r
2024 taskENTER_CRITICAL();
\r
2026 /* The queue is no longer contained in the set. */
\r
2027 pxQueueOrSemaphore->pxQueueSetContainer = NULL;
\r
2029 taskEXIT_CRITICAL();
\r
2034 } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */
\r
2036 #endif /* configUSE_QUEUE_SETS */
\r
2037 /*-----------------------------------------------------------*/
\r
2039 #if ( configUSE_QUEUE_SETS == 1 )
\r
2041 xQueueSetMemberHandle xQueueSelectFromSet( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks )
\r
2043 xQueueSetMemberHandle xReturn = NULL;
\r
2045 ( void ) xQueueGenericReceive( ( xQueueHandle ) xQueueSet, &xReturn, xBlockTimeTicks, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */
\r
2049 #endif /* configUSE_QUEUE_SETS */
\r
2050 /*-----------------------------------------------------------*/
\r
2052 #if ( configUSE_QUEUE_SETS == 1 )
\r
2054 xQueueSetMemberHandle xQueueSelectFromSetFromISR( xQueueSetHandle xQueueSet )
\r
2056 xQueueSetMemberHandle xReturn = NULL;
\r
2058 ( void ) xQueueReceiveFromISR( ( xQueueHandle ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */
\r
2062 #endif /* configUSE_QUEUE_SETS */
\r
2063 /*-----------------------------------------------------------*/
\r
2065 #if ( configUSE_QUEUE_SETS == 1 )
\r
2067 static portBASE_TYPE prvNotifyQueueSetContainer( const xQUEUE * const pxQueue, portBASE_TYPE xCopyPosition )
\r
2069 xQUEUE *pxQueueSetContainer = pxQueue->pxQueueSetContainer;
\r
2070 portBASE_TYPE xReturn = pdFALSE;
\r
2072 configASSERT( pxQueueSetContainer );
\r
2073 configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );
\r
2075 if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )
\r
2077 traceQUEUE_SEND( pxQueueSetContainer );
\r
2078 /* The data copies is the handle of the queue that contains data. */
\r
2079 prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition );
\r
2080 if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE )
\r
2082 if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE )
\r
2084 /* The task waiting has a higher priority */
\r
2093 #endif /* configUSE_QUEUE_SETS */
\r