2 FreeRTOS V7.1.0 - 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
166 portBASE_TYPE xQueueGenericReset( xQueueHandle pxQueue, portBASE_TYPE xNewQueue ) PRIVILEGED_FUNCTION;
\r
169 * Co-routine queue functions differ from task queue functions. Co-routines are
\r
170 * an optional component.
\r
172 #if configUSE_CO_ROUTINES == 1
\r
173 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) PRIVILEGED_FUNCTION;
\r
174 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;
\r
175 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
\r
176 signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
\r
180 * The queue registry is just a means for kernel aware debuggers to locate
\r
181 * queue structures. It has no other purpose so is an optional component.
\r
183 #if configQUEUE_REGISTRY_SIZE > 0
\r
185 /* The type stored within the queue registry array. This allows a name
\r
186 to be assigned to each queue making kernel aware debugging a little
\r
187 more user friendly. */
\r
188 typedef struct QUEUE_REGISTRY_ITEM
\r
190 signed char *pcQueueName;
\r
191 xQueueHandle xHandle;
\r
192 } xQueueRegistryItem;
\r
194 /* The queue registry is simply an array of xQueueRegistryItem structures.
\r
195 The pcQueueName member of a structure being NULL is indicative of the
\r
196 array position being vacant. */
\r
197 xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
\r
199 /* Removes a queue from the registry by simply setting the pcQueueName
\r
201 static void vQueueUnregisterQueue( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
\r
202 void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName ) PRIVILEGED_FUNCTION;
\r
206 * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not
\r
207 * prevent an ISR from adding or removing items to the queue, but does prevent
\r
208 * an ISR from removing tasks from the queue event lists. If an ISR finds a
\r
209 * queue is locked it will instead increment the appropriate queue lock count
\r
210 * to indicate that a task may require unblocking. When the queue in unlocked
\r
211 * these lock counts are inspected, and the appropriate action taken.
\r
213 static void prvUnlockQueue( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
216 * Uses a critical section to determine if there is any data in a queue.
\r
218 * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
\r
220 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
223 * Uses a critical section to determine if there is any space in a queue.
\r
225 * @return pdTRUE if there is no space, otherwise pdFALSE;
\r
227 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
230 * Copies an item into the queue, either at the front of the queue or the
\r
231 * back of the queue.
\r
233 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION;
\r
236 * Copies an item out of a queue.
\r
238 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer ) PRIVILEGED_FUNCTION;
\r
239 /*-----------------------------------------------------------*/
\r
242 * Macro to mark a queue as locked. Locking a queue prevents an ISR from
\r
243 * accessing the queue event lists.
\r
245 #define prvLockQueue( pxQueue ) \
\r
246 taskENTER_CRITICAL(); \
\r
248 if( ( pxQueue )->xRxLock == queueUNLOCKED ) \
\r
250 ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED; \
\r
252 if( ( pxQueue )->xTxLock == queueUNLOCKED ) \
\r
254 ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED; \
\r
257 taskEXIT_CRITICAL()
\r
258 /*-----------------------------------------------------------*/
\r
261 /*-----------------------------------------------------------
\r
262 * PUBLIC QUEUE MANAGEMENT API documented in queue.h
\r
263 *----------------------------------------------------------*/
\r
265 portBASE_TYPE xQueueGenericReset( xQueueHandle pxQueue, portBASE_TYPE xNewQueue )
\r
267 portBASE_TYPE xReturn = pdPASS;
\r
269 configASSERT( pxQueue );
\r
271 /* If the queue being reset has already been used (has not just been
\r
272 created), then only reset the queue if its event lists are empty. */
\r
273 if( xNewQueue != pdTRUE )
\r
275 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
280 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
286 if( xReturn == pdPASS )
\r
288 pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize );
\r
289 pxQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
\r
290 pxQueue->pcWriteTo = pxQueue->pcHead;
\r
291 pxQueue->pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( unsigned portBASE_TYPE ) 1U ) * pxQueue->uxItemSize );
\r
292 pxQueue->xRxLock = queueUNLOCKED;
\r
293 pxQueue->xTxLock = queueUNLOCKED;
\r
295 /* Ensure the event queues start with the correct state. */
\r
296 vListInitialise( &( pxQueue->xTasksWaitingToSend ) );
\r
297 vListInitialise( &( pxQueue->xTasksWaitingToReceive ) );
\r
302 /*-----------------------------------------------------------*/
\r
304 xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType )
\r
306 xQUEUE *pxNewQueue;
\r
307 size_t xQueueSizeInBytes;
\r
308 xQueueHandle xReturn = NULL;
\r
310 /* Remove compiler warnings about unused parameters should
\r
311 configUSE_TRACE_FACILITY not be set to 1. */
\r
312 ( void ) ucQueueType;
\r
314 /* Allocate the new queue structure. */
\r
315 if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )
\r
317 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
\r
318 if( pxNewQueue != NULL )
\r
320 /* Create the list of pointers to queue items. The queue is one byte
\r
321 longer than asked for to make wrap checking easier/faster. */
\r
322 xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1;
\r
324 pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes );
\r
325 if( pxNewQueue->pcHead != NULL )
\r
327 /* Initialise the queue members as described above where the
\r
328 queue type is defined. */
\r
329 pxNewQueue->uxLength = uxQueueLength;
\r
330 pxNewQueue->uxItemSize = uxItemSize;
\r
331 xQueueGenericReset( pxNewQueue, pdTRUE );
\r
332 #if ( configUSE_TRACE_FACILITY == 1 )
\r
334 pxNewQueue->ucQueueType = ucQueueType;
\r
336 #endif /* configUSE_TRACE_FACILITY */
\r
338 traceQUEUE_CREATE( pxNewQueue );
\r
339 xReturn = pxNewQueue;
\r
343 traceQUEUE_CREATE_FAILED( ucQueueType );
\r
344 vPortFree( pxNewQueue );
\r
349 configASSERT( xReturn );
\r
353 /*-----------------------------------------------------------*/
\r
355 #if ( configUSE_MUTEXES == 1 )
\r
357 xQueueHandle xQueueCreateMutex( unsigned char ucQueueType )
\r
359 xQUEUE *pxNewQueue;
\r
361 /* Prevent compiler warnings about unused parameters if
\r
362 configUSE_TRACE_FACILITY does not equal 1. */
\r
363 ( void ) ucQueueType;
\r
365 /* Allocate the new queue structure. */
\r
366 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
\r
367 if( pxNewQueue != NULL )
\r
369 /* Information required for priority inheritance. */
\r
370 pxNewQueue->pxMutexHolder = NULL;
\r
371 pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
\r
373 /* Queues used as a mutex no data is actually copied into or out
\r
375 pxNewQueue->pcWriteTo = NULL;
\r
376 pxNewQueue->pcReadFrom = NULL;
\r
378 /* Each mutex has a length of 1 (like a binary semaphore) and
\r
379 an item size of 0 as nothing is actually copied into or out
\r
381 pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
\r
382 pxNewQueue->uxLength = ( unsigned portBASE_TYPE ) 1U;
\r
383 pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 0U;
\r
384 pxNewQueue->xRxLock = queueUNLOCKED;
\r
385 pxNewQueue->xTxLock = queueUNLOCKED;
\r
387 #if ( configUSE_TRACE_FACILITY == 1 )
\r
389 pxNewQueue->ucQueueType = ucQueueType;
\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 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_RECURSIVE_MUTEXES == 1
\r
416 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex )
\r
418 portBASE_TYPE xReturn;
\r
420 configASSERT( pxMutex );
\r
422 /* If this is the task that holds the mutex then pxMutexHolder will not
\r
423 change outside of this task. If this task does not hold the mutex then
\r
424 pxMutexHolder can never coincidentally equal the tasks handle, and as
\r
425 this is the only condition we are interested in it does not matter if
\r
426 pxMutexHolder is accessed simultaneously by another task. Therefore no
\r
427 mutual exclusion is required to test the pxMutexHolder variable. */
\r
428 if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
\r
430 traceGIVE_MUTEX_RECURSIVE( pxMutex );
\r
432 /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to
\r
433 the task handle, therefore no underflow check is required. Also,
\r
434 uxRecursiveCallCount is only modified by the mutex holder, and as
\r
435 there can only be one, no mutual exclusion is required to modify the
\r
436 uxRecursiveCallCount member. */
\r
437 ( pxMutex->uxRecursiveCallCount )--;
\r
439 /* Have we unwound the call count? */
\r
440 if( pxMutex->uxRecursiveCallCount == 0 )
\r
442 /* Return the mutex. This will automatically unblock any other
\r
443 task that might be waiting to access the mutex. */
\r
444 xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
\r
451 /* We cannot give the mutex because we are not the holder. */
\r
454 traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
\r
460 #endif /* configUSE_RECURSIVE_MUTEXES */
\r
461 /*-----------------------------------------------------------*/
\r
463 #if configUSE_RECURSIVE_MUTEXES == 1
\r
465 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime )
\r
467 portBASE_TYPE xReturn;
\r
469 configASSERT( pxMutex );
\r
471 /* Comments regarding mutual exclusion as per those within
\r
472 xQueueGiveMutexRecursive(). */
\r
474 traceTAKE_MUTEX_RECURSIVE( pxMutex );
\r
476 if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
\r
478 ( pxMutex->uxRecursiveCallCount )++;
\r
483 xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );
\r
485 /* pdPASS will only be returned if we successfully obtained the mutex,
\r
486 we may have blocked to reach here. */
\r
487 if( xReturn == pdPASS )
\r
489 ( pxMutex->uxRecursiveCallCount )++;
\r
493 traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );
\r
500 #endif /* configUSE_RECURSIVE_MUTEXES */
\r
501 /*-----------------------------------------------------------*/
\r
503 #if configUSE_COUNTING_SEMAPHORES == 1
\r
505 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount )
\r
507 xQueueHandle pxHandle;
\r
509 pxHandle = xQueueGenericCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
\r
511 if( pxHandle != NULL )
\r
513 pxHandle->uxMessagesWaiting = uxInitialCount;
\r
515 traceCREATE_COUNTING_SEMAPHORE();
\r
519 traceCREATE_COUNTING_SEMAPHORE_FAILED();
\r
522 configASSERT( pxHandle );
\r
526 #endif /* configUSE_COUNTING_SEMAPHORES */
\r
527 /*-----------------------------------------------------------*/
\r
529 signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
\r
531 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
532 xTimeOutType xTimeOut;
\r
534 configASSERT( pxQueue );
\r
535 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
537 /* This function relaxes the coding standard somewhat to allow return
\r
538 statements within the function itself. This is done in the interest
\r
539 of execution time efficiency. */
\r
542 taskENTER_CRITICAL();
\r
544 /* Is there room on the queue now? To be running we must be
\r
545 the highest priority task wanting to access the queue. */
\r
546 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
548 traceQUEUE_SEND( pxQueue );
\r
549 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
551 /* If there was a task waiting for data to arrive on the
\r
552 queue then unblock it now. */
\r
553 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
555 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
557 /* The unblocked task has a priority higher than
\r
558 our own so yield immediately. Yes it is ok to do
\r
559 this from within the critical section - the kernel
\r
560 takes care of that. */
\r
561 portYIELD_WITHIN_API();
\r
565 taskEXIT_CRITICAL();
\r
567 /* Return to the original privilege level before exiting the
\r
573 if( xTicksToWait == ( portTickType ) 0 )
\r
575 /* The queue was full and no block time is specified (or
\r
576 the block time has expired) so leave now. */
\r
577 taskEXIT_CRITICAL();
\r
579 /* Return to the original privilege level before exiting
\r
581 traceQUEUE_SEND_FAILED( pxQueue );
\r
582 return errQUEUE_FULL;
\r
584 else if( xEntryTimeSet == pdFALSE )
\r
586 /* The queue was full and a block time was specified so
\r
587 configure the timeout structure. */
\r
588 vTaskSetTimeOutState( &xTimeOut );
\r
589 xEntryTimeSet = pdTRUE;
\r
593 taskEXIT_CRITICAL();
\r
595 /* Interrupts and other tasks can send to and receive from the queue
\r
596 now the critical section has been exited. */
\r
599 prvLockQueue( pxQueue );
\r
601 /* Update the timeout state to see if it has expired yet. */
\r
602 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
604 if( prvIsQueueFull( pxQueue ) != pdFALSE )
\r
606 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
\r
607 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
\r
609 /* Unlocking the queue means queue events can effect the
\r
610 event list. It is possible that interrupts occurring now
\r
611 remove this task from the event list again - but as the
\r
612 scheduler is suspended the task will go onto the pending
\r
613 ready last instead of the actual ready list. */
\r
614 prvUnlockQueue( pxQueue );
\r
616 /* Resuming the scheduler will move tasks from the pending
\r
617 ready list into the ready list - so it is feasible that this
\r
618 task is already in a ready list before it yields - in which
\r
619 case the yield will not cause a context switch unless there
\r
620 is also a higher priority task in the pending ready list. */
\r
621 if( xTaskResumeAll() == pdFALSE )
\r
623 portYIELD_WITHIN_API();
\r
629 prvUnlockQueue( pxQueue );
\r
630 ( void ) xTaskResumeAll();
\r
635 /* The timeout has expired. */
\r
636 prvUnlockQueue( pxQueue );
\r
637 ( void ) xTaskResumeAll();
\r
639 /* Return to the original privilege level before exiting the
\r
641 traceQUEUE_SEND_FAILED( pxQueue );
\r
642 return errQUEUE_FULL;
\r
646 /*-----------------------------------------------------------*/
\r
648 #if configUSE_ALTERNATIVE_API == 1
\r
650 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
\r
652 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
653 xTimeOutType xTimeOut;
\r
655 configASSERT( pxQueue );
\r
656 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
660 taskENTER_CRITICAL();
\r
662 /* Is there room on the queue now? To be running we must be
\r
663 the highest priority task wanting to access the queue. */
\r
664 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
666 traceQUEUE_SEND( pxQueue );
\r
667 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
669 /* If there was a task waiting for data to arrive on the
\r
670 queue then unblock it now. */
\r
671 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
673 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
675 /* The unblocked task has a priority higher than
\r
676 our own so yield immediately. */
\r
677 portYIELD_WITHIN_API();
\r
681 taskEXIT_CRITICAL();
\r
686 if( xTicksToWait == ( portTickType ) 0 )
\r
688 taskEXIT_CRITICAL();
\r
689 return errQUEUE_FULL;
\r
691 else if( xEntryTimeSet == pdFALSE )
\r
693 vTaskSetTimeOutState( &xTimeOut );
\r
694 xEntryTimeSet = pdTRUE;
\r
698 taskEXIT_CRITICAL();
\r
700 taskENTER_CRITICAL();
\r
702 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
704 if( prvIsQueueFull( pxQueue ) != pdFALSE )
\r
706 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
\r
707 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
\r
708 portYIELD_WITHIN_API();
\r
713 taskEXIT_CRITICAL();
\r
714 traceQUEUE_SEND_FAILED( pxQueue );
\r
715 return errQUEUE_FULL;
\r
718 taskEXIT_CRITICAL();
\r
722 #endif /* configUSE_ALTERNATIVE_API */
\r
723 /*-----------------------------------------------------------*/
\r
725 #if configUSE_ALTERNATIVE_API == 1
\r
727 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
\r
729 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
730 xTimeOutType xTimeOut;
\r
731 signed char *pcOriginalReadPosition;
\r
733 configASSERT( pxQueue );
\r
734 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
738 taskENTER_CRITICAL();
\r
740 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
742 /* Remember our read position in case we are just peeking. */
\r
743 pcOriginalReadPosition = pxQueue->pcReadFrom;
\r
745 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
747 if( xJustPeeking == pdFALSE )
\r
749 traceQUEUE_RECEIVE( pxQueue );
\r
751 /* We are actually removing data. */
\r
752 --( pxQueue->uxMessagesWaiting );
\r
754 #if ( configUSE_MUTEXES == 1 )
\r
756 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
758 /* Record the information required to implement
\r
759 priority inheritance should it become necessary. */
\r
760 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
\r
765 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
767 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
769 portYIELD_WITHIN_API();
\r
775 traceQUEUE_PEEK( pxQueue );
\r
777 /* We are not removing the data, so reset our read
\r
779 pxQueue->pcReadFrom = pcOriginalReadPosition;
\r
781 /* The data is being left in the queue, so see if there are
\r
782 any other tasks waiting for the data. */
\r
783 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
785 /* Tasks that are removed from the event list will get added to
\r
786 the pending ready list as the scheduler is still suspended. */
\r
787 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
789 /* The task waiting has a higher priority than this task. */
\r
790 portYIELD_WITHIN_API();
\r
796 taskEXIT_CRITICAL();
\r
801 if( xTicksToWait == ( portTickType ) 0 )
\r
803 taskEXIT_CRITICAL();
\r
804 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
805 return errQUEUE_EMPTY;
\r
807 else if( xEntryTimeSet == pdFALSE )
\r
809 vTaskSetTimeOutState( &xTimeOut );
\r
810 xEntryTimeSet = pdTRUE;
\r
814 taskEXIT_CRITICAL();
\r
816 taskENTER_CRITICAL();
\r
818 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
820 if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
\r
822 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
\r
824 #if ( configUSE_MUTEXES == 1 )
\r
826 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
828 portENTER_CRITICAL();
\r
829 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
\r
830 portEXIT_CRITICAL();
\r
835 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
836 portYIELD_WITHIN_API();
\r
841 taskEXIT_CRITICAL();
\r
842 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
843 return errQUEUE_EMPTY;
\r
846 taskEXIT_CRITICAL();
\r
851 #endif /* configUSE_ALTERNATIVE_API */
\r
852 /*-----------------------------------------------------------*/
\r
854 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )
\r
856 signed portBASE_TYPE xReturn;
\r
857 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
859 configASSERT( pxQueue );
\r
860 configASSERT( pxHigherPriorityTaskWoken );
\r
861 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
863 /* Similar to xQueueGenericSend, except we don't block if there is no room
\r
864 in the queue. Also we don't directly wake a task that was blocked on a
\r
865 queue read, instead we return a flag to say whether a context switch is
\r
866 required or not (i.e. has a task with a higher priority than us been woken
\r
868 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
870 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
872 traceQUEUE_SEND_FROM_ISR( pxQueue );
\r
874 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
876 /* If the queue is locked we do not alter the event list. This will
\r
877 be done when the queue is unlocked later. */
\r
878 if( pxQueue->xTxLock == queueUNLOCKED )
\r
880 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
882 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
884 /* The task waiting has a higher priority so record that a
\r
885 context switch is required. */
\r
886 *pxHigherPriorityTaskWoken = pdTRUE;
\r
892 /* Increment the lock count so the task that unlocks the queue
\r
893 knows that data was posted while it was locked. */
\r
894 ++( pxQueue->xTxLock );
\r
901 traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
\r
902 xReturn = errQUEUE_FULL;
\r
905 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
909 /*-----------------------------------------------------------*/
\r
911 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
\r
913 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
914 xTimeOutType xTimeOut;
\r
915 signed char *pcOriginalReadPosition;
\r
917 configASSERT( pxQueue );
\r
918 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
920 /* This function relaxes the coding standard somewhat to allow return
\r
921 statements within the function itself. This is done in the interest
\r
922 of execution time efficiency. */
\r
926 taskENTER_CRITICAL();
\r
928 /* Is there data in the queue now? To be running we must be
\r
929 the highest priority task wanting to access the queue. */
\r
930 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
932 /* Remember our read position in case we are just peeking. */
\r
933 pcOriginalReadPosition = pxQueue->pcReadFrom;
\r
935 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
937 if( xJustPeeking == pdFALSE )
\r
939 traceQUEUE_RECEIVE( pxQueue );
\r
941 /* We are actually removing data. */
\r
942 --( pxQueue->uxMessagesWaiting );
\r
944 #if ( configUSE_MUTEXES == 1 )
\r
946 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
948 /* Record the information required to implement
\r
949 priority inheritance should it become necessary. */
\r
950 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
\r
955 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
957 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
959 portYIELD_WITHIN_API();
\r
965 traceQUEUE_PEEK( pxQueue );
\r
967 /* We are not removing the data, so reset our read
\r
969 pxQueue->pcReadFrom = pcOriginalReadPosition;
\r
971 /* The data is being left in the queue, so see if there are
\r
972 any other tasks waiting for the data. */
\r
973 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
975 /* Tasks that are removed from the event list will get added to
\r
976 the pending ready list as the scheduler is still suspended. */
\r
977 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
979 /* The task waiting has a higher priority than this task. */
\r
980 portYIELD_WITHIN_API();
\r
986 taskEXIT_CRITICAL();
\r
991 if( xTicksToWait == ( portTickType ) 0 )
\r
993 /* The queue was empty and no block time is specified (or
\r
994 the block time has expired) so leave now. */
\r
995 taskEXIT_CRITICAL();
\r
996 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
997 return errQUEUE_EMPTY;
\r
999 else if( xEntryTimeSet == pdFALSE )
\r
1001 /* The queue was empty and a block time was specified so
\r
1002 configure the timeout structure. */
\r
1003 vTaskSetTimeOutState( &xTimeOut );
\r
1004 xEntryTimeSet = pdTRUE;
\r
1008 taskEXIT_CRITICAL();
\r
1010 /* Interrupts and other tasks can send to and receive from the queue
\r
1011 now the critical section has been exited. */
\r
1013 vTaskSuspendAll();
\r
1014 prvLockQueue( pxQueue );
\r
1016 /* Update the timeout state to see if it has expired yet. */
\r
1017 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
1019 if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
\r
1021 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
\r
1023 #if ( configUSE_MUTEXES == 1 )
\r
1025 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
1027 portENTER_CRITICAL();
\r
1029 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
\r
1031 portEXIT_CRITICAL();
\r
1036 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
1037 prvUnlockQueue( pxQueue );
\r
1038 if( xTaskResumeAll() == pdFALSE )
\r
1040 portYIELD_WITHIN_API();
\r
1046 prvUnlockQueue( pxQueue );
\r
1047 ( void ) xTaskResumeAll();
\r
1052 prvUnlockQueue( pxQueue );
\r
1053 ( void ) xTaskResumeAll();
\r
1054 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
1055 return errQUEUE_EMPTY;
\r
1059 /*-----------------------------------------------------------*/
\r
1061 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )
\r
1063 signed portBASE_TYPE xReturn;
\r
1064 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
1066 configASSERT( pxQueue );
\r
1067 configASSERT( pxTaskWoken );
\r
1068 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
1070 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1072 /* We cannot block from an ISR, so check there is data available. */
\r
1073 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1075 traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
\r
1077 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
1078 --( pxQueue->uxMessagesWaiting );
\r
1080 /* If the queue is locked we will not modify the event list. Instead
\r
1081 we update the lock count so the task that unlocks the queue will know
\r
1082 that an ISR has removed data while the queue was locked. */
\r
1083 if( pxQueue->xRxLock == queueUNLOCKED )
\r
1085 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1087 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1089 /* The task waiting has a higher priority than us so
\r
1090 force a context switch. */
\r
1091 *pxTaskWoken = pdTRUE;
\r
1097 /* Increment the lock count so the task that unlocks the queue
\r
1098 knows that data was removed while it was locked. */
\r
1099 ++( pxQueue->xRxLock );
\r
1107 traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
\r
1110 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1114 /*-----------------------------------------------------------*/
\r
1116 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue )
\r
1118 unsigned portBASE_TYPE uxReturn;
\r
1120 configASSERT( pxQueue );
\r
1122 taskENTER_CRITICAL();
\r
1123 uxReturn = pxQueue->uxMessagesWaiting;
\r
1124 taskEXIT_CRITICAL();
\r
1128 /*-----------------------------------------------------------*/
\r
1130 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue )
\r
1132 unsigned portBASE_TYPE uxReturn;
\r
1134 configASSERT( pxQueue );
\r
1136 uxReturn = pxQueue->uxMessagesWaiting;
\r
1140 /*-----------------------------------------------------------*/
\r
1142 void vQueueDelete( xQueueHandle pxQueue )
\r
1144 configASSERT( pxQueue );
\r
1146 traceQUEUE_DELETE( pxQueue );
\r
1147 vQueueUnregisterQueue( pxQueue );
\r
1148 vPortFree( pxQueue->pcHead );
\r
1149 vPortFree( pxQueue );
\r
1151 /*-----------------------------------------------------------*/
\r
1153 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1155 unsigned char ucQueueGetQueueNumber( xQueueHandle pxQueue )
\r
1157 return pxQueue->ucQueueNumber;
\r
1161 /*-----------------------------------------------------------*/
\r
1163 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1165 void vQueueSetQueueNumber( xQueueHandle pxQueue, unsigned char ucQueueNumber )
\r
1167 pxQueue->ucQueueNumber = ucQueueNumber;
\r
1171 /*-----------------------------------------------------------*/
\r
1173 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1175 unsigned char ucQueueGetQueueType( xQueueHandle pxQueue )
\r
1177 return pxQueue->ucQueueType;
\r
1181 /*-----------------------------------------------------------*/
\r
1183 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )
\r
1185 if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )
\r
1187 #if ( configUSE_MUTEXES == 1 )
\r
1189 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
1191 /* The mutex is no longer being held. */
\r
1192 vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
\r
1193 pxQueue->pxMutexHolder = NULL;
\r
1198 else if( xPosition == queueSEND_TO_BACK )
\r
1200 memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
\r
1201 pxQueue->pcWriteTo += pxQueue->uxItemSize;
\r
1202 if( pxQueue->pcWriteTo >= pxQueue->pcTail )
\r
1204 pxQueue->pcWriteTo = pxQueue->pcHead;
\r
1209 memcpy( ( void * ) pxQueue->pcReadFrom, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
\r
1210 pxQueue->pcReadFrom -= pxQueue->uxItemSize;
\r
1211 if( pxQueue->pcReadFrom < pxQueue->pcHead )
\r
1213 pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
\r
1217 ++( pxQueue->uxMessagesWaiting );
\r
1219 /*-----------------------------------------------------------*/
\r
1221 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
\r
1223 if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
\r
1225 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1226 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1228 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1230 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1233 /*-----------------------------------------------------------*/
\r
1235 static void prvUnlockQueue( xQueueHandle pxQueue )
\r
1237 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
\r
1239 /* The lock counts contains the number of extra data items placed or
\r
1240 removed from the queue while the queue was locked. When a queue is
\r
1241 locked items can be added or removed, but the event lists cannot be
\r
1243 taskENTER_CRITICAL();
\r
1245 /* See if data was added to the queue while it was locked. */
\r
1246 while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )
\r
1248 /* Data was posted while the queue was locked. Are any tasks
\r
1249 blocked waiting for data to become available? */
\r
1250 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1252 /* Tasks that are removed from the event list will get added to
\r
1253 the pending ready list as the scheduler is still suspended. */
\r
1254 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1256 /* The task waiting has a higher priority so record that a
\r
1257 context switch is required. */
\r
1258 vTaskMissedYield();
\r
1261 --( pxQueue->xTxLock );
\r
1269 pxQueue->xTxLock = queueUNLOCKED;
\r
1271 taskEXIT_CRITICAL();
\r
1273 /* Do the same for the Rx lock. */
\r
1274 taskENTER_CRITICAL();
\r
1276 while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )
\r
1278 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1280 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1282 vTaskMissedYield();
\r
1285 --( pxQueue->xRxLock );
\r
1293 pxQueue->xRxLock = queueUNLOCKED;
\r
1295 taskEXIT_CRITICAL();
\r
1297 /*-----------------------------------------------------------*/
\r
1299 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue )
\r
1301 signed portBASE_TYPE xReturn;
\r
1303 taskENTER_CRITICAL();
\r
1304 xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
\r
1305 taskEXIT_CRITICAL();
\r
1309 /*-----------------------------------------------------------*/
\r
1311 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue )
\r
1313 signed portBASE_TYPE xReturn;
\r
1315 configASSERT( pxQueue );
\r
1316 xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
\r
1320 /*-----------------------------------------------------------*/
\r
1322 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue )
\r
1324 signed portBASE_TYPE xReturn;
\r
1326 taskENTER_CRITICAL();
\r
1327 xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
\r
1328 taskEXIT_CRITICAL();
\r
1332 /*-----------------------------------------------------------*/
\r
1334 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue )
\r
1336 signed portBASE_TYPE xReturn;
\r
1338 configASSERT( pxQueue );
\r
1339 xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
\r
1343 /*-----------------------------------------------------------*/
\r
1345 #if configUSE_CO_ROUTINES == 1
\r
1346 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )
\r
1348 signed portBASE_TYPE xReturn;
\r
1350 /* If the queue is already full we may have to block. A critical section
\r
1351 is required to prevent an interrupt removing something from the queue
\r
1352 between the check to see if the queue is full and blocking on the queue. */
\r
1353 portDISABLE_INTERRUPTS();
\r
1355 if( prvIsQueueFull( pxQueue ) != pdFALSE )
\r
1357 /* The queue is full - do we want to block or just leave without
\r
1359 if( xTicksToWait > ( portTickType ) 0 )
\r
1361 /* As this is called from a coroutine we cannot block directly, but
\r
1362 return indicating that we need to block. */
\r
1363 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
\r
1364 portENABLE_INTERRUPTS();
\r
1365 return errQUEUE_BLOCKED;
\r
1369 portENABLE_INTERRUPTS();
\r
1370 return errQUEUE_FULL;
\r
1374 portENABLE_INTERRUPTS();
\r
1378 portDISABLE_INTERRUPTS();
\r
1380 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
1382 /* There is room in the queue, copy the data into the queue. */
\r
1383 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
\r
1386 /* Were any co-routines waiting for data to become available? */
\r
1387 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1389 /* In this instance the co-routine could be placed directly
\r
1390 into the ready list as we are within a critical section.
\r
1391 Instead the same pending ready list mechanism is used as if
\r
1392 the event were caused from within an interrupt. */
\r
1393 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1395 /* The co-routine waiting has a higher priority so record
\r
1396 that a yield might be appropriate. */
\r
1397 xReturn = errQUEUE_YIELD;
\r
1403 xReturn = errQUEUE_FULL;
\r
1406 portENABLE_INTERRUPTS();
\r
1411 /*-----------------------------------------------------------*/
\r
1413 #if configUSE_CO_ROUTINES == 1
\r
1414 signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )
\r
1416 signed portBASE_TYPE xReturn;
\r
1418 /* If the queue is already empty we may have to block. A critical section
\r
1419 is required to prevent an interrupt adding something to the queue
\r
1420 between the check to see if the queue is empty and blocking on the queue. */
\r
1421 portDISABLE_INTERRUPTS();
\r
1423 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
\r
1425 /* There are no messages in the queue, do we want to block or just
\r
1426 leave with nothing? */
\r
1427 if( xTicksToWait > ( portTickType ) 0 )
\r
1429 /* As this is a co-routine we cannot block directly, but return
\r
1430 indicating that we need to block. */
\r
1431 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
\r
1432 portENABLE_INTERRUPTS();
\r
1433 return errQUEUE_BLOCKED;
\r
1437 portENABLE_INTERRUPTS();
\r
1438 return errQUEUE_FULL;
\r
1442 portENABLE_INTERRUPTS();
\r
1446 portDISABLE_INTERRUPTS();
\r
1448 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1450 /* Data is available from the queue. */
\r
1451 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1452 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1454 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1456 --( pxQueue->uxMessagesWaiting );
\r
1457 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1461 /* Were any co-routines waiting for space to become available? */
\r
1462 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1464 /* In this instance the co-routine could be placed directly
\r
1465 into the ready list as we are within a critical section.
\r
1466 Instead the same pending ready list mechanism is used as if
\r
1467 the event were caused from within an interrupt. */
\r
1468 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1470 xReturn = errQUEUE_YIELD;
\r
1479 portENABLE_INTERRUPTS();
\r
1484 /*-----------------------------------------------------------*/
\r
1488 #if configUSE_CO_ROUTINES == 1
\r
1489 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
\r
1491 /* Cannot block within an ISR so if there is no space on the queue then
\r
1492 exit without doing anything. */
\r
1493 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
1495 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
\r
1497 /* We only want to wake one co-routine per ISR, so check that a
\r
1498 co-routine has not already been woken. */
\r
1499 if( xCoRoutinePreviouslyWoken == pdFALSE )
\r
1501 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1503 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1511 return xCoRoutinePreviouslyWoken;
\r
1514 /*-----------------------------------------------------------*/
\r
1516 #if configUSE_CO_ROUTINES == 1
\r
1517 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )
\r
1519 signed portBASE_TYPE xReturn;
\r
1521 /* We cannot block from an ISR, so check there is data available. If
\r
1522 not then just leave without doing anything. */
\r
1523 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1525 /* Copy the data from the queue. */
\r
1526 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1527 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1529 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1531 --( pxQueue->uxMessagesWaiting );
\r
1532 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1534 if( ( *pxCoRoutineWoken ) == pdFALSE )
\r
1536 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1538 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1540 *pxCoRoutineWoken = pdTRUE;
\r
1555 /*-----------------------------------------------------------*/
\r
1557 #if configQUEUE_REGISTRY_SIZE > 0
\r
1559 void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )
\r
1561 unsigned portBASE_TYPE ux;
\r
1563 /* See if there is an empty space in the registry. A NULL name denotes
\r
1565 for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
\r
1567 if( xQueueRegistry[ ux ].pcQueueName == NULL )
\r
1569 /* Store the information on this queue. */
\r
1570 xQueueRegistry[ ux ].pcQueueName = pcQueueName;
\r
1571 xQueueRegistry[ ux ].xHandle = xQueue;
\r
1578 /*-----------------------------------------------------------*/
\r
1580 #if configQUEUE_REGISTRY_SIZE > 0
\r
1582 static void vQueueUnregisterQueue( xQueueHandle xQueue )
\r
1584 unsigned portBASE_TYPE ux;
\r
1586 /* See if the handle of the queue being unregistered in actually in the
\r
1588 for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
\r
1590 if( xQueueRegistry[ ux ].xHandle == xQueue )
\r
1592 /* Set the name to NULL to show that this slot if free again. */
\r
1593 xQueueRegistry[ ux ].pcQueueName = NULL;
\r
1601 /*-----------------------------------------------------------*/
\r
1603 #if configUSE_TIMERS == 1
\r
1605 void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait )
\r
1607 /* This function should not be called by application code hence the
\r
1608 'Restricted' in its name. It is not part of the public API. It is
\r
1609 designed for use by kernel code, and has special calling requirements.
\r
1610 It can result in vListInsert() being called on a list that can only
\r
1611 possibly ever have one item in it, so the list will be fast, but even
\r
1612 so it should be called with the scheduler locked and not from a critical
\r
1615 /* Only do anything if there are no messages in the queue. This function
\r
1616 will not actually cause the task to block, just place it on a blocked
\r
1617 list. It will not block until the scheduler is unlocked - at which
\r
1618 time a yield will be performed. If an item is added to the queue while
\r
1619 the queue is locked, and the calling task blocks on the queue, then the
\r
1620 calling task will be immediately unblocked when the queue is unlocked. */
\r
1621 prvLockQueue( pxQueue );
\r
1622 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U )
\r
1624 /* There is nothing in the queue, block for the specified period. */
\r
1625 vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
1627 prvUnlockQueue( pxQueue );
\r