2 FreeRTOS V7.0.2 - Copyright (C) 2011 Real Time Engineers Ltd.
\r
5 ***************************************************************************
\r
7 * FreeRTOS tutorial books are available in pdf and paperback. *
\r
8 * Complete, revised, and edited pdf reference manuals are also *
\r
11 * Purchasing FreeRTOS documentation will not only help you, by *
\r
12 * ensuring you get running as quickly as possible and with an *
\r
13 * in-depth knowledge of how to use FreeRTOS, it will also help *
\r
14 * the FreeRTOS project to continue with its mission of providing *
\r
15 * professional grade, cross platform, de facto standard solutions *
\r
16 * for microcontrollers - completely free of charge! *
\r
18 * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
\r
20 * Thank you for using FreeRTOS, and thank you for your support! *
\r
22 ***************************************************************************
\r
25 This file is part of the FreeRTOS distribution.
\r
27 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
28 the terms of the GNU General Public License (version 2) as published by the
\r
29 Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
\r
30 >>>NOTE<<< The modification to the GPL is included to allow you to
\r
31 distribute a combined work that includes FreeRTOS without being obliged to
\r
32 provide the source code for proprietary components outside of the FreeRTOS
\r
33 kernel. FreeRTOS is distributed in the hope that it will be useful, but
\r
34 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
\r
35 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
\r
36 more details. You should have received a copy of the GNU General Public
\r
37 License and the FreeRTOS license exception along with FreeRTOS; if not it
\r
38 can be viewed here: http://www.freertos.org/a00114.html and also obtained
\r
39 by writing to Richard Barry, contact details for whom are available on the
\r
44 http://www.FreeRTOS.org - Documentation, latest information, license and
\r
47 http://www.SafeRTOS.com - A version that is certified for use in safety
\r
50 http://www.OpenRTOS.com - Commercial support, development, porting,
\r
51 licensing and training services.
\r
57 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
\r
58 all the API functions to use the MPU wrappers. That should only be done when
\r
59 task.h is included from an application file. */
\r
60 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
62 #include "FreeRTOS.h"
\r
65 #if ( configUSE_CO_ROUTINES == 1 )
\r
66 #include "croutine.h"
\r
69 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
71 /*-----------------------------------------------------------
\r
72 * PUBLIC LIST API documented in list.h
\r
73 *----------------------------------------------------------*/
\r
75 /* Constants used with the cRxLock and cTxLock structure members. */
\r
76 #define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 )
\r
77 #define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 )
\r
79 #define queueERRONEOUS_UNBLOCK ( -1 )
\r
81 /* For internal use only. */
\r
82 #define queueSEND_TO_BACK ( 0 )
\r
83 #define queueSEND_TO_FRONT ( 1 )
\r
85 /* Effectively make a union out of the xQUEUE structure. */
\r
86 #define pxMutexHolder pcTail
\r
87 #define uxQueueType pcHead
\r
88 #define uxRecursiveCallCount pcReadFrom
\r
89 #define queueQUEUE_IS_MUTEX NULL
\r
91 /* Semaphores do not actually store or copy data, so have an items size of
\r
93 #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portBASE_TYPE ) 0 )
\r
94 #define queueDONT_BLOCK ( ( portTickType ) 0U )
\r
95 #define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0U )
\r
97 /* These definitions *must* match those in queue.h. */
\r
98 #define queueQUEUE_TYPE_BASE ( 0U )
\r
99 #define queueQUEUE_TYPE_MUTEX ( 1U )
\r
100 #define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( 2U )
\r
101 #define queueQUEUE_TYPE_BINARY_SEMAPHORE ( 3U )
\r
102 #define queueQUEUE_TYPE_RECURSIVE_MUTEX ( 4U )
\r
105 * Definition of the queue used by the scheduler.
\r
106 * Items are queued by copy, not reference.
\r
108 typedef struct QueueDefinition
\r
110 signed char *pcHead; /*< Points to the beginning of the queue storage area. */
\r
111 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
113 signed char *pcWriteTo; /*< Points to the free next place in the storage area. */
\r
114 signed char *pcReadFrom; /*< Points to the last place that a queued item was read from. */
\r
116 xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */
\r
117 xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */
\r
119 volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */
\r
120 unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
\r
121 unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */
\r
123 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
124 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
126 #if ( configUSE_TRACE_FACILITY == 1 )
\r
127 unsigned char ucQueueNumber;
\r
128 unsigned char ucQueueType;
\r
132 /*-----------------------------------------------------------*/
\r
135 * Inside this file xQueueHandle is a pointer to a xQUEUE structure.
\r
136 * To keep the definition private the API header file defines it as a
\r
139 typedef xQUEUE * xQueueHandle;
\r
142 * Prototypes for public functions are included here so we don't have to
\r
143 * include the API header file (as it defines xQueueHandle differently). These
\r
144 * functions are documented in the API header file.
\r
146 xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType ) PRIVILEGED_FUNCTION;
\r
147 signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
\r
148 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
149 void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
\r
150 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
\r
151 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;
\r
152 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;
\r
153 xQueueHandle xQueueCreateMutex( unsigned char ucQueueType ) PRIVILEGED_FUNCTION;
\r
154 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) PRIVILEGED_FUNCTION;
\r
155 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) PRIVILEGED_FUNCTION;
\r
156 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ) PRIVILEGED_FUNCTION;
\r
157 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
\r
158 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;
\r
159 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
160 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
161 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
162 void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
\r
163 unsigned char ucQueueGetQueueNumber( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
164 void vQueueSetQueueNumber( xQueueHandle pxQueue, unsigned char ucQueueNumber ) PRIVILEGED_FUNCTION;
\r
165 unsigned char ucQueueGetQueueType( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
168 * Co-routine queue functions differ from task queue functions. Co-routines are
\r
169 * an optional component.
\r
171 #if configUSE_CO_ROUTINES == 1
\r
172 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) PRIVILEGED_FUNCTION;
\r
173 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;
\r
174 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
\r
175 signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
\r
179 * The queue registry is just a means for kernel aware debuggers to locate
\r
180 * queue structures. It has no other purpose so is an optional component.
\r
182 #if configQUEUE_REGISTRY_SIZE > 0
\r
184 /* The type stored within the queue registry array. This allows a name
\r
185 to be assigned to each queue making kernel aware debugging a little
\r
186 more user friendly. */
\r
187 typedef struct QUEUE_REGISTRY_ITEM
\r
189 signed char *pcQueueName;
\r
190 xQueueHandle xHandle;
\r
191 } xQueueRegistryItem;
\r
193 /* The queue registry is simply an array of xQueueRegistryItem structures.
\r
194 The pcQueueName member of a structure being NULL is indicative of the
\r
195 array position being vacant. */
\r
196 xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
\r
198 /* Removes a queue from the registry by simply setting the pcQueueName
\r
200 static void vQueueUnregisterQueue( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
\r
201 void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName ) PRIVILEGED_FUNCTION;
\r
205 * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not
\r
206 * prevent an ISR from adding or removing items to the queue, but does prevent
\r
207 * an ISR from removing tasks from the queue event lists. If an ISR finds a
\r
208 * queue is locked it will instead increment the appropriate queue lock count
\r
209 * to indicate that a task may require unblocking. When the queue in unlocked
\r
210 * these lock counts are inspected, and the appropriate action taken.
\r
212 static void prvUnlockQueue( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
215 * Uses a critical section to determine if there is any data in a queue.
\r
217 * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
\r
219 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
222 * Uses a critical section to determine if there is any space in a queue.
\r
224 * @return pdTRUE if there is no space, otherwise pdFALSE;
\r
226 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
229 * Copies an item into the queue, either at the front of the queue or the
\r
230 * back of the queue.
\r
232 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION;
\r
235 * Copies an item out of a queue.
\r
237 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer ) PRIVILEGED_FUNCTION;
\r
238 /*-----------------------------------------------------------*/
\r
241 * Macro to mark a queue as locked. Locking a queue prevents an ISR from
\r
242 * accessing the queue event lists.
\r
244 #define prvLockQueue( pxQueue ) \
\r
245 taskENTER_CRITICAL(); \
\r
247 if( ( pxQueue )->xRxLock == queueUNLOCKED ) \
\r
249 ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED; \
\r
251 if( ( pxQueue )->xTxLock == queueUNLOCKED ) \
\r
253 ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED; \
\r
256 taskEXIT_CRITICAL()
\r
257 /*-----------------------------------------------------------*/
\r
260 /*-----------------------------------------------------------
\r
261 * PUBLIC QUEUE MANAGEMENT API documented in queue.h
\r
262 *----------------------------------------------------------*/
\r
264 xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType )
\r
266 xQUEUE *pxNewQueue;
\r
267 size_t xQueueSizeInBytes;
\r
268 xQueueHandle xReturn = NULL;
\r
270 /* Remove compiler warnings about unused parameters should
\r
271 configUSE_TRACE_FACILITY not be set to 1. */
\r
272 ( void ) ucQueueType;
\r
274 /* Allocate the new queue structure. */
\r
275 if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )
\r
277 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
\r
278 if( pxNewQueue != NULL )
\r
280 /* Create the list of pointers to queue items. The queue is one byte
\r
281 longer than asked for to make wrap checking easier/faster. */
\r
282 xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1;
\r
284 pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes );
\r
285 if( pxNewQueue->pcHead != NULL )
\r
287 /* Initialise the queue members as described above where the
\r
288 queue type is defined. */
\r
289 pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize );
\r
290 pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
\r
291 pxNewQueue->pcWriteTo = pxNewQueue->pcHead;
\r
292 pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - ( unsigned portBASE_TYPE ) 1U ) * uxItemSize );
\r
293 pxNewQueue->uxLength = uxQueueLength;
\r
294 pxNewQueue->uxItemSize = uxItemSize;
\r
295 pxNewQueue->xRxLock = queueUNLOCKED;
\r
296 pxNewQueue->xTxLock = queueUNLOCKED;
\r
297 #if ( configUSE_TRACE_FACILITY == 1 )
\r
299 pxNewQueue->ucQueueType = ucQueueType;
\r
301 #endif /* configUSE_TRACE_FACILITY */
\r
303 /* Likewise ensure the event queues start with the correct state. */
\r
304 vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
\r
305 vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
\r
307 traceQUEUE_CREATE( pxNewQueue );
\r
308 xReturn = pxNewQueue;
\r
312 traceQUEUE_CREATE_FAILED( ucQueueType );
\r
313 vPortFree( pxNewQueue );
\r
318 configASSERT( xReturn );
\r
322 /*-----------------------------------------------------------*/
\r
324 #if ( configUSE_MUTEXES == 1 )
\r
326 xQueueHandle xQueueCreateMutex( unsigned char ucQueueType )
\r
328 xQUEUE *pxNewQueue;
\r
330 /* Prevent compiler warnings about unused parameters if
\r
331 configUSE_TRACE_FACILITY does not equal 1. */
\r
332 ( void ) ucQueueType;
\r
334 /* Allocate the new queue structure. */
\r
335 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
\r
336 if( pxNewQueue != NULL )
\r
338 /* Information required for priority inheritance. */
\r
339 pxNewQueue->pxMutexHolder = NULL;
\r
340 pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
\r
342 /* Queues used as a mutex no data is actually copied into or out
\r
344 pxNewQueue->pcWriteTo = NULL;
\r
345 pxNewQueue->pcReadFrom = NULL;
\r
347 /* Each mutex has a length of 1 (like a binary semaphore) and
\r
348 an item size of 0 as nothing is actually copied into or out
\r
350 pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
\r
351 pxNewQueue->uxLength = ( unsigned portBASE_TYPE ) 1U;
\r
352 pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 0U;
\r
353 pxNewQueue->xRxLock = queueUNLOCKED;
\r
354 pxNewQueue->xTxLock = queueUNLOCKED;
\r
356 #if ( configUSE_TRACE_FACILITY == 1 )
\r
358 pxNewQueue->ucQueueType = ucQueueType;
\r
362 /* Ensure the event queues start with the correct state. */
\r
363 vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
\r
364 vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
\r
366 traceCREATE_MUTEX( pxNewQueue );
\r
368 /* Start with the semaphore in the expected state. */
\r
369 xQueueGenericSend( pxNewQueue, NULL, ( portTickType ) 0U, queueSEND_TO_BACK );
\r
373 traceCREATE_MUTEX_FAILED();
\r
376 configASSERT( pxNewQueue );
\r
380 #endif /* configUSE_MUTEXES */
\r
381 /*-----------------------------------------------------------*/
\r
383 #if configUSE_RECURSIVE_MUTEXES == 1
\r
385 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex )
\r
387 portBASE_TYPE xReturn;
\r
389 configASSERT( pxMutex );
\r
391 /* If this is the task that holds the mutex then pxMutexHolder will not
\r
392 change outside of this task. If this task does not hold the mutex then
\r
393 pxMutexHolder can never coincidentally equal the tasks handle, and as
\r
394 this is the only condition we are interested in it does not matter if
\r
395 pxMutexHolder is accessed simultaneously by another task. Therefore no
\r
396 mutual exclusion is required to test the pxMutexHolder variable. */
\r
397 if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
\r
399 traceGIVE_MUTEX_RECURSIVE( pxMutex );
\r
401 /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to
\r
402 the task handle, therefore no underflow check is required. Also,
\r
403 uxRecursiveCallCount is only modified by the mutex holder, and as
\r
404 there can only be one, no mutual exclusion is required to modify the
\r
405 uxRecursiveCallCount member. */
\r
406 ( pxMutex->uxRecursiveCallCount )--;
\r
408 /* Have we unwound the call count? */
\r
409 if( pxMutex->uxRecursiveCallCount == 0 )
\r
411 /* Return the mutex. This will automatically unblock any other
\r
412 task that might be waiting to access the mutex. */
\r
413 xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
\r
420 /* We cannot give the mutex because we are not the holder. */
\r
423 traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
\r
429 #endif /* configUSE_RECURSIVE_MUTEXES */
\r
430 /*-----------------------------------------------------------*/
\r
432 #if configUSE_RECURSIVE_MUTEXES == 1
\r
434 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime )
\r
436 portBASE_TYPE xReturn;
\r
438 configASSERT( pxMutex );
\r
440 /* Comments regarding mutual exclusion as per those within
\r
441 xQueueGiveMutexRecursive(). */
\r
443 traceTAKE_MUTEX_RECURSIVE( pxMutex );
\r
445 if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
\r
447 ( pxMutex->uxRecursiveCallCount )++;
\r
452 xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );
\r
454 /* pdPASS will only be returned if we successfully obtained the mutex,
\r
455 we may have blocked to reach here. */
\r
456 if( xReturn == pdPASS )
\r
458 ( pxMutex->uxRecursiveCallCount )++;
\r
462 traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );
\r
469 #endif /* configUSE_RECURSIVE_MUTEXES */
\r
470 /*-----------------------------------------------------------*/
\r
472 #if configUSE_COUNTING_SEMAPHORES == 1
\r
474 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount )
\r
476 xQueueHandle pxHandle;
\r
478 pxHandle = xQueueGenericCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
\r
480 if( pxHandle != NULL )
\r
482 pxHandle->uxMessagesWaiting = uxInitialCount;
\r
484 traceCREATE_COUNTING_SEMAPHORE();
\r
488 traceCREATE_COUNTING_SEMAPHORE_FAILED();
\r
491 configASSERT( pxHandle );
\r
495 #endif /* configUSE_COUNTING_SEMAPHORES */
\r
496 /*-----------------------------------------------------------*/
\r
498 signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
\r
500 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
501 xTimeOutType xTimeOut;
\r
503 configASSERT( pxQueue );
\r
504 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
506 /* This function relaxes the coding standard somewhat to allow return
\r
507 statements within the function itself. This is done in the interest
\r
508 of execution time efficiency. */
\r
511 taskENTER_CRITICAL();
\r
513 /* Is there room on the queue now? To be running we must be
\r
514 the highest priority task wanting to access the queue. */
\r
515 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
517 traceQUEUE_SEND( pxQueue );
\r
518 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
520 /* If there was a task waiting for data to arrive on the
\r
521 queue then unblock it now. */
\r
522 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
524 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
526 /* The unblocked task has a priority higher than
\r
527 our own so yield immediately. Yes it is ok to do
\r
528 this from within the critical section - the kernel
\r
529 takes care of that. */
\r
530 portYIELD_WITHIN_API();
\r
534 taskEXIT_CRITICAL();
\r
536 /* Return to the original privilege level before exiting the
\r
542 if( xTicksToWait == ( portTickType ) 0 )
\r
544 /* The queue was full and no block time is specified (or
\r
545 the block time has expired) so leave now. */
\r
546 taskEXIT_CRITICAL();
\r
548 /* Return to the original privilege level before exiting
\r
550 traceQUEUE_SEND_FAILED( pxQueue );
\r
551 return errQUEUE_FULL;
\r
553 else if( xEntryTimeSet == pdFALSE )
\r
555 /* The queue was full and a block time was specified so
\r
556 configure the timeout structure. */
\r
557 vTaskSetTimeOutState( &xTimeOut );
\r
558 xEntryTimeSet = pdTRUE;
\r
562 taskEXIT_CRITICAL();
\r
564 /* Interrupts and other tasks can send to and receive from the queue
\r
565 now the critical section has been exited. */
\r
568 prvLockQueue( pxQueue );
\r
570 /* Update the timeout state to see if it has expired yet. */
\r
571 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
573 if( prvIsQueueFull( pxQueue ) != pdFALSE )
\r
575 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
\r
576 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
\r
578 /* Unlocking the queue means queue events can effect the
\r
579 event list. It is possible that interrupts occurring now
\r
580 remove this task from the event list again - but as the
\r
581 scheduler is suspended the task will go onto the pending
\r
582 ready last instead of the actual ready list. */
\r
583 prvUnlockQueue( pxQueue );
\r
585 /* Resuming the scheduler will move tasks from the pending
\r
586 ready list into the ready list - so it is feasible that this
\r
587 task is already in a ready list before it yields - in which
\r
588 case the yield will not cause a context switch unless there
\r
589 is also a higher priority task in the pending ready list. */
\r
590 if( xTaskResumeAll() == pdFALSE )
\r
592 portYIELD_WITHIN_API();
\r
598 prvUnlockQueue( pxQueue );
\r
599 ( void ) xTaskResumeAll();
\r
604 /* The timeout has expired. */
\r
605 prvUnlockQueue( pxQueue );
\r
606 ( void ) xTaskResumeAll();
\r
608 /* Return to the original privilege level before exiting the
\r
610 traceQUEUE_SEND_FAILED( pxQueue );
\r
611 return errQUEUE_FULL;
\r
615 /*-----------------------------------------------------------*/
\r
617 #if configUSE_ALTERNATIVE_API == 1
\r
619 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
\r
621 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
622 xTimeOutType xTimeOut;
\r
624 configASSERT( pxQueue );
\r
625 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
629 taskENTER_CRITICAL();
\r
631 /* Is there room on the queue now? To be running we must be
\r
632 the highest priority task wanting to access the queue. */
\r
633 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
635 traceQUEUE_SEND( pxQueue );
\r
636 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
638 /* If there was a task waiting for data to arrive on the
\r
639 queue then unblock it now. */
\r
640 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
642 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
644 /* The unblocked task has a priority higher than
\r
645 our own so yield immediately. */
\r
646 portYIELD_WITHIN_API();
\r
650 taskEXIT_CRITICAL();
\r
655 if( xTicksToWait == ( portTickType ) 0 )
\r
657 taskEXIT_CRITICAL();
\r
658 return errQUEUE_FULL;
\r
660 else if( xEntryTimeSet == pdFALSE )
\r
662 vTaskSetTimeOutState( &xTimeOut );
\r
663 xEntryTimeSet = pdTRUE;
\r
667 taskEXIT_CRITICAL();
\r
669 taskENTER_CRITICAL();
\r
671 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
673 if( prvIsQueueFull( pxQueue ) != pdFALSE )
\r
675 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
\r
676 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
\r
677 portYIELD_WITHIN_API();
\r
682 taskEXIT_CRITICAL();
\r
683 traceQUEUE_SEND_FAILED( pxQueue );
\r
684 return errQUEUE_FULL;
\r
687 taskEXIT_CRITICAL();
\r
691 #endif /* configUSE_ALTERNATIVE_API */
\r
692 /*-----------------------------------------------------------*/
\r
694 #if configUSE_ALTERNATIVE_API == 1
\r
696 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
\r
698 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
699 xTimeOutType xTimeOut;
\r
700 signed char *pcOriginalReadPosition;
\r
702 configASSERT( pxQueue );
\r
703 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
707 taskENTER_CRITICAL();
\r
709 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
711 /* Remember our read position in case we are just peeking. */
\r
712 pcOriginalReadPosition = pxQueue->pcReadFrom;
\r
714 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
716 if( xJustPeeking == pdFALSE )
\r
718 traceQUEUE_RECEIVE( pxQueue );
\r
720 /* We are actually removing data. */
\r
721 --( pxQueue->uxMessagesWaiting );
\r
723 #if ( configUSE_MUTEXES == 1 )
\r
725 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
727 /* Record the information required to implement
\r
728 priority inheritance should it become necessary. */
\r
729 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
\r
734 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
736 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
738 portYIELD_WITHIN_API();
\r
744 traceQUEUE_PEEK( pxQueue );
\r
746 /* We are not removing the data, so reset our read
\r
748 pxQueue->pcReadFrom = pcOriginalReadPosition;
\r
750 /* The data is being left in the queue, so see if there are
\r
751 any other tasks waiting for the data. */
\r
752 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
754 /* Tasks that are removed from the event list will get added to
\r
755 the pending ready list as the scheduler is still suspended. */
\r
756 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
758 /* The task waiting has a higher priority than this task. */
\r
759 portYIELD_WITHIN_API();
\r
765 taskEXIT_CRITICAL();
\r
770 if( xTicksToWait == ( portTickType ) 0 )
\r
772 taskEXIT_CRITICAL();
\r
773 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
774 return errQUEUE_EMPTY;
\r
776 else if( xEntryTimeSet == pdFALSE )
\r
778 vTaskSetTimeOutState( &xTimeOut );
\r
779 xEntryTimeSet = pdTRUE;
\r
783 taskEXIT_CRITICAL();
\r
785 taskENTER_CRITICAL();
\r
787 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
789 if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
\r
791 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
\r
793 #if ( configUSE_MUTEXES == 1 )
\r
795 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
797 portENTER_CRITICAL();
\r
798 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
\r
799 portEXIT_CRITICAL();
\r
804 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
805 portYIELD_WITHIN_API();
\r
810 taskEXIT_CRITICAL();
\r
811 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
812 return errQUEUE_EMPTY;
\r
815 taskEXIT_CRITICAL();
\r
820 #endif /* configUSE_ALTERNATIVE_API */
\r
821 /*-----------------------------------------------------------*/
\r
823 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )
\r
825 signed portBASE_TYPE xReturn;
\r
826 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
828 configASSERT( pxQueue );
\r
829 configASSERT( pxHigherPriorityTaskWoken );
\r
830 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
832 /* Similar to xQueueGenericSend, except we don't block if there is no room
\r
833 in the queue. Also we don't directly wake a task that was blocked on a
\r
834 queue read, instead we return a flag to say whether a context switch is
\r
835 required or not (i.e. has a task with a higher priority than us been woken
\r
837 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
839 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
841 traceQUEUE_SEND_FROM_ISR( pxQueue );
\r
843 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
845 /* If the queue is locked we do not alter the event list. This will
\r
846 be done when the queue is unlocked later. */
\r
847 if( pxQueue->xTxLock == queueUNLOCKED )
\r
849 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
851 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
853 /* The task waiting has a higher priority so record that a
\r
854 context switch is required. */
\r
855 *pxHigherPriorityTaskWoken = pdTRUE;
\r
861 /* Increment the lock count so the task that unlocks the queue
\r
862 knows that data was posted while it was locked. */
\r
863 ++( pxQueue->xTxLock );
\r
870 traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
\r
871 xReturn = errQUEUE_FULL;
\r
874 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
878 /*-----------------------------------------------------------*/
\r
880 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
\r
882 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
883 xTimeOutType xTimeOut;
\r
884 signed char *pcOriginalReadPosition;
\r
886 configASSERT( pxQueue );
\r
887 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
889 /* This function relaxes the coding standard somewhat to allow return
\r
890 statements within the function itself. This is done in the interest
\r
891 of execution time efficiency. */
\r
895 taskENTER_CRITICAL();
\r
897 /* Is there data in the queue now? To be running we must be
\r
898 the highest priority task wanting to access the queue. */
\r
899 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
901 /* Remember our read position in case we are just peeking. */
\r
902 pcOriginalReadPosition = pxQueue->pcReadFrom;
\r
904 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
906 if( xJustPeeking == pdFALSE )
\r
908 traceQUEUE_RECEIVE( pxQueue );
\r
910 /* We are actually removing data. */
\r
911 --( pxQueue->uxMessagesWaiting );
\r
913 #if ( configUSE_MUTEXES == 1 )
\r
915 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
917 /* Record the information required to implement
\r
918 priority inheritance should it become necessary. */
\r
919 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
\r
924 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
926 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
928 portYIELD_WITHIN_API();
\r
934 traceQUEUE_PEEK( pxQueue );
\r
936 /* We are not removing the data, so reset our read
\r
938 pxQueue->pcReadFrom = pcOriginalReadPosition;
\r
940 /* The data is being left in the queue, so see if there are
\r
941 any other tasks waiting for the data. */
\r
942 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
944 /* Tasks that are removed from the event list will get added to
\r
945 the pending ready list as the scheduler is still suspended. */
\r
946 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
948 /* The task waiting has a higher priority than this task. */
\r
949 portYIELD_WITHIN_API();
\r
955 taskEXIT_CRITICAL();
\r
960 if( xTicksToWait == ( portTickType ) 0 )
\r
962 /* The queue was empty and no block time is specified (or
\r
963 the block time has expired) so leave now. */
\r
964 taskEXIT_CRITICAL();
\r
965 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
966 return errQUEUE_EMPTY;
\r
968 else if( xEntryTimeSet == pdFALSE )
\r
970 /* The queue was empty and a block time was specified so
\r
971 configure the timeout structure. */
\r
972 vTaskSetTimeOutState( &xTimeOut );
\r
973 xEntryTimeSet = pdTRUE;
\r
977 taskEXIT_CRITICAL();
\r
979 /* Interrupts and other tasks can send to and receive from the queue
\r
980 now the critical section has been exited. */
\r
983 prvLockQueue( pxQueue );
\r
985 /* Update the timeout state to see if it has expired yet. */
\r
986 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
988 if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
\r
990 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
\r
992 #if ( configUSE_MUTEXES == 1 )
\r
994 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
996 portENTER_CRITICAL();
\r
998 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
\r
1000 portEXIT_CRITICAL();
\r
1005 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
1006 prvUnlockQueue( pxQueue );
\r
1007 if( xTaskResumeAll() == pdFALSE )
\r
1009 portYIELD_WITHIN_API();
\r
1015 prvUnlockQueue( pxQueue );
\r
1016 ( void ) xTaskResumeAll();
\r
1021 prvUnlockQueue( pxQueue );
\r
1022 ( void ) xTaskResumeAll();
\r
1023 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
1024 return errQUEUE_EMPTY;
\r
1028 /*-----------------------------------------------------------*/
\r
1030 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )
\r
1032 signed portBASE_TYPE xReturn;
\r
1033 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
1035 configASSERT( pxQueue );
\r
1036 configASSERT( pxTaskWoken );
\r
1037 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
1039 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1041 /* We cannot block from an ISR, so check there is data available. */
\r
1042 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1044 traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
\r
1046 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
1047 --( pxQueue->uxMessagesWaiting );
\r
1049 /* If the queue is locked we will not modify the event list. Instead
\r
1050 we update the lock count so the task that unlocks the queue will know
\r
1051 that an ISR has removed data while the queue was locked. */
\r
1052 if( pxQueue->xRxLock == queueUNLOCKED )
\r
1054 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1056 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1058 /* The task waiting has a higher priority than us so
\r
1059 force a context switch. */
\r
1060 *pxTaskWoken = pdTRUE;
\r
1066 /* Increment the lock count so the task that unlocks the queue
\r
1067 knows that data was removed while it was locked. */
\r
1068 ++( pxQueue->xRxLock );
\r
1076 traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
\r
1079 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1083 /*-----------------------------------------------------------*/
\r
1085 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue )
\r
1087 unsigned portBASE_TYPE uxReturn;
\r
1089 configASSERT( pxQueue );
\r
1091 taskENTER_CRITICAL();
\r
1092 uxReturn = pxQueue->uxMessagesWaiting;
\r
1093 taskEXIT_CRITICAL();
\r
1097 /*-----------------------------------------------------------*/
\r
1099 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue )
\r
1101 unsigned portBASE_TYPE uxReturn;
\r
1103 configASSERT( pxQueue );
\r
1105 uxReturn = pxQueue->uxMessagesWaiting;
\r
1109 /*-----------------------------------------------------------*/
\r
1111 void vQueueDelete( xQueueHandle pxQueue )
\r
1113 configASSERT( pxQueue );
\r
1115 traceQUEUE_DELETE( pxQueue );
\r
1116 vQueueUnregisterQueue( pxQueue );
\r
1117 vPortFree( pxQueue->pcHead );
\r
1118 vPortFree( pxQueue );
\r
1120 /*-----------------------------------------------------------*/
\r
1122 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1124 unsigned char ucQueueGetQueueNumber( xQueueHandle pxQueue )
\r
1126 return pxQueue->ucQueueNumber;
\r
1130 /*-----------------------------------------------------------*/
\r
1132 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1134 void vQueueSetQueueNumber( xQueueHandle pxQueue, unsigned char ucQueueNumber )
\r
1136 pxQueue->ucQueueNumber = ucQueueNumber;
\r
1140 /*-----------------------------------------------------------*/
\r
1142 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1144 unsigned char ucQueueGetQueueType( xQueueHandle pxQueue )
\r
1146 return pxQueue->ucQueueType;
\r
1150 /*-----------------------------------------------------------*/
\r
1152 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )
\r
1154 if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )
\r
1156 #if ( configUSE_MUTEXES == 1 )
\r
1158 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
1160 /* The mutex is no longer being held. */
\r
1161 vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
\r
1162 pxQueue->pxMutexHolder = NULL;
\r
1167 else if( xPosition == queueSEND_TO_BACK )
\r
1169 memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
\r
1170 pxQueue->pcWriteTo += pxQueue->uxItemSize;
\r
1171 if( pxQueue->pcWriteTo >= pxQueue->pcTail )
\r
1173 pxQueue->pcWriteTo = pxQueue->pcHead;
\r
1178 memcpy( ( void * ) pxQueue->pcReadFrom, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
\r
1179 pxQueue->pcReadFrom -= pxQueue->uxItemSize;
\r
1180 if( pxQueue->pcReadFrom < pxQueue->pcHead )
\r
1182 pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
\r
1186 ++( pxQueue->uxMessagesWaiting );
\r
1188 /*-----------------------------------------------------------*/
\r
1190 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
\r
1192 if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
\r
1194 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1195 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1197 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1199 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1202 /*-----------------------------------------------------------*/
\r
1204 static void prvUnlockQueue( xQueueHandle pxQueue )
\r
1206 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
\r
1208 /* The lock counts contains the number of extra data items placed or
\r
1209 removed from the queue while the queue was locked. When a queue is
\r
1210 locked items can be added or removed, but the event lists cannot be
\r
1212 taskENTER_CRITICAL();
\r
1214 /* See if data was added to the queue while it was locked. */
\r
1215 while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )
\r
1217 /* Data was posted while the queue was locked. Are any tasks
\r
1218 blocked waiting for data to become available? */
\r
1219 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1221 /* Tasks that are removed from the event list will get added to
\r
1222 the pending ready list as the scheduler is still suspended. */
\r
1223 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1225 /* The task waiting has a higher priority so record that a
\r
1226 context switch is required. */
\r
1227 vTaskMissedYield();
\r
1230 --( pxQueue->xTxLock );
\r
1238 pxQueue->xTxLock = queueUNLOCKED;
\r
1240 taskEXIT_CRITICAL();
\r
1242 /* Do the same for the Rx lock. */
\r
1243 taskENTER_CRITICAL();
\r
1245 while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )
\r
1247 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1249 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1251 vTaskMissedYield();
\r
1254 --( pxQueue->xRxLock );
\r
1262 pxQueue->xRxLock = queueUNLOCKED;
\r
1264 taskEXIT_CRITICAL();
\r
1266 /*-----------------------------------------------------------*/
\r
1268 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue )
\r
1270 signed portBASE_TYPE xReturn;
\r
1272 taskENTER_CRITICAL();
\r
1273 xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
\r
1274 taskEXIT_CRITICAL();
\r
1278 /*-----------------------------------------------------------*/
\r
1280 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue )
\r
1282 signed portBASE_TYPE xReturn;
\r
1284 configASSERT( pxQueue );
\r
1285 xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
\r
1289 /*-----------------------------------------------------------*/
\r
1291 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue )
\r
1293 signed portBASE_TYPE xReturn;
\r
1295 taskENTER_CRITICAL();
\r
1296 xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
\r
1297 taskEXIT_CRITICAL();
\r
1301 /*-----------------------------------------------------------*/
\r
1303 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue )
\r
1305 signed portBASE_TYPE xReturn;
\r
1307 configASSERT( pxQueue );
\r
1308 xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
\r
1312 /*-----------------------------------------------------------*/
\r
1314 #if configUSE_CO_ROUTINES == 1
\r
1315 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )
\r
1317 signed portBASE_TYPE xReturn;
\r
1319 /* If the queue is already full we may have to block. A critical section
\r
1320 is required to prevent an interrupt removing something from the queue
\r
1321 between the check to see if the queue is full and blocking on the queue. */
\r
1322 portDISABLE_INTERRUPTS();
\r
1324 if( prvIsQueueFull( pxQueue ) != pdFALSE )
\r
1326 /* The queue is full - do we want to block or just leave without
\r
1328 if( xTicksToWait > ( portTickType ) 0 )
\r
1330 /* As this is called from a coroutine we cannot block directly, but
\r
1331 return indicating that we need to block. */
\r
1332 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
\r
1333 portENABLE_INTERRUPTS();
\r
1334 return errQUEUE_BLOCKED;
\r
1338 portENABLE_INTERRUPTS();
\r
1339 return errQUEUE_FULL;
\r
1343 portENABLE_INTERRUPTS();
\r
1347 portDISABLE_INTERRUPTS();
\r
1349 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
1351 /* There is room in the queue, copy the data into the queue. */
\r
1352 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
\r
1355 /* Were any co-routines waiting for data to become available? */
\r
1356 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1358 /* In this instance the co-routine could be placed directly
\r
1359 into the ready list as we are within a critical section.
\r
1360 Instead the same pending ready list mechanism is used as if
\r
1361 the event were caused from within an interrupt. */
\r
1362 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1364 /* The co-routine waiting has a higher priority so record
\r
1365 that a yield might be appropriate. */
\r
1366 xReturn = errQUEUE_YIELD;
\r
1372 xReturn = errQUEUE_FULL;
\r
1375 portENABLE_INTERRUPTS();
\r
1380 /*-----------------------------------------------------------*/
\r
1382 #if configUSE_CO_ROUTINES == 1
\r
1383 signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )
\r
1385 signed portBASE_TYPE xReturn;
\r
1387 /* If the queue is already empty we may have to block. A critical section
\r
1388 is required to prevent an interrupt adding something to the queue
\r
1389 between the check to see if the queue is empty and blocking on the queue. */
\r
1390 portDISABLE_INTERRUPTS();
\r
1392 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
\r
1394 /* There are no messages in the queue, do we want to block or just
\r
1395 leave with nothing? */
\r
1396 if( xTicksToWait > ( portTickType ) 0 )
\r
1398 /* As this is a co-routine we cannot block directly, but return
\r
1399 indicating that we need to block. */
\r
1400 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
\r
1401 portENABLE_INTERRUPTS();
\r
1402 return errQUEUE_BLOCKED;
\r
1406 portENABLE_INTERRUPTS();
\r
1407 return errQUEUE_FULL;
\r
1411 portENABLE_INTERRUPTS();
\r
1415 portDISABLE_INTERRUPTS();
\r
1417 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1419 /* Data is available from the queue. */
\r
1420 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1421 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1423 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1425 --( pxQueue->uxMessagesWaiting );
\r
1426 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1430 /* Were any co-routines waiting for space to become available? */
\r
1431 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1433 /* In this instance the co-routine could be placed directly
\r
1434 into the ready list as we are within a critical section.
\r
1435 Instead the same pending ready list mechanism is used as if
\r
1436 the event were caused from within an interrupt. */
\r
1437 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1439 xReturn = errQUEUE_YIELD;
\r
1448 portENABLE_INTERRUPTS();
\r
1453 /*-----------------------------------------------------------*/
\r
1457 #if configUSE_CO_ROUTINES == 1
\r
1458 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
\r
1460 /* Cannot block within an ISR so if there is no space on the queue then
\r
1461 exit without doing anything. */
\r
1462 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
1464 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
\r
1466 /* We only want to wake one co-routine per ISR, so check that a
\r
1467 co-routine has not already been woken. */
\r
1468 if( xCoRoutinePreviouslyWoken == pdFALSE )
\r
1470 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1472 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1480 return xCoRoutinePreviouslyWoken;
\r
1483 /*-----------------------------------------------------------*/
\r
1485 #if configUSE_CO_ROUTINES == 1
\r
1486 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )
\r
1488 signed portBASE_TYPE xReturn;
\r
1490 /* We cannot block from an ISR, so check there is data available. If
\r
1491 not then just leave without doing anything. */
\r
1492 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1494 /* Copy the data from the queue. */
\r
1495 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1496 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1498 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1500 --( pxQueue->uxMessagesWaiting );
\r
1501 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1503 if( ( *pxCoRoutineWoken ) == pdFALSE )
\r
1505 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1507 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1509 *pxCoRoutineWoken = pdTRUE;
\r
1524 /*-----------------------------------------------------------*/
\r
1526 #if configQUEUE_REGISTRY_SIZE > 0
\r
1528 void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )
\r
1530 unsigned portBASE_TYPE ux;
\r
1532 /* See if there is an empty space in the registry. A NULL name denotes
\r
1534 for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
\r
1536 if( xQueueRegistry[ ux ].pcQueueName == NULL )
\r
1538 /* Store the information on this queue. */
\r
1539 xQueueRegistry[ ux ].pcQueueName = pcQueueName;
\r
1540 xQueueRegistry[ ux ].xHandle = xQueue;
\r
1547 /*-----------------------------------------------------------*/
\r
1549 #if configQUEUE_REGISTRY_SIZE > 0
\r
1551 static void vQueueUnregisterQueue( xQueueHandle xQueue )
\r
1553 unsigned portBASE_TYPE ux;
\r
1555 /* See if the handle of the queue being unregistered in actually in the
\r
1557 for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
\r
1559 if( xQueueRegistry[ ux ].xHandle == xQueue )
\r
1561 /* Set the name to NULL to show that this slot if free again. */
\r
1562 xQueueRegistry[ ux ].pcQueueName = NULL;
\r
1570 /*-----------------------------------------------------------*/
\r
1572 #if configUSE_TIMERS == 1
\r
1574 void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait )
\r
1576 /* This function should not be called by application code hence the
\r
1577 'Restricted' in its name. It is not part of the public API. It is
\r
1578 designed for use by kernel code, and has special calling requirements.
\r
1579 It can result in vListInsert() being called on a list that can only
\r
1580 possibly ever have one item in it, so the list will be fast, but even
\r
1581 so it should be called with the scheduler locked and not from a critical
\r
1584 /* Only do anything if there are no messages in the queue. This function
\r
1585 will not actually cause the task to block, just place it on a blocked
\r
1586 list. It will not block until the scheduler is unlocked - at which
\r
1587 time a yield will be performed. If an item is added to the queue while
\r
1588 the queue is locked, and the calling task blocks on the queue, then the
\r
1589 calling task will be immediately unblocked when the queue is unlocked. */
\r
1590 prvLockQueue( pxQueue );
\r
1591 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U )
\r
1593 /* There is nothing in the queue, block for the specified period. */
\r
1594 vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
1596 prvUnlockQueue( pxQueue );
\r