2 FreeRTOS V5.4.0 - Copyright (C) 2003-2009 Richard Barry.
\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
50 #include "FreeRTOS.h"
\r
52 #include "croutine.h"
\r
54 /*-----------------------------------------------------------
\r
55 * PUBLIC LIST API documented in list.h
\r
56 *----------------------------------------------------------*/
\r
58 /* Constants used with the cRxLock and cTxLock structure members. */
\r
59 #define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 )
\r
60 #define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 )
\r
62 #define queueERRONEOUS_UNBLOCK ( -1 )
\r
64 /* For internal use only. */
\r
65 #define queueSEND_TO_BACK ( 0 )
\r
66 #define queueSEND_TO_FRONT ( 1 )
\r
68 /* Effectively make a union out of the xQUEUE structure. */
\r
69 #define pxMutexHolder pcTail
\r
70 #define uxQueueType pcHead
\r
71 #define uxRecursiveCallCount pcReadFrom
\r
72 #define queueQUEUE_IS_MUTEX NULL
\r
74 /* Semaphores do not actually store or copy data, so have an items size of
\r
76 #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( 0 )
\r
77 #define queueDONT_BLOCK ( ( portTickType ) 0 )
\r
78 #define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0 )
\r
81 * Definition of the queue used by the scheduler.
\r
82 * Items are queued by copy, not reference.
\r
84 typedef struct QueueDefinition
\r
86 signed portCHAR *pcHead; /*< Points to the beginning of the queue storage area. */
\r
87 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
89 signed portCHAR *pcWriteTo; /*< Points to the free next place in the storage area. */
\r
90 signed portCHAR *pcReadFrom; /*< Points to the last place that a queued item was read from. */
\r
92 xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */
\r
93 xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */
\r
95 volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */
\r
96 unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
\r
97 unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */
\r
99 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
100 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
103 /*-----------------------------------------------------------*/
\r
106 * Inside this file xQueueHandle is a pointer to a xQUEUE structure.
\r
107 * To keep the definition private the API header file defines it as a
\r
110 typedef xQUEUE * xQueueHandle;
\r
113 * Prototypes for public functions are included here so we don't have to
\r
114 * include the API header file (as it defines xQueueHandle differently). These
\r
115 * functions are documented in the API header file.
\r
117 xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize );
\r
118 signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );
\r
119 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue );
\r
120 void vQueueDelete( xQueueHandle xQueue );
\r
121 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition );
\r
122 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );
\r
123 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken );
\r
124 xQueueHandle xQueueCreateMutex( void );
\r
125 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount );
\r
126 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime );
\r
127 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex );
\r
128 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );
\r
129 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );
\r
130 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue );
\r
131 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue );
\r
132 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue );
\r
135 * Co-routine queue functions differ from task queue functions. Co-routines are
\r
136 * an optional component.
\r
138 #if configUSE_CO_ROUTINES == 1
\r
139 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken );
\r
140 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken );
\r
141 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait );
\r
142 signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait );
\r
146 * The queue registry is just a means for kernel aware debuggers to locate
\r
147 * queue structures. It has no other purpose so is an optional component.
\r
149 #if configQUEUE_REGISTRY_SIZE > 0
\r
151 /* The type stored within the queue registry array. This allows a name
\r
152 to be assigned to each queue making kernel aware debugging a little
\r
153 more user friendly. */
\r
154 typedef struct QUEUE_REGISTRY_ITEM
\r
156 signed portCHAR *pcQueueName;
\r
157 xQueueHandle xHandle;
\r
158 } xQueueRegistryItem;
\r
160 /* The queue registry is simply an array of xQueueRegistryItem structures.
\r
161 The pcQueueName member of a structure being NULL is indicative of the
\r
162 array position being vacant. */
\r
163 xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
\r
165 /* Removes a queue from the registry by simply setting the pcQueueName
\r
167 static void vQueueUnregisterQueue( xQueueHandle xQueue );
\r
168 void vQueueAddToRegistry( xQueueHandle xQueue, signed portCHAR *pcQueueName );
\r
172 * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not
\r
173 * prevent an ISR from adding or removing items to the queue, but does prevent
\r
174 * an ISR from removing tasks from the queue event lists. If an ISR finds a
\r
175 * queue is locked it will instead increment the appropriate queue lock count
\r
176 * to indicate that a task may require unblocking. When the queue in unlocked
\r
177 * these lock counts are inspected, and the appropriate action taken.
\r
179 static void prvUnlockQueue( xQueueHandle pxQueue );
\r
182 * Uses a critical section to determine if there is any data in a queue.
\r
184 * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
\r
186 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue );
\r
189 * Uses a critical section to determine if there is any space in a queue.
\r
191 * @return pdTRUE if there is no space, otherwise pdFALSE;
\r
193 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue );
\r
196 * Copies an item into the queue, either at the front of the queue or the
\r
197 * back of the queue.
\r
199 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition );
\r
202 * Copies an item out of a queue.
\r
204 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer );
\r
205 /*-----------------------------------------------------------*/
\r
208 * Macro to mark a queue as locked. Locking a queue prevents an ISR from
\r
209 * accessing the queue event lists.
\r
211 #define prvLockQueue( pxQueue ) \
\r
213 taskENTER_CRITICAL(); \
\r
215 if( pxQueue->xRxLock == queueUNLOCKED ) \
\r
217 pxQueue->xRxLock = queueLOCKED_UNMODIFIED; \
\r
219 if( pxQueue->xTxLock == queueUNLOCKED ) \
\r
221 pxQueue->xTxLock = queueLOCKED_UNMODIFIED; \
\r
224 taskEXIT_CRITICAL(); \
\r
226 /*-----------------------------------------------------------*/
\r
229 /*-----------------------------------------------------------
\r
230 * PUBLIC QUEUE MANAGEMENT API documented in queue.h
\r
231 *----------------------------------------------------------*/
\r
233 xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize )
\r
235 xQUEUE *pxNewQueue;
\r
236 size_t xQueueSizeInBytes;
\r
238 /* Allocate the new queue structure. */
\r
239 if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )
\r
241 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
\r
242 if( pxNewQueue != NULL )
\r
244 /* Create the list of pointers to queue items. The queue is one byte
\r
245 longer than asked for to make wrap checking easier/faster. */
\r
246 xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1;
\r
248 pxNewQueue->pcHead = ( signed portCHAR * ) pvPortMalloc( xQueueSizeInBytes );
\r
249 if( pxNewQueue->pcHead != NULL )
\r
251 /* Initialise the queue members as described above where the
\r
252 queue type is defined. */
\r
253 pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize );
\r
254 pxNewQueue->uxMessagesWaiting = 0;
\r
255 pxNewQueue->pcWriteTo = pxNewQueue->pcHead;
\r
256 pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - 1 ) * uxItemSize );
\r
257 pxNewQueue->uxLength = uxQueueLength;
\r
258 pxNewQueue->uxItemSize = uxItemSize;
\r
259 pxNewQueue->xRxLock = queueUNLOCKED;
\r
260 pxNewQueue->xTxLock = queueUNLOCKED;
\r
262 /* Likewise ensure the event queues start with the correct state. */
\r
263 vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
\r
264 vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
\r
266 traceQUEUE_CREATE( pxNewQueue );
\r
272 traceQUEUE_CREATE_FAILED();
\r
273 vPortFree( pxNewQueue );
\r
278 /* Will only reach here if we could not allocate enough memory or no memory
\r
282 /*-----------------------------------------------------------*/
\r
284 #if ( configUSE_MUTEXES == 1 )
\r
286 xQueueHandle xQueueCreateMutex( void )
\r
288 xQUEUE *pxNewQueue;
\r
290 /* Allocate the new queue structure. */
\r
291 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
\r
292 if( pxNewQueue != NULL )
\r
294 /* Information required for priority inheritance. */
\r
295 pxNewQueue->pxMutexHolder = NULL;
\r
296 pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
\r
298 /* Queues used as a mutex no data is actually copied into or out
\r
300 pxNewQueue->pcWriteTo = NULL;
\r
301 pxNewQueue->pcReadFrom = NULL;
\r
303 /* Each mutex has a length of 1 (like a binary semaphore) and
\r
304 an item size of 0 as nothing is actually copied into or out
\r
306 pxNewQueue->uxMessagesWaiting = 0;
\r
307 pxNewQueue->uxLength = 1;
\r
308 pxNewQueue->uxItemSize = 0;
\r
309 pxNewQueue->xRxLock = queueUNLOCKED;
\r
310 pxNewQueue->xTxLock = queueUNLOCKED;
\r
312 /* Ensure the event queues start with the correct state. */
\r
313 vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
\r
314 vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
\r
316 /* Start with the semaphore in the expected state. */
\r
317 xQueueGenericSend( pxNewQueue, NULL, 0, queueSEND_TO_BACK );
\r
319 traceCREATE_MUTEX( pxNewQueue );
\r
323 traceCREATE_MUTEX_FAILED();
\r
329 #endif /* configUSE_MUTEXES */
\r
330 /*-----------------------------------------------------------*/
\r
332 #if configUSE_RECURSIVE_MUTEXES == 1
\r
334 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex )
\r
336 portBASE_TYPE xReturn;
\r
338 /* If this is the task that holds the mutex then pxMutexHolder will not
\r
339 change outside of this task. If this task does not hold the mutex then
\r
340 pxMutexHolder can never coincidentally equal the tasks handle, and as
\r
341 this is the only condition we are interested in it does not matter if
\r
342 pxMutexHolder is accessed simultaneously by another task. Therefore no
\r
343 mutual exclusion is required to test the pxMutexHolder variable. */
\r
344 if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
\r
346 traceGIVE_MUTEX_RECURSIVE( pxMutex );
\r
348 /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to
\r
349 the task handle, therefore no underflow check is required. Also,
\r
350 uxRecursiveCallCount is only modified by the mutex holder, and as
\r
351 there can only be one, no mutual exclusion is required to modify the
\r
352 uxRecursiveCallCount member. */
\r
353 ( pxMutex->uxRecursiveCallCount )--;
\r
355 /* Have we unwound the call count? */
\r
356 if( pxMutex->uxRecursiveCallCount == 0 )
\r
358 /* Return the mutex. This will automatically unblock any other
\r
359 task that might be waiting to access the mutex. */
\r
360 xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
\r
367 /* We cannot give the mutex because we are not the holder. */
\r
370 traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
\r
376 #endif /* configUSE_RECURSIVE_MUTEXES */
\r
377 /*-----------------------------------------------------------*/
\r
379 #if configUSE_RECURSIVE_MUTEXES == 1
\r
381 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime )
\r
383 portBASE_TYPE xReturn;
\r
385 /* Comments regarding mutual exclusion as per those within
\r
386 xQueueGiveMutexRecursive(). */
\r
388 traceTAKE_MUTEX_RECURSIVE( pxMutex );
\r
390 if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
\r
392 ( pxMutex->uxRecursiveCallCount )++;
\r
397 xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );
\r
399 /* pdPASS will only be returned if we successfully obtained the mutex,
\r
400 we may have blocked to reach here. */
\r
401 if( xReturn == pdPASS )
\r
403 ( pxMutex->uxRecursiveCallCount )++;
\r
410 #endif /* configUSE_RECURSIVE_MUTEXES */
\r
411 /*-----------------------------------------------------------*/
\r
413 #if configUSE_COUNTING_SEMAPHORES == 1
\r
415 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount )
\r
417 xQueueHandle pxHandle;
\r
419 pxHandle = xQueueCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH );
\r
421 if( pxHandle != NULL )
\r
423 pxHandle->uxMessagesWaiting = uxInitialCount;
\r
425 traceCREATE_COUNTING_SEMAPHORE();
\r
429 traceCREATE_COUNTING_SEMAPHORE_FAILED();
\r
435 #endif /* configUSE_COUNTING_SEMAPHORES */
\r
436 /*-----------------------------------------------------------*/
\r
438 signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
\r
440 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
441 xTimeOutType xTimeOut;
\r
443 /* This function relaxes the coding standard somewhat to allow return
\r
444 statements within the function itself. This is done in the interest
\r
445 of execution time efficiency. */
\r
449 taskENTER_CRITICAL();
\r
451 /* Is there room on the queue now? To be running we must be
\r
452 the highest priority task wanting to access the queue. */
\r
453 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
455 traceQUEUE_SEND( pxQueue );
\r
456 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
458 /* If there was a task waiting for data to arrive on the
\r
459 queue then unblock it now. */
\r
460 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
462 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
464 /* The unblocked task has a priority higher than
\r
465 our own so yield immediately. Yes it is ok to do
\r
466 this from within the critical section - the kernel
\r
467 takes care of that. */
\r
472 taskEXIT_CRITICAL();
\r
477 if( xTicksToWait == ( portTickType ) 0 )
\r
479 /* The queue was full and no block time is specified (or
\r
480 the block time has expired) so leave now. */
\r
481 taskEXIT_CRITICAL();
\r
482 traceQUEUE_SEND_FAILED( pxQueue );
\r
483 return errQUEUE_FULL;
\r
485 else if( xEntryTimeSet == pdFALSE )
\r
487 /* The queue was full and a block time was specified so
\r
488 configure the timeout structure. */
\r
489 vTaskSetTimeOutState( &xTimeOut );
\r
490 xEntryTimeSet = pdTRUE;
\r
494 taskEXIT_CRITICAL();
\r
496 /* Interrupts and other tasks can send to and receive from the queue
\r
497 now the critical section has been exited. */
\r
500 prvLockQueue( pxQueue );
\r
502 /* Update the timeout state to see if it has expired yet. */
\r
503 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
505 if( prvIsQueueFull( pxQueue ) )
\r
507 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
\r
508 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
\r
510 /* Unlocking the queue means queue events can effect the
\r
511 event list. It is possible that interrupts occurring now
\r
512 remove this task from the event list again - but as the
\r
513 scheduler is suspended the task will go onto the pending
\r
514 ready last instead of the actual ready list. */
\r
515 prvUnlockQueue( pxQueue );
\r
517 /* Resuming the scheduler will move tasks from the pending
\r
518 ready list into the ready list - so it is feasible that this
\r
519 task is already in a ready list before it yields - in which
\r
520 case the yield will not cause a context switch unless there
\r
521 is also a higher priority task in the pending ready list. */
\r
522 if( !xTaskResumeAll() )
\r
530 prvUnlockQueue( pxQueue );
\r
531 ( void ) xTaskResumeAll();
\r
536 /* The timeout has expired. */
\r
537 prvUnlockQueue( pxQueue );
\r
538 ( void ) xTaskResumeAll();
\r
539 traceQUEUE_SEND_FAILED( pxQueue );
\r
540 return errQUEUE_FULL;
\r
544 /*-----------------------------------------------------------*/
\r
546 #if configUSE_ALTERNATIVE_API == 1
\r
548 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
\r
550 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
551 xTimeOutType xTimeOut;
\r
555 taskENTER_CRITICAL();
\r
557 /* Is there room on the queue now? To be running we must be
\r
558 the highest priority task wanting to access the queue. */
\r
559 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
561 traceQUEUE_SEND( pxQueue );
\r
562 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
564 /* If there was a task waiting for data to arrive on the
\r
565 queue then unblock it now. */
\r
566 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
568 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
570 /* The unblocked task has a priority higher than
\r
571 our own so yield immediately. */
\r
576 taskEXIT_CRITICAL();
\r
581 if( xTicksToWait == ( portTickType ) 0 )
\r
583 taskEXIT_CRITICAL();
\r
584 return errQUEUE_FULL;
\r
586 else if( xEntryTimeSet == pdFALSE )
\r
588 vTaskSetTimeOutState( &xTimeOut );
\r
589 xEntryTimeSet = pdTRUE;
\r
593 taskEXIT_CRITICAL();
\r
595 taskENTER_CRITICAL();
\r
597 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
599 if( prvIsQueueFull( pxQueue ) )
\r
601 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
\r
602 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
\r
608 taskEXIT_CRITICAL();
\r
609 traceQUEUE_SEND_FAILED( pxQueue );
\r
610 return errQUEUE_FULL;
\r
613 taskEXIT_CRITICAL();
\r
617 #endif /* configUSE_ALTERNATIVE_API */
\r
618 /*-----------------------------------------------------------*/
\r
620 #if configUSE_ALTERNATIVE_API == 1
\r
622 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
\r
624 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
625 xTimeOutType xTimeOut;
\r
626 signed portCHAR *pcOriginalReadPosition;
\r
630 taskENTER_CRITICAL();
\r
632 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
634 /* Remember our read position in case we are just peeking. */
\r
635 pcOriginalReadPosition = pxQueue->pcReadFrom;
\r
637 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
639 if( xJustPeeking == pdFALSE )
\r
641 traceQUEUE_RECEIVE( pxQueue );
\r
643 /* We are actually removing data. */
\r
644 --( pxQueue->uxMessagesWaiting );
\r
646 #if ( configUSE_MUTEXES == 1 )
\r
648 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
650 /* Record the information required to implement
\r
651 priority inheritance should it become necessary. */
\r
652 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
\r
657 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
659 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
667 traceQUEUE_PEEK( pxQueue );
\r
669 /* We are not removing the data, so reset our read
\r
671 pxQueue->pcReadFrom = pcOriginalReadPosition;
\r
673 /* The data is being left in the queue, so see if there are
\r
674 any other tasks waiting for the data. */
\r
675 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
\r
677 /* Tasks that are removed from the event list will get added to
\r
678 the pending ready list as the scheduler is still suspended. */
\r
679 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
681 /* The task waiting has a higher priority than this task. */
\r
688 taskEXIT_CRITICAL();
\r
693 if( xTicksToWait == ( portTickType ) 0 )
\r
695 taskEXIT_CRITICAL();
\r
696 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
697 return errQUEUE_EMPTY;
\r
699 else if( xEntryTimeSet == pdFALSE )
\r
701 vTaskSetTimeOutState( &xTimeOut );
\r
702 xEntryTimeSet = pdTRUE;
\r
706 taskEXIT_CRITICAL();
\r
708 taskENTER_CRITICAL();
\r
710 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
712 if( prvIsQueueEmpty( pxQueue ) )
\r
714 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
\r
716 #if ( configUSE_MUTEXES == 1 )
\r
718 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
720 portENTER_CRITICAL();
\r
721 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
\r
722 portEXIT_CRITICAL();
\r
727 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
733 taskEXIT_CRITICAL();
\r
734 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
735 return errQUEUE_EMPTY;
\r
738 taskEXIT_CRITICAL();
\r
743 #endif /* configUSE_ALTERNATIVE_API */
\r
744 /*-----------------------------------------------------------*/
\r
746 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )
\r
748 signed portBASE_TYPE xReturn;
\r
749 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
751 /* Similar to xQueueGenericSend, except we don't block if there is no room
\r
752 in the queue. Also we don't directly wake a task that was blocked on a
\r
753 queue read, instead we return a flag to say whether a context switch is
\r
754 required or not (i.e. has a task with a higher priority than us been woken
\r
756 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
758 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
760 traceQUEUE_SEND_FROM_ISR( pxQueue );
\r
762 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
764 /* If the queue is locked we do not alter the event list. This will
\r
765 be done when the queue is unlocked later. */
\r
766 if( pxQueue->xTxLock == queueUNLOCKED )
\r
768 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
\r
770 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
772 /* The task waiting has a higher priority so record that a
\r
773 context switch is required. */
\r
774 *pxHigherPriorityTaskWoken = pdTRUE;
\r
780 /* Increment the lock count so the task that unlocks the queue
\r
781 knows that data was posted while it was locked. */
\r
782 ++( pxQueue->xTxLock );
\r
789 traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
\r
790 xReturn = errQUEUE_FULL;
\r
793 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
797 /*-----------------------------------------------------------*/
\r
799 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
\r
801 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
\r
802 xTimeOutType xTimeOut;
\r
803 signed portCHAR *pcOriginalReadPosition;
\r
805 /* This function relaxes the coding standard somewhat to allow return
\r
806 statements within the function itself. This is done in the interest
\r
807 of execution time efficiency. */
\r
811 taskENTER_CRITICAL();
\r
813 /* Is there data in the queue now? To be running we must be
\r
814 the highest priority task wanting to access the queue. */
\r
815 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
817 /* Remember our read position in case we are just peeking. */
\r
818 pcOriginalReadPosition = pxQueue->pcReadFrom;
\r
820 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
822 if( xJustPeeking == pdFALSE )
\r
824 traceQUEUE_RECEIVE( pxQueue );
\r
826 /* We are actually removing data. */
\r
827 --( pxQueue->uxMessagesWaiting );
\r
829 #if ( configUSE_MUTEXES == 1 )
\r
831 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
833 /* Record the information required to implement
\r
834 priority inheritance should it become necessary. */
\r
835 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
\r
840 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
842 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
850 traceQUEUE_PEEK( pxQueue );
\r
852 /* We are not removing the data, so reset our read
\r
854 pxQueue->pcReadFrom = pcOriginalReadPosition;
\r
856 /* The data is being left in the queue, so see if there are
\r
857 any other tasks waiting for the data. */
\r
858 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
\r
860 /* Tasks that are removed from the event list will get added to
\r
861 the pending ready list as the scheduler is still suspended. */
\r
862 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
864 /* The task waiting has a higher priority than this task. */
\r
871 taskEXIT_CRITICAL();
\r
876 if( xTicksToWait == ( portTickType ) 0 )
\r
878 /* The queue was empty and no block time is specified (or
\r
879 the block time has expired) so leave now. */
\r
880 taskEXIT_CRITICAL();
\r
881 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
882 return errQUEUE_EMPTY;
\r
884 else if( xEntryTimeSet == pdFALSE )
\r
886 /* The queue was empty and a block time was specified so
\r
887 configure the timeout structure. */
\r
888 vTaskSetTimeOutState( &xTimeOut );
\r
889 xEntryTimeSet = pdTRUE;
\r
893 taskEXIT_CRITICAL();
\r
895 /* Interrupts and other tasks can send to and receive from the queue
\r
896 now the critical section has been exited. */
\r
899 prvLockQueue( pxQueue );
\r
901 /* Update the timeout state to see if it has expired yet. */
\r
902 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
904 if( prvIsQueueEmpty( pxQueue ) )
\r
906 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
\r
908 #if ( configUSE_MUTEXES == 1 )
\r
910 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
912 portENTER_CRITICAL();
\r
914 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
\r
916 portEXIT_CRITICAL();
\r
921 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
922 prvUnlockQueue( pxQueue );
\r
923 if( !xTaskResumeAll() )
\r
931 prvUnlockQueue( pxQueue );
\r
932 ( void ) xTaskResumeAll();
\r
937 prvUnlockQueue( pxQueue );
\r
938 ( void ) xTaskResumeAll();
\r
939 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
940 return errQUEUE_EMPTY;
\r
944 /*-----------------------------------------------------------*/
\r
946 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )
\r
948 signed portBASE_TYPE xReturn;
\r
949 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
951 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
953 /* We cannot block from an ISR, so check there is data available. */
\r
954 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
956 traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
\r
958 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
959 --( pxQueue->uxMessagesWaiting );
\r
961 /* If the queue is locked we will not modify the event list. Instead
\r
962 we update the lock count so the task that unlocks the queue will know
\r
963 that an ISR has removed data while the queue was locked. */
\r
964 if( pxQueue->xRxLock == queueUNLOCKED )
\r
966 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
\r
968 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
970 /* The task waiting has a higher priority than us so
\r
971 force a context switch. */
\r
972 *pxTaskWoken = pdTRUE;
\r
978 /* Increment the lock count so the task that unlocks the queue
\r
979 knows that data was removed while it was locked. */
\r
980 ++( pxQueue->xRxLock );
\r
988 traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
\r
991 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
995 /*-----------------------------------------------------------*/
\r
997 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue )
\r
999 unsigned portBASE_TYPE uxReturn;
\r
1001 taskENTER_CRITICAL();
\r
1002 uxReturn = pxQueue->uxMessagesWaiting;
\r
1003 taskEXIT_CRITICAL();
\r
1007 /*-----------------------------------------------------------*/
\r
1009 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue )
\r
1011 unsigned portBASE_TYPE uxReturn;
\r
1013 uxReturn = pxQueue->uxMessagesWaiting;
\r
1017 /*-----------------------------------------------------------*/
\r
1019 void vQueueDelete( xQueueHandle pxQueue )
\r
1021 traceQUEUE_DELETE( pxQueue );
\r
1022 vQueueUnregisterQueue( pxQueue );
\r
1023 vPortFree( pxQueue->pcHead );
\r
1024 vPortFree( pxQueue );
\r
1026 /*-----------------------------------------------------------*/
\r
1028 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )
\r
1030 if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )
\r
1032 #if ( configUSE_MUTEXES == 1 )
\r
1034 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
1036 /* The mutex is no longer being held. */
\r
1037 vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
\r
1038 pxQueue->pxMutexHolder = NULL;
\r
1043 else if( xPosition == queueSEND_TO_BACK )
\r
1045 memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
\r
1046 pxQueue->pcWriteTo += pxQueue->uxItemSize;
\r
1047 if( pxQueue->pcWriteTo >= pxQueue->pcTail )
\r
1049 pxQueue->pcWriteTo = pxQueue->pcHead;
\r
1054 memcpy( ( void * ) pxQueue->pcReadFrom, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
\r
1055 pxQueue->pcReadFrom -= pxQueue->uxItemSize;
\r
1056 if( pxQueue->pcReadFrom < pxQueue->pcHead )
\r
1058 pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
\r
1062 ++( pxQueue->uxMessagesWaiting );
\r
1064 /*-----------------------------------------------------------*/
\r
1066 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
\r
1068 if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
\r
1070 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1071 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1073 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1075 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1078 /*-----------------------------------------------------------*/
\r
1080 static void prvUnlockQueue( xQueueHandle pxQueue )
\r
1082 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
\r
1084 /* The lock counts contains the number of extra data items placed or
\r
1085 removed from the queue while the queue was locked. When a queue is
\r
1086 locked items can be added or removed, but the event lists cannot be
\r
1088 taskENTER_CRITICAL();
\r
1090 /* See if data was added to the queue while it was locked. */
\r
1091 while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )
\r
1093 /* Data was posted while the queue was locked. Are any tasks
\r
1094 blocked waiting for data to become available? */
\r
1095 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
\r
1097 /* Tasks that are removed from the event list will get added to
\r
1098 the pending ready list as the scheduler is still suspended. */
\r
1099 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1101 /* The task waiting has a higher priority so record that a
\r
1102 context switch is required. */
\r
1103 vTaskMissedYield();
\r
1106 --( pxQueue->xTxLock );
\r
1114 pxQueue->xTxLock = queueUNLOCKED;
\r
1116 taskEXIT_CRITICAL();
\r
1118 /* Do the same for the Rx lock. */
\r
1119 taskENTER_CRITICAL();
\r
1121 while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )
\r
1123 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
\r
1125 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1127 vTaskMissedYield();
\r
1130 --( pxQueue->xRxLock );
\r
1138 pxQueue->xRxLock = queueUNLOCKED;
\r
1140 taskEXIT_CRITICAL();
\r
1142 /*-----------------------------------------------------------*/
\r
1144 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue )
\r
1146 signed portBASE_TYPE xReturn;
\r
1148 taskENTER_CRITICAL();
\r
1149 xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
\r
1150 taskEXIT_CRITICAL();
\r
1154 /*-----------------------------------------------------------*/
\r
1156 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue )
\r
1158 signed portBASE_TYPE xReturn;
\r
1160 xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
\r
1164 /*-----------------------------------------------------------*/
\r
1166 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue )
\r
1168 signed portBASE_TYPE xReturn;
\r
1170 taskENTER_CRITICAL();
\r
1171 xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
\r
1172 taskEXIT_CRITICAL();
\r
1176 /*-----------------------------------------------------------*/
\r
1178 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue )
\r
1180 signed portBASE_TYPE xReturn;
\r
1182 xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
\r
1186 /*-----------------------------------------------------------*/
\r
1188 #if configUSE_CO_ROUTINES == 1
\r
1189 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )
\r
1191 signed portBASE_TYPE xReturn;
\r
1193 /* If the queue is already full we may have to block. A critical section
\r
1194 is required to prevent an interrupt removing something from the queue
\r
1195 between the check to see if the queue is full and blocking on the queue. */
\r
1196 portDISABLE_INTERRUPTS();
\r
1198 if( prvIsQueueFull( pxQueue ) )
\r
1200 /* The queue is full - do we want to block or just leave without
\r
1202 if( xTicksToWait > ( portTickType ) 0 )
\r
1204 /* As this is called from a coroutine we cannot block directly, but
\r
1205 return indicating that we need to block. */
\r
1206 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
\r
1207 portENABLE_INTERRUPTS();
\r
1208 return errQUEUE_BLOCKED;
\r
1212 portENABLE_INTERRUPTS();
\r
1213 return errQUEUE_FULL;
\r
1217 portENABLE_INTERRUPTS();
\r
1221 portDISABLE_INTERRUPTS();
\r
1223 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
1225 /* There is room in the queue, copy the data into the queue. */
\r
1226 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
\r
1229 /* Were any co-routines waiting for data to become available? */
\r
1230 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
\r
1232 /* In this instance the co-routine could be placed directly
\r
1233 into the ready list as we are within a critical section.
\r
1234 Instead the same pending ready list mechanism is used as if
\r
1235 the event were caused from within an interrupt. */
\r
1236 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1238 /* The co-routine waiting has a higher priority so record
\r
1239 that a yield might be appropriate. */
\r
1240 xReturn = errQUEUE_YIELD;
\r
1246 xReturn = errQUEUE_FULL;
\r
1249 portENABLE_INTERRUPTS();
\r
1254 /*-----------------------------------------------------------*/
\r
1256 #if configUSE_CO_ROUTINES == 1
\r
1257 signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )
\r
1259 signed portBASE_TYPE xReturn;
\r
1261 /* If the queue is already empty we may have to block. A critical section
\r
1262 is required to prevent an interrupt adding something to the queue
\r
1263 between the check to see if the queue is empty and blocking on the queue. */
\r
1264 portDISABLE_INTERRUPTS();
\r
1266 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
\r
1268 /* There are no messages in the queue, do we want to block or just
\r
1269 leave with nothing? */
\r
1270 if( xTicksToWait > ( portTickType ) 0 )
\r
1272 /* As this is a co-routine we cannot block directly, but return
\r
1273 indicating that we need to block. */
\r
1274 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
\r
1275 portENABLE_INTERRUPTS();
\r
1276 return errQUEUE_BLOCKED;
\r
1280 portENABLE_INTERRUPTS();
\r
1281 return errQUEUE_FULL;
\r
1285 portENABLE_INTERRUPTS();
\r
1289 portDISABLE_INTERRUPTS();
\r
1291 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1293 /* Data is available from the queue. */
\r
1294 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1295 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1297 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1299 --( pxQueue->uxMessagesWaiting );
\r
1300 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1304 /* Were any co-routines waiting for space to become available? */
\r
1305 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
\r
1307 /* In this instance the co-routine could be placed directly
\r
1308 into the ready list as we are within a critical section.
\r
1309 Instead the same pending ready list mechanism is used as if
\r
1310 the event were caused from within an interrupt. */
\r
1311 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1313 xReturn = errQUEUE_YIELD;
\r
1322 portENABLE_INTERRUPTS();
\r
1327 /*-----------------------------------------------------------*/
\r
1331 #if configUSE_CO_ROUTINES == 1
\r
1332 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
\r
1334 /* Cannot block within an ISR so if there is no space on the queue then
\r
1335 exit without doing anything. */
\r
1336 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
1338 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
\r
1340 /* We only want to wake one co-routine per ISR, so check that a
\r
1341 co-routine has not already been woken. */
\r
1342 if( !xCoRoutinePreviouslyWoken )
\r
1344 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
\r
1346 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1354 return xCoRoutinePreviouslyWoken;
\r
1357 /*-----------------------------------------------------------*/
\r
1359 #if configUSE_CO_ROUTINES == 1
\r
1360 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )
\r
1362 signed portBASE_TYPE xReturn;
\r
1364 /* We cannot block from an ISR, so check there is data available. If
\r
1365 not then just leave without doing anything. */
\r
1366 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1368 /* Copy the data from the queue. */
\r
1369 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1370 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1372 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1374 --( pxQueue->uxMessagesWaiting );
\r
1375 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1377 if( !( *pxCoRoutineWoken ) )
\r
1379 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
\r
1381 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1383 *pxCoRoutineWoken = pdTRUE;
\r
1398 /*-----------------------------------------------------------*/
\r
1400 #if configQUEUE_REGISTRY_SIZE > 0
\r
1402 void vQueueAddToRegistry( xQueueHandle xQueue, signed portCHAR *pcQueueName )
\r
1404 unsigned portBASE_TYPE ux;
\r
1406 /* See if there is an empty space in the registry. A NULL name denotes
\r
1408 for( ux = 0; ux < configQUEUE_REGISTRY_SIZE; ux++ )
\r
1410 if( xQueueRegistry[ ux ].pcQueueName == NULL )
\r
1412 /* Store the information on this queue. */
\r
1413 xQueueRegistry[ ux ].pcQueueName = pcQueueName;
\r
1414 xQueueRegistry[ ux ].xHandle = xQueue;
\r
1421 /*-----------------------------------------------------------*/
\r
1423 #if configQUEUE_REGISTRY_SIZE > 0
\r
1425 static void vQueueUnregisterQueue( xQueueHandle xQueue )
\r
1427 unsigned portBASE_TYPE ux;
\r
1429 /* See if the handle of the queue being unregistered in actually in the
\r
1431 for( ux = 0; ux < configQUEUE_REGISTRY_SIZE; ux++ )
\r
1433 if( xQueueRegistry[ ux ].xHandle == xQueue )
\r
1435 /* Set the name to NULL to show that this slot if free again. */
\r
1436 xQueueRegistry[ ux ].pcQueueName = NULL;
\r