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
70 #include "croutine.h"
\r
72 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
74 /*-----------------------------------------------------------
\r
75 * PUBLIC LIST API documented in list.h
\r
76 *----------------------------------------------------------*/
\r
78 /* Constants used with the cRxLock and cTxLock structure members. */
\r
79 #define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 )
\r
80 #define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 )
\r
82 #define queueERRONEOUS_UNBLOCK ( -1 )
\r
84 /* For internal use only. */
\r
85 #define queueSEND_TO_BACK ( 0 )
\r
86 #define queueSEND_TO_FRONT ( 1 )
\r
88 /* Effectively make a union out of the xQUEUE structure. */
\r
89 #define pxMutexHolder pcTail
\r
90 #define uxQueueType pcHead
\r
91 #define uxRecursiveCallCount pcReadFrom
\r
92 #define queueQUEUE_IS_MUTEX NULL
\r
94 /* Semaphores do not actually store or copy data, so have an items size of
\r
96 #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( 0 )
\r
97 #define queueDONT_BLOCK ( ( portTickType ) 0 )
\r
98 #define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0 )
\r
101 * Definition of the queue used by the scheduler.
\r
102 * Items are queued by copy, not reference.
\r
104 typedef struct QueueDefinition
\r
106 signed char *pcHead; /*< Points to the beginning of the queue storage area. */
\r
107 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
109 signed char *pcWriteTo; /*< Points to the free next place in the storage area. */
\r
110 signed char *pcReadFrom; /*< Points to the last place that a queued item was read from. */
\r
112 xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */
\r
113 xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */
\r
115 volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */
\r
116 unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
\r
117 unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */
\r
119 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
120 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
123 /*-----------------------------------------------------------*/
\r
126 * Inside this file xQueueHandle is a pointer to a xQUEUE structure.
\r
127 * To keep the definition private the API header file defines it as a
\r
130 typedef xQUEUE * xQueueHandle;
\r
133 * Prototypes for public functions are included here so we don't have to
\r
134 * include the API header file (as it defines xQueueHandle differently). These
\r
135 * functions are documented in the API header file.
\r
137 xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ) PRIVILEGED_FUNCTION;
\r
138 signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
\r
139 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
140 void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
\r
141 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
\r
142 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;
\r
143 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;
\r
144 xQueueHandle xQueueCreateMutex( void ) PRIVILEGED_FUNCTION;
\r
145 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) PRIVILEGED_FUNCTION;
\r
146 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) PRIVILEGED_FUNCTION;
\r
147 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ) PRIVILEGED_FUNCTION;
\r
148 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
\r
149 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;
\r
150 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
151 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
152 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
153 void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
\r
156 * Co-routine queue functions differ from task queue functions. Co-routines are
\r
157 * an optional component.
\r
159 #if configUSE_CO_ROUTINES == 1
\r
160 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) PRIVILEGED_FUNCTION;
\r
161 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;
\r
162 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
\r
163 signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
\r
167 * The queue registry is just a means for kernel aware debuggers to locate
\r
168 * queue structures. It has no other purpose so is an optional component.
\r
170 #if configQUEUE_REGISTRY_SIZE > 0
\r
172 /* The type stored within the queue registry array. This allows a name
\r
173 to be assigned to each queue making kernel aware debugging a little
\r
174 more user friendly. */
\r
175 typedef struct QUEUE_REGISTRY_ITEM
\r
177 signed char *pcQueueName;
\r
178 xQueueHandle xHandle;
\r
179 } xQueueRegistryItem;
\r
181 /* The queue registry is simply an array of xQueueRegistryItem structures.
\r
182 The pcQueueName member of a structure being NULL is indicative of the
\r
183 array position being vacant. */
\r
184 xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
\r
186 /* Removes a queue from the registry by simply setting the pcQueueName
\r
188 static void vQueueUnregisterQueue( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
\r
189 void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName ) PRIVILEGED_FUNCTION;
\r
193 * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not
\r
194 * prevent an ISR from adding or removing items to the queue, but does prevent
\r
195 * an ISR from removing tasks from the queue event lists. If an ISR finds a
\r
196 * queue is locked it will instead increment the appropriate queue lock count
\r
197 * to indicate that a task may require unblocking. When the queue in unlocked
\r
198 * these lock counts are inspected, and the appropriate action taken.
\r
200 static void prvUnlockQueue( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
203 * Uses a critical section to determine if there is any data in a queue.
\r
205 * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
\r
207 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
210 * Uses a critical section to determine if there is any space in a queue.
\r
212 * @return pdTRUE if there is no space, otherwise pdFALSE;
\r
214 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
217 * Copies an item into the queue, either at the front of the queue or the
\r
218 * back of the queue.
\r
220 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION;
\r
223 * Copies an item out of a queue.
\r
225 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer ) PRIVILEGED_FUNCTION;
\r
226 /*-----------------------------------------------------------*/
\r
229 * Macro to mark a queue as locked. Locking a queue prevents an ISR from
\r
230 * accessing the queue event lists.
\r
232 #define prvLockQueue( pxQueue ) \
\r
233 taskENTER_CRITICAL(); \
\r
235 if( ( pxQueue )->xRxLock == queueUNLOCKED ) \
\r
237 ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED; \
\r
239 if( ( pxQueue )->xTxLock == queueUNLOCKED ) \
\r
241 ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED; \
\r
244 taskEXIT_CRITICAL()
\r
245 /*-----------------------------------------------------------*/
\r
248 /*-----------------------------------------------------------
\r
249 * PUBLIC QUEUE MANAGEMENT API documented in queue.h
\r
250 *----------------------------------------------------------*/
\r
252 xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize )
\r
254 xQUEUE *pxNewQueue;
\r
255 size_t xQueueSizeInBytes;
\r
256 xQueueHandle xReturn = NULL;
\r
258 /* Allocate the new queue structure. */
\r
259 if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )
\r
261 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
\r
262 if( pxNewQueue != NULL )
\r
264 /* Create the list of pointers to queue items. The queue is one byte
\r
265 longer than asked for to make wrap checking easier/faster. */
\r
266 xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1;
\r
268 pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes );
\r
269 if( pxNewQueue->pcHead != NULL )
\r
271 /* Initialise the queue members as described above where the
\r
272 queue type is defined. */
\r
273 pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize );
\r
274 pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
\r
275 pxNewQueue->pcWriteTo = pxNewQueue->pcHead;
\r
276 pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - ( unsigned portBASE_TYPE ) 1U ) * uxItemSize );
\r
277 pxNewQueue->uxLength = uxQueueLength;
\r
278 pxNewQueue->uxItemSize = uxItemSize;
\r
279 pxNewQueue->xRxLock = queueUNLOCKED;
\r
280 pxNewQueue->xTxLock = queueUNLOCKED;
\r
282 /* Likewise ensure the event queues start with the correct state. */
\r
283 vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
\r
284 vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
\r
286 traceQUEUE_CREATE( pxNewQueue );
\r
287 xReturn = pxNewQueue;
\r
291 traceQUEUE_CREATE_FAILED();
\r
292 vPortFree( pxNewQueue );
\r
297 configASSERT( xReturn );
\r
301 /*-----------------------------------------------------------*/
\r
303 #if ( configUSE_MUTEXES == 1 )
\r
305 xQueueHandle xQueueCreateMutex( void )
\r
307 xQUEUE *pxNewQueue;
\r
309 /* Allocate the new queue structure. */
\r
310 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
\r
311 if( pxNewQueue != NULL )
\r
313 /* Information required for priority inheritance. */
\r
314 pxNewQueue->pxMutexHolder = NULL;
\r
315 pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
\r
317 /* Queues used as a mutex no data is actually copied into or out
\r
319 pxNewQueue->pcWriteTo = NULL;
\r
320 pxNewQueue->pcReadFrom = NULL;
\r
322 /* Each mutex has a length of 1 (like a binary semaphore) and
\r
323 an item size of 0 as nothing is actually copied into or out
\r
325 pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
\r
326 pxNewQueue->uxLength = ( unsigned portBASE_TYPE ) 1U;
\r
327 pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 0U;
\r
328 pxNewQueue->xRxLock = queueUNLOCKED;
\r
329 pxNewQueue->xTxLock = queueUNLOCKED;
\r
331 /* Ensure the event queues start with the correct state. */
\r
332 vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
\r
333 vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
\r
335 /* Start with the semaphore in the expected state. */
\r
336 xQueueGenericSend( pxNewQueue, NULL, ( portTickType ) 0U, queueSEND_TO_BACK );
\r
338 traceCREATE_MUTEX( pxNewQueue );
\r
342 traceCREATE_MUTEX_FAILED();
\r
345 configASSERT( pxNewQueue );
\r
349 #endif /* configUSE_MUTEXES */
\r
350 /*-----------------------------------------------------------*/
\r
352 #if configUSE_RECURSIVE_MUTEXES == 1
\r
354 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex )
\r
356 portBASE_TYPE xReturn;
\r
358 configASSERT( pxMutex );
\r
360 /* If this is the task that holds the mutex then pxMutexHolder will not
\r
361 change outside of this task. If this task does not hold the mutex then
\r
362 pxMutexHolder can never coincidentally equal the tasks handle, and as
\r
363 this is the only condition we are interested in it does not matter if
\r
364 pxMutexHolder is accessed simultaneously by another task. Therefore no
\r
365 mutual exclusion is required to test the pxMutexHolder variable. */
\r
366 if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
\r
368 traceGIVE_MUTEX_RECURSIVE( pxMutex );
\r
370 /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to
\r
371 the task handle, therefore no underflow check is required. Also,
\r
372 uxRecursiveCallCount is only modified by the mutex holder, and as
\r
373 there can only be one, no mutual exclusion is required to modify the
\r
374 uxRecursiveCallCount member. */
\r
375 ( pxMutex->uxRecursiveCallCount )--;
\r
377 /* Have we unwound the call count? */
\r
378 if( pxMutex->uxRecursiveCallCount == 0 )
\r
380 /* Return the mutex. This will automatically unblock any other
\r
381 task that might be waiting to access the mutex. */
\r
382 xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
\r
389 /* We cannot give the mutex because we are not the holder. */
\r
392 traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
\r
398 #endif /* configUSE_RECURSIVE_MUTEXES */
\r
399 /*-----------------------------------------------------------*/
\r
401 #if configUSE_RECURSIVE_MUTEXES == 1
\r
403 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime )
\r
405 portBASE_TYPE xReturn;
\r
407 configASSERT( pxMutex );
\r
409 /* Comments regarding mutual exclusion as per those within
\r
410 xQueueGiveMutexRecursive(). */
\r
412 traceTAKE_MUTEX_RECURSIVE( pxMutex );
\r
414 if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
\r
416 ( pxMutex->uxRecursiveCallCount )++;
\r
421 xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );
\r
423 /* pdPASS will only be returned if we successfully obtained the mutex,
\r
424 we may have blocked to reach here. */
\r
425 if( xReturn == pdPASS )
\r
427 ( pxMutex->uxRecursiveCallCount )++;
\r
431 traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );
\r
438 #endif /* configUSE_RECURSIVE_MUTEXES */
\r
439 /*-----------------------------------------------------------*/
\r
441 #if configUSE_COUNTING_SEMAPHORES == 1
\r
443 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount )
\r
445 xQueueHandle pxHandle;
\r
447 pxHandle = xQueueCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH );
\r
449 if( pxHandle != NULL )
\r
451 pxHandle->uxMessagesWaiting = uxInitialCount;
\r
453 traceCREATE_COUNTING_SEMAPHORE();
\r
457 traceCREATE_COUNTING_SEMAPHORE_FAILED();
\r
460 configASSERT( pxHandle );
\r
464 #endif /* configUSE_COUNTING_SEMAPHORES */
\r
465 /*-----------------------------------------------------------*/
\r
467 signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
\r
469 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
470 xTimeOutType xTimeOut;
\r
472 configASSERT( pxQueue );
\r
473 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
475 /* This function relaxes the coding standard somewhat to allow return
\r
476 statements within the function itself. This is done in the interest
\r
477 of execution time efficiency. */
\r
480 taskENTER_CRITICAL();
\r
482 /* Is there room on the queue now? To be running we must be
\r
483 the highest priority task wanting to access the queue. */
\r
484 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
486 traceQUEUE_SEND( pxQueue );
\r
487 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
489 /* If there was a task waiting for data to arrive on the
\r
490 queue then unblock it now. */
\r
491 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
493 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
495 /* The unblocked task has a priority higher than
\r
496 our own so yield immediately. Yes it is ok to do
\r
497 this from within the critical section - the kernel
\r
498 takes care of that. */
\r
499 portYIELD_WITHIN_API();
\r
503 taskEXIT_CRITICAL();
\r
505 /* Return to the original privilege level before exiting the
\r
511 if( xTicksToWait == ( portTickType ) 0 )
\r
513 /* The queue was full and no block time is specified (or
\r
514 the block time has expired) so leave now. */
\r
515 taskEXIT_CRITICAL();
\r
517 /* Return to the original privilege level before exiting
\r
519 traceQUEUE_SEND_FAILED( pxQueue );
\r
520 return errQUEUE_FULL;
\r
522 else if( xEntryTimeSet == pdFALSE )
\r
524 /* The queue was full and a block time was specified so
\r
525 configure the timeout structure. */
\r
526 vTaskSetTimeOutState( &xTimeOut );
\r
527 xEntryTimeSet = pdTRUE;
\r
531 taskEXIT_CRITICAL();
\r
533 /* Interrupts and other tasks can send to and receive from the queue
\r
534 now the critical section has been exited. */
\r
537 prvLockQueue( pxQueue );
\r
539 /* Update the timeout state to see if it has expired yet. */
\r
540 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
542 if( prvIsQueueFull( pxQueue ) )
\r
544 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
\r
545 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
\r
547 /* Unlocking the queue means queue events can effect the
\r
548 event list. It is possible that interrupts occurring now
\r
549 remove this task from the event list again - but as the
\r
550 scheduler is suspended the task will go onto the pending
\r
551 ready last instead of the actual ready list. */
\r
552 prvUnlockQueue( pxQueue );
\r
554 /* Resuming the scheduler will move tasks from the pending
\r
555 ready list into the ready list - so it is feasible that this
\r
556 task is already in a ready list before it yields - in which
\r
557 case the yield will not cause a context switch unless there
\r
558 is also a higher priority task in the pending ready list. */
\r
559 if( !xTaskResumeAll() )
\r
561 portYIELD_WITHIN_API();
\r
567 prvUnlockQueue( pxQueue );
\r
568 ( void ) xTaskResumeAll();
\r
573 /* The timeout has expired. */
\r
574 prvUnlockQueue( pxQueue );
\r
575 ( void ) xTaskResumeAll();
\r
577 /* Return to the original privilege level before exiting the
\r
579 traceQUEUE_SEND_FAILED( pxQueue );
\r
580 return errQUEUE_FULL;
\r
584 /*-----------------------------------------------------------*/
\r
586 #if configUSE_ALTERNATIVE_API == 1
\r
588 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
\r
590 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
591 xTimeOutType xTimeOut;
\r
593 configASSERT( pxQueue );
\r
594 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
598 taskENTER_CRITICAL();
\r
600 /* Is there room on the queue now? To be running we must be
\r
601 the highest priority task wanting to access the queue. */
\r
602 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
604 traceQUEUE_SEND( pxQueue );
\r
605 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
607 /* If there was a task waiting for data to arrive on the
\r
608 queue then unblock it now. */
\r
609 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
611 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
613 /* The unblocked task has a priority higher than
\r
614 our own so yield immediately. */
\r
615 portYIELD_WITHIN_API();
\r
619 taskEXIT_CRITICAL();
\r
624 if( xTicksToWait == ( portTickType ) 0 )
\r
626 taskEXIT_CRITICAL();
\r
627 return errQUEUE_FULL;
\r
629 else if( xEntryTimeSet == pdFALSE )
\r
631 vTaskSetTimeOutState( &xTimeOut );
\r
632 xEntryTimeSet = pdTRUE;
\r
636 taskEXIT_CRITICAL();
\r
638 taskENTER_CRITICAL();
\r
640 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
642 if( prvIsQueueFull( pxQueue ) )
\r
644 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
\r
645 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
\r
646 portYIELD_WITHIN_API();
\r
651 taskEXIT_CRITICAL();
\r
652 traceQUEUE_SEND_FAILED( pxQueue );
\r
653 return errQUEUE_FULL;
\r
656 taskEXIT_CRITICAL();
\r
660 #endif /* configUSE_ALTERNATIVE_API */
\r
661 /*-----------------------------------------------------------*/
\r
663 #if configUSE_ALTERNATIVE_API == 1
\r
665 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
\r
667 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
668 xTimeOutType xTimeOut;
\r
669 signed char *pcOriginalReadPosition;
\r
671 configASSERT( pxQueue );
\r
672 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
676 taskENTER_CRITICAL();
\r
678 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
680 /* Remember our read position in case we are just peeking. */
\r
681 pcOriginalReadPosition = pxQueue->pcReadFrom;
\r
683 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
685 if( xJustPeeking == pdFALSE )
\r
687 traceQUEUE_RECEIVE( pxQueue );
\r
689 /* We are actually removing data. */
\r
690 --( pxQueue->uxMessagesWaiting );
\r
692 #if ( configUSE_MUTEXES == 1 )
\r
694 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
696 /* Record the information required to implement
\r
697 priority inheritance should it become necessary. */
\r
698 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
\r
703 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
705 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
707 portYIELD_WITHIN_API();
\r
713 traceQUEUE_PEEK( pxQueue );
\r
715 /* We are not removing the data, so reset our read
\r
717 pxQueue->pcReadFrom = pcOriginalReadPosition;
\r
719 /* The data is being left in the queue, so see if there are
\r
720 any other tasks waiting for the data. */
\r
721 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
723 /* Tasks that are removed from the event list will get added to
\r
724 the pending ready list as the scheduler is still suspended. */
\r
725 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
727 /* The task waiting has a higher priority than this task. */
\r
728 portYIELD_WITHIN_API();
\r
734 taskEXIT_CRITICAL();
\r
739 if( xTicksToWait == ( portTickType ) 0 )
\r
741 taskEXIT_CRITICAL();
\r
742 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
743 return errQUEUE_EMPTY;
\r
745 else if( xEntryTimeSet == pdFALSE )
\r
747 vTaskSetTimeOutState( &xTimeOut );
\r
748 xEntryTimeSet = pdTRUE;
\r
752 taskEXIT_CRITICAL();
\r
754 taskENTER_CRITICAL();
\r
756 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
758 if( prvIsQueueEmpty( pxQueue ) )
\r
760 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
\r
762 #if ( configUSE_MUTEXES == 1 )
\r
764 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
766 portENTER_CRITICAL();
\r
767 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
\r
768 portEXIT_CRITICAL();
\r
773 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
774 portYIELD_WITHIN_API();
\r
779 taskEXIT_CRITICAL();
\r
780 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
781 return errQUEUE_EMPTY;
\r
784 taskEXIT_CRITICAL();
\r
789 #endif /* configUSE_ALTERNATIVE_API */
\r
790 /*-----------------------------------------------------------*/
\r
792 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )
\r
794 signed portBASE_TYPE xReturn;
\r
795 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
797 configASSERT( pxQueue );
\r
798 configASSERT( pxHigherPriorityTaskWoken );
\r
799 configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
801 /* Similar to xQueueGenericSend, except we don't block if there is no room
\r
802 in the queue. Also we don't directly wake a task that was blocked on a
\r
803 queue read, instead we return a flag to say whether a context switch is
\r
804 required or not (i.e. has a task with a higher priority than us been woken
\r
806 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
808 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
810 traceQUEUE_SEND_FROM_ISR( pxQueue );
\r
812 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
814 /* If the queue is locked we do not alter the event list. This will
\r
815 be done when the queue is unlocked later. */
\r
816 if( pxQueue->xTxLock == queueUNLOCKED )
\r
818 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
820 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
822 /* The task waiting has a higher priority so record that a
\r
823 context switch is required. */
\r
824 *pxHigherPriorityTaskWoken = pdTRUE;
\r
830 /* Increment the lock count so the task that unlocks the queue
\r
831 knows that data was posted while it was locked. */
\r
832 ++( pxQueue->xTxLock );
\r
839 traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
\r
840 xReturn = errQUEUE_FULL;
\r
843 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
847 /*-----------------------------------------------------------*/
\r
849 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
\r
851 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
852 xTimeOutType xTimeOut;
\r
853 signed char *pcOriginalReadPosition;
\r
855 configASSERT( pxQueue );
\r
856 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
858 /* This function relaxes the coding standard somewhat to allow return
\r
859 statements within the function itself. This is done in the interest
\r
860 of execution time efficiency. */
\r
864 taskENTER_CRITICAL();
\r
866 /* Is there data in the queue now? To be running we must be
\r
867 the highest priority task wanting to access the queue. */
\r
868 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
870 /* Remember our read position in case we are just peeking. */
\r
871 pcOriginalReadPosition = pxQueue->pcReadFrom;
\r
873 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
875 if( xJustPeeking == pdFALSE )
\r
877 traceQUEUE_RECEIVE( pxQueue );
\r
879 /* We are actually removing data. */
\r
880 --( pxQueue->uxMessagesWaiting );
\r
882 #if ( configUSE_MUTEXES == 1 )
\r
884 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
886 /* Record the information required to implement
\r
887 priority inheritance should it become necessary. */
\r
888 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
\r
893 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
895 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
897 portYIELD_WITHIN_API();
\r
903 traceQUEUE_PEEK( pxQueue );
\r
905 /* We are not removing the data, so reset our read
\r
907 pxQueue->pcReadFrom = pcOriginalReadPosition;
\r
909 /* The data is being left in the queue, so see if there are
\r
910 any other tasks waiting for the data. */
\r
911 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
913 /* Tasks that are removed from the event list will get added to
\r
914 the pending ready list as the scheduler is still suspended. */
\r
915 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
917 /* The task waiting has a higher priority than this task. */
\r
918 portYIELD_WITHIN_API();
\r
924 taskEXIT_CRITICAL();
\r
929 if( xTicksToWait == ( portTickType ) 0 )
\r
931 /* The queue was empty and no block time is specified (or
\r
932 the block time has expired) so leave now. */
\r
933 taskEXIT_CRITICAL();
\r
934 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
935 return errQUEUE_EMPTY;
\r
937 else if( xEntryTimeSet == pdFALSE )
\r
939 /* The queue was empty and a block time was specified so
\r
940 configure the timeout structure. */
\r
941 vTaskSetTimeOutState( &xTimeOut );
\r
942 xEntryTimeSet = pdTRUE;
\r
946 taskEXIT_CRITICAL();
\r
948 /* Interrupts and other tasks can send to and receive from the queue
\r
949 now the critical section has been exited. */
\r
952 prvLockQueue( pxQueue );
\r
954 /* Update the timeout state to see if it has expired yet. */
\r
955 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
957 if( prvIsQueueEmpty( pxQueue ) )
\r
959 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
\r
961 #if ( configUSE_MUTEXES == 1 )
\r
963 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
965 portENTER_CRITICAL();
\r
967 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
\r
969 portEXIT_CRITICAL();
\r
974 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
975 prvUnlockQueue( pxQueue );
\r
976 if( !xTaskResumeAll() )
\r
978 portYIELD_WITHIN_API();
\r
984 prvUnlockQueue( pxQueue );
\r
985 ( void ) xTaskResumeAll();
\r
990 prvUnlockQueue( pxQueue );
\r
991 ( void ) xTaskResumeAll();
\r
992 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
993 return errQUEUE_EMPTY;
\r
997 /*-----------------------------------------------------------*/
\r
999 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )
\r
1001 signed portBASE_TYPE xReturn;
\r
1002 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
1004 configASSERT( pxQueue );
\r
1005 configASSERT( pxTaskWoken );
\r
1006 configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
\r
1008 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1010 /* We cannot block from an ISR, so check there is data available. */
\r
1011 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1013 traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
\r
1015 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
1016 --( pxQueue->uxMessagesWaiting );
\r
1018 /* If the queue is locked we will not modify the event list. Instead
\r
1019 we update the lock count so the task that unlocks the queue will know
\r
1020 that an ISR has removed data while the queue was locked. */
\r
1021 if( pxQueue->xRxLock == queueUNLOCKED )
\r
1023 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1025 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1027 /* The task waiting has a higher priority than us so
\r
1028 force a context switch. */
\r
1029 *pxTaskWoken = pdTRUE;
\r
1035 /* Increment the lock count so the task that unlocks the queue
\r
1036 knows that data was removed while it was locked. */
\r
1037 ++( pxQueue->xRxLock );
\r
1045 traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
\r
1048 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1052 /*-----------------------------------------------------------*/
\r
1054 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue )
\r
1056 unsigned portBASE_TYPE uxReturn;
\r
1058 configASSERT( pxQueue );
\r
1060 taskENTER_CRITICAL();
\r
1061 uxReturn = pxQueue->uxMessagesWaiting;
\r
1062 taskEXIT_CRITICAL();
\r
1066 /*-----------------------------------------------------------*/
\r
1068 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue )
\r
1070 unsigned portBASE_TYPE uxReturn;
\r
1072 configASSERT( pxQueue );
\r
1074 uxReturn = pxQueue->uxMessagesWaiting;
\r
1078 /*-----------------------------------------------------------*/
\r
1080 void vQueueDelete( xQueueHandle pxQueue )
\r
1082 configASSERT( pxQueue );
\r
1084 traceQUEUE_DELETE( pxQueue );
\r
1085 vQueueUnregisterQueue( pxQueue );
\r
1086 vPortFree( pxQueue->pcHead );
\r
1087 vPortFree( pxQueue );
\r
1089 /*-----------------------------------------------------------*/
\r
1091 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )
\r
1093 if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )
\r
1095 #if ( configUSE_MUTEXES == 1 )
\r
1097 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
1099 /* The mutex is no longer being held. */
\r
1100 vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
\r
1101 pxQueue->pxMutexHolder = NULL;
\r
1106 else if( xPosition == queueSEND_TO_BACK )
\r
1108 memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
\r
1109 pxQueue->pcWriteTo += pxQueue->uxItemSize;
\r
1110 if( pxQueue->pcWriteTo >= pxQueue->pcTail )
\r
1112 pxQueue->pcWriteTo = pxQueue->pcHead;
\r
1117 memcpy( ( void * ) pxQueue->pcReadFrom, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
\r
1118 pxQueue->pcReadFrom -= pxQueue->uxItemSize;
\r
1119 if( pxQueue->pcReadFrom < pxQueue->pcHead )
\r
1121 pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
\r
1125 ++( pxQueue->uxMessagesWaiting );
\r
1127 /*-----------------------------------------------------------*/
\r
1129 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
\r
1131 if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
\r
1133 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1134 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1136 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1138 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1141 /*-----------------------------------------------------------*/
\r
1143 static void prvUnlockQueue( xQueueHandle pxQueue )
\r
1145 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
\r
1147 /* The lock counts contains the number of extra data items placed or
\r
1148 removed from the queue while the queue was locked. When a queue is
\r
1149 locked items can be added or removed, but the event lists cannot be
\r
1151 taskENTER_CRITICAL();
\r
1153 /* See if data was added to the queue while it was locked. */
\r
1154 while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )
\r
1156 /* Data was posted while the queue was locked. Are any tasks
\r
1157 blocked waiting for data to become available? */
\r
1158 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1160 /* Tasks that are removed from the event list will get added to
\r
1161 the pending ready list as the scheduler is still suspended. */
\r
1162 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1164 /* The task waiting has a higher priority so record that a
\r
1165 context switch is required. */
\r
1166 vTaskMissedYield();
\r
1169 --( pxQueue->xTxLock );
\r
1177 pxQueue->xTxLock = queueUNLOCKED;
\r
1179 taskEXIT_CRITICAL();
\r
1181 /* Do the same for the Rx lock. */
\r
1182 taskENTER_CRITICAL();
\r
1184 while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )
\r
1186 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1188 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1190 vTaskMissedYield();
\r
1193 --( pxQueue->xRxLock );
\r
1201 pxQueue->xRxLock = queueUNLOCKED;
\r
1203 taskEXIT_CRITICAL();
\r
1205 /*-----------------------------------------------------------*/
\r
1207 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue )
\r
1209 signed portBASE_TYPE xReturn;
\r
1211 taskENTER_CRITICAL();
\r
1212 xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
\r
1213 taskEXIT_CRITICAL();
\r
1217 /*-----------------------------------------------------------*/
\r
1219 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue )
\r
1221 signed portBASE_TYPE xReturn;
\r
1223 configASSERT( pxQueue );
\r
1224 xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
\r
1228 /*-----------------------------------------------------------*/
\r
1230 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue )
\r
1232 signed portBASE_TYPE xReturn;
\r
1234 taskENTER_CRITICAL();
\r
1235 xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
\r
1236 taskEXIT_CRITICAL();
\r
1240 /*-----------------------------------------------------------*/
\r
1242 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue )
\r
1244 signed portBASE_TYPE xReturn;
\r
1246 configASSERT( pxQueue );
\r
1247 xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
\r
1251 /*-----------------------------------------------------------*/
\r
1253 #if configUSE_CO_ROUTINES == 1
\r
1254 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )
\r
1256 signed portBASE_TYPE xReturn;
\r
1258 /* If the queue is already full we may have to block. A critical section
\r
1259 is required to prevent an interrupt removing something from the queue
\r
1260 between the check to see if the queue is full and blocking on the queue. */
\r
1261 portDISABLE_INTERRUPTS();
\r
1263 if( prvIsQueueFull( pxQueue ) )
\r
1265 /* The queue is full - do we want to block or just leave without
\r
1267 if( xTicksToWait > ( portTickType ) 0 )
\r
1269 /* As this is called from a coroutine we cannot block directly, but
\r
1270 return indicating that we need to block. */
\r
1271 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
\r
1272 portENABLE_INTERRUPTS();
\r
1273 return errQUEUE_BLOCKED;
\r
1277 portENABLE_INTERRUPTS();
\r
1278 return errQUEUE_FULL;
\r
1282 portENABLE_INTERRUPTS();
\r
1286 portDISABLE_INTERRUPTS();
\r
1288 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
1290 /* There is room in the queue, copy the data into the queue. */
\r
1291 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
\r
1294 /* Were any co-routines waiting for data to become available? */
\r
1295 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1297 /* In this instance the co-routine could be placed directly
\r
1298 into the ready list as we are within a critical section.
\r
1299 Instead the same pending ready list mechanism is used as if
\r
1300 the event were caused from within an interrupt. */
\r
1301 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1303 /* The co-routine waiting has a higher priority so record
\r
1304 that a yield might be appropriate. */
\r
1305 xReturn = errQUEUE_YIELD;
\r
1311 xReturn = errQUEUE_FULL;
\r
1314 portENABLE_INTERRUPTS();
\r
1319 /*-----------------------------------------------------------*/
\r
1321 #if configUSE_CO_ROUTINES == 1
\r
1322 signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )
\r
1324 signed portBASE_TYPE xReturn;
\r
1326 /* If the queue is already empty we may have to block. A critical section
\r
1327 is required to prevent an interrupt adding something to the queue
\r
1328 between the check to see if the queue is empty and blocking on the queue. */
\r
1329 portDISABLE_INTERRUPTS();
\r
1331 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
\r
1333 /* There are no messages in the queue, do we want to block or just
\r
1334 leave with nothing? */
\r
1335 if( xTicksToWait > ( portTickType ) 0 )
\r
1337 /* As this is a co-routine we cannot block directly, but return
\r
1338 indicating that we need to block. */
\r
1339 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
\r
1340 portENABLE_INTERRUPTS();
\r
1341 return errQUEUE_BLOCKED;
\r
1345 portENABLE_INTERRUPTS();
\r
1346 return errQUEUE_FULL;
\r
1350 portENABLE_INTERRUPTS();
\r
1354 portDISABLE_INTERRUPTS();
\r
1356 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1358 /* Data is available from the queue. */
\r
1359 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1360 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1362 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1364 --( pxQueue->uxMessagesWaiting );
\r
1365 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1369 /* Were any co-routines waiting for space to become available? */
\r
1370 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1372 /* In this instance the co-routine could be placed directly
\r
1373 into the ready list as we are within a critical section.
\r
1374 Instead the same pending ready list mechanism is used as if
\r
1375 the event were caused from within an interrupt. */
\r
1376 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1378 xReturn = errQUEUE_YIELD;
\r
1387 portENABLE_INTERRUPTS();
\r
1392 /*-----------------------------------------------------------*/
\r
1396 #if configUSE_CO_ROUTINES == 1
\r
1397 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
\r
1399 /* Cannot block within an ISR so if there is no space on the queue then
\r
1400 exit without doing anything. */
\r
1401 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
1403 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
\r
1405 /* We only want to wake one co-routine per ISR, so check that a
\r
1406 co-routine has not already been woken. */
\r
1407 if( !xCoRoutinePreviouslyWoken )
\r
1409 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
1411 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1419 return xCoRoutinePreviouslyWoken;
\r
1422 /*-----------------------------------------------------------*/
\r
1424 #if configUSE_CO_ROUTINES == 1
\r
1425 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )
\r
1427 signed portBASE_TYPE xReturn;
\r
1429 /* We cannot block from an ISR, so check there is data available. If
\r
1430 not then just leave without doing anything. */
\r
1431 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1433 /* Copy the data from the queue. */
\r
1434 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1435 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1437 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1439 --( pxQueue->uxMessagesWaiting );
\r
1440 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1442 if( !( *pxCoRoutineWoken ) )
\r
1444 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
1446 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1448 *pxCoRoutineWoken = pdTRUE;
\r
1463 /*-----------------------------------------------------------*/
\r
1465 #if configQUEUE_REGISTRY_SIZE > 0
\r
1467 void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )
\r
1469 unsigned portBASE_TYPE ux;
\r
1471 /* See if there is an empty space in the registry. A NULL name denotes
\r
1473 for( ux = ( unsigned portBASE_TYPE ) 0U; ux < configQUEUE_REGISTRY_SIZE; ux++ )
\r
1475 if( xQueueRegistry[ ux ].pcQueueName == NULL )
\r
1477 /* Store the information on this queue. */
\r
1478 xQueueRegistry[ ux ].pcQueueName = pcQueueName;
\r
1479 xQueueRegistry[ ux ].xHandle = xQueue;
\r
1486 /*-----------------------------------------------------------*/
\r
1488 #if configQUEUE_REGISTRY_SIZE > 0
\r
1490 static void vQueueUnregisterQueue( xQueueHandle xQueue )
\r
1492 unsigned portBASE_TYPE ux;
\r
1494 /* See if the handle of the queue being unregistered in actually in the
\r
1496 for( ux = ( unsigned portBASE_TYPE ) 0U; ux < configQUEUE_REGISTRY_SIZE; ux++ )
\r
1498 if( xQueueRegistry[ ux ].xHandle == xQueue )
\r
1500 /* Set the name to NULL to show that this slot if free again. */
\r
1501 xQueueRegistry[ ux ].pcQueueName = NULL;
\r
1509 /*-----------------------------------------------------------*/
\r
1511 #if configUSE_TIMERS == 1
\r
1513 void vQueueWaitForMessageRestricted( xQueueHandle pxQueue, portTickType xTicksToWait )
\r
1515 /* This function should not be called by application code hence the
\r
1516 'Restricted' in its name. It is not part of the public API. It is
\r
1517 designed for use by kernel code, and has special calling requirements.
\r
1518 It can result in vListInsert() being called on a list that can only
\r
1519 possibly ever have one item in it, so the list will be fast, but even
\r
1520 so it should be called with the scheduler locked and not from a critical
\r
1523 /* Only do anything if there are no messages in the queue. This function
\r
1524 will not actually cause the task to block, just place it on a blocked
\r
1525 list. It will not block until the scheduler is unlocked - at which
\r
1526 time a yield will be performed. If an item is added to the queue while
\r
1527 the queue is locked, and the calling task blocks on the queue, then the
\r
1528 calling task will be immediately unblocked when the queue is unlocked. */
\r
1529 prvLockQueue( pxQueue );
\r
1530 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U )
\r
1532 /* There is nothing in the queue, block for the specified period,
\r
1533 provided the period is not zero. This guards against the case
\r
1534 where the time to wake is set to zero because there are no active
\r
1535 timers, but the tick count value also happens to be zero - creating
\r
1536 a block time of zero which confuses the logic. */
\r
1537 if( 1 )//_RB_if( xTicksToWait != 0U ) //_RB_ This should not be needed as the scheduler is suspended so the tick count cannot increment.
\r
1539 vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
1542 prvUnlockQueue( pxQueue );
\r