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 portBASE_TYPE uxQueueNumber;
\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 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
573 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
575 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
\r
580 /* This function relaxes the coding standard somewhat to allow return
\r
581 statements within the function itself. This is done in the interest
\r
582 of execution time efficiency. */
\r
585 taskENTER_CRITICAL();
\r
587 /* Is there room on the queue now? The running task must be
\r
588 the highest priority task wanting to access the queue. If
\r
589 the head item in the queue is to be overwritten then it does
\r
590 not matter if the queue is full. */
\r
591 if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
\r
593 traceQUEUE_SEND( pxQueue );
\r
594 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
596 #if ( configUSE_QUEUE_SETS == 1 )
\r
598 if( pxQueue->pxQueueSetContainer != NULL )
\r
600 if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )
\r
602 /* The queue is a member of a queue set, and posting
\r
603 to the queue set caused a higher priority task to
\r
604 unblock. A context switch is required. */
\r
605 queueYIELD_IF_USING_PREEMPTION();
\r
610 /* If there was a task waiting for data to arrive on the
\r
611 queue then unblock it now. */
\r
612 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
614 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
616 /* The unblocked task has a priority higher than
\r
617 our own so yield immediately. Yes it is ok to
\r
618 do this from within the critical section - the
\r
619 kernel takes care of that. */
\r
620 queueYIELD_IF_USING_PREEMPTION();
\r
625 #else /* configUSE_QUEUE_SETS */
\r
627 /* If there was a task waiting for data to arrive on the
\r
628 queue then unblock it now. */
\r
629 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
631 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
633 /* The unblocked task has a priority higher than
\r
634 our own so yield immediately. Yes it is ok to do
\r
635 this from within the critical section - the kernel
\r
636 takes care of that. */
\r
637 queueYIELD_IF_USING_PREEMPTION();
\r
641 #endif /* configUSE_QUEUE_SETS */
\r
643 taskEXIT_CRITICAL();
\r
645 /* Return to the original privilege level before exiting the
\r
651 if( xTicksToWait == ( portTickType ) 0 )
\r
653 /* The queue was full and no block time is specified (or
\r
654 the block time has expired) so leave now. */
\r
655 taskEXIT_CRITICAL();
\r
657 /* Return to the original privilege level before exiting
\r
659 traceQUEUE_SEND_FAILED( pxQueue );
\r
660 return errQUEUE_FULL;
\r
662 else if( xEntryTimeSet == pdFALSE )
\r
664 /* The queue was full and a block time was specified so
\r
665 configure the timeout structure. */
\r
666 vTaskSetTimeOutState( &xTimeOut );
\r
667 xEntryTimeSet = pdTRUE;
\r
671 /* Entry time was already set. */
\r
675 taskEXIT_CRITICAL();
\r
677 /* Interrupts and other tasks can send to and receive from the queue
\r
678 now the critical section has been exited. */
\r
681 prvLockQueue( pxQueue );
\r
683 /* Update the timeout state to see if it has expired yet. */
\r
684 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
686 if( prvIsQueueFull( pxQueue ) != pdFALSE )
\r
688 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
\r
689 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
\r
691 /* Unlocking the queue means queue events can effect the
\r
692 event list. It is possible that interrupts occurring now
\r
693 remove this task from the event list again - but as the
\r
694 scheduler is suspended the task will go onto the pending
\r
695 ready last instead of the actual ready list. */
\r
696 prvUnlockQueue( pxQueue );
\r
698 /* Resuming the scheduler will move tasks from the pending
\r
699 ready list into the ready list - so it is feasible that this
\r
700 task is already in a ready list before it yields - in which
\r
701 case the yield will not cause a context switch unless there
\r
702 is also a higher priority task in the pending ready list. */
\r
703 if( xTaskResumeAll() == pdFALSE )
\r
705 portYIELD_WITHIN_API();
\r
711 prvUnlockQueue( pxQueue );
\r
712 ( void ) xTaskResumeAll();
\r
717 /* The timeout has expired. */
\r
718 prvUnlockQueue( pxQueue );
\r
719 ( void ) xTaskResumeAll();
\r
721 /* Return to the original privilege level before exiting the
\r
723 traceQUEUE_SEND_FAILED( pxQueue );
\r
724 return errQUEUE_FULL;
\r
728 /*-----------------------------------------------------------*/
\r
730 #if ( configUSE_ALTERNATIVE_API == 1 )
\r
732 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
\r
734 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
735 xTimeOutType xTimeOut;
\r
736 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
738 configASSERT( pxQueue );
\r
739 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
743 taskENTER_CRITICAL();
\r
745 /* Is there room on the queue now? To be running we must be
\r
746 the highest priority task wanting to access the queue. */
\r
747 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
749 traceQUEUE_SEND( pxQueue );
\r
750 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
752 /* If there was a task waiting for data to arrive on the
\r
753 queue then unblock it now. */
\r
754 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
756 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
758 /* The unblocked task has a priority higher than
\r
759 our own so yield immediately. */
\r
760 portYIELD_WITHIN_API();
\r
764 taskEXIT_CRITICAL();
\r
769 if( xTicksToWait == ( portTickType ) 0 )
\r
771 taskEXIT_CRITICAL();
\r
772 return errQUEUE_FULL;
\r
774 else if( xEntryTimeSet == pdFALSE )
\r
776 vTaskSetTimeOutState( &xTimeOut );
\r
777 xEntryTimeSet = pdTRUE;
\r
781 taskEXIT_CRITICAL();
\r
783 taskENTER_CRITICAL();
\r
785 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
787 if( prvIsQueueFull( pxQueue ) != pdFALSE )
\r
789 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
\r
790 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
\r
791 portYIELD_WITHIN_API();
\r
796 taskEXIT_CRITICAL();
\r
797 traceQUEUE_SEND_FAILED( pxQueue );
\r
798 return errQUEUE_FULL;
\r
801 taskEXIT_CRITICAL();
\r
805 #endif /* configUSE_ALTERNATIVE_API */
\r
806 /*-----------------------------------------------------------*/
\r
808 #if ( configUSE_ALTERNATIVE_API == 1 )
\r
810 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
\r
812 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
813 xTimeOutType xTimeOut;
\r
814 signed char *pcOriginalReadPosition;
\r
815 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
817 configASSERT( pxQueue );
\r
818 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
822 taskENTER_CRITICAL();
\r
824 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
826 /* Remember our read position in case we are just peeking. */
\r
827 pcOriginalReadPosition = pxQueue->u.pcReadFrom;
\r
829 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
831 if( xJustPeeking == pdFALSE )
\r
833 traceQUEUE_RECEIVE( pxQueue );
\r
835 /* Data is actually being removed (not just peeked). */
\r
836 --( pxQueue->uxMessagesWaiting );
\r
838 #if ( configUSE_MUTEXES == 1 )
\r
840 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
842 /* Record the information required to implement
\r
843 priority inheritance should it become necessary. */
\r
844 pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle();
\r
849 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
851 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
853 portYIELD_WITHIN_API();
\r
859 traceQUEUE_PEEK( pxQueue );
\r
861 /* We are not removing the data, so reset our read
\r
863 pxQueue->u.pcReadFrom = pcOriginalReadPosition;
\r
865 /* The data is being left in the queue, so see if there are
\r
866 any other tasks waiting for the data. */
\r
867 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
869 /* Tasks that are removed from the event list will get added to
\r
870 the pending ready list as the scheduler is still suspended. */
\r
871 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
873 /* The task waiting has a higher priority than this task. */
\r
874 portYIELD_WITHIN_API();
\r
880 taskEXIT_CRITICAL();
\r
885 if( xTicksToWait == ( portTickType ) 0 )
\r
887 taskEXIT_CRITICAL();
\r
888 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
889 return errQUEUE_EMPTY;
\r
891 else if( xEntryTimeSet == pdFALSE )
\r
893 vTaskSetTimeOutState( &xTimeOut );
\r
894 xEntryTimeSet = pdTRUE;
\r
898 taskEXIT_CRITICAL();
\r
900 taskENTER_CRITICAL();
\r
902 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
904 if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
\r
906 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
\r
908 #if ( configUSE_MUTEXES == 1 )
\r
910 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
912 taskENTER_CRITICAL();
\r
914 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
\r
916 taskEXIT_CRITICAL();
\r
921 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
922 portYIELD_WITHIN_API();
\r
927 taskEXIT_CRITICAL();
\r
928 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
929 return errQUEUE_EMPTY;
\r
932 taskEXIT_CRITICAL();
\r
937 #endif /* configUSE_ALTERNATIVE_API */
\r
938 /*-----------------------------------------------------------*/
\r
940 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )
\r
942 signed portBASE_TYPE xReturn;
\r
943 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
944 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
946 configASSERT( pxQueue );
\r
947 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
948 configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
\r
950 /* RTOS ports that support interrupt nesting have the concept of a maximum
\r
951 system call (or maximum API call) interrupt priority. Interrupts that are
\r
952 above the maximum system call priority are kept permanently enabled, even
\r
953 when the RTOS kernel is in a critical section, but cannot make any calls to
\r
954 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
\r
955 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
956 failure if a FreeRTOS API function is called from an interrupt that has been
\r
957 assigned a priority above the configured maximum system call priority.
\r
958 Only FreeRTOS functions that end in FromISR can be called from interrupts
\r
959 that have been assigned a priority at or (logically) below the maximum
\r
960 system call interrupt priority. FreeRTOS maintains a separate interrupt
\r
961 safe API to ensure interrupt entry is as fast and as simple as possible.
\r
962 More information (albeit Cortex-M specific) is provided on the following
\r
963 link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
964 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
966 /* Similar to xQueueGenericSend, except we don't block if there is no room
\r
967 in the queue. Also we don't directly wake a task that was blocked on a
\r
968 queue read, instead we return a flag to say whether a context switch is
\r
969 required or not (i.e. has a task with a higher priority than us been woken
\r
971 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
973 if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
\r
975 traceQUEUE_SEND_FROM_ISR( pxQueue );
\r
977 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
979 /* If the queue is locked we do not alter the event list. This will
\r
980 be done when the queue is unlocked later. */
\r
981 if( pxQueue->xTxLock == queueUNLOCKED )
\r
983 #if ( configUSE_QUEUE_SETS == 1 )
\r
985 if( pxQueue->pxQueueSetContainer != NULL )
\r
987 if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )
\r
989 /* The queue is a member of a queue set, and posting
\r
990 to the queue set caused a higher priority task to
\r
991 unblock. A context switch is required. */
\r
992 if( pxHigherPriorityTaskWoken != NULL )
\r
994 *pxHigherPriorityTaskWoken = pdTRUE;
\r
1000 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1002 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1004 /* The task waiting has a higher priority so record that a
\r
1005 context switch is required. */
\r
1006 if( pxHigherPriorityTaskWoken != NULL )
\r
1008 *pxHigherPriorityTaskWoken = pdTRUE;
\r
1014 #else /* configUSE_QUEUE_SETS */
\r
1016 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1018 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1020 /* The task waiting has a higher priority so record that a
\r
1021 context switch is required. */
\r
1022 if( pxHigherPriorityTaskWoken != NULL )
\r
1024 *pxHigherPriorityTaskWoken = pdTRUE;
\r
1029 #endif /* configUSE_QUEUE_SETS */
\r
1033 /* Increment the lock count so the task that unlocks the queue
\r
1034 knows that data was posted while it was locked. */
\r
1035 ++( pxQueue->xTxLock );
\r
1042 traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
\r
1043 xReturn = errQUEUE_FULL;
\r
1046 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1050 /*-----------------------------------------------------------*/
\r
1052 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
\r
1054 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
1055 xTimeOutType xTimeOut;
\r
1056 signed char *pcOriginalReadPosition;
\r
1057 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
1059 configASSERT( pxQueue );
\r
1060 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
1061 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
1063 configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
\r
1067 /* This function relaxes the coding standard somewhat to allow return
\r
1068 statements within the function itself. This is done in the interest
\r
1069 of execution time efficiency. */
\r
1073 taskENTER_CRITICAL();
\r
1075 /* Is there data in the queue now? To be running we must be
\r
1076 the highest priority task wanting to access the queue. */
\r
1077 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1079 /* Remember the read position in case the queue is only being
\r
1081 pcOriginalReadPosition = pxQueue->u.pcReadFrom;
\r
1083 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
1085 if( xJustPeeking == pdFALSE )
\r
1087 traceQUEUE_RECEIVE( pxQueue );
\r
1089 /* Actually removing data, not just peeking. */
\r
1090 --( pxQueue->uxMessagesWaiting );
\r
1092 #if ( configUSE_MUTEXES == 1 )
\r
1094 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
1096 /* Record the information required to implement
\r
1097 priority inheritance should it become necessary. */
\r
1098 pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle(); /*lint !e961 Cast is not redundant as xTaskHandle is a typedef. */
\r
1103 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1105 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
1107 queueYIELD_IF_USING_PREEMPTION();
\r
1113 traceQUEUE_PEEK( pxQueue );
\r
1115 /* The data is not being removed, so reset the read
\r
1117 pxQueue->u.pcReadFrom = pcOriginalReadPosition;
\r
1119 /* The data is being left in the queue, so see if there are
\r
1120 any other tasks waiting for the data. */
\r
1121 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1123 /* Tasks that are removed from the event list will get added to
\r
1124 the pending ready list as the scheduler is still suspended. */
\r
1125 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1127 /* The task waiting has a higher priority than this task. */
\r
1128 queueYIELD_IF_USING_PREEMPTION();
\r
1133 taskEXIT_CRITICAL();
\r
1138 if( xTicksToWait == ( portTickType ) 0 )
\r
1140 /* The queue was empty and no block time is specified (or
\r
1141 the block time has expired) so leave now. */
\r
1142 taskEXIT_CRITICAL();
\r
1143 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
1144 return errQUEUE_EMPTY;
\r
1146 else if( xEntryTimeSet == pdFALSE )
\r
1148 /* The queue was empty and a block time was specified so
\r
1149 configure the timeout structure. */
\r
1150 vTaskSetTimeOutState( &xTimeOut );
\r
1151 xEntryTimeSet = pdTRUE;
\r
1155 /* Entry time was already set. */
\r
1159 taskEXIT_CRITICAL();
\r
1161 /* Interrupts and other tasks can send to and receive from the queue
\r
1162 now the critical section has been exited. */
\r
1164 vTaskSuspendAll();
\r
1165 prvLockQueue( pxQueue );
\r
1167 /* Update the timeout state to see if it has expired yet. */
\r
1168 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
1170 if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
\r
1172 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
\r
1174 #if ( configUSE_MUTEXES == 1 )
\r
1176 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
1178 taskENTER_CRITICAL();
\r
1180 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
\r
1182 taskEXIT_CRITICAL();
\r
1187 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
1188 prvUnlockQueue( pxQueue );
\r
1189 if( xTaskResumeAll() == pdFALSE )
\r
1191 portYIELD_WITHIN_API();
\r
1197 prvUnlockQueue( pxQueue );
\r
1198 ( void ) xTaskResumeAll();
\r
1203 prvUnlockQueue( pxQueue );
\r
1204 ( void ) xTaskResumeAll();
\r
1205 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
1206 return errQUEUE_EMPTY;
\r
1210 /*-----------------------------------------------------------*/
\r
1212 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle xQueue, void * const pvBuffer, signed portBASE_TYPE *pxHigherPriorityTaskWoken )
\r
1214 signed portBASE_TYPE xReturn;
\r
1215 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
1216 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
1218 configASSERT( pxQueue );
\r
1219 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
1221 /* RTOS ports that support interrupt nesting have the concept of a maximum
\r
1222 system call (or maximum API call) interrupt priority. Interrupts that are
\r
1223 above the maximum system call priority are kept permanently enabled, even
\r
1224 when the RTOS kernel is in a critical section, but cannot make any calls to
\r
1225 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
\r
1226 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1227 failure if a FreeRTOS API function is called from an interrupt that has been
\r
1228 assigned a priority above the configured maximum system call priority.
\r
1229 Only FreeRTOS functions that end in FromISR can be called from interrupts
\r
1230 that have been assigned a priority at or (logically) below the maximum
\r
1231 system call interrupt priority. FreeRTOS maintains a separate interrupt
\r
1232 safe API to ensure interrupt entry is as fast and as simple as possible.
\r
1233 More information (albeit Cortex-M specific) is provided on the following
\r
1234 link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1235 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1237 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1239 /* Cannot block in an ISR, so check there is data available. */
\r
1240 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1242 traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
\r
1244 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
1245 --( pxQueue->uxMessagesWaiting );
\r
1247 /* If the queue is locked the event list will not be modified.
\r
1248 Instead update the lock count so the task that unlocks the queue
\r
1249 will know that an ISR has removed data while the queue was
\r
1251 if( pxQueue->xRxLock == queueUNLOCKED )
\r
1253 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1255 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1257 /* The task waiting has a higher priority than us so
\r
1258 force a context switch. */
\r
1259 if( pxHigherPriorityTaskWoken != NULL )
\r
1261 *pxHigherPriorityTaskWoken = pdTRUE;
\r
1268 /* Increment the lock count so the task that unlocks the queue
\r
1269 knows that data was removed while it was locked. */
\r
1270 ++( pxQueue->xRxLock );
\r
1278 traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
\r
1281 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1285 /*-----------------------------------------------------------*/
\r
1287 signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue, void * const pvBuffer )
\r
1289 signed portBASE_TYPE xReturn;
\r
1290 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
1291 signed char *pcOriginalReadPosition;
\r
1292 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
1294 configASSERT( pxQueue );
\r
1295 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
1297 /* RTOS ports that support interrupt nesting have the concept of a maximum
\r
1298 system call (or maximum API call) interrupt priority. Interrupts that are
\r
1299 above the maximum system call priority are kept permanently enabled, even
\r
1300 when the RTOS kernel is in a critical section, but cannot make any calls to
\r
1301 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
\r
1302 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1303 failure if a FreeRTOS API function is called from an interrupt that has been
\r
1304 assigned a priority above the configured maximum system call priority.
\r
1305 Only FreeRTOS functions that end in FromISR can be called from interrupts
\r
1306 that have been assigned a priority at or (logically) below the maximum
\r
1307 system call interrupt priority. FreeRTOS maintains a separate interrupt
\r
1308 safe API to ensure interrupt entry is as fast and as simple as possible.
\r
1309 More information (albeit Cortex-M specific) is provided on the following
\r
1310 link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1311 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1313 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1315 /* Cannot block in an ISR, so check there is data available. */
\r
1316 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1318 traceQUEUE_PEEK_FROM_ISR( pxQueue );
\r
1320 /* Remember the read position so it can be reset as nothing is
\r
1321 actually being removed from the queue. */
\r
1322 pcOriginalReadPosition = pxQueue->u.pcReadFrom;
\r
1323 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
1324 pxQueue->u.pcReadFrom = pcOriginalReadPosition;
\r
1331 traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue );
\r
1334 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1338 /*-----------------------------------------------------------*/
\r
1340 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue )
\r
1342 unsigned portBASE_TYPE uxReturn;
\r
1344 configASSERT( xQueue );
\r
1346 taskENTER_CRITICAL();
\r
1347 uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting;
\r
1348 taskEXIT_CRITICAL();
\r
1351 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
\r
1352 /*-----------------------------------------------------------*/
\r
1354 unsigned portBASE_TYPE uxQueueSpacesAvailable( const xQueueHandle xQueue )
\r
1356 unsigned portBASE_TYPE uxReturn;
\r
1359 pxQueue = ( xQUEUE * ) xQueue;
\r
1360 configASSERT( pxQueue );
\r
1362 taskENTER_CRITICAL();
\r
1363 uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting;
\r
1364 taskEXIT_CRITICAL();
\r
1367 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
\r
1368 /*-----------------------------------------------------------*/
\r
1370 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle xQueue )
\r
1372 unsigned portBASE_TYPE uxReturn;
\r
1374 configASSERT( xQueue );
\r
1376 uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting;
\r
1379 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
\r
1380 /*-----------------------------------------------------------*/
\r
1382 void vQueueDelete( xQueueHandle xQueue )
\r
1384 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
1386 configASSERT( pxQueue );
\r
1388 traceQUEUE_DELETE( pxQueue );
\r
1389 #if ( configQUEUE_REGISTRY_SIZE > 0 )
\r
1391 vQueueUnregisterQueue( pxQueue );
\r
1394 vPortFree( pxQueue->pcHead );
\r
1395 vPortFree( pxQueue );
\r
1397 /*-----------------------------------------------------------*/
\r
1399 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1401 unsigned portBASE_TYPE uxQueueGetQueueNumber( xQueueHandle xQueue )
\r
1403 return ( ( xQUEUE * ) xQueue )->uxQueueNumber;
\r
1406 #endif /* configUSE_TRACE_FACILITY */
\r
1407 /*-----------------------------------------------------------*/
\r
1409 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1411 void vQueueSetQueueNumber( xQueueHandle xQueue, unsigned portBASE_TYPE uxQueueNumber )
\r
1413 ( ( xQUEUE * ) xQueue )->uxQueueNumber = uxQueueNumber;
\r
1416 #endif /* configUSE_TRACE_FACILITY */
\r
1417 /*-----------------------------------------------------------*/
\r
1419 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1421 unsigned char ucQueueGetQueueType( xQueueHandle xQueue )
\r
1423 return ( ( xQUEUE * ) xQueue )->ucQueueType;
\r
1426 #endif /* configUSE_TRACE_FACILITY */
\r
1427 /*-----------------------------------------------------------*/
\r
1429 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )
\r
1431 if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )
\r
1433 #if ( configUSE_MUTEXES == 1 )
\r
1435 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
1437 /* The mutex is no longer being held. */
\r
1438 vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
\r
1439 pxQueue->pxMutexHolder = NULL;
\r
1442 #endif /* configUSE_MUTEXES */
\r
1444 else if( xPosition == queueSEND_TO_BACK )
\r
1446 ( 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
1447 pxQueue->pcWriteTo += pxQueue->uxItemSize;
\r
1448 if( pxQueue->pcWriteTo >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */
\r
1450 pxQueue->pcWriteTo = pxQueue->pcHead;
\r
1455 ( 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
1456 pxQueue->u.pcReadFrom -= pxQueue->uxItemSize;
\r
1457 if( pxQueue->u.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */
\r
1459 pxQueue->u.pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
\r
1462 if( xPosition == queueOVERWRITE )
\r
1464 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1466 /* An item is not being added but overwritten, so subtract
\r
1467 one from the recorded number of items in the queue so when
\r
1468 one is added again below the number of recorded items remains
\r
1470 --( pxQueue->uxMessagesWaiting );
\r
1475 ++( pxQueue->uxMessagesWaiting );
\r
1477 /*-----------------------------------------------------------*/
\r
1479 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, void * const pvBuffer )
\r
1481 if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
\r
1483 pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
\r
1484 if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */
\r
1486 pxQueue->u.pcReadFrom = pxQueue->pcHead;
\r
1488 ( 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
1491 /*-----------------------------------------------------------*/
\r
1493 static void prvUnlockQueue( xQUEUE *pxQueue )
\r
1495 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
\r
1497 /* The lock counts contains the number of extra data items placed or
\r
1498 removed from the queue while the queue was locked. When a queue is
\r
1499 locked items can be added or removed, but the event lists cannot be
\r
1501 taskENTER_CRITICAL();
\r
1503 /* See if data was added to the queue while it was locked. */
\r
1504 while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )
\r
1506 /* Data was posted while the queue was locked. Are any tasks
\r
1507 blocked waiting for data to become available? */
\r
1508 #if ( configUSE_QUEUE_SETS == 1 )
\r
1510 if( pxQueue->pxQueueSetContainer != NULL )
\r
1512 if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) == pdTRUE )
\r
1514 /* The queue is a member of a queue set, and posting to
\r
1515 the queue set caused a higher priority task to unblock.
\r
1516 A context switch is required. */
\r
1517 vTaskMissedYield();
\r
1522 /* Tasks that are removed from the event list will get added to
\r
1523 the pending ready list as the scheduler is still suspended. */
\r
1524 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1526 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1528 /* The task waiting has a higher priority so record that a
\r
1529 context switch is required. */
\r
1530 vTaskMissedYield();
\r
1539 #else /* configUSE_QUEUE_SETS */
\r
1541 /* Tasks that are removed from the event list will get added to
\r
1542 the pending ready list as the scheduler is still suspended. */
\r
1543 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1545 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1547 /* The task waiting has a higher priority so record that a
\r
1548 context switch is required. */
\r
1549 vTaskMissedYield();
\r
1557 #endif /* configUSE_QUEUE_SETS */
\r
1559 --( pxQueue->xTxLock );
\r
1562 pxQueue->xTxLock = queueUNLOCKED;
\r
1564 taskEXIT_CRITICAL();
\r
1566 /* Do the same for the Rx lock. */
\r
1567 taskENTER_CRITICAL();
\r
1569 while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )
\r
1571 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1573 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1575 vTaskMissedYield();
\r
1578 --( pxQueue->xRxLock );
\r
1586 pxQueue->xRxLock = queueUNLOCKED;
\r
1588 taskEXIT_CRITICAL();
\r
1590 /*-----------------------------------------------------------*/
\r
1592 static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue )
\r
1594 signed portBASE_TYPE xReturn;
\r
1596 taskENTER_CRITICAL();
\r
1598 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
\r
1604 xReturn = pdFALSE;
\r
1607 taskEXIT_CRITICAL();
\r
1611 /*-----------------------------------------------------------*/
\r
1613 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle xQueue )
\r
1615 signed portBASE_TYPE xReturn;
\r
1617 configASSERT( xQueue );
\r
1618 if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
\r
1624 xReturn = pdFALSE;
\r
1628 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
\r
1629 /*-----------------------------------------------------------*/
\r
1631 static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue )
\r
1633 signed portBASE_TYPE xReturn;
\r
1635 taskENTER_CRITICAL();
\r
1637 if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )
\r
1643 xReturn = pdFALSE;
\r
1646 taskEXIT_CRITICAL();
\r
1650 /*-----------------------------------------------------------*/
\r
1652 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle xQueue )
\r
1654 signed portBASE_TYPE xReturn;
\r
1656 configASSERT( xQueue );
\r
1657 if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( ( xQUEUE * ) xQueue )->uxLength )
\r
1663 xReturn = pdFALSE;
\r
1667 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
\r
1668 /*-----------------------------------------------------------*/
\r
1670 #if ( configUSE_CO_ROUTINES == 1 )
\r
1672 signed portBASE_TYPE xQueueCRSend( xQueueHandle xQueue, const void *pvItemToQueue, portTickType xTicksToWait )
\r
1674 signed portBASE_TYPE xReturn;
\r
1675 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
1677 /* If the queue is already full we may have to block. A critical section
\r
1678 is required to prevent an interrupt removing something from the queue
\r
1679 between the check to see if the queue is full and blocking on the queue. */
\r
1680 portDISABLE_INTERRUPTS();
\r
1682 if( prvIsQueueFull( pxQueue ) != pdFALSE )
\r
1684 /* The queue is full - do we want to block or just leave without
\r
1686 if( xTicksToWait > ( portTickType ) 0 )
\r
1688 /* As this is called from a coroutine we cannot block directly, but
\r
1689 return indicating that we need to block. */
\r
1690 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
\r
1691 portENABLE_INTERRUPTS();
\r
1692 return errQUEUE_BLOCKED;
\r
1696 portENABLE_INTERRUPTS();
\r
1697 return errQUEUE_FULL;
\r
1701 portENABLE_INTERRUPTS();
\r
1703 portDISABLE_INTERRUPTS();
\r
1705 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
1707 /* There is room in the queue, copy the data into the queue. */
\r
1708 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
\r
1711 /* Were any co-routines waiting for data to become available? */
\r
1712 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1714 /* In this instance the co-routine could be placed directly
\r
1715 into the ready list as we are within a critical section.
\r
1716 Instead the same pending ready list mechanism is used as if
\r
1717 the event were caused from within an interrupt. */
\r
1718 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1720 /* The co-routine waiting has a higher priority so record
\r
1721 that a yield might be appropriate. */
\r
1722 xReturn = errQUEUE_YIELD;
\r
1728 xReturn = errQUEUE_FULL;
\r
1731 portENABLE_INTERRUPTS();
\r
1736 #endif /* configUSE_CO_ROUTINES */
\r
1737 /*-----------------------------------------------------------*/
\r
1739 #if ( configUSE_CO_ROUTINES == 1 )
\r
1741 signed portBASE_TYPE xQueueCRReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait )
\r
1743 signed portBASE_TYPE xReturn;
\r
1744 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
1746 /* If the queue is already empty we may have to block. A critical section
\r
1747 is required to prevent an interrupt adding something to the queue
\r
1748 between the check to see if the queue is empty and blocking on the queue. */
\r
1749 portDISABLE_INTERRUPTS();
\r
1751 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
\r
1753 /* There are no messages in the queue, do we want to block or just
\r
1754 leave with nothing? */
\r
1755 if( xTicksToWait > ( portTickType ) 0 )
\r
1757 /* As this is a co-routine we cannot block directly, but return
\r
1758 indicating that we need to block. */
\r
1759 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
\r
1760 portENABLE_INTERRUPTS();
\r
1761 return errQUEUE_BLOCKED;
\r
1765 portENABLE_INTERRUPTS();
\r
1766 return errQUEUE_FULL;
\r
1770 portENABLE_INTERRUPTS();
\r
1772 portDISABLE_INTERRUPTS();
\r
1774 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1776 /* Data is available from the queue. */
\r
1777 pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
\r
1778 if( pxQueue->u.pcReadFrom >= pxQueue->pcTail )
\r
1780 pxQueue->u.pcReadFrom = pxQueue->pcHead;
\r
1782 --( pxQueue->uxMessagesWaiting );
\r
1783 ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1787 /* Were any co-routines waiting for space to become available? */
\r
1788 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1790 /* In this instance the co-routine could be placed directly
\r
1791 into the ready list as we are within a critical section.
\r
1792 Instead the same pending ready list mechanism is used as if
\r
1793 the event were caused from within an interrupt. */
\r
1794 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1796 xReturn = errQUEUE_YIELD;
\r
1805 portENABLE_INTERRUPTS();
\r
1810 #endif /* configUSE_CO_ROUTINES */
\r
1811 /*-----------------------------------------------------------*/
\r
1813 #if ( configUSE_CO_ROUTINES == 1 )
\r
1815 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
\r
1817 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
1819 /* Cannot block within an ISR so if there is no space on the queue then
\r
1820 exit without doing anything. */
\r
1821 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
1823 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
\r
1825 /* We only want to wake one co-routine per ISR, so check that a
\r
1826 co-routine has not already been woken. */
\r
1827 if( xCoRoutinePreviouslyWoken == pdFALSE )
\r
1829 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1831 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1839 return xCoRoutinePreviouslyWoken;
\r
1842 #endif /* configUSE_CO_ROUTINES */
\r
1843 /*-----------------------------------------------------------*/
\r
1845 #if ( configUSE_CO_ROUTINES == 1 )
\r
1847 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle xQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )
\r
1849 signed portBASE_TYPE xReturn;
\r
1850 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
1852 /* We cannot block from an ISR, so check there is data available. If
\r
1853 not then just leave without doing anything. */
\r
1854 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1856 /* Copy the data from the queue. */
\r
1857 pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
\r
1858 if( pxQueue->u.pcReadFrom >= pxQueue->pcTail )
\r
1860 pxQueue->u.pcReadFrom = pxQueue->pcHead;
\r
1862 --( pxQueue->uxMessagesWaiting );
\r
1863 ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1865 if( ( *pxCoRoutineWoken ) == pdFALSE )
\r
1867 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1869 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1871 *pxCoRoutineWoken = pdTRUE;
\r
1886 #endif /* configUSE_CO_ROUTINES */
\r
1887 /*-----------------------------------------------------------*/
\r
1889 #if ( configQUEUE_REGISTRY_SIZE > 0 )
\r
1891 void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )
\r
1893 unsigned portBASE_TYPE ux;
\r
1895 /* See if there is an empty space in the registry. A NULL name denotes
\r
1897 for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
\r
1899 if( xQueueRegistry[ ux ].pcQueueName == NULL )
\r
1901 /* Store the information on this queue. */
\r
1902 xQueueRegistry[ ux ].pcQueueName = pcQueueName;
\r
1903 xQueueRegistry[ ux ].xHandle = xQueue;
\r
1909 #endif /* configQUEUE_REGISTRY_SIZE */
\r
1910 /*-----------------------------------------------------------*/
\r
1912 #if ( configQUEUE_REGISTRY_SIZE > 0 )
\r
1914 void vQueueUnregisterQueue( xQueueHandle xQueue )
\r
1916 unsigned portBASE_TYPE ux;
\r
1918 /* See if the handle of the queue being unregistered in actually in the
\r
1920 for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
\r
1922 if( xQueueRegistry[ ux ].xHandle == xQueue )
\r
1924 /* Set the name to NULL to show that this slot if free again. */
\r
1925 xQueueRegistry[ ux ].pcQueueName = NULL;
\r
1930 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
\r
1932 #endif /* configQUEUE_REGISTRY_SIZE */
\r
1933 /*-----------------------------------------------------------*/
\r
1935 #if ( configUSE_TIMERS == 1 )
\r
1937 void vQueueWaitForMessageRestricted( xQueueHandle xQueue, portTickType xTicksToWait )
\r
1939 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
\r
1941 /* This function should not be called by application code hence the
\r
1942 'Restricted' in its name. It is not part of the public API. It is
\r
1943 designed for use by kernel code, and has special calling requirements.
\r
1944 It can result in vListInsert() being called on a list that can only
\r
1945 possibly ever have one item in it, so the list will be fast, but even
\r
1946 so it should be called with the scheduler locked and not from a critical
\r
1949 /* Only do anything if there are no messages in the queue. This function
\r
1950 will not actually cause the task to block, just place it on a blocked
\r
1951 list. It will not block until the scheduler is unlocked - at which
\r
1952 time a yield will be performed. If an item is added to the queue while
\r
1953 the queue is locked, and the calling task blocks on the queue, then the
\r
1954 calling task will be immediately unblocked when the queue is unlocked. */
\r
1955 prvLockQueue( pxQueue );
\r
1956 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U )
\r
1958 /* There is nothing in the queue, block for the specified period. */
\r
1959 vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
1961 prvUnlockQueue( pxQueue );
\r
1964 #endif /* configUSE_TIMERS */
\r
1965 /*-----------------------------------------------------------*/
\r
1967 #if ( configUSE_QUEUE_SETS == 1 )
\r
1969 xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength )
\r
1971 xQueueSetHandle pxQueue;
\r
1973 pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( xQUEUE * ), queueQUEUE_TYPE_SET );
\r
1978 #endif /* configUSE_QUEUE_SETS */
\r
1979 /*-----------------------------------------------------------*/
\r
1981 #if ( configUSE_QUEUE_SETS == 1 )
\r
1983 portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )
\r
1985 portBASE_TYPE xReturn;
\r
1987 if( ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )
\r
1989 /* Cannot add a queue/semaphore to more than one queue set. */
\r
1992 else if( ( ( xQUEUE * ) xQueueOrSemaphore )->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 )
\r
1994 /* Cannot add a queue/semaphore to a queue set if there are already
\r
1995 items in the queue/semaphore. */
\r
2000 taskENTER_CRITICAL();
\r
2002 ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet;
\r
2004 taskEXIT_CRITICAL();
\r
2011 #endif /* configUSE_QUEUE_SETS */
\r
2012 /*-----------------------------------------------------------*/
\r
2014 #if ( configUSE_QUEUE_SETS == 1 )
\r
2016 portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )
\r
2018 portBASE_TYPE xReturn;
\r
2019 xQUEUE * const pxQueueOrSemaphore = ( xQUEUE * ) xQueueOrSemaphore;
\r
2021 if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet )
\r
2023 /* The queue was not a member of the set. */
\r
2026 else if( pxQueueOrSemaphore->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 )
\r
2028 /* It is dangerous to remove a queue from a set when the queue is
\r
2029 not empty because the queue set will still hold pending events for
\r
2035 taskENTER_CRITICAL();
\r
2037 /* The queue is no longer contained in the set. */
\r
2038 pxQueueOrSemaphore->pxQueueSetContainer = NULL;
\r
2040 taskEXIT_CRITICAL();
\r
2045 } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */
\r
2047 #endif /* configUSE_QUEUE_SETS */
\r
2048 /*-----------------------------------------------------------*/
\r
2050 #if ( configUSE_QUEUE_SETS == 1 )
\r
2052 xQueueSetMemberHandle xQueueSelectFromSet( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks )
\r
2054 xQueueSetMemberHandle xReturn = NULL;
\r
2056 ( void ) xQueueGenericReceive( ( xQueueHandle ) xQueueSet, &xReturn, xBlockTimeTicks, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */
\r
2060 #endif /* configUSE_QUEUE_SETS */
\r
2061 /*-----------------------------------------------------------*/
\r
2063 #if ( configUSE_QUEUE_SETS == 1 )
\r
2065 xQueueSetMemberHandle xQueueSelectFromSetFromISR( xQueueSetHandle xQueueSet )
\r
2067 xQueueSetMemberHandle xReturn = NULL;
\r
2069 ( void ) xQueueReceiveFromISR( ( xQueueHandle ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */
\r
2073 #endif /* configUSE_QUEUE_SETS */
\r
2074 /*-----------------------------------------------------------*/
\r
2076 #if ( configUSE_QUEUE_SETS == 1 )
\r
2078 static portBASE_TYPE prvNotifyQueueSetContainer( const xQUEUE * const pxQueue, portBASE_TYPE xCopyPosition )
\r
2080 xQUEUE *pxQueueSetContainer = pxQueue->pxQueueSetContainer;
\r
2081 portBASE_TYPE xReturn = pdFALSE;
\r
2083 configASSERT( pxQueueSetContainer );
\r
2084 configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );
\r
2086 if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )
\r
2088 traceQUEUE_SEND( pxQueueSetContainer );
\r
2089 /* The data copies is the handle of the queue that contains data. */
\r
2090 prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition );
\r
2091 if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE )
\r
2093 if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE )
\r
2095 /* The task waiting has a higher priority */
\r
2104 #endif /* configUSE_QUEUE_SETS */
\r