2 FreeRTOS V5.4.2 - Copyright (C) 2009 Real Time Engineers Ltd.
\r
4 This file is part of the FreeRTOS distribution.
\r
6 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
7 the terms of the GNU General Public License (version 2) as published by the
\r
8 Free Software Foundation and modified by the FreeRTOS exception.
\r
9 **NOTE** The exception to the GPL is included to allow you to distribute a
\r
10 combined work that includes FreeRTOS without being obliged to provide the
\r
11 source code for proprietary components outside of the FreeRTOS kernel.
\r
12 Alternative commercial license and support terms are also available upon
\r
13 request. See the licensing section of http://www.FreeRTOS.org for full
\r
16 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
\r
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
\r
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
\r
21 You should have received a copy of the GNU General Public License along
\r
22 with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59
\r
23 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
\r
26 ***************************************************************************
\r
28 * Looking for a quick start? Then check out the FreeRTOS eBook! *
\r
29 * See http://www.FreeRTOS.org/Documentation for details *
\r
31 ***************************************************************************
\r
35 Please ensure to read the configuration and relevant port sections of the
\r
36 online documentation.
\r
38 http://www.FreeRTOS.org - Documentation, latest information, license and
\r
41 http://www.SafeRTOS.com - A version that is certified for use in safety
\r
44 http://www.OpenRTOS.com - Commercial support, development, porting,
\r
45 licensing and training services.
\r
51 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
\r
52 all the API functions to use the MPU wrappers. That should only be done when
\r
53 task.h is included from an application file. */
\r
54 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
56 #include "FreeRTOS.h"
\r
58 #include "croutine.h"
\r
60 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
62 /*-----------------------------------------------------------
\r
63 * PUBLIC LIST API documented in list.h
\r
64 *----------------------------------------------------------*/
\r
66 /* Constants used with the cRxLock and cTxLock structure members. */
\r
67 #define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 )
\r
68 #define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 )
\r
70 #define queueERRONEOUS_UNBLOCK ( -1 )
\r
72 /* For internal use only. */
\r
73 #define queueSEND_TO_BACK ( 0 )
\r
74 #define queueSEND_TO_FRONT ( 1 )
\r
76 /* Effectively make a union out of the xQUEUE structure. */
\r
77 #define pxMutexHolder pcTail
\r
78 #define uxQueueType pcHead
\r
79 #define uxRecursiveCallCount pcReadFrom
\r
80 #define queueQUEUE_IS_MUTEX NULL
\r
82 /* Semaphores do not actually store or copy data, so have an items size of
\r
84 #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( 0 )
\r
85 #define queueDONT_BLOCK ( ( portTickType ) 0 )
\r
86 #define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0 )
\r
89 * Definition of the queue used by the scheduler.
\r
90 * Items are queued by copy, not reference.
\r
92 typedef struct QueueDefinition
\r
94 signed portCHAR *pcHead; /*< Points to the beginning of the queue storage area. */
\r
95 signed portCHAR *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
97 signed portCHAR *pcWriteTo; /*< Points to the free next place in the storage area. */
\r
98 signed portCHAR *pcReadFrom; /*< Points to the last place that a queued item was read from. */
\r
100 xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */
\r
101 xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */
\r
103 volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */
\r
104 unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
\r
105 unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */
\r
107 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
108 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
111 /*-----------------------------------------------------------*/
\r
114 * Inside this file xQueueHandle is a pointer to a xQUEUE structure.
\r
115 * To keep the definition private the API header file defines it as a
\r
118 typedef xQUEUE * xQueueHandle;
\r
121 * Prototypes for public functions are included here so we don't have to
\r
122 * include the API header file (as it defines xQueueHandle differently). These
\r
123 * functions are documented in the API header file.
\r
125 xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ) PRIVILEGED_FUNCTION;
\r
126 signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
\r
127 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
128 void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
\r
129 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
\r
130 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;
\r
131 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;
\r
132 xQueueHandle xQueueCreateMutex( void ) PRIVILEGED_FUNCTION;
\r
133 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) PRIVILEGED_FUNCTION;
\r
134 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) PRIVILEGED_FUNCTION;
\r
135 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ) PRIVILEGED_FUNCTION;
\r
136 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
\r
137 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;
\r
138 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
139 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
140 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
143 * Co-routine queue functions differ from task queue functions. Co-routines are
\r
144 * an optional component.
\r
146 #if configUSE_CO_ROUTINES == 1
\r
147 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) PRIVILEGED_FUNCTION;
\r
148 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;
\r
149 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
\r
150 signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
\r
154 * The queue registry is just a means for kernel aware debuggers to locate
\r
155 * queue structures. It has no other purpose so is an optional component.
\r
157 #if configQUEUE_REGISTRY_SIZE > 0
\r
159 /* The type stored within the queue registry array. This allows a name
\r
160 to be assigned to each queue making kernel aware debugging a little
\r
161 more user friendly. */
\r
162 typedef struct QUEUE_REGISTRY_ITEM
\r
164 signed portCHAR *pcQueueName;
\r
165 xQueueHandle xHandle;
\r
166 } xQueueRegistryItem;
\r
168 /* The queue registry is simply an array of xQueueRegistryItem structures.
\r
169 The pcQueueName member of a structure being NULL is indicative of the
\r
170 array position being vacant. */
\r
171 xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
\r
173 /* Removes a queue from the registry by simply setting the pcQueueName
\r
175 static void vQueueUnregisterQueue( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
\r
176 void vQueueAddToRegistry( xQueueHandle xQueue, signed portCHAR *pcQueueName ) PRIVILEGED_FUNCTION;
\r
180 * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not
\r
181 * prevent an ISR from adding or removing items to the queue, but does prevent
\r
182 * an ISR from removing tasks from the queue event lists. If an ISR finds a
\r
183 * queue is locked it will instead increment the appropriate queue lock count
\r
184 * to indicate that a task may require unblocking. When the queue in unlocked
\r
185 * these lock counts are inspected, and the appropriate action taken.
\r
187 static void prvUnlockQueue( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
190 * Uses a critical section to determine if there is any data in a queue.
\r
192 * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
\r
194 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
197 * Uses a critical section to determine if there is any space in a queue.
\r
199 * @return pdTRUE if there is no space, otherwise pdFALSE;
\r
201 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
\r
204 * Copies an item into the queue, either at the front of the queue or the
\r
205 * back of the queue.
\r
207 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION;
\r
210 * Copies an item out of a queue.
\r
212 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer ) PRIVILEGED_FUNCTION;
\r
213 /*-----------------------------------------------------------*/
\r
216 * Macro to mark a queue as locked. Locking a queue prevents an ISR from
\r
217 * accessing the queue event lists.
\r
219 #define prvLockQueue( pxQueue ) \
\r
221 taskENTER_CRITICAL(); \
\r
223 if( pxQueue->xRxLock == queueUNLOCKED ) \
\r
225 pxQueue->xRxLock = queueLOCKED_UNMODIFIED; \
\r
227 if( pxQueue->xTxLock == queueUNLOCKED ) \
\r
229 pxQueue->xTxLock = queueLOCKED_UNMODIFIED; \
\r
232 taskEXIT_CRITICAL(); \
\r
234 /*-----------------------------------------------------------*/
\r
237 /*-----------------------------------------------------------
\r
238 * PUBLIC QUEUE MANAGEMENT API documented in queue.h
\r
239 *----------------------------------------------------------*/
\r
241 xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize )
\r
243 xQUEUE *pxNewQueue;
\r
244 size_t xQueueSizeInBytes;
\r
246 /* Allocate the new queue structure. */
\r
247 if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )
\r
249 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
\r
250 if( pxNewQueue != NULL )
\r
252 /* Create the list of pointers to queue items. The queue is one byte
\r
253 longer than asked for to make wrap checking easier/faster. */
\r
254 xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1;
\r
256 pxNewQueue->pcHead = ( signed portCHAR * ) pvPortMalloc( xQueueSizeInBytes );
\r
257 if( pxNewQueue->pcHead != NULL )
\r
259 /* Initialise the queue members as described above where the
\r
260 queue type is defined. */
\r
261 pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize );
\r
262 pxNewQueue->uxMessagesWaiting = 0;
\r
263 pxNewQueue->pcWriteTo = pxNewQueue->pcHead;
\r
264 pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - 1 ) * uxItemSize );
\r
265 pxNewQueue->uxLength = uxQueueLength;
\r
266 pxNewQueue->uxItemSize = uxItemSize;
\r
267 pxNewQueue->xRxLock = queueUNLOCKED;
\r
268 pxNewQueue->xTxLock = queueUNLOCKED;
\r
270 /* Likewise ensure the event queues start with the correct state. */
\r
271 vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
\r
272 vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
\r
274 traceQUEUE_CREATE( pxNewQueue );
\r
279 traceQUEUE_CREATE_FAILED();
\r
280 vPortFree( pxNewQueue );
\r
285 /* Will only reach here if we could not allocate enough memory or no memory
\r
289 /*-----------------------------------------------------------*/
\r
291 #if ( configUSE_MUTEXES == 1 )
\r
293 xQueueHandle xQueueCreateMutex( void )
\r
295 xQUEUE *pxNewQueue;
\r
297 /* Allocate the new queue structure. */
\r
298 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
\r
299 if( pxNewQueue != NULL )
\r
301 /* Information required for priority inheritance. */
\r
302 pxNewQueue->pxMutexHolder = NULL;
\r
303 pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
\r
305 /* Queues used as a mutex no data is actually copied into or out
\r
307 pxNewQueue->pcWriteTo = NULL;
\r
308 pxNewQueue->pcReadFrom = NULL;
\r
310 /* Each mutex has a length of 1 (like a binary semaphore) and
\r
311 an item size of 0 as nothing is actually copied into or out
\r
313 pxNewQueue->uxMessagesWaiting = 0;
\r
314 pxNewQueue->uxLength = 1;
\r
315 pxNewQueue->uxItemSize = 0;
\r
316 pxNewQueue->xRxLock = queueUNLOCKED;
\r
317 pxNewQueue->xTxLock = queueUNLOCKED;
\r
319 /* Ensure the event queues start with the correct state. */
\r
320 vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
\r
321 vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
\r
323 /* Start with the semaphore in the expected state. */
\r
324 xQueueGenericSend( pxNewQueue, NULL, 0, queueSEND_TO_BACK );
\r
326 traceCREATE_MUTEX( pxNewQueue );
\r
330 traceCREATE_MUTEX_FAILED();
\r
336 #endif /* configUSE_MUTEXES */
\r
337 /*-----------------------------------------------------------*/
\r
339 #if configUSE_RECURSIVE_MUTEXES == 1
\r
341 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex )
\r
343 portBASE_TYPE xReturn;
\r
345 /* If this is the task that holds the mutex then pxMutexHolder will not
\r
346 change outside of this task. If this task does not hold the mutex then
\r
347 pxMutexHolder can never coincidentally equal the tasks handle, and as
\r
348 this is the only condition we are interested in it does not matter if
\r
349 pxMutexHolder is accessed simultaneously by another task. Therefore no
\r
350 mutual exclusion is required to test the pxMutexHolder variable. */
\r
351 if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
\r
353 traceGIVE_MUTEX_RECURSIVE( pxMutex );
\r
355 /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to
\r
356 the task handle, therefore no underflow check is required. Also,
\r
357 uxRecursiveCallCount is only modified by the mutex holder, and as
\r
358 there can only be one, no mutual exclusion is required to modify the
\r
359 uxRecursiveCallCount member. */
\r
360 ( pxMutex->uxRecursiveCallCount )--;
\r
362 /* Have we unwound the call count? */
\r
363 if( pxMutex->uxRecursiveCallCount == 0 )
\r
365 /* Return the mutex. This will automatically unblock any other
\r
366 task that might be waiting to access the mutex. */
\r
367 xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
\r
374 /* We cannot give the mutex because we are not the holder. */
\r
377 traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
\r
383 #endif /* configUSE_RECURSIVE_MUTEXES */
\r
384 /*-----------------------------------------------------------*/
\r
386 #if configUSE_RECURSIVE_MUTEXES == 1
\r
388 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime )
\r
390 portBASE_TYPE xReturn;
\r
392 /* Comments regarding mutual exclusion as per those within
\r
393 xQueueGiveMutexRecursive(). */
\r
395 traceTAKE_MUTEX_RECURSIVE( pxMutex );
\r
397 if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
\r
399 ( pxMutex->uxRecursiveCallCount )++;
\r
404 xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );
\r
406 /* pdPASS will only be returned if we successfully obtained the mutex,
\r
407 we may have blocked to reach here. */
\r
408 if( xReturn == pdPASS )
\r
410 ( pxMutex->uxRecursiveCallCount )++;
\r
417 #endif /* configUSE_RECURSIVE_MUTEXES */
\r
418 /*-----------------------------------------------------------*/
\r
420 #if configUSE_COUNTING_SEMAPHORES == 1
\r
422 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount )
\r
424 xQueueHandle pxHandle;
\r
426 pxHandle = xQueueCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH );
\r
428 if( pxHandle != NULL )
\r
430 pxHandle->uxMessagesWaiting = uxInitialCount;
\r
432 traceCREATE_COUNTING_SEMAPHORE();
\r
436 traceCREATE_COUNTING_SEMAPHORE_FAILED();
\r
442 #endif /* configUSE_COUNTING_SEMAPHORES */
\r
443 /*-----------------------------------------------------------*/
\r
445 signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
\r
447 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
448 xTimeOutType xTimeOut;
\r
450 /* This function relaxes the coding standard somewhat to allow return
\r
451 statements within the function itself. This is done in the interest
\r
452 of execution time efficiency. */
\r
455 taskENTER_CRITICAL();
\r
457 /* Is there room on the queue now? To be running we must be
\r
458 the highest priority task wanting to access the queue. */
\r
459 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
461 traceQUEUE_SEND( pxQueue );
\r
462 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
464 /* If there was a task waiting for data to arrive on the
\r
465 queue then unblock it now. */
\r
466 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
468 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
470 /* The unblocked task has a priority higher than
\r
471 our own so yield immediately. Yes it is ok to do
\r
472 this from within the critical section - the kernel
\r
473 takes care of that. */
\r
474 portYIELD_WITHIN_API();
\r
478 taskEXIT_CRITICAL();
\r
480 /* Return to the original privilege level before exiting the
\r
486 if( xTicksToWait == ( portTickType ) 0 )
\r
488 /* The queue was full and no block time is specified (or
\r
489 the block time has expired) so leave now. */
\r
490 taskEXIT_CRITICAL();
\r
492 /* Return to the original privilege level before exiting
\r
494 traceQUEUE_SEND_FAILED( pxQueue );
\r
495 return errQUEUE_FULL;
\r
497 else if( xEntryTimeSet == pdFALSE )
\r
499 /* The queue was full and a block time was specified so
\r
500 configure the timeout structure. */
\r
501 vTaskSetTimeOutState( &xTimeOut );
\r
502 xEntryTimeSet = pdTRUE;
\r
506 taskEXIT_CRITICAL();
\r
508 /* Interrupts and other tasks can send to and receive from the queue
\r
509 now the critical section has been exited. */
\r
512 prvLockQueue( pxQueue );
\r
514 /* Update the timeout state to see if it has expired yet. */
\r
515 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
517 if( prvIsQueueFull( pxQueue ) )
\r
519 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
\r
520 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
\r
522 /* Unlocking the queue means queue events can effect the
\r
523 event list. It is possible that interrupts occurring now
\r
524 remove this task from the event list again - but as the
\r
525 scheduler is suspended the task will go onto the pending
\r
526 ready last instead of the actual ready list. */
\r
527 prvUnlockQueue( pxQueue );
\r
529 /* Resuming the scheduler will move tasks from the pending
\r
530 ready list into the ready list - so it is feasible that this
\r
531 task is already in a ready list before it yields - in which
\r
532 case the yield will not cause a context switch unless there
\r
533 is also a higher priority task in the pending ready list. */
\r
534 if( !xTaskResumeAll() )
\r
536 portYIELD_WITHIN_API();
\r
542 prvUnlockQueue( pxQueue );
\r
543 ( void ) xTaskResumeAll();
\r
548 /* The timeout has expired. */
\r
549 prvUnlockQueue( pxQueue );
\r
550 ( void ) xTaskResumeAll();
\r
552 /* Return to the original privilege level before exiting the
\r
554 traceQUEUE_SEND_FAILED( pxQueue );
\r
555 return errQUEUE_FULL;
\r
559 /*-----------------------------------------------------------*/
\r
561 #if configUSE_ALTERNATIVE_API == 1
\r
563 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
\r
565 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
566 xTimeOutType xTimeOut;
\r
570 taskENTER_CRITICAL();
\r
572 /* Is there room on the queue now? To be running we must be
\r
573 the highest priority task wanting to access the queue. */
\r
574 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
576 traceQUEUE_SEND( pxQueue );
\r
577 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
579 /* If there was a task waiting for data to arrive on the
\r
580 queue then unblock it now. */
\r
581 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
583 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
585 /* The unblocked task has a priority higher than
\r
586 our own so yield immediately. */
\r
587 portYIELD_WITHIN_API();
\r
591 taskEXIT_CRITICAL();
\r
596 if( xTicksToWait == ( portTickType ) 0 )
\r
598 taskEXIT_CRITICAL();
\r
599 return errQUEUE_FULL;
\r
601 else if( xEntryTimeSet == pdFALSE )
\r
603 vTaskSetTimeOutState( &xTimeOut );
\r
604 xEntryTimeSet = pdTRUE;
\r
608 taskEXIT_CRITICAL();
\r
610 taskENTER_CRITICAL();
\r
612 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
614 if( prvIsQueueFull( pxQueue ) )
\r
616 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
\r
617 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
\r
618 portYIELD_WITHIN_API();
\r
623 taskEXIT_CRITICAL();
\r
624 traceQUEUE_SEND_FAILED( pxQueue );
\r
625 return errQUEUE_FULL;
\r
628 taskEXIT_CRITICAL();
\r
632 #endif /* configUSE_ALTERNATIVE_API */
\r
633 /*-----------------------------------------------------------*/
\r
635 #if configUSE_ALTERNATIVE_API == 1
\r
637 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
\r
639 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
640 xTimeOutType xTimeOut;
\r
641 signed portCHAR *pcOriginalReadPosition;
\r
645 taskENTER_CRITICAL();
\r
647 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
649 /* Remember our read position in case we are just peeking. */
\r
650 pcOriginalReadPosition = pxQueue->pcReadFrom;
\r
652 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
654 if( xJustPeeking == pdFALSE )
\r
656 traceQUEUE_RECEIVE( pxQueue );
\r
658 /* We are actually removing data. */
\r
659 --( pxQueue->uxMessagesWaiting );
\r
661 #if ( configUSE_MUTEXES == 1 )
\r
663 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
665 /* Record the information required to implement
\r
666 priority inheritance should it become necessary. */
\r
667 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
\r
672 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
674 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
676 portYIELD_WITHIN_API();
\r
682 traceQUEUE_PEEK( pxQueue );
\r
684 /* We are not removing the data, so reset our read
\r
686 pxQueue->pcReadFrom = pcOriginalReadPosition;
\r
688 /* The data is being left in the queue, so see if there are
\r
689 any other tasks waiting for the data. */
\r
690 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
\r
692 /* Tasks that are removed from the event list will get added to
\r
693 the pending ready list as the scheduler is still suspended. */
\r
694 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
696 /* The task waiting has a higher priority than this task. */
\r
697 portYIELD_WITHIN_API();
\r
703 taskEXIT_CRITICAL();
\r
708 if( xTicksToWait == ( portTickType ) 0 )
\r
710 taskEXIT_CRITICAL();
\r
711 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
712 return errQUEUE_EMPTY;
\r
714 else if( xEntryTimeSet == pdFALSE )
\r
716 vTaskSetTimeOutState( &xTimeOut );
\r
717 xEntryTimeSet = pdTRUE;
\r
721 taskEXIT_CRITICAL();
\r
723 taskENTER_CRITICAL();
\r
725 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
727 if( prvIsQueueEmpty( pxQueue ) )
\r
729 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
\r
731 #if ( configUSE_MUTEXES == 1 )
\r
733 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
735 portENTER_CRITICAL();
\r
736 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
\r
737 portEXIT_CRITICAL();
\r
742 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
743 portYIELD_WITHIN_API();
\r
748 taskEXIT_CRITICAL();
\r
749 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
750 return errQUEUE_EMPTY;
\r
753 taskEXIT_CRITICAL();
\r
758 #endif /* configUSE_ALTERNATIVE_API */
\r
759 /*-----------------------------------------------------------*/
\r
761 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )
\r
763 signed portBASE_TYPE xReturn;
\r
764 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
766 /* Similar to xQueueGenericSend, except we don't block if there is no room
\r
767 in the queue. Also we don't directly wake a task that was blocked on a
\r
768 queue read, instead we return a flag to say whether a context switch is
\r
769 required or not (i.e. has a task with a higher priority than us been woken
\r
771 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
773 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
775 traceQUEUE_SEND_FROM_ISR( pxQueue );
\r
777 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
779 /* If the queue is locked we do not alter the event list. This will
\r
780 be done when the queue is unlocked later. */
\r
781 if( pxQueue->xTxLock == queueUNLOCKED )
\r
783 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
\r
785 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
787 /* The task waiting has a higher priority so record that a
\r
788 context switch is required. */
\r
789 *pxHigherPriorityTaskWoken = pdTRUE;
\r
795 /* Increment the lock count so the task that unlocks the queue
\r
796 knows that data was posted while it was locked. */
\r
797 ++( pxQueue->xTxLock );
\r
804 traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
\r
805 xReturn = errQUEUE_FULL;
\r
808 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
812 /*-----------------------------------------------------------*/
\r
814 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
\r
816 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
817 xTimeOutType xTimeOut;
\r
818 signed portCHAR *pcOriginalReadPosition;
\r
820 /* This function relaxes the coding standard somewhat to allow return
\r
821 statements within the function itself. This is done in the interest
\r
822 of execution time efficiency. */
\r
826 taskENTER_CRITICAL();
\r
828 /* Is there data in the queue now? To be running we must be
\r
829 the highest priority task wanting to access the queue. */
\r
830 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
832 /* Remember our read position in case we are just peeking. */
\r
833 pcOriginalReadPosition = pxQueue->pcReadFrom;
\r
835 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
837 if( xJustPeeking == pdFALSE )
\r
839 traceQUEUE_RECEIVE( pxQueue );
\r
841 /* We are actually removing data. */
\r
842 --( pxQueue->uxMessagesWaiting );
\r
844 #if ( configUSE_MUTEXES == 1 )
\r
846 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
848 /* Record the information required to implement
\r
849 priority inheritance should it become necessary. */
\r
850 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
\r
855 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
857 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
859 portYIELD_WITHIN_API();
\r
865 traceQUEUE_PEEK( pxQueue );
\r
867 /* We are not removing the data, so reset our read
\r
869 pxQueue->pcReadFrom = pcOriginalReadPosition;
\r
871 /* The data is being left in the queue, so see if there are
\r
872 any other tasks waiting for the data. */
\r
873 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
\r
875 /* Tasks that are removed from the event list will get added to
\r
876 the pending ready list as the scheduler is still suspended. */
\r
877 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
879 /* The task waiting has a higher priority than this task. */
\r
880 portYIELD_WITHIN_API();
\r
886 taskEXIT_CRITICAL();
\r
891 if( xTicksToWait == ( portTickType ) 0 )
\r
893 /* The queue was empty and no block time is specified (or
\r
894 the block time has expired) so leave now. */
\r
895 taskEXIT_CRITICAL();
\r
896 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
897 return errQUEUE_EMPTY;
\r
899 else if( xEntryTimeSet == pdFALSE )
\r
901 /* The queue was empty and a block time was specified so
\r
902 configure the timeout structure. */
\r
903 vTaskSetTimeOutState( &xTimeOut );
\r
904 xEntryTimeSet = pdTRUE;
\r
908 taskEXIT_CRITICAL();
\r
910 /* Interrupts and other tasks can send to and receive from the queue
\r
911 now the critical section has been exited. */
\r
914 prvLockQueue( pxQueue );
\r
916 /* Update the timeout state to see if it has expired yet. */
\r
917 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
919 if( prvIsQueueEmpty( pxQueue ) )
\r
921 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
\r
923 #if ( configUSE_MUTEXES == 1 )
\r
925 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
927 portENTER_CRITICAL();
\r
929 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
\r
931 portEXIT_CRITICAL();
\r
936 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
937 prvUnlockQueue( pxQueue );
\r
938 if( !xTaskResumeAll() )
\r
940 portYIELD_WITHIN_API();
\r
946 prvUnlockQueue( pxQueue );
\r
947 ( void ) xTaskResumeAll();
\r
952 prvUnlockQueue( pxQueue );
\r
953 ( void ) xTaskResumeAll();
\r
954 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
955 return errQUEUE_EMPTY;
\r
959 /*-----------------------------------------------------------*/
\r
961 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )
\r
963 signed portBASE_TYPE xReturn;
\r
964 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
966 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
968 /* We cannot block from an ISR, so check there is data available. */
\r
969 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
971 traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
\r
973 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
974 --( pxQueue->uxMessagesWaiting );
\r
976 /* If the queue is locked we will not modify the event list. Instead
\r
977 we update the lock count so the task that unlocks the queue will know
\r
978 that an ISR has removed data while the queue was locked. */
\r
979 if( pxQueue->xRxLock == queueUNLOCKED )
\r
981 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
\r
983 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
985 /* The task waiting has a higher priority than us so
\r
986 force a context switch. */
\r
987 *pxTaskWoken = pdTRUE;
\r
993 /* Increment the lock count so the task that unlocks the queue
\r
994 knows that data was removed while it was locked. */
\r
995 ++( pxQueue->xRxLock );
\r
1003 traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
\r
1006 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1010 /*-----------------------------------------------------------*/
\r
1012 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue )
\r
1014 unsigned portBASE_TYPE uxReturn;
\r
1016 taskENTER_CRITICAL();
\r
1017 uxReturn = pxQueue->uxMessagesWaiting;
\r
1018 taskEXIT_CRITICAL();
\r
1022 /*-----------------------------------------------------------*/
\r
1024 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue )
\r
1026 unsigned portBASE_TYPE uxReturn;
\r
1028 uxReturn = pxQueue->uxMessagesWaiting;
\r
1032 /*-----------------------------------------------------------*/
\r
1034 void vQueueDelete( xQueueHandle pxQueue )
\r
1036 traceQUEUE_DELETE( pxQueue );
\r
1037 vQueueUnregisterQueue( pxQueue );
\r
1038 vPortFree( pxQueue->pcHead );
\r
1039 vPortFree( pxQueue );
\r
1041 /*-----------------------------------------------------------*/
\r
1043 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )
\r
1045 if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )
\r
1047 #if ( configUSE_MUTEXES == 1 )
\r
1049 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
1051 /* The mutex is no longer being held. */
\r
1052 vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
\r
1053 pxQueue->pxMutexHolder = NULL;
\r
1058 else if( xPosition == queueSEND_TO_BACK )
\r
1060 memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
\r
1061 pxQueue->pcWriteTo += pxQueue->uxItemSize;
\r
1062 if( pxQueue->pcWriteTo >= pxQueue->pcTail )
\r
1064 pxQueue->pcWriteTo = pxQueue->pcHead;
\r
1069 memcpy( ( void * ) pxQueue->pcReadFrom, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
\r
1070 pxQueue->pcReadFrom -= pxQueue->uxItemSize;
\r
1071 if( pxQueue->pcReadFrom < pxQueue->pcHead )
\r
1073 pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
\r
1077 ++( pxQueue->uxMessagesWaiting );
\r
1079 /*-----------------------------------------------------------*/
\r
1081 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
\r
1083 if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
\r
1085 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1086 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1088 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1090 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1093 /*-----------------------------------------------------------*/
\r
1095 static void prvUnlockQueue( xQueueHandle pxQueue )
\r
1097 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
\r
1099 /* The lock counts contains the number of extra data items placed or
\r
1100 removed from the queue while the queue was locked. When a queue is
\r
1101 locked items can be added or removed, but the event lists cannot be
\r
1103 taskENTER_CRITICAL();
\r
1105 /* See if data was added to the queue while it was locked. */
\r
1106 while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )
\r
1108 /* Data was posted while the queue was locked. Are any tasks
\r
1109 blocked waiting for data to become available? */
\r
1110 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
\r
1112 /* Tasks that are removed from the event list will get added to
\r
1113 the pending ready list as the scheduler is still suspended. */
\r
1114 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1116 /* The task waiting has a higher priority so record that a
\r
1117 context switch is required. */
\r
1118 vTaskMissedYield();
\r
1121 --( pxQueue->xTxLock );
\r
1129 pxQueue->xTxLock = queueUNLOCKED;
\r
1131 taskEXIT_CRITICAL();
\r
1133 /* Do the same for the Rx lock. */
\r
1134 taskENTER_CRITICAL();
\r
1136 while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )
\r
1138 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
\r
1140 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1142 vTaskMissedYield();
\r
1145 --( pxQueue->xRxLock );
\r
1153 pxQueue->xRxLock = queueUNLOCKED;
\r
1155 taskEXIT_CRITICAL();
\r
1157 /*-----------------------------------------------------------*/
\r
1159 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue )
\r
1161 signed portBASE_TYPE xReturn;
\r
1163 taskENTER_CRITICAL();
\r
1164 xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
\r
1165 taskEXIT_CRITICAL();
\r
1169 /*-----------------------------------------------------------*/
\r
1171 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue )
\r
1173 signed portBASE_TYPE xReturn;
\r
1175 xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
\r
1179 /*-----------------------------------------------------------*/
\r
1181 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue )
\r
1183 signed portBASE_TYPE xReturn;
\r
1185 taskENTER_CRITICAL();
\r
1186 xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
\r
1187 taskEXIT_CRITICAL();
\r
1191 /*-----------------------------------------------------------*/
\r
1193 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue )
\r
1195 signed portBASE_TYPE xReturn;
\r
1197 xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
\r
1201 /*-----------------------------------------------------------*/
\r
1203 #if configUSE_CO_ROUTINES == 1
\r
1204 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )
\r
1206 signed portBASE_TYPE xReturn;
\r
1208 /* If the queue is already full we may have to block. A critical section
\r
1209 is required to prevent an interrupt removing something from the queue
\r
1210 between the check to see if the queue is full and blocking on the queue. */
\r
1211 portDISABLE_INTERRUPTS();
\r
1213 if( prvIsQueueFull( pxQueue ) )
\r
1215 /* The queue is full - do we want to block or just leave without
\r
1217 if( xTicksToWait > ( portTickType ) 0 )
\r
1219 /* As this is called from a coroutine we cannot block directly, but
\r
1220 return indicating that we need to block. */
\r
1221 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
\r
1222 portENABLE_INTERRUPTS();
\r
1223 return errQUEUE_BLOCKED;
\r
1227 portENABLE_INTERRUPTS();
\r
1228 return errQUEUE_FULL;
\r
1232 portENABLE_INTERRUPTS();
\r
1236 portDISABLE_INTERRUPTS();
\r
1238 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
1240 /* There is room in the queue, copy the data into the queue. */
\r
1241 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
\r
1244 /* Were any co-routines waiting for data to become available? */
\r
1245 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
\r
1247 /* In this instance the co-routine could be placed directly
\r
1248 into the ready list as we are within a critical section.
\r
1249 Instead the same pending ready list mechanism is used as if
\r
1250 the event were caused from within an interrupt. */
\r
1251 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1253 /* The co-routine waiting has a higher priority so record
\r
1254 that a yield might be appropriate. */
\r
1255 xReturn = errQUEUE_YIELD;
\r
1261 xReturn = errQUEUE_FULL;
\r
1264 portENABLE_INTERRUPTS();
\r
1269 /*-----------------------------------------------------------*/
\r
1271 #if configUSE_CO_ROUTINES == 1
\r
1272 signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )
\r
1274 signed portBASE_TYPE xReturn;
\r
1276 /* If the queue is already empty we may have to block. A critical section
\r
1277 is required to prevent an interrupt adding something to the queue
\r
1278 between the check to see if the queue is empty and blocking on the queue. */
\r
1279 portDISABLE_INTERRUPTS();
\r
1281 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
\r
1283 /* There are no messages in the queue, do we want to block or just
\r
1284 leave with nothing? */
\r
1285 if( xTicksToWait > ( portTickType ) 0 )
\r
1287 /* As this is a co-routine we cannot block directly, but return
\r
1288 indicating that we need to block. */
\r
1289 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
\r
1290 portENABLE_INTERRUPTS();
\r
1291 return errQUEUE_BLOCKED;
\r
1295 portENABLE_INTERRUPTS();
\r
1296 return errQUEUE_FULL;
\r
1300 portENABLE_INTERRUPTS();
\r
1304 portDISABLE_INTERRUPTS();
\r
1306 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1308 /* Data is available from the queue. */
\r
1309 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1310 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1312 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1314 --( pxQueue->uxMessagesWaiting );
\r
1315 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1319 /* Were any co-routines waiting for space to become available? */
\r
1320 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
\r
1322 /* In this instance the co-routine could be placed directly
\r
1323 into the ready list as we are within a critical section.
\r
1324 Instead the same pending ready list mechanism is used as if
\r
1325 the event were caused from within an interrupt. */
\r
1326 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1328 xReturn = errQUEUE_YIELD;
\r
1337 portENABLE_INTERRUPTS();
\r
1342 /*-----------------------------------------------------------*/
\r
1346 #if configUSE_CO_ROUTINES == 1
\r
1347 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
\r
1349 /* Cannot block within an ISR so if there is no space on the queue then
\r
1350 exit without doing anything. */
\r
1351 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
1353 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
\r
1355 /* We only want to wake one co-routine per ISR, so check that a
\r
1356 co-routine has not already been woken. */
\r
1357 if( !xCoRoutinePreviouslyWoken )
\r
1359 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
\r
1361 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1369 return xCoRoutinePreviouslyWoken;
\r
1372 /*-----------------------------------------------------------*/
\r
1374 #if configUSE_CO_ROUTINES == 1
\r
1375 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )
\r
1377 signed portBASE_TYPE xReturn;
\r
1379 /* We cannot block from an ISR, so check there is data available. If
\r
1380 not then just leave without doing anything. */
\r
1381 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1383 /* Copy the data from the queue. */
\r
1384 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1385 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1387 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1389 --( pxQueue->uxMessagesWaiting );
\r
1390 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1392 if( !( *pxCoRoutineWoken ) )
\r
1394 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
\r
1396 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1398 *pxCoRoutineWoken = pdTRUE;
\r
1413 /*-----------------------------------------------------------*/
\r
1415 #if configQUEUE_REGISTRY_SIZE > 0
\r
1417 void vQueueAddToRegistry( xQueueHandle xQueue, signed portCHAR *pcQueueName )
\r
1419 unsigned portBASE_TYPE ux;
\r
1421 /* See if there is an empty space in the registry. A NULL name denotes
\r
1423 for( ux = 0; ux < configQUEUE_REGISTRY_SIZE; ux++ )
\r
1425 if( xQueueRegistry[ ux ].pcQueueName == NULL )
\r
1427 /* Store the information on this queue. */
\r
1428 xQueueRegistry[ ux ].pcQueueName = pcQueueName;
\r
1429 xQueueRegistry[ ux ].xHandle = xQueue;
\r
1436 /*-----------------------------------------------------------*/
\r
1438 #if configQUEUE_REGISTRY_SIZE > 0
\r
1440 static void vQueueUnregisterQueue( xQueueHandle xQueue )
\r
1442 unsigned portBASE_TYPE ux;
\r
1444 /* See if the handle of the queue being unregistered in actually in the
\r
1446 for( ux = 0; ux < configQUEUE_REGISTRY_SIZE; ux++ )
\r
1448 if( xQueueRegistry[ ux ].xHandle == xQueue )
\r
1450 /* Set the name to NULL to show that this slot if free again. */
\r
1451 xQueueRegistry[ ux ].pcQueueName = NULL;
\r