2 FreeRTOS.org V4.8.0 - Copyright (C) 2003-2008 Richard Barry.
\r
4 This file is part of the FreeRTOS.org distribution.
\r
6 FreeRTOS.org is free software; you can redistribute it and/or modify
\r
7 it under the terms of the GNU General Public License as published by
\r
8 the Free Software Foundation; either version 2 of the License, or
\r
9 (at your option) any later version.
\r
11 FreeRTOS.org is distributed in the hope that it will be useful,
\r
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 GNU General Public License for more details.
\r
16 You should have received a copy of the GNU General Public License
\r
17 along with FreeRTOS.org; if not, write to the Free Software
\r
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
20 A special exception to the GPL can be applied should you wish to distribute
\r
21 a combined work that includes FreeRTOS.org, without being obliged to provide
\r
22 the source code for any proprietary components. See the licensing section
\r
23 of http://www.FreeRTOS.org for full details of how and when the exception
\r
26 ***************************************************************************
\r
27 ***************************************************************************
\r
29 * SAVE TIME AND MONEY! Why not get us to quote to get FreeRTOS.org *
\r
30 * running on your hardware - or even write all or part of your application*
\r
31 * for you? See http://www.OpenRTOS.com for details. *
\r
33 ***************************************************************************
\r
34 ***************************************************************************
\r
36 Please ensure to read the configuration and relevant port sections of the
\r
37 online documentation.
\r
39 http://www.FreeRTOS.org - Documentation, latest information, license and
\r
42 http://www.SafeRTOS.com - A version that is certified for use in safety
\r
45 http://www.OpenRTOS.com - Commercial support, development, porting,
\r
46 licensing and training services.
\r
51 #include "FreeRTOS.h"
\r
53 #include "croutine.h"
\r
55 /*-----------------------------------------------------------
\r
56 * PUBLIC LIST API documented in list.h
\r
57 *----------------------------------------------------------*/
\r
59 /* Constants used with the cRxLock and cTxLock structure members. */
\r
60 #define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 )
\r
61 #define queueERRONEOUS_UNBLOCK ( -1 )
\r
63 /* For internal use only. */
\r
64 #define queueSEND_TO_BACK ( 0 )
\r
65 #define queueSEND_TO_FRONT ( 1 )
\r
67 /* Effectively make a union out of the xQUEUE structure. */
\r
68 #define pxMutexHolder pcTail
\r
69 #define uxQueueType pcHead
\r
70 #define uxRecursiveCallCount pcReadFrom
\r
71 #define queueQUEUE_IS_MUTEX NULL
\r
73 /* Semaphores do not actually store or copy data, so have an items size of
\r
75 #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( 0 )
\r
76 #define queueDONT_BLOCK ( ( portTickType ) 0 )
\r
77 #define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0 )
\r
79 * Definition of the queue used by the scheduler.
\r
80 * Items are queued by copy, not reference.
\r
82 typedef struct QueueDefinition
\r
84 signed portCHAR *pcHead; /*< Points to the beginning of the queue storage area. */
\r
85 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
87 signed portCHAR *pcWriteTo; /*< Points to the free next place in the storage area. */
\r
88 signed portCHAR *pcReadFrom; /*< Points to the last place that a queued item was read from. */
\r
90 xList xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */
\r
91 xList xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */
\r
93 volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */
\r
94 unsigned portBASE_TYPE uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
\r
95 unsigned portBASE_TYPE uxItemSize; /*< The size of each items that the queue will hold. */
\r
97 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
98 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
100 /*-----------------------------------------------------------*/
\r
103 * Inside this file xQueueHandle is a pointer to a xQUEUE structure.
\r
104 * To keep the definition private the API header file defines it as a
\r
107 typedef xQUEUE * xQueueHandle;
\r
110 * Prototypes for public functions are included here so we don't have to
\r
111 * include the API header file (as it defines xQueueHandle differently). These
\r
112 * functions are documented in the API header file.
\r
114 xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize );
\r
115 signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );
\r
116 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle const pxQueue );
\r
117 void vQueueDelete( xQueueHandle xQueue );
\r
118 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken, portBASE_TYPE xCopyPosition );
\r
119 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );
\r
120 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, const void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken );
\r
121 xQueueHandle xQueueCreateMutex( void );
\r
122 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount );
\r
123 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime );
\r
124 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex );
\r
125 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );
\r
126 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );
\r
127 portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle const pxQueue );
\r
128 portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle const pxQueue );
\r
129 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle const pxQueue );
\r
132 #if configUSE_CO_ROUTINES == 1
\r
133 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken );
\r
134 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken );
\r
135 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait );
\r
136 signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait );
\r
140 * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not
\r
141 * prevent an ISR from adding or removing items to the queue, but does prevent
\r
142 * an ISR from removing tasks from the queue event lists. If an ISR finds a
\r
143 * queue is locked it will instead increment the appropriate queue lock count
\r
144 * to indicate that a task may require unblocking. When the queue in unlocked
\r
145 * these lock counts are inspected, and the appropriate action taken.
\r
147 static void prvUnlockQueue( xQueueHandle pxQueue );
\r
150 * Uses a critical section to determine if there is any data in a queue.
\r
152 * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
\r
154 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle const pxQueue );
\r
157 * Uses a critical section to determine if there is any space in a queue.
\r
159 * @return pdTRUE if there is no space, otherwise pdFALSE;
\r
161 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle const pxQueue );
\r
164 * Copies an item into the queue, either at the front of the queue or the
\r
165 * back of the queue.
\r
167 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition );
\r
170 * Copies an item out of a queue.
\r
172 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer );
\r
173 /*-----------------------------------------------------------*/
\r
176 * Macro to mark a queue as locked. Locking a queue prevents an ISR from
\r
177 * accessing the queue event lists.
\r
179 #define prvLockQueue( pxQueue ) \
\r
181 taskENTER_CRITICAL(); \
\r
182 ++( pxQueue->xRxLock ); \
\r
183 ++( pxQueue->xTxLock ); \
\r
184 taskEXIT_CRITICAL(); \
\r
186 /*-----------------------------------------------------------*/
\r
189 /*-----------------------------------------------------------
\r
190 * PUBLIC QUEUE MANAGEMENT API documented in queue.h
\r
191 *----------------------------------------------------------*/
\r
193 xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize )
\r
195 xQUEUE *pxNewQueue;
\r
196 size_t xQueueSizeInBytes;
\r
198 /* Allocate the new queue structure. */
\r
199 if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )
\r
201 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
\r
202 if( pxNewQueue != NULL )
\r
204 /* Create the list of pointers to queue items. The queue is one byte
\r
205 longer than asked for to make wrap checking easier/faster. */
\r
206 xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1;
\r
208 pxNewQueue->pcHead = ( signed portCHAR * ) pvPortMalloc( xQueueSizeInBytes );
\r
209 if( pxNewQueue->pcHead != NULL )
\r
211 /* Initialise the queue members as described above where the
\r
212 queue type is defined. */
\r
213 pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize );
\r
214 pxNewQueue->uxMessagesWaiting = 0;
\r
215 pxNewQueue->pcWriteTo = pxNewQueue->pcHead;
\r
216 pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - 1 ) * uxItemSize );
\r
217 pxNewQueue->uxLength = uxQueueLength;
\r
218 pxNewQueue->uxItemSize = uxItemSize;
\r
219 pxNewQueue->xRxLock = queueUNLOCKED;
\r
220 pxNewQueue->xTxLock = queueUNLOCKED;
\r
222 /* Likewise ensure the event queues start with the correct state. */
\r
223 vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
\r
224 vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
\r
226 traceQUEUE_CREATE( pxNewQueue );
\r
232 traceQUEUE_CREATE_FAILED();
\r
233 vPortFree( pxNewQueue );
\r
238 /* Will only reach here if we could not allocate enough memory or no memory
\r
242 /*-----------------------------------------------------------*/
\r
244 #if ( configUSE_MUTEXES == 1 )
\r
246 xQueueHandle xQueueCreateMutex( void )
\r
248 xQUEUE *pxNewQueue;
\r
250 /* Allocate the new queue structure. */
\r
251 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
\r
252 if( pxNewQueue != NULL )
\r
254 /* Information required for priority inheritance. */
\r
255 pxNewQueue->pxMutexHolder = NULL;
\r
256 pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
\r
258 /* Queues used as a mutex no data is actually copied into or out
\r
260 pxNewQueue->pcWriteTo = NULL;
\r
261 pxNewQueue->pcReadFrom = NULL;
\r
263 /* Each mutex has a length of 1 (like a binary semaphore) and
\r
264 an item size of 0 as nothing is actually copied into or out
\r
266 pxNewQueue->uxMessagesWaiting = 0;
\r
267 pxNewQueue->uxLength = 1;
\r
268 pxNewQueue->uxItemSize = 0;
\r
269 pxNewQueue->xRxLock = queueUNLOCKED;
\r
270 pxNewQueue->xTxLock = queueUNLOCKED;
\r
272 /* Ensure the event queues start with the correct state. */
\r
273 vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
\r
274 vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
\r
276 /* Start with the semaphore in the expected state. */
\r
277 xQueueGenericSend( pxNewQueue, NULL, 0, queueSEND_TO_BACK );
\r
279 traceCREATE_MUTEX( pxNewQueue );
\r
283 traceCREATE_MUTEX_FAILED();
\r
289 #endif /* configUSE_MUTEXES */
\r
290 /*-----------------------------------------------------------*/
\r
292 #if configUSE_RECURSIVE_MUTEXES == 1
\r
294 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex )
\r
296 portBASE_TYPE xReturn;
\r
298 /* If this is the task that holds the mutex then pxMutexHolder will not
\r
299 change outside of this task. If this task does not hold the mutex then
\r
300 pxMutexHolder can never coincidentally equal the tasks handle, and as
\r
301 this is the only condition we are interested in it does not matter if
\r
302 pxMutexHolder is accessed simultaneously by another task. Therefore no
\r
303 mutual exclusion is required to test the pxMutexHolder variable. */
\r
304 if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
\r
306 /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to
\r
307 the task handle, therefore no underflow check is required. Also,
\r
308 uxRecursiveCallCount is only modified by the mutex holder, and as
\r
309 there can only be one, no mutual exclusion is required to modify the
\r
310 uxRecursiveCallCount member. */
\r
311 ( pxMutex->uxRecursiveCallCount )--;
\r
313 /* Have we unwound the call count? */
\r
314 if( pxMutex->uxRecursiveCallCount == 0 )
\r
316 /* Return the mutex. This will automatically unblock any other
\r
317 task that might be waiting to access the mutex. */
\r
318 xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
\r
323 traceGIVE_MUTEX_RECURSIVE( pxMutex );
\r
327 /* We cannot give the mutex because we are not the holder. */
\r
330 traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
\r
336 #endif /* configUSE_RECURSIVE_MUTEXES */
\r
337 /*-----------------------------------------------------------*/
\r
339 #if configUSE_RECURSIVE_MUTEXES == 1
\r
341 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime )
\r
343 portBASE_TYPE xReturn;
\r
345 /* Comments regarding mutual exclusion as per those within
\r
346 xQueueGiveMutexRecursive(). */
\r
348 if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
\r
350 ( pxMutex->uxRecursiveCallCount )++;
\r
355 xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );
\r
357 /* pdPASS will only be returned if we successfully obtained the mutex,
\r
358 we may have blocked to reach here. */
\r
359 if( xReturn == pdPASS )
\r
361 ( pxMutex->uxRecursiveCallCount )++;
\r
365 traceTAKE_MUTEX_RECURSIVE( pxMutex );
\r
370 #endif /* configUSE_RECURSIVE_MUTEXES */
\r
371 /*-----------------------------------------------------------*/
\r
373 #if configUSE_COUNTING_SEMAPHORES == 1
\r
375 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount )
\r
377 xQueueHandle pxHandle;
\r
379 pxHandle = xQueueCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH );
\r
381 if( pxHandle != NULL )
\r
383 pxHandle->uxMessagesWaiting = uxInitialCount;
\r
385 traceCREATE_COUNTING_SEMAPHORE();
\r
389 traceCREATE_COUNTING_SEMAPHORE_FAILED();
\r
395 #endif /* configUSE_COUNTING_SEMAPHORES */
\r
396 /*-----------------------------------------------------------*/
\r
398 signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
\r
400 signed portBASE_TYPE xReturn = pdTRUE;
\r
401 xTimeOutType xTimeOut;
\r
405 /* If xTicksToWait is zero then we are not going to block even
\r
406 if there is no room in the queue to post. */
\r
407 if( xTicksToWait > ( portTickType ) 0 )
\r
410 prvLockQueue( pxQueue );
\r
412 if( xReturn == pdTRUE )
\r
414 /* This is the first time through - we need to capture the
\r
415 time while the scheduler is locked to ensure we attempt to
\r
416 block at least once. */
\r
417 vTaskSetTimeOutState( &xTimeOut );
\r
420 if( prvIsQueueFull( pxQueue ) )
\r
422 /* Need to call xTaskCheckForTimeout again as time could
\r
423 have passed since it was last called if this is not the
\r
424 first time around this loop. */
\r
425 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
427 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
\r
428 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
\r
430 /* Unlocking the queue means queue events can effect the
\r
431 event list. It is possible that interrupts occurring now
\r
432 remove this task from the event list again - but as the
\r
433 scheduler is suspended the task will go onto the pending
\r
434 ready last instead of the actual ready list. */
\r
435 prvUnlockQueue( pxQueue );
\r
437 /* Resuming the scheduler will move tasks from the pending
\r
438 ready list into the ready list - so it is feasible that this
\r
439 task is already in a ready list before it yields - in which
\r
440 case the yield will not cause a context switch unless there
\r
441 is also a higher priority task in the pending ready list. */
\r
442 if( !xTaskResumeAll() )
\r
449 prvUnlockQueue( pxQueue );
\r
450 ( void ) xTaskResumeAll();
\r
455 /* The queue was not full so we can just unlock the
\r
456 scheduler and queue again before carrying on. */
\r
457 prvUnlockQueue( pxQueue );
\r
458 ( void ) xTaskResumeAll();
\r
462 /* Higher priority tasks and interrupts can execute during
\r
463 this time and could possible refill the queue - even if we
\r
464 unblocked because space became available. */
\r
466 taskENTER_CRITICAL();
\r
468 /* Is there room on the queue now? To be running we must be
\r
469 the highest priority task wanting to access the queue. */
\r
470 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
472 traceQUEUE_SEND( pxQueue );
\r
473 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
476 /* If there was a task waiting for data to arrive on the
\r
477 queue then unblock it now. */
\r
478 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
480 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
482 /* The unblocked task has a priority higher than
\r
483 our own so yield immediately. */
\r
490 /* Setting xReturn to errQUEUE_FULL will force its timeout
\r
491 to be re-evaluated. This is necessary in case interrupts
\r
492 and higher priority tasks accessed the queue between this
\r
493 task being unblocked and subsequently attempting to write
\r
495 xReturn = errQUEUE_FULL;
\r
498 taskEXIT_CRITICAL();
\r
500 if( xReturn == errQUEUE_FULL )
\r
502 if( xTicksToWait > ( portTickType ) 0 )
\r
504 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
506 xReturn = queueERRONEOUS_UNBLOCK;
\r
510 traceQUEUE_SEND_FAILED( pxQueue );
\r
515 traceQUEUE_SEND_FAILED( pxQueue );
\r
519 while( xReturn == queueERRONEOUS_UNBLOCK );
\r
523 /*-----------------------------------------------------------*/
\r
525 #if configUSE_ALTERNATIVE_API == 1
\r
527 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
\r
529 signed portBASE_TYPE xReturn = pdPASS;
\r
530 xTimeOutType xTimeOut;
\r
532 /* The source code that implements the alternative (Alt) API is
\r
533 simpler because it makes more use of critical sections. This is
\r
534 the approach taken by many other RTOSes, but FreeRTOS.org has the
\r
535 preferred fully featured API too. The fully featured API has more
\r
536 complex code that takes longer to execute, but makes less use of
\r
537 critical sections. */
\r
541 /* If xTicksToWait is zero then we are not going to block even
\r
542 if there is no room in the queue to post. */
\r
543 if( xTicksToWait > ( portTickType ) 0 )
\r
545 portENTER_CRITICAL();
\r
547 if( xReturn == pdPASS )
\r
549 /* This is the first time through - capture the time
\r
550 inside the critical section to ensure we attempt to
\r
551 block at least once. */
\r
552 vTaskSetTimeOutState( &xTimeOut );
\r
555 if( prvIsQueueFull( pxQueue ) )
\r
557 /* Need to call xTaskCheckForTimeout again as time could
\r
558 have passed since it was last called if this is not the
\r
559 first time around this loop. */
\r
560 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
562 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
\r
563 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
\r
565 /* This will exit the critical section, then re-enter when
\r
566 the task next runs. */
\r
571 portEXIT_CRITICAL();
\r
574 /* Higher priority tasks and interrupts can execute during
\r
575 this time and could possible refill the queue - even if we
\r
576 unblocked because space became available. */
\r
578 taskENTER_CRITICAL();
\r
580 /* Is there room on the queue now? To be running we must be
\r
581 the highest priority task wanting to access the queue. */
\r
582 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
584 traceQUEUE_SEND( pxQueue );
\r
585 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
588 /* If there was a task waiting for data to arrive on the
\r
589 queue then unblock it now. */
\r
590 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
\r
592 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
\r
594 /* The unblocked task has a priority higher than
\r
595 our own so yield immediately. */
\r
602 /* Setting xReturn to errQUEUE_FULL will force its timeout
\r
603 to be re-evaluated. This is necessary in case interrupts
\r
604 and higher priority tasks accessed the queue between this
\r
605 task being unblocked and subsequently attempting to write
\r
607 xReturn = errQUEUE_FULL;
\r
610 taskEXIT_CRITICAL();
\r
612 if( xReturn == errQUEUE_FULL )
\r
614 if( xTicksToWait > ( portTickType ) 0 )
\r
616 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
618 xReturn = queueERRONEOUS_UNBLOCK;
\r
622 traceQUEUE_SEND_FAILED( pxQueue );
\r
627 traceQUEUE_SEND_FAILED( pxQueue );
\r
631 while( xReturn == queueERRONEOUS_UNBLOCK );
\r
636 #endif /* configUSE_ALTERNATIVE_API */
\r
637 /*-----------------------------------------------------------*/
\r
639 #if configUSE_ALTERNATIVE_API == 1
\r
641 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
\r
643 signed portBASE_TYPE xReturn = pdTRUE;
\r
644 xTimeOutType xTimeOut;
\r
645 signed portCHAR *pcOriginalReadPosition;
\r
647 /* The source code that implements the alternative (Alt) API is
\r
648 simpler because it makes more use of critical sections. This is
\r
649 the approach taken by many other RTOSes, but FreeRTOS.org has the
\r
650 preferred fully featured API too. The fully featured API has more
\r
651 complex code that takes longer to execute, but makes less use of
\r
652 critical sections. */
\r
656 /* If there are no messages in the queue we may have to block. */
\r
657 if( xTicksToWait > ( portTickType ) 0 )
\r
659 portENTER_CRITICAL();
\r
661 if( xReturn == pdPASS )
\r
663 /* This is the first time through - capture the time
\r
664 inside the critical section to ensure we attempt to
\r
665 block at least once. */
\r
666 vTaskSetTimeOutState( &xTimeOut );
\r
669 if( prvIsQueueEmpty( pxQueue ) )
\r
671 /* Need to call xTaskCheckForTimeout again as time could
\r
672 have passed since it was last called if this is not the
\r
673 first time around this loop. */
\r
674 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
676 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
\r
678 #if ( configUSE_MUTEXES == 1 )
\r
680 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
682 portENTER_CRITICAL();
\r
683 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
\r
684 portEXIT_CRITICAL();
\r
689 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
694 portEXIT_CRITICAL();
\r
697 taskENTER_CRITICAL();
\r
699 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
701 /* Remember our read position in case we are just peeking. */
\r
702 pcOriginalReadPosition = pxQueue->pcReadFrom;
\r
704 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
706 if( xJustPeeking == pdFALSE )
\r
708 traceQUEUE_RECEIVE( pxQueue );
\r
710 /* We are actually removing data. */
\r
711 --( pxQueue->uxMessagesWaiting );
\r
713 #if ( configUSE_MUTEXES == 1 )
\r
715 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
717 /* Record the information required to implement
\r
718 priority inheritance should it become necessary. */
\r
719 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
\r
724 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
726 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
734 traceQUEUE_PEEK( pxQueue );
\r
736 /* We are not removing the data, so reset our read
\r
738 pxQueue->pcReadFrom = pcOriginalReadPosition;
\r
740 /* The data is being left in the queue, so see if there are
\r
741 any other tasks waiting for the data. */
\r
742 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
\r
744 /* Tasks that are removed from the event list will get added to
\r
745 the pending ready list as the scheduler is still suspended. */
\r
746 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
748 /* The task waiting has a higher priority that this task. */
\r
759 xReturn = errQUEUE_EMPTY;
\r
762 taskEXIT_CRITICAL();
\r
764 if( xReturn == errQUEUE_EMPTY )
\r
766 if( xTicksToWait > ( portTickType ) 0 )
\r
768 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
770 xReturn = queueERRONEOUS_UNBLOCK;
\r
774 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
779 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
782 } while( xReturn == queueERRONEOUS_UNBLOCK );
\r
788 #endif /* configUSE_ALTERNATIVE_API */
\r
789 /*-----------------------------------------------------------*/
\r
791 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken, portBASE_TYPE xCopyPosition )
\r
793 /* Similar to xQueueGenericSend, except we don't block if there is no room
\r
794 in the queue. Also we don't directly wake a task that was blocked on a
\r
795 queue read, instead we return a flag to say whether a context switch is
\r
796 required or not (i.e. has a task with a higher priority than us been woken
\r
798 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
800 traceQUEUE_SEND_FROM_ISR( pxQueue );
\r
802 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
\r
804 /* If the queue is locked we do not alter the event list. This will
\r
805 be done when the queue is unlocked later. */
\r
806 if( pxQueue->xTxLock == queueUNLOCKED )
\r
808 /* We only want to wake one task per ISR, so check that a task has
\r
809 not already been woken. */
\r
810 if( !xTaskPreviouslyWoken )
\r
812 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
\r
814 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
816 /* The task waiting has a higher priority so record that a
\r
817 context switch is required. */
\r
825 /* Increment the lock count so the task that unlocks the queue
\r
826 knows that data was posted while it was locked. */
\r
827 ++( pxQueue->xTxLock );
\r
832 traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
\r
835 return xTaskPreviouslyWoken;
\r
837 /*-----------------------------------------------------------*/
\r
839 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
\r
841 signed portBASE_TYPE xReturn = pdTRUE;
\r
842 xTimeOutType xTimeOut;
\r
843 signed portCHAR *pcOriginalReadPosition;
\r
847 /* If there are no messages in the queue we may have to block. */
\r
848 if( xTicksToWait > ( portTickType ) 0 )
\r
851 prvLockQueue( pxQueue );
\r
853 if( xReturn == pdTRUE )
\r
855 /* This is the first time through - we need to capture the
\r
856 time while the scheduler is locked to ensure we attempt to
\r
857 block at least once. */
\r
858 vTaskSetTimeOutState( &xTimeOut );
\r
861 if( prvIsQueueEmpty( pxQueue ) )
\r
863 /* Need to call xTaskCheckForTimeout again as time could
\r
864 have passed since it was last called if this is not the
\r
865 first time around this loop. */
\r
866 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
868 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
\r
870 #if ( configUSE_MUTEXES == 1 )
\r
872 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
874 portENTER_CRITICAL();
\r
875 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
\r
876 portEXIT_CRITICAL();
\r
881 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
\r
882 prvUnlockQueue( pxQueue );
\r
883 if( !xTaskResumeAll() )
\r
890 prvUnlockQueue( pxQueue );
\r
891 ( void ) xTaskResumeAll();
\r
896 prvUnlockQueue( pxQueue );
\r
897 ( void ) xTaskResumeAll();
\r
901 taskENTER_CRITICAL();
\r
903 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
905 /* Remember our read position in case we are just peeking. */
\r
906 pcOriginalReadPosition = pxQueue->pcReadFrom;
\r
908 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
910 if( xJustPeeking == pdFALSE )
\r
912 traceQUEUE_RECEIVE( pxQueue );
\r
914 /* We are actually removing data. */
\r
915 --( pxQueue->uxMessagesWaiting );
\r
917 #if ( configUSE_MUTEXES == 1 )
\r
919 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
921 /* Record the information required to implement
\r
922 priority inheritance should it become necessary. */
\r
923 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
\r
928 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
\r
930 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
\r
938 traceQUEUE_PEEK( pxQueue );
\r
940 /* We are not removing the data, so reset our read
\r
942 pxQueue->pcReadFrom = pcOriginalReadPosition;
\r
944 /* The data is being left in the queue, so see if there are
\r
945 any other tasks waiting for the data. */
\r
946 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
\r
948 /* Tasks that are removed from the event list will get added to
\r
949 the pending ready list as the scheduler is still suspended. */
\r
950 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
952 /* The task waiting has a higher priority that this task. */
\r
963 xReturn = errQUEUE_EMPTY;
\r
966 taskEXIT_CRITICAL();
\r
968 if( xReturn == errQUEUE_EMPTY )
\r
970 if( xTicksToWait > 0 )
\r
972 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
\r
974 xReturn = queueERRONEOUS_UNBLOCK;
\r
978 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
983 traceQUEUE_RECEIVE_FAILED( pxQueue );
\r
986 } while( xReturn == queueERRONEOUS_UNBLOCK );
\r
990 /*-----------------------------------------------------------*/
\r
992 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, const void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )
\r
994 signed portBASE_TYPE xReturn;
\r
996 /* We cannot block from an ISR, so check there is data available. */
\r
997 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
999 traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
\r
1001 prvCopyDataFromQueue( pxQueue, pvBuffer );
\r
1002 --( pxQueue->uxMessagesWaiting );
\r
1004 /* If the queue is locked we will not modify the event list. Instead
\r
1005 we update the lock count so the task that unlocks the queue will know
\r
1006 that an ISR has removed data while the queue was locked. */
\r
1007 if( pxQueue->xRxLock == queueUNLOCKED )
\r
1009 /* We only want to wake one task per ISR, so check that a task has
\r
1010 not already been woken. */
\r
1011 if( !( *pxTaskWoken ) )
\r
1013 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
\r
1015 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1017 /* The task waiting has a higher priority than us so
\r
1018 force a context switch. */
\r
1019 *pxTaskWoken = pdTRUE;
\r
1026 /* Increment the lock count so the task that unlocks the queue
\r
1027 knows that data was removed while it was locked. */
\r
1028 ++( pxQueue->xRxLock );
\r
1036 traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
\r
1041 /*-----------------------------------------------------------*/
\r
1043 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle const pxQueue )
\r
1045 unsigned portBASE_TYPE uxReturn;
\r
1047 taskENTER_CRITICAL();
\r
1048 uxReturn = pxQueue->uxMessagesWaiting;
\r
1049 taskEXIT_CRITICAL();
\r
1053 /*-----------------------------------------------------------*/
\r
1055 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue )
\r
1057 unsigned portBASE_TYPE uxReturn;
\r
1059 uxReturn = pxQueue->uxMessagesWaiting;
\r
1063 /*-----------------------------------------------------------*/
\r
1065 void vQueueDelete( xQueueHandle pxQueue )
\r
1067 traceQUEUE_DELETE( pxQueue );
\r
1069 vPortFree( pxQueue->pcHead );
\r
1070 vPortFree( pxQueue );
\r
1072 /*-----------------------------------------------------------*/
\r
1074 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )
\r
1076 if( pxQueue->uxItemSize == 0 )
\r
1078 #if ( configUSE_MUTEXES == 1 )
\r
1080 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
\r
1082 /* The mutex is no longer being held. */
\r
1083 vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
\r
1084 pxQueue->pxMutexHolder = NULL;
\r
1089 else if( xPosition == queueSEND_TO_BACK )
\r
1091 memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
\r
1092 pxQueue->pcWriteTo += pxQueue->uxItemSize;
\r
1093 if( pxQueue->pcWriteTo >= pxQueue->pcTail )
\r
1095 pxQueue->pcWriteTo = pxQueue->pcHead;
\r
1100 memcpy( ( void * ) pxQueue->pcReadFrom, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
\r
1101 pxQueue->pcReadFrom -= pxQueue->uxItemSize;
\r
1102 if( pxQueue->pcReadFrom < pxQueue->pcHead )
\r
1104 pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
\r
1108 ++( pxQueue->uxMessagesWaiting );
\r
1110 /*-----------------------------------------------------------*/
\r
1112 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
\r
1114 if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
\r
1116 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1117 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1119 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1121 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1124 /*-----------------------------------------------------------*/
\r
1126 static void prvUnlockQueue( xQueueHandle pxQueue )
\r
1128 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
\r
1130 /* The lock counts contains the number of extra data items placed or
\r
1131 removed from the queue while the queue was locked. When a queue is
\r
1132 locked items can be added or removed, but the event lists cannot be
\r
1134 taskENTER_CRITICAL();
\r
1136 --( pxQueue->xTxLock );
\r
1138 /* See if data was added to the queue while it was locked. */
\r
1139 if( pxQueue->xTxLock > queueUNLOCKED )
\r
1141 pxQueue->xTxLock = queueUNLOCKED;
\r
1143 /* Data was posted while the queue was locked. Are any tasks
\r
1144 blocked waiting for data to become available? */
\r
1145 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
\r
1147 /* Tasks that are removed from the event list will get added to
\r
1148 the pending ready list as the scheduler is still suspended. */
\r
1149 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1151 /* The task waiting has a higher priority so record that a
\r
1152 context switch is required. */
\r
1153 vTaskMissedYield();
\r
1158 taskEXIT_CRITICAL();
\r
1160 /* Do the same for the Rx lock. */
\r
1161 taskENTER_CRITICAL();
\r
1163 --( pxQueue->xRxLock );
\r
1165 if( pxQueue->xRxLock > queueUNLOCKED )
\r
1167 pxQueue->xRxLock = queueUNLOCKED;
\r
1169 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
\r
1171 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1173 vTaskMissedYield();
\r
1178 taskEXIT_CRITICAL();
\r
1180 /*-----------------------------------------------------------*/
\r
1182 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle const pxQueue )
\r
1184 signed portBASE_TYPE xReturn;
\r
1186 taskENTER_CRITICAL();
\r
1187 xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
\r
1188 taskEXIT_CRITICAL();
\r
1192 /*-----------------------------------------------------------*/
\r
1194 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue )
\r
1196 signed portBASE_TYPE xReturn;
\r
1198 xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
\r
1202 /*-----------------------------------------------------------*/
\r
1204 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle const pxQueue )
\r
1206 signed portBASE_TYPE xReturn;
\r
1208 taskENTER_CRITICAL();
\r
1209 xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
\r
1210 taskEXIT_CRITICAL();
\r
1214 /*-----------------------------------------------------------*/
\r
1216 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue )
\r
1218 signed portBASE_TYPE xReturn;
\r
1220 xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
\r
1224 /*-----------------------------------------------------------*/
\r
1226 #if configUSE_CO_ROUTINES == 1
\r
1227 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )
\r
1229 signed portBASE_TYPE xReturn;
\r
1231 /* If the queue is already full we may have to block. A critical section
\r
1232 is required to prevent an interrupt removing something from the queue
\r
1233 between the check to see if the queue is full and blocking on the queue. */
\r
1234 portDISABLE_INTERRUPTS();
\r
1236 if( prvIsQueueFull( pxQueue ) )
\r
1238 /* The queue is full - do we want to block or just leave without
\r
1240 if( xTicksToWait > ( portTickType ) 0 )
\r
1242 /* As this is called from a coroutine we cannot block directly, but
\r
1243 return indicating that we need to block. */
\r
1244 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
\r
1245 portENABLE_INTERRUPTS();
\r
1246 return errQUEUE_BLOCKED;
\r
1250 portENABLE_INTERRUPTS();
\r
1251 return errQUEUE_FULL;
\r
1255 portENABLE_INTERRUPTS();
\r
1259 portDISABLE_INTERRUPTS();
\r
1261 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
1263 /* There is room in the queue, copy the data into the queue. */
\r
1264 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
\r
1267 /* Were any co-routines waiting for data to become available? */
\r
1268 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
\r
1270 /* In this instance the co-routine could be placed directly
\r
1271 into the ready list as we are within a critical section.
\r
1272 Instead the same pending ready list mechanism is used as if
\r
1273 the event were caused from within an interrupt. */
\r
1274 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1276 /* The co-routine waiting has a higher priority so record
\r
1277 that a yield might be appropriate. */
\r
1278 xReturn = errQUEUE_YIELD;
\r
1284 xReturn = errQUEUE_FULL;
\r
1287 portENABLE_INTERRUPTS();
\r
1292 /*-----------------------------------------------------------*/
\r
1294 #if configUSE_CO_ROUTINES == 1
\r
1295 signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )
\r
1297 signed portBASE_TYPE xReturn;
\r
1299 /* If the queue is already empty we may have to block. A critical section
\r
1300 is required to prevent an interrupt adding something to the queue
\r
1301 between the check to see if the queue is empty and blocking on the queue. */
\r
1302 portDISABLE_INTERRUPTS();
\r
1304 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
\r
1306 /* There are no messages in the queue, do we want to block or just
\r
1307 leave with nothing? */
\r
1308 if( xTicksToWait > ( portTickType ) 0 )
\r
1310 /* As this is a co-routine we cannot block directly, but return
\r
1311 indicating that we need to block. */
\r
1312 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
\r
1313 portENABLE_INTERRUPTS();
\r
1314 return errQUEUE_BLOCKED;
\r
1318 portENABLE_INTERRUPTS();
\r
1319 return errQUEUE_FULL;
\r
1323 portENABLE_INTERRUPTS();
\r
1327 portDISABLE_INTERRUPTS();
\r
1329 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1331 /* Data is available from the queue. */
\r
1332 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1333 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1335 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1337 --( pxQueue->uxMessagesWaiting );
\r
1338 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1342 /* Were any co-routines waiting for space to become available? */
\r
1343 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
\r
1345 /* In this instance the co-routine could be placed directly
\r
1346 into the ready list as we are within a critical section.
\r
1347 Instead the same pending ready list mechanism is used as if
\r
1348 the event were caused from within an interrupt. */
\r
1349 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1351 xReturn = errQUEUE_YIELD;
\r
1360 portENABLE_INTERRUPTS();
\r
1365 /*-----------------------------------------------------------*/
\r
1369 #if configUSE_CO_ROUTINES == 1
\r
1370 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
\r
1372 /* Cannot block within an ISR so if there is no space on the queue then
\r
1373 exit without doing anything. */
\r
1374 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
\r
1376 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
\r
1378 /* We only want to wake one co-routine per ISR, so check that a
\r
1379 co-routine has not already been woken. */
\r
1380 if( !xCoRoutinePreviouslyWoken )
\r
1382 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
\r
1384 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
\r
1392 return xCoRoutinePreviouslyWoken;
\r
1395 /*-----------------------------------------------------------*/
\r
1397 #if configUSE_CO_ROUTINES == 1
\r
1398 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )
\r
1400 signed portBASE_TYPE xReturn;
\r
1402 /* We cannot block from an ISR, so check there is data available. If
\r
1403 not then just leave without doing anything. */
\r
1404 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
\r
1406 /* Copy the data from the queue. */
\r
1407 pxQueue->pcReadFrom += pxQueue->uxItemSize;
\r
1408 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
\r
1410 pxQueue->pcReadFrom = pxQueue->pcHead;
\r
1412 --( pxQueue->uxMessagesWaiting );
\r
1413 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
\r
1415 if( !( *pxCoRoutineWoken ) )
\r
1417 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
\r
1419 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
\r
1421 *pxCoRoutineWoken = pdTRUE;
\r
1436 /*-----------------------------------------------------------*/
\r