2 FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.
\r
5 FreeRTOS supports many tools and architectures. V7.0.0 is sponsored by:
\r
6 Atollic AB - Atollic provides professional embedded systems development
\r
7 tools for C/C++ development, code analysis and test automation.
\r
8 See http://www.atollic.com
\r
11 ***************************************************************************
\r
13 * FreeRTOS tutorial books are available in pdf and paperback. *
\r
14 * Complete, revised, and edited pdf reference manuals are also *
\r
17 * Purchasing FreeRTOS documentation will not only help you, by *
\r
18 * ensuring you get running as quickly as possible and with an *
\r
19 * in-depth knowledge of how to use FreeRTOS, it will also help *
\r
20 * the FreeRTOS project to continue with its mission of providing *
\r
21 * professional grade, cross platform, de facto standard solutions *
\r
22 * for microcontrollers - completely free of charge! *
\r
24 * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
\r
26 * Thank you for using FreeRTOS, and thank you for your support! *
\r
28 ***************************************************************************
\r
31 This file is part of the FreeRTOS distribution.
\r
33 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
34 the terms of the GNU General Public License (version 2) as published by the
\r
35 Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
\r
36 >>>NOTE<<< The modification to the GPL is included to allow you to
\r
37 distribute a combined work that includes FreeRTOS without being obliged to
\r
38 provide the source code for proprietary components outside of the FreeRTOS
\r
39 kernel. FreeRTOS is distributed in the hope that it will be useful, but
\r
40 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
\r
41 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
\r
42 more details. You should have received a copy of the GNU General Public
\r
43 License and the FreeRTOS license exception along with FreeRTOS; if not it
\r
44 can be viewed here: http://www.freertos.org/a00114.html and also obtained
\r
45 by writing to Richard Barry, contact details for whom are available on the
\r
50 http://www.FreeRTOS.org - Documentation, latest information, license and
\r
53 http://www.SafeRTOS.com - A version that is certified for use in safety
\r
56 http://www.OpenRTOS.com - Commercial support, development, porting,
\r
57 licensing and training services.
\r
63 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
\r
64 all the API functions to use the MPU wrappers. That should only be done when
\r
65 task.h is included from an application file. */
\r
66 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
68 #include "FreeRTOS.h"
\r
71 #if ( configUSE_CO_ROUTINES == 1 )
\r
72 #include "croutine.h"
\r
75 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
77 /*-----------------------------------------------------------
\r
78 * PUBLIC LIST API documented in list.h
\r
79 *----------------------------------------------------------*/
\r
81 /* Constants used with the cRxLock and cTxLock structure members. */
\r
82 #define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 )
\r
83 #define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 )
\r
85 #define queueERRONEOUS_UNBLOCK ( -1 )
\r
87 /* For internal use only. */
\r
88 #define queueSEND_TO_BACK ( 0 )
\r
89 #define queueSEND_TO_FRONT ( 1 )
\r
91 /* Effectively make a union out of the xQUEUE structure. */
\r
92 #define pxMutexHolder pcTail
\r
93 #define uxQueueType pcHead
\r
94 #define uxRecursiveCallCount pcReadFrom
\r
95 #define queueQUEUE_IS_MUTEX NULL
\r
97 /* Semaphores do not actually store or copy data, so have an items size of
\r
99 #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portBASE_TYPE ) 0 )
\r
100 #define queueDONT_BLOCK ( ( portTickType ) 0U )
\r
101 #define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0U )
\r
104 * Definition of the queue used by the scheduler.
\r
105 * Items are queued by copy, not reference.
\r
107 typedef struct QueueDefinition
\r
109 signed char *pcHead; /*< Points to the beginning of the queue storage area. */
\r
110 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
112 signed char *pcWriteTo; /*< Points to the free next place in the storage area. */
\r
113 signed char *pcReadFrom; /*< Points to the last place that a queued item was read from. */
\r
115 xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */
\r
116 xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */
\r
118 volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */
\r
119 unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
\r
120 unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */
\r
122 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
123 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 /*-----------------------------------------------------------*/
\r
129 * Inside this file xQueueHandle is a pointer to a xQUEUE structure.
\r
130 * To keep the definition private the API header file defines it as a
\r
133 typedef xQUEUE * xQueueHandle;
\r
136 * Prototypes for public functions are included here so we don't have to
\r
137 * include the API header file (as it defines xQueueHandle differently). These
\r
138 * functions are documented in the API header file.
\r
140 xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ) PRIVILEGED_FUNCTION;
\r
141 signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
\r
142 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
143 void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
\r
144 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
\r
145 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;
\r
146 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;
\r
147 xQueueHandle xQueueCreateMutex( void ) PRIVILEGED_FUNCTION;
\r
148 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) PRIVILEGED_FUNCTION;
\r
149 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) PRIVILEGED_FUNCTION;
\r
150 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ) PRIVILEGED_FUNCTION;
\r
151 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
\r
152 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;
\r
153 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
154 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
155 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
156 void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
\r
159 * Co-routine queue functions differ from task queue functions. Co-routines are
\r
160 * an optional component.
\r
162 #if configUSE_CO_ROUTINES == 1
\r
163 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) PRIVILEGED_FUNCTION;
\r
164 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;
\r
165 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
\r
166 signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
\r
170 * The queue registry is just a means for kernel aware debuggers to locate
\r
171 * queue structures. It has no other purpose so is an optional component.
\r
173 #if configQUEUE_REGISTRY_SIZE > 0
\r
175 /* The type stored within the queue registry array. This allows a name
\r
176 to be assigned to each queue making kernel aware debugging a little
\r
177 more user friendly. */
\r
178 typedef struct QUEUE_REGISTRY_ITEM
\r
180 signed char *pcQueueName;
\r
181 xQueueHandle xHandle;
\r
182 } xQueueRegistryItem;
\r
184 /* The queue registry is simply an array of xQueueRegistryItem structures.
\r
185 The pcQueueName member of a structure being NULL is indicative of the
\r
186 array position being vacant. */
\r
187 xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
\r
189 /* Removes a queue from the registry by simply setting the pcQueueName
\r
191 static void vQueueUnregisterQueue( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
\r
192 void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName ) PRIVILEGED_FUNCTION;
\r
196 * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not
\r
197 * prevent an ISR from adding or removing items to the queue, but does prevent
\r
198 * an ISR from removing tasks from the queue event lists. If an ISR finds a
\r
199 * queue is locked it will instead increment the appropriate queue lock count
\r
200 * to indicate that a task may require unblocking. When the queue in unlocked
\r
201 * these lock counts are inspected, and the appropriate action taken.
\r
203 static void prvUnlockQueue( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
206 * Uses a critical section to determine if there is any data in a queue.
\r
208 * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
\r
210 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
213 * Uses a critical section to determine if there is any space in a queue.
\r
215 * @return pdTRUE if there is no space, otherwise pdFALSE;
\r
217 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
220 * Copies an item into the queue, either at the front of the queue or the
\r
221 * back of the queue.
\r
223 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION;
\r
226 * Copies an item out of a queue.
\r
228 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer ) PRIVILEGED_FUNCTION;
\r
229 /*-----------------------------------------------------------*/
\r
232 * Macro to mark a queue as locked. Locking a queue prevents an ISR from
\r
233 * accessing the queue event lists.
\r
235 #define prvLockQueue( pxQueue ) \
\r
236 taskENTER_CRITICAL(); \
\r
238 if( ( pxQueue )->xRxLock == queueUNLOCKED ) \
\r
240 ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED; \
\r
242 if( ( pxQueue )->xTxLock == queueUNLOCKED ) \
\r
244 ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED; \
\r
247 taskEXIT_CRITICAL()
\r
248 /*-----------------------------------------------------------*/
\r
251 /*-----------------------------------------------------------
\r
252 * PUBLIC QUEUE MANAGEMENT API documented in queue.h
\r
253 *----------------------------------------------------------*/
\r
255 xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize )
\r
257 xQUEUE *pxNewQueue;
\r
258 size_t xQueueSizeInBytes;
\r
259 xQueueHandle xReturn = NULL;
\r
261 /* Allocate the new queue structure. */
\r
262 if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )
\r
264 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
\r
265 if( pxNewQueue != NULL )
\r
267 /* Create the list of pointers to queue items. The queue is one byte
\r
268 longer than asked for to make wrap checking easier/faster. */
\r
269 xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1;
\r
271 pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes );
\r
272 if( pxNewQueue->pcHead != NULL )
\r
274 /* Initialise the queue members as described above where the
\r
275 queue type is defined. */
\r
276 pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize );
\r
277 pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
\r
278 pxNewQueue->pcWriteTo = pxNewQueue->pcHead;
\r
279 pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - ( unsigned portBASE_TYPE ) 1U ) * uxItemSize );
\r
280 pxNewQueue->uxLength = uxQueueLength;
\r
281 pxNewQueue->uxItemSize = uxItemSize;
\r
282 pxNewQueue->xRxLock = queueUNLOCKED;
\r
283 pxNewQueue->xTxLock = queueUNLOCKED;
\r
285 /* Likewise ensure the event queues start with the correct state. */
\r
286 vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
\r
287 vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
\r
289 traceQUEUE_CREATE( pxNewQueue );
\r
290 xReturn = pxNewQueue;
\r
294 traceQUEUE_CREATE_FAILED();
\r
295 vPortFree( pxNewQueue );
\r
300 configASSERT( xReturn );
\r
304 /*-----------------------------------------------------------*/
\r
306 #if ( configUSE_MUTEXES == 1 )
\r
308 xQueueHandle xQueueCreateMutex( void )
\r
310 xQUEUE *pxNewQueue;
\r
312 /* Allocate the new queue structure. */
\r
313 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
\r
314 if( pxNewQueue != NULL )
\r
316 /* Information required for priority inheritance. */
\r
317 pxNewQueue->pxMutexHolder = NULL;
\r
318 pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
\r
320 /* Queues used as a mutex no data is actually copied into or out
\r
322 pxNewQueue->pcWriteTo = NULL;
\r
323 pxNewQueue->pcReadFrom = NULL;
\r
325 /* Each mutex has a length of 1 (like a binary semaphore) and
\r
326 an item size of 0 as nothing is actually copied into or out
\r
328 pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
\r
329 pxNewQueue->uxLength = ( unsigned portBASE_TYPE ) 1U;
\r
330 pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 0U;
\r
331 pxNewQueue->xRxLock = queueUNLOCKED;
\r
332 pxNewQueue->xTxLock = queueUNLOCKED;
\r
334 /* Ensure the event queues start with the correct state. */
\r
335 vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
\r
336 vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
\r
338 /* Start with the semaphore in the expected state. */
\r
339 xQueueGenericSend( pxNewQueue, NULL, ( portTickType ) 0U, queueSEND_TO_BACK );
\r
341 traceCREATE_MUTEX( pxNewQueue );
\r
345 traceCREATE_MUTEX_FAILED();
\r
348 configASSERT( pxNewQueue );
\r
352 #endif /* configUSE_MUTEXES */
\r
353 /*-----------------------------------------------------------*/
\r
355 #if configUSE_RECURSIVE_MUTEXES == 1
\r
357 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex )
\r
359 portBASE_TYPE xReturn;
\r
361 configASSERT( pxMutex );
\r
363 /* If this is the task that holds the mutex then pxMutexHolder will not
\r
364 change outside of this task. If this task does not hold the mutex then
\r
365 pxMutexHolder can never coincidentally equal the tasks handle, and as
\r
366 this is the only condition we are interested in it does not matter if
\r
367 pxMutexHolder is accessed simultaneously by another task. Therefore no
\r
368 mutual exclusion is required to test the pxMutexHolder variable. */
\r
369 if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
\r
371 traceGIVE_MUTEX_RECURSIVE( pxMutex );
\r
373 /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to
\r
374 the task handle, therefore no underflow check is required. Also,
\r
375 uxRecursiveCallCount is only modified by the mutex holder, and as
\r
376 there can only be one, no mutual exclusion is required to modify the
\r
377 uxRecursiveCallCount member. */
\r
378 ( pxMutex->uxRecursiveCallCount )--;
\r
380 /* Have we unwound the call count? */
\r
381 if( pxMutex->uxRecursiveCallCount == 0 )
\r
383 /* Return the mutex. This will automatically unblock any other
\r
384 task that might be waiting to access the mutex. */
\r
385 xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
\r
392 /* We cannot give the mutex because we are not the holder. */
\r
395 traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
\r
401 #endif /* configUSE_RECURSIVE_MUTEXES */
\r
402 /*-----------------------------------------------------------*/
\r
404 #if configUSE_RECURSIVE_MUTEXES == 1
\r
406 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime )
\r
408 portBASE_TYPE xReturn;
\r
410 configASSERT( pxMutex );
\r
412 /* Comments regarding mutual exclusion as per those within
\r
413 xQueueGiveMutexRecursive(). */
\r
415 traceTAKE_MUTEX_RECURSIVE( pxMutex );
\r
417 if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
\r
419 ( pxMutex->uxRecursiveCallCount )++;
\r
424 xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );
\r
426 /* pdPASS will only be returned if we successfully obtained the mutex,
\r
427 we may have blocked to reach here. */
\r
428 if( xReturn == pdPASS )
\r
430 ( pxMutex->uxRecursiveCallCount )++;
\r
434 traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );
\r
441 #endif /* configUSE_RECURSIVE_MUTEXES */
\r
442 /*-----------------------------------------------------------*/
\r
444 #if configUSE_COUNTING_SEMAPHORES == 1
\r
446 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount )
\r
448 xQueueHandle pxHandle;
\r
450 pxHandle = xQueueCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH );
\r
452 if( pxHandle != NULL )
\r
454 pxHandle->uxMessagesWaiting = uxInitialCount;
\r
456 traceCREATE_COUNTING_SEMAPHORE();
\r
460 traceCREATE_COUNTING_SEMAPHORE_FAILED();
\r
463 configASSERT( pxHandle );
\r
467 #endif /* configUSE_COUNTING_SEMAPHORES */
\r
468 /*-----------------------------------------------------------*/
\r
470 signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
\r
472 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
473 xTimeOutType xTimeOut;
\r
475 configASSERT( pxQueue );
\r
476 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
478 /* This function relaxes the coding standard somewhat to allow return
\r
479 statements within the function itself. This is done in the interest
\r
480 of execution time efficiency. */
\r
483 taskENTER_CRITICAL();
\r
485 /* Is there room on the queue now? To be running we must be
\r
486 the highest priority task wanting to access the queue. */
\r
487 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
489 traceQUEUE_SEND( pxQueue );
\r
490 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
492 /* If there was a task waiting for data to arrive on the
\r
493 queue then unblock it now. */
\r
494 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
496 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
498 /* The unblocked task has a priority higher than
\r
499 our own so yield immediately. Yes it is ok to do
\r
500 this from within the critical section - the kernel
\r
501 takes care of that. */
\r
502 portYIELD_WITHIN_API();
\r
506 taskEXIT_CRITICAL();
\r
508 /* Return to the original privilege level before exiting the
\r
514 if( xTicksToWait == ( portTickType ) 0 )
\r
516 /* The queue was full and no block time is specified (or
\r
517 the block time has expired) so leave now. */
\r
518 taskEXIT_CRITICAL();
\r
520 /* Return to the original privilege level before exiting
\r
522 traceQUEUE_SEND_FAILED( pxQueue );
\r
523 return errQUEUE_FULL;
\r
525 else if( xEntryTimeSet == pdFALSE )
\r
527 /* The queue was full and a block time was specified so
\r
528 configure the timeout structure. */
\r
529 vTaskSetTimeOutState( &xTimeOut );
\r
530 xEntryTimeSet = pdTRUE;
\r
534 taskEXIT_CRITICAL();
\r
536 /* Interrupts and other tasks can send to and receive from the queue
\r
537 now the critical section has been exited. */
\r
540 prvLockQueue( pxQueue );
\r
542 /* Update the timeout state to see if it has expired yet. */
\r
543 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
545 if( prvIsQueueFull( pxQueue ) != pdFALSE )
\r
547 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
\r
548 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
\r
550 /* Unlocking the queue means queue events can effect the
\r
551 event list. It is possible that interrupts occurring now
\r
552 remove this task from the event list again - but as the
\r
553 scheduler is suspended the task will go onto the pending
\r
554 ready last instead of the actual ready list. */
\r
555 prvUnlockQueue( pxQueue );
\r
557 /* Resuming the scheduler will move tasks from the pending
\r
558 ready list into the ready list - so it is feasible that this
\r
559 task is already in a ready list before it yields - in which
\r
560 case the yield will not cause a context switch unless there
\r
561 is also a higher priority task in the pending ready list. */
\r
562 if( xTaskResumeAll() == pdFALSE )
\r
564 portYIELD_WITHIN_API();
\r
570 prvUnlockQueue( pxQueue );
\r
571 ( void ) xTaskResumeAll();
\r
576 /* The timeout has expired. */
\r
577 prvUnlockQueue( pxQueue );
\r
578 ( void ) xTaskResumeAll();
\r
580 /* Return to the original privilege level before exiting the
\r
582 traceQUEUE_SEND_FAILED( pxQueue );
\r
583 return errQUEUE_FULL;
\r
587 /*-----------------------------------------------------------*/
\r
589 #if configUSE_ALTERNATIVE_API == 1
\r
591 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
\r
593 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
594 xTimeOutType xTimeOut;
\r
596 configASSERT( pxQueue );
\r
597 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
601 taskENTER_CRITICAL();
\r
603 /* Is there room on the queue now? To be running we must be
\r
604 the highest priority task wanting to access the queue. */
\r
605 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
607 traceQUEUE_SEND( pxQueue );
\r
608 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
610 /* If there was a task waiting for data to arrive on the
\r
611 queue then unblock it now. */
\r
612 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
614 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
616 /* The unblocked task has a priority higher than
\r
617 our own so yield immediately. */
\r
618 portYIELD_WITHIN_API();
\r
622 taskEXIT_CRITICAL();
\r
627 if( xTicksToWait == ( portTickType ) 0 )
\r
629 taskEXIT_CRITICAL();
\r
630 return errQUEUE_FULL;
\r
632 else if( xEntryTimeSet == pdFALSE )
\r
634 vTaskSetTimeOutState( &xTimeOut );
\r
635 xEntryTimeSet = pdTRUE;
\r
639 taskEXIT_CRITICAL();
\r
641 taskENTER_CRITICAL();
\r
643 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
645 if( prvIsQueueFull( pxQueue ) != pdFALSE )
\r
647 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
\r
648 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
\r
649 portYIELD_WITHIN_API();
\r
654 taskEXIT_CRITICAL();
\r
655 traceQUEUE_SEND_FAILED( pxQueue );
\r
656 return errQUEUE_FULL;
\r
659 taskEXIT_CRITICAL();
\r
663 #endif /* configUSE_ALTERNATIVE_API */
\r
664 /*-----------------------------------------------------------*/
\r
666 #if configUSE_ALTERNATIVE_API == 1
\r
668 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
\r
670 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
671 xTimeOutType xTimeOut;
\r
672 signed char *pcOriginalReadPosition;
\r
674 configASSERT( pxQueue );
\r
675 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
679 taskENTER_CRITICAL();
\r
681 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
683 /* Remember our read position in case we are just peeking. */
\r
684 pcOriginalReadPosition = pxQueue->pcReadFrom;
\r
686 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
688 if( xJustPeeking == pdFALSE )
\r
690 traceQUEUE_RECEIVE( pxQueue );
\r
692 /* We are actually removing data. */
\r
693 --( pxQueue->uxMessagesWaiting );
\r
695 #if ( configUSE_MUTEXES == 1 )
\r
697 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
699 /* Record the information required to implement
\r
700 priority inheritance should it become necessary. */
\r
701 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
\r
706 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
708 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
710 portYIELD_WITHIN_API();
\r
716 traceQUEUE_PEEK( pxQueue );
\r
718 /* We are not removing the data, so reset our read
\r
720 pxQueue->pcReadFrom = pcOriginalReadPosition;
\r
722 /* The data is being left in the queue, so see if there are
\r
723 any other tasks waiting for the data. */
\r
724 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
726 /* Tasks that are removed from the event list will get added to
\r
727 the pending ready list as the scheduler is still suspended. */
\r
728 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
730 /* The task waiting has a higher priority than this task. */
\r
731 portYIELD_WITHIN_API();
\r
737 taskEXIT_CRITICAL();
\r
742 if( xTicksToWait == ( portTickType ) 0 )
\r
744 taskEXIT_CRITICAL();
\r
745 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
746 return errQUEUE_EMPTY;
\r
748 else if( xEntryTimeSet == pdFALSE )
\r
750 vTaskSetTimeOutState( &xTimeOut );
\r
751 xEntryTimeSet = pdTRUE;
\r
755 taskEXIT_CRITICAL();
\r
757 taskENTER_CRITICAL();
\r
759 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
761 if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
\r
763 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
\r
765 #if ( configUSE_MUTEXES == 1 )
\r
767 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
769 portENTER_CRITICAL();
\r
770 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
\r
771 portEXIT_CRITICAL();
\r
776 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
777 portYIELD_WITHIN_API();
\r
782 taskEXIT_CRITICAL();
\r
783 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
784 return errQUEUE_EMPTY;
\r
787 taskEXIT_CRITICAL();
\r
792 #endif /* configUSE_ALTERNATIVE_API */
\r
793 /*-----------------------------------------------------------*/
\r
795 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )
\r
797 signed portBASE_TYPE xReturn;
\r
798 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
800 configASSERT( pxQueue );
\r
801 configASSERT( pxHigherPriorityTaskWoken );
\r
802 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
804 /* Similar to xQueueGenericSend, except we don't block if there is no room
\r
805 in the queue. Also we don't directly wake a task that was blocked on a
\r
806 queue read, instead we return a flag to say whether a context switch is
\r
807 required or not (i.e. has a task with a higher priority than us been woken
\r
809 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
811 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
813 traceQUEUE_SEND_FROM_ISR( pxQueue );
\r
815 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
817 /* If the queue is locked we do not alter the event list. This will
\r
818 be done when the queue is unlocked later. */
\r
819 if( pxQueue->xTxLock == queueUNLOCKED )
\r
821 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
823 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
825 /* The task waiting has a higher priority so record that a
\r
826 context switch is required. */
\r
827 *pxHigherPriorityTaskWoken = pdTRUE;
\r
833 /* Increment the lock count so the task that unlocks the queue
\r
834 knows that data was posted while it was locked. */
\r
835 ++( pxQueue->xTxLock );
\r
842 traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
\r
843 xReturn = errQUEUE_FULL;
\r
846 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
850 /*-----------------------------------------------------------*/
\r
852 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
\r
854 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
855 xTimeOutType xTimeOut;
\r
856 signed char *pcOriginalReadPosition;
\r
858 configASSERT( pxQueue );
\r
859 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
861 /* This function relaxes the coding standard somewhat to allow return
\r
862 statements within the function itself. This is done in the interest
\r
863 of execution time efficiency. */
\r
867 taskENTER_CRITICAL();
\r
869 /* Is there data in the queue now? To be running we must be
\r
870 the highest priority task wanting to access the queue. */
\r
871 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
873 /* Remember our read position in case we are just peeking. */
\r
874 pcOriginalReadPosition = pxQueue->pcReadFrom;
\r
876 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
878 if( xJustPeeking == pdFALSE )
\r
880 traceQUEUE_RECEIVE( pxQueue );
\r
882 /* We are actually removing data. */
\r
883 --( pxQueue->uxMessagesWaiting );
\r
885 #if ( configUSE_MUTEXES == 1 )
\r
887 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
889 /* Record the information required to implement
\r
890 priority inheritance should it become necessary. */
\r
891 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
\r
896 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
898 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
900 portYIELD_WITHIN_API();
\r
906 traceQUEUE_PEEK( pxQueue );
\r
908 /* We are not removing the data, so reset our read
\r
910 pxQueue->pcReadFrom = pcOriginalReadPosition;
\r
912 /* The data is being left in the queue, so see if there are
\r
913 any other tasks waiting for the data. */
\r
914 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
916 /* Tasks that are removed from the event list will get added to
\r
917 the pending ready list as the scheduler is still suspended. */
\r
918 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
920 /* The task waiting has a higher priority than this task. */
\r
921 portYIELD_WITHIN_API();
\r
927 taskEXIT_CRITICAL();
\r
932 if( xTicksToWait == ( portTickType ) 0 )
\r
934 /* The queue was empty and no block time is specified (or
\r
935 the block time has expired) so leave now. */
\r
936 taskEXIT_CRITICAL();
\r
937 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
938 return errQUEUE_EMPTY;
\r
940 else if( xEntryTimeSet == pdFALSE )
\r
942 /* The queue was empty and a block time was specified so
\r
943 configure the timeout structure. */
\r
944 vTaskSetTimeOutState( &xTimeOut );
\r
945 xEntryTimeSet = pdTRUE;
\r
949 taskEXIT_CRITICAL();
\r
951 /* Interrupts and other tasks can send to and receive from the queue
\r
952 now the critical section has been exited. */
\r
955 prvLockQueue( pxQueue );
\r
957 /* Update the timeout state to see if it has expired yet. */
\r
958 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
960 if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
\r
962 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
\r
964 #if ( configUSE_MUTEXES == 1 )
\r
966 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
968 portENTER_CRITICAL();
\r
970 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
\r
972 portEXIT_CRITICAL();
\r
977 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
978 prvUnlockQueue( pxQueue );
\r
979 if( xTaskResumeAll() == pdFALSE )
\r
981 portYIELD_WITHIN_API();
\r
987 prvUnlockQueue( pxQueue );
\r
988 ( void ) xTaskResumeAll();
\r
993 prvUnlockQueue( pxQueue );
\r
994 ( void ) xTaskResumeAll();
\r
995 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
996 return errQUEUE_EMPTY;
\r
1000 /*-----------------------------------------------------------*/
\r
1002 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )
\r
1004 signed portBASE_TYPE xReturn;
\r
1005 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
1007 configASSERT( pxQueue );
\r
1008 configASSERT( pxTaskWoken );
\r
1009 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
1011 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1013 /* We cannot block from an ISR, so check there is data available. */
\r
1014 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1016 traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
\r
1018 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
1019 --( pxQueue->uxMessagesWaiting );
\r
1021 /* If the queue is locked we will not modify the event list. Instead
\r
1022 we update the lock count so the task that unlocks the queue will know
\r
1023 that an ISR has removed data while the queue was locked. */
\r
1024 if( pxQueue->xRxLock == queueUNLOCKED )
\r
1026 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1028 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1030 /* The task waiting has a higher priority than us so
\r
1031 force a context switch. */
\r
1032 *pxTaskWoken = pdTRUE;
\r
1038 /* Increment the lock count so the task that unlocks the queue
\r
1039 knows that data was removed while it was locked. */
\r
1040 ++( pxQueue->xRxLock );
\r
1048 traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
\r
1051 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1055 /*-----------------------------------------------------------*/
\r
1057 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue )
\r
1059 unsigned portBASE_TYPE uxReturn;
\r
1061 configASSERT( pxQueue );
\r
1063 taskENTER_CRITICAL();
\r
1064 uxReturn = pxQueue->uxMessagesWaiting;
\r
1065 taskEXIT_CRITICAL();
\r
1069 /*-----------------------------------------------------------*/
\r
1071 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue )
\r
1073 unsigned portBASE_TYPE uxReturn;
\r
1075 configASSERT( pxQueue );
\r
1077 uxReturn = pxQueue->uxMessagesWaiting;
\r
1081 /*-----------------------------------------------------------*/
\r
1083 void vQueueDelete( xQueueHandle pxQueue )
\r
1085 configASSERT( pxQueue );
\r
1087 traceQUEUE_DELETE( pxQueue );
\r
1088 vQueueUnregisterQueue( pxQueue );
\r
1089 vPortFree( pxQueue->pcHead );
\r
1090 vPortFree( pxQueue );
\r
1092 /*-----------------------------------------------------------*/
\r
1094 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )
\r
1096 if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )
\r
1098 #if ( configUSE_MUTEXES == 1 )
\r
1100 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
1102 /* The mutex is no longer being held. */
\r
1103 vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
\r
1104 pxQueue->pxMutexHolder = NULL;
\r
1109 else if( xPosition == queueSEND_TO_BACK )
\r
1111 memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
\r
1112 pxQueue->pcWriteTo += pxQueue->uxItemSize;
\r
1113 if( pxQueue->pcWriteTo >= pxQueue->pcTail )
\r
1115 pxQueue->pcWriteTo = pxQueue->pcHead;
\r
1120 memcpy( ( void * ) pxQueue->pcReadFrom, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
\r
1121 pxQueue->pcReadFrom -= pxQueue->uxItemSize;
\r
1122 if( pxQueue->pcReadFrom < pxQueue->pcHead )
\r
1124 pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
\r
1128 ++( pxQueue->uxMessagesWaiting );
\r
1130 /*-----------------------------------------------------------*/
\r
1132 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
\r
1134 if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
\r
1136 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1137 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1139 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1141 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1144 /*-----------------------------------------------------------*/
\r
1146 static void prvUnlockQueue( xQueueHandle pxQueue )
\r
1148 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
\r
1150 /* The lock counts contains the number of extra data items placed or
\r
1151 removed from the queue while the queue was locked. When a queue is
\r
1152 locked items can be added or removed, but the event lists cannot be
\r
1154 taskENTER_CRITICAL();
\r
1156 /* See if data was added to the queue while it was locked. */
\r
1157 while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )
\r
1159 /* Data was posted while the queue was locked. Are any tasks
\r
1160 blocked waiting for data to become available? */
\r
1161 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1163 /* Tasks that are removed from the event list will get added to
\r
1164 the pending ready list as the scheduler is still suspended. */
\r
1165 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1167 /* The task waiting has a higher priority so record that a
\r
1168 context switch is required. */
\r
1169 vTaskMissedYield();
\r
1172 --( pxQueue->xTxLock );
\r
1180 pxQueue->xTxLock = queueUNLOCKED;
\r
1182 taskEXIT_CRITICAL();
\r
1184 /* Do the same for the Rx lock. */
\r
1185 taskENTER_CRITICAL();
\r
1187 while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )
\r
1189 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1191 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1193 vTaskMissedYield();
\r
1196 --( pxQueue->xRxLock );
\r
1204 pxQueue->xRxLock = queueUNLOCKED;
\r
1206 taskEXIT_CRITICAL();
\r
1208 /*-----------------------------------------------------------*/
\r
1210 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue )
\r
1212 signed portBASE_TYPE xReturn;
\r
1214 taskENTER_CRITICAL();
\r
1215 xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
\r
1216 taskEXIT_CRITICAL();
\r
1220 /*-----------------------------------------------------------*/
\r
1222 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue )
\r
1224 signed portBASE_TYPE xReturn;
\r
1226 configASSERT( pxQueue );
\r
1227 xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
\r
1231 /*-----------------------------------------------------------*/
\r
1233 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue )
\r
1235 signed portBASE_TYPE xReturn;
\r
1237 taskENTER_CRITICAL();
\r
1238 xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
\r
1239 taskEXIT_CRITICAL();
\r
1243 /*-----------------------------------------------------------*/
\r
1245 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue )
\r
1247 signed portBASE_TYPE xReturn;
\r
1249 configASSERT( pxQueue );
\r
1250 xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
\r
1254 /*-----------------------------------------------------------*/
\r
1256 #if configUSE_CO_ROUTINES == 1
\r
1257 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )
\r
1259 signed portBASE_TYPE xReturn;
\r
1261 /* If the queue is already full we may have to block. A critical section
\r
1262 is required to prevent an interrupt removing something from the queue
\r
1263 between the check to see if the queue is full and blocking on the queue. */
\r
1264 portDISABLE_INTERRUPTS();
\r
1266 if( prvIsQueueFull( pxQueue ) != pdFALSE )
\r
1268 /* The queue is full - do we want to block or just leave without
\r
1270 if( xTicksToWait > ( portTickType ) 0 )
\r
1272 /* As this is called from a coroutine we cannot block directly, but
\r
1273 return indicating that we need to block. */
\r
1274 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
\r
1275 portENABLE_INTERRUPTS();
\r
1276 return errQUEUE_BLOCKED;
\r
1280 portENABLE_INTERRUPTS();
\r
1281 return errQUEUE_FULL;
\r
1285 portENABLE_INTERRUPTS();
\r
1289 portDISABLE_INTERRUPTS();
\r
1291 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
1293 /* There is room in the queue, copy the data into the queue. */
\r
1294 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
\r
1297 /* Were any co-routines waiting for data to become available? */
\r
1298 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1300 /* In this instance the co-routine could be placed directly
\r
1301 into the ready list as we are within a critical section.
\r
1302 Instead the same pending ready list mechanism is used as if
\r
1303 the event were caused from within an interrupt. */
\r
1304 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1306 /* The co-routine waiting has a higher priority so record
\r
1307 that a yield might be appropriate. */
\r
1308 xReturn = errQUEUE_YIELD;
\r
1314 xReturn = errQUEUE_FULL;
\r
1317 portENABLE_INTERRUPTS();
\r
1322 /*-----------------------------------------------------------*/
\r
1324 #if configUSE_CO_ROUTINES == 1
\r
1325 signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )
\r
1327 signed portBASE_TYPE xReturn;
\r
1329 /* If the queue is already empty we may have to block. A critical section
\r
1330 is required to prevent an interrupt adding something to the queue
\r
1331 between the check to see if the queue is empty and blocking on the queue. */
\r
1332 portDISABLE_INTERRUPTS();
\r
1334 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
\r
1336 /* There are no messages in the queue, do we want to block or just
\r
1337 leave with nothing? */
\r
1338 if( xTicksToWait > ( portTickType ) 0 )
\r
1340 /* As this is a co-routine we cannot block directly, but return
\r
1341 indicating that we need to block. */
\r
1342 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
\r
1343 portENABLE_INTERRUPTS();
\r
1344 return errQUEUE_BLOCKED;
\r
1348 portENABLE_INTERRUPTS();
\r
1349 return errQUEUE_FULL;
\r
1353 portENABLE_INTERRUPTS();
\r
1357 portDISABLE_INTERRUPTS();
\r
1359 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1361 /* Data is available from the queue. */
\r
1362 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1363 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1365 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1367 --( pxQueue->uxMessagesWaiting );
\r
1368 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1372 /* Were any co-routines waiting for space to become available? */
\r
1373 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1375 /* In this instance the co-routine could be placed directly
\r
1376 into the ready list as we are within a critical section.
\r
1377 Instead the same pending ready list mechanism is used as if
\r
1378 the event were caused from within an interrupt. */
\r
1379 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1381 xReturn = errQUEUE_YIELD;
\r
1390 portENABLE_INTERRUPTS();
\r
1395 /*-----------------------------------------------------------*/
\r
1399 #if configUSE_CO_ROUTINES == 1
\r
1400 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
\r
1402 /* Cannot block within an ISR so if there is no space on the queue then
\r
1403 exit without doing anything. */
\r
1404 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
1406 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
\r
1408 /* We only want to wake one co-routine per ISR, so check that a
\r
1409 co-routine has not already been woken. */
\r
1410 if( xCoRoutinePreviouslyWoken == pdFALSE )
\r
1412 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1414 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1422 return xCoRoutinePreviouslyWoken;
\r
1425 /*-----------------------------------------------------------*/
\r
1427 #if configUSE_CO_ROUTINES == 1
\r
1428 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )
\r
1430 signed portBASE_TYPE xReturn;
\r
1432 /* We cannot block from an ISR, so check there is data available. If
\r
1433 not then just leave without doing anything. */
\r
1434 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1436 /* Copy the data from the queue. */
\r
1437 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1438 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1440 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1442 --( pxQueue->uxMessagesWaiting );
\r
1443 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1445 if( ( *pxCoRoutineWoken ) == pdFALSE )
\r
1447 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1449 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1451 *pxCoRoutineWoken = pdTRUE;
\r
1466 /*-----------------------------------------------------------*/
\r
1468 #if configQUEUE_REGISTRY_SIZE > 0
\r
1470 void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )
\r
1472 unsigned portBASE_TYPE ux;
\r
1474 /* See if there is an empty space in the registry. A NULL name denotes
\r
1476 for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
\r
1478 if( xQueueRegistry[ ux ].pcQueueName == NULL )
\r
1480 /* Store the information on this queue. */
\r
1481 xQueueRegistry[ ux ].pcQueueName = pcQueueName;
\r
1482 xQueueRegistry[ ux ].xHandle = xQueue;
\r
1489 /*-----------------------------------------------------------*/
\r
1491 #if configQUEUE_REGISTRY_SIZE > 0
\r
1493 static void vQueueUnregisterQueue( xQueueHandle xQueue )
\r
1495 unsigned portBASE_TYPE ux;
\r
1497 /* See if the handle of the queue being unregistered in actually in the
\r
1499 for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
\r
1501 if( xQueueRegistry[ ux ].xHandle == xQueue )
\r
1503 /* Set the name to NULL to show that this slot if free again. */
\r
1504 xQueueRegistry[ ux ].pcQueueName = NULL;
\r
1512 /*-----------------------------------------------------------*/
\r
1514 #if configUSE_TIMERS == 1
\r
1516 void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait )
\r
1518 /* This function should not be called by application code hence the
\r
1519 'Restricted' in its name. It is not part of the public API. It is
\r
1520 designed for use by kernel code, and has special calling requirements.
\r
1521 It can result in vListInsert() being called on a list that can only
\r
1522 possibly ever have one item in it, so the list will be fast, but even
\r
1523 so it should be called with the scheduler locked and not from a critical
\r
1526 /* Only do anything if there are no messages in the queue. This function
\r
1527 will not actually cause the task to block, just place it on a blocked
\r
1528 list. It will not block until the scheduler is unlocked - at which
\r
1529 time a yield will be performed. If an item is added to the queue while
\r
1530 the queue is locked, and the calling task blocks on the queue, then the
\r
1531 calling task will be immediately unblocked when the queue is unlocked. */
\r
1532 prvLockQueue( pxQueue );
\r
1533 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U )
\r
1535 /* There is nothing in the queue, block for the specified period. */
\r
1536 vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
1538 prvUnlockQueue( pxQueue );
\r