Rohit Grover / FreeRTOS

Dependents:   Nucleo freertos_test FreeRTOS_test freertos_bluetooth ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers queue.c Source File

queue.c

00001 /*
00002     FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.
00003     All rights reserved
00004 
00005     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
00006 
00007     ***************************************************************************
00008      *                                                                       *
00009      *    FreeRTOS provides completely free yet professionally developed,    *
00010      *    robust, strictly quality controlled, supported, and cross          *
00011      *    platform software that has become a de facto standard.             *
00012      *                                                                       *
00013      *    Help yourself get started quickly and support the FreeRTOS         *
00014      *    project by purchasing a FreeRTOS tutorial book, reference          *
00015      *    manual, or both from: http://www.FreeRTOS.org/Documentation        *
00016      *                                                                       *
00017      *    Thank you!                                                         *
00018      *                                                                       *
00019     ***************************************************************************
00020 
00021     This file is part of the FreeRTOS distribution.
00022 
00023     FreeRTOS is free software; you can redistribute it and/or modify it under
00024     the terms of the GNU General Public License (version 2) as published by the
00025     Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
00026 
00027     >>! NOTE: The modification to the GPL is included to allow you to distribute
00028     >>! a combined work that includes FreeRTOS without being obliged to provide
00029     >>! the source code for proprietary components outside of the FreeRTOS
00030     >>! kernel.
00031 
00032     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
00033     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00034     FOR A PARTICULAR PURPOSE.  Full license text is available from the following
00035     link: http://www.freertos.org/a00114.html
00036 
00037     1 tab == 4 spaces!
00038 
00039     ***************************************************************************
00040      *                                                                       *
00041      *    Having a problem?  Start by reading the FAQ "My application does   *
00042      *    not run, what could be wrong?"                                     *
00043      *                                                                       *
00044      *    http://www.FreeRTOS.org/FAQHelp.html                               *
00045      *                                                                       *
00046     ***************************************************************************
00047 
00048     http://www.FreeRTOS.org - Documentation, books, training, latest versions,
00049     license and Real Time Engineers Ltd. contact details.
00050 
00051     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
00052     including FreeRTOS+Trace - an indispensable productivity tool, a DOS
00053     compatible FAT file system, and our tiny thread aware UDP/IP stack.
00054 
00055     http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
00056     Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS
00057     licenses offer ticketed support, indemnification and middleware.
00058 
00059     http://www.SafeRTOS.com - High Integrity Systems also provide a safety
00060     engineered and independently SIL3 certified version for use in safety and
00061     mission critical applications that require provable dependability.
00062 
00063     1 tab == 4 spaces!
00064 */
00065 
00066 #include <stdlib.h>
00067 #include <string.h>
00068 
00069 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
00070 all the API functions to use the MPU wrappers.  That should only be done when
00071 task.h is included from an application file. */
00072 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
00073 
00074 #include "FreeRTOS.h"
00075 #include "task.h"
00076 #include "queue.h"
00077 
00078 #if ( configUSE_CO_ROUTINES == 1 )
00079     #include "croutine.h"
00080 #endif
00081 
00082 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the
00083 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
00084 header files above, but not in this file, in order to generate the correct
00085 privileged Vs unprivileged linkage and placement. */
00086 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
00087 
00088 
00089 /* Constants used with the cRxLock and xTxLock structure members. */
00090 #define queueUNLOCKED                   ( ( signed portBASE_TYPE ) -1 )
00091 #define queueLOCKED_UNMODIFIED          ( ( signed portBASE_TYPE ) 0 )
00092 
00093 /* When the xQUEUE structure is used to represent a base queue its pcHead and
00094 pcTail members are used as pointers into the queue storage area.  When the
00095 xQUEUE structure is used to represent a mutex pcHead and pcTail pointers are
00096 not necessary, and the pcHead pointer is set to NULL to indicate that the
00097 pcTail pointer actually points to the mutex holder (if any).  Map alternative
00098 names to the pcHead and pcTail structure members to ensure the readability of
00099 the code is maintained despite this dual use of two structure members.  An
00100 alternative implementation would be to use a union, but use of a union is
00101 against the coding standard (although an exception to the standard has been
00102 permitted where the dual use also significantly changes the type of the
00103 structure member). */
00104 #define pxMutexHolder                   pcTail
00105 #define uxQueueType                     pcHead
00106 #define queueQUEUE_IS_MUTEX             NULL
00107 
00108 /* Semaphores do not actually store or copy data, so have an item size of
00109 zero. */
00110 #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portBASE_TYPE ) 0 )
00111 #define queueMUTEX_GIVE_BLOCK_TIME       ( ( portTickType ) 0U )
00112 
00113 #if( configUSE_PREEMPTION == 0 )
00114     /* If the cooperative scheduler is being used then a yield should not be
00115     performed just because a higher priority task has been woken. */
00116     #define queueYIELD_IF_USING_PREEMPTION()
00117 #else
00118     #define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
00119 #endif
00120 
00121 /*
00122  * Definition of the queue used by the scheduler.
00123  * Items are queued by copy, not reference.
00124  */
00125 typedef struct QueueDefinition
00126 {
00127     signed char *pcHead;                    /*< Points to the beginning of the queue storage area. */
00128     signed char *pcTail;                    /*< Points to the byte at the end of the queue storage area.  Once more byte is allocated than necessary to store the queue items, this is used as a marker. */
00129 
00130     signed char *pcWriteTo;                 /*< Points to the free next place in the storage area. */
00131 
00132     union                                   /* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */
00133     {
00134         signed char *pcReadFrom;            /*< Points to the last place that a queued item was read from when the structure is used as a queue. */
00135         unsigned portBASE_TYPE uxRecursiveCallCount;/*< Maintains a count of the numebr of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */
00136     } u;
00137 
00138     xList xTasksWaitingToSend;              /*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */
00139     xList xTasksWaitingToReceive;           /*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */
00140 
00141     volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */
00142     unsigned portBASE_TYPE uxLength;        /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
00143     unsigned portBASE_TYPE uxItemSize;      /*< The size of each items that the queue will hold. */
00144 
00145     volatile 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. */
00146     volatile 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. */
00147 
00148     #if ( configUSE_TRACE_FACILITY == 1 )
00149         unsigned char ucQueueNumber;
00150         unsigned char ucQueueType;
00151     #endif
00152 
00153     #if ( configUSE_QUEUE_SETS == 1 )
00154         struct QueueDefinition *pxQueueSetContainer;
00155     #endif
00156 
00157 } xQUEUE;
00158 /*-----------------------------------------------------------*/
00159 
00160 /*
00161  * The queue registry is just a means for kernel aware debuggers to locate
00162  * queue structures.  It has no other purpose so is an optional component.
00163  */
00164 #if ( configQUEUE_REGISTRY_SIZE > 0 )
00165 
00166     /* The type stored within the queue registry array.  This allows a name
00167     to be assigned to each queue making kernel aware debugging a little
00168     more user friendly. */
00169     typedef struct QUEUE_REGISTRY_ITEM
00170     {
00171         signed char *pcQueueName;
00172         xQueueHandle xHandle;
00173     } xQueueRegistryItem;
00174 
00175     /* The queue registry is simply an array of xQueueRegistryItem structures.
00176     The pcQueueName member of a structure being NULL is indicative of the
00177     array position being vacant. */
00178     xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
00179 
00180 #endif /* configQUEUE_REGISTRY_SIZE */
00181 
00182 /*
00183  * Unlocks a queue locked by a call to prvLockQueue.  Locking a queue does not
00184  * prevent an ISR from adding or removing items to the queue, but does prevent
00185  * an ISR from removing tasks from the queue event lists.  If an ISR finds a
00186  * queue is locked it will instead increment the appropriate queue lock count
00187  * to indicate that a task may require unblocking.  When the queue in unlocked
00188  * these lock counts are inspected, and the appropriate action taken.
00189  */
00190 static void prvUnlockQueue( xQUEUE *pxQueue ) PRIVILEGED_FUNCTION;
00191 
00192 /*
00193  * Uses a critical section to determine if there is any data in a queue.
00194  *
00195  * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
00196  */
00197 static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue ) PRIVILEGED_FUNCTION;
00198 
00199 /*
00200  * Uses a critical section to determine if there is any space in a queue.
00201  *
00202  * @return pdTRUE if there is no space, otherwise pdFALSE;
00203  */
00204 static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue ) PRIVILEGED_FUNCTION;
00205 
00206 /*
00207  * Copies an item into the queue, either at the front of the queue or the
00208  * back of the queue.
00209  */
00210 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION;
00211 
00212 /*
00213  * Copies an item out of a queue.
00214  */
00215 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION;
00216 
00217 #if ( configUSE_QUEUE_SETS == 1 )
00218     /*
00219      * Checks to see if a queue is a member of a queue set, and if so, notifies
00220      * the queue set that the queue contains data.
00221      */
00222     static portBASE_TYPE prvNotifyQueueSetContainer( const xQUEUE * const pxQueue, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
00223 #endif
00224 
00225 /*-----------------------------------------------------------*/
00226 
00227 /*
00228  * Macro to mark a queue as locked.  Locking a queue prevents an ISR from
00229  * accessing the queue event lists.
00230  */
00231 #define prvLockQueue( pxQueue )                             \
00232     taskENTER_CRITICAL();                                   \
00233     {                                                       \
00234         if( ( pxQueue )->xRxLock == queueUNLOCKED )         \
00235         {                                                   \
00236             ( pxQueue )->xRxLock = queueLOCKED_UNMODIFIED;  \
00237         }                                                   \
00238         if( ( pxQueue )->xTxLock == queueUNLOCKED )         \
00239         {                                                   \
00240             ( pxQueue )->xTxLock = queueLOCKED_UNMODIFIED;  \
00241         }                                                   \
00242     }                                                       \
00243     taskEXIT_CRITICAL()
00244 /*-----------------------------------------------------------*/
00245 
00246 portBASE_TYPE xQueueGenericReset( xQueueHandle xQueue, portBASE_TYPE xNewQueue )
00247 {
00248 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
00249 
00250     configASSERT( pxQueue );
00251 
00252     taskENTER_CRITICAL();
00253     {
00254         pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize );
00255         pxQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
00256         pxQueue->pcWriteTo = pxQueue->pcHead;
00257         pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( unsigned portBASE_TYPE ) 1U ) * pxQueue->uxItemSize );
00258         pxQueue->xRxLock = queueUNLOCKED;
00259         pxQueue->xTxLock = queueUNLOCKED;
00260 
00261         if( xNewQueue == pdFALSE )
00262         {
00263             /* If there are tasks blocked waiting to read from the queue, then
00264             the tasks will remain blocked as after this function exits the queue
00265             will still be empty.  If there are tasks blocked waiting to write to
00266             the queue, then one should be unblocked as after this function exits
00267             it will be possible to write to it. */
00268             if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
00269             {
00270                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
00271                 {
00272                     queueYIELD_IF_USING_PREEMPTION();
00273                 }
00274             }
00275         }
00276         else
00277         {
00278             /* Ensure the event queues start in the correct state. */
00279             vListInitialise( &( pxQueue->xTasksWaitingToSend ) );
00280             vListInitialise( &( pxQueue->xTasksWaitingToReceive ) );
00281         }
00282     }
00283     taskEXIT_CRITICAL();
00284 
00285     /* A value is returned for calling semantic consistency with previous
00286     versions. */
00287     return pdPASS;
00288 }
00289 /*-----------------------------------------------------------*/
00290 
00291 xQueueHandle xQueueGenericCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize, unsigned char ucQueueType )
00292 {
00293 xQUEUE *pxNewQueue;
00294 size_t xQueueSizeInBytes;
00295 xQueueHandle xReturn = NULL;
00296 
00297     /* Remove compiler warnings about unused parameters should
00298     configUSE_TRACE_FACILITY not be set to 1. */
00299     ( void ) ucQueueType;
00300 
00301     /* Allocate the new queue structure. */
00302     if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )
00303     {
00304         pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
00305         if( pxNewQueue != NULL )
00306         {
00307             /* Create the list of pointers to queue items.  The queue is one byte
00308             longer than asked for to make wrap checking easier/faster. */
00309             xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
00310 
00311             pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes );
00312             if( pxNewQueue->pcHead != NULL )
00313             {
00314                 /* Initialise the queue members as described above where the
00315                 queue type is defined. */
00316                 pxNewQueue->uxLength = uxQueueLength;
00317                 pxNewQueue->uxItemSize = uxItemSize;
00318                 ( void ) xQueueGenericReset( pxNewQueue, pdTRUE );
00319 
00320                 #if ( configUSE_TRACE_FACILITY == 1 )
00321                 {
00322                     pxNewQueue->ucQueueType = ucQueueType;
00323                 }
00324                 #endif /* configUSE_TRACE_FACILITY */
00325 
00326                 #if( configUSE_QUEUE_SETS == 1 )
00327                 {
00328                     pxNewQueue->pxQueueSetContainer = NULL;
00329                 }
00330                 #endif /* configUSE_QUEUE_SETS */
00331 
00332                 traceQUEUE_CREATE( pxNewQueue );
00333                 xReturn = pxNewQueue;
00334             }
00335             else
00336             {
00337                 traceQUEUE_CREATE_FAILED( ucQueueType );
00338                 vPortFree( pxNewQueue );
00339             }
00340         }
00341     }
00342 
00343     configASSERT( xReturn );
00344 
00345     return xReturn;
00346 }
00347 /*-----------------------------------------------------------*/
00348 
00349 #if ( configUSE_MUTEXES == 1 )
00350 
00351     xQueueHandle xQueueCreateMutex( unsigned char ucQueueType )
00352     {
00353     xQUEUE *pxNewQueue;
00354 
00355         /* Prevent compiler warnings about unused parameters if
00356         configUSE_TRACE_FACILITY does not equal 1. */
00357         ( void ) ucQueueType;
00358 
00359         /* Allocate the new queue structure. */
00360         pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
00361         if( pxNewQueue != NULL )
00362         {
00363             /* Information required for priority inheritance. */
00364             pxNewQueue->pxMutexHolder = NULL;
00365             pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
00366 
00367             /* Queues used as a mutex no data is actually copied into or out
00368             of the queue. */
00369             pxNewQueue->pcWriteTo = NULL;
00370             pxNewQueue->u.pcReadFrom = NULL;
00371 
00372             /* Each mutex has a length of 1 (like a binary semaphore) and
00373             an item size of 0 as nothing is actually copied into or out
00374             of the mutex. */
00375             pxNewQueue->uxMessagesWaiting = ( unsigned portBASE_TYPE ) 0U;
00376             pxNewQueue->uxLength = ( unsigned portBASE_TYPE ) 1U;
00377             pxNewQueue->uxItemSize = ( unsigned portBASE_TYPE ) 0U;
00378             pxNewQueue->xRxLock = queueUNLOCKED;
00379             pxNewQueue->xTxLock = queueUNLOCKED;
00380 
00381             #if ( configUSE_TRACE_FACILITY == 1 )
00382             {
00383                 pxNewQueue->ucQueueType = ucQueueType;
00384             }
00385             #endif
00386 
00387             #if ( configUSE_QUEUE_SETS == 1 )
00388             {
00389                 pxNewQueue->pxQueueSetContainer = NULL;
00390             }
00391             #endif
00392 
00393             /* Ensure the event queues start with the correct state. */
00394             vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
00395             vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
00396 
00397             traceCREATE_MUTEX( pxNewQueue );
00398 
00399             /* Start with the semaphore in the expected state. */
00400             ( void ) xQueueGenericSend( pxNewQueue, NULL, ( portTickType ) 0U, queueSEND_TO_BACK );
00401         }
00402         else
00403         {
00404             traceCREATE_MUTEX_FAILED();
00405         }
00406 
00407         configASSERT( pxNewQueue );
00408         return pxNewQueue;
00409     }
00410 
00411 #endif /* configUSE_MUTEXES */
00412 /*-----------------------------------------------------------*/
00413 
00414 #if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
00415 
00416     void* xQueueGetMutexHolder( xQueueHandle xSemaphore )
00417     {
00418     void *pxReturn;
00419 
00420         /* This function is called by xSemaphoreGetMutexHolder(), and should not
00421         be called directly.  Note:  This is is a good way of determining if the
00422         calling task is the mutex holder, but not a good way of determining the
00423         identity of the mutex holder, as the holder may change between the
00424         following critical section exiting and the function returning. */
00425         taskENTER_CRITICAL();
00426         {
00427             if( ( ( xQUEUE * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX )
00428             {
00429                 pxReturn = ( void * ) ( ( xQUEUE * ) xSemaphore )->pxMutexHolder;
00430             }
00431             else
00432             {
00433                 pxReturn = NULL;
00434             }
00435         }
00436         taskEXIT_CRITICAL();
00437 
00438         return pxReturn;
00439     }
00440 
00441 #endif
00442 /*-----------------------------------------------------------*/
00443 
00444 #if ( configUSE_RECURSIVE_MUTEXES == 1 )
00445 
00446     portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex )
00447     {
00448     portBASE_TYPE xReturn;
00449     xQUEUE * const pxMutex = ( xQUEUE * ) xMutex;
00450 
00451         configASSERT( pxMutex );
00452 
00453         /* If this is the task that holds the mutex then pxMutexHolder will not
00454         change outside of this task.  If this task does not hold the mutex then
00455         pxMutexHolder can never coincidentally equal the tasks handle, and as
00456         this is the only condition we are interested in it does not matter if
00457         pxMutexHolder is accessed simultaneously by another task.  Therefore no
00458         mutual exclusion is required to test the pxMutexHolder variable. */
00459         if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Not a redundant cast as xTaskHandle is a typedef. */
00460         {
00461             traceGIVE_MUTEX_RECURSIVE( pxMutex );
00462 
00463             /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to
00464             the task handle, therefore no underflow check is required.  Also,
00465             uxRecursiveCallCount is only modified by the mutex holder, and as
00466             there can only be one, no mutual exclusion is required to modify the
00467             uxRecursiveCallCount member. */
00468             ( pxMutex->u.uxRecursiveCallCount )--;
00469 
00470             /* Have we unwound the call count? */
00471             if( pxMutex->u.uxRecursiveCallCount == ( unsigned portBASE_TYPE ) 0 )
00472             {
00473                 /* Return the mutex.  This will automatically unblock any other
00474                 task that might be waiting to access the mutex. */
00475                 ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
00476             }
00477 
00478             xReturn = pdPASS;
00479         }
00480         else
00481         {
00482             /* We cannot give the mutex because we are not the holder. */
00483             xReturn = pdFAIL;
00484 
00485             traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
00486         }
00487 
00488         return xReturn;
00489     }
00490 
00491 #endif /* configUSE_RECURSIVE_MUTEXES */
00492 /*-----------------------------------------------------------*/
00493 
00494 #if ( configUSE_RECURSIVE_MUTEXES == 1 )
00495 
00496     portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime )
00497     {
00498     portBASE_TYPE xReturn;
00499     xQUEUE * const pxMutex = ( xQUEUE * ) xMutex;
00500 
00501         configASSERT( pxMutex );
00502 
00503         /* Comments regarding mutual exclusion as per those within
00504         xQueueGiveMutexRecursive(). */
00505 
00506         traceTAKE_MUTEX_RECURSIVE( pxMutex );
00507 
00508         if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() ) /*lint !e961 Cast is not redundant as xTaskHandle is a typedef. */
00509         {
00510             ( pxMutex->u.uxRecursiveCallCount )++;
00511             xReturn = pdPASS;
00512         }
00513         else
00514         {
00515             xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );
00516 
00517             /* pdPASS will only be returned if we successfully obtained the mutex,
00518             we may have blocked to reach here. */
00519             if( xReturn == pdPASS )
00520             {
00521                 ( pxMutex->u.uxRecursiveCallCount )++;
00522             }
00523             else
00524             {
00525                 traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );
00526             }
00527         }
00528 
00529         return xReturn;
00530     }
00531 
00532 #endif /* configUSE_RECURSIVE_MUTEXES */
00533 /*-----------------------------------------------------------*/
00534 
00535 #if ( configUSE_COUNTING_SEMAPHORES == 1 )
00536 
00537     xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount )
00538     {
00539     xQueueHandle xHandle;
00540 
00541         configASSERT( uxMaxCount != 0 );
00542         configASSERT( uxInitialCount <= uxMaxCount );
00543 
00544         xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
00545 
00546         if( xHandle != NULL )
00547         {
00548             ( ( xQUEUE * ) xHandle )->uxMessagesWaiting = uxInitialCount;
00549 
00550             traceCREATE_COUNTING_SEMAPHORE();
00551         }
00552         else
00553         {
00554             traceCREATE_COUNTING_SEMAPHORE_FAILED();
00555         }
00556 
00557         configASSERT( xHandle );
00558         return xHandle;
00559     }
00560 
00561 #endif /* configUSE_COUNTING_SEMAPHORES */
00562 /*-----------------------------------------------------------*/
00563 
00564 signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
00565 {
00566 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
00567 xTimeOutType xTimeOut;
00568 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
00569 
00570     configASSERT( pxQueue );
00571     configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
00572     configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
00573 
00574     /* This function relaxes the coding standard somewhat to allow return
00575     statements within the function itself.  This is done in the interest
00576     of execution time efficiency. */
00577     for( ;; )
00578     {
00579         taskENTER_CRITICAL();
00580         {
00581             /* Is there room on the queue now?  The running task must be
00582             the highest priority task wanting to access the queue.  If
00583             the head item in the queue is to be overwritten then it does
00584             not matter if the queue is full. */
00585             if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
00586             {
00587                 traceQUEUE_SEND( pxQueue );
00588                 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
00589 
00590                 #if ( configUSE_QUEUE_SETS == 1 )
00591                 {
00592                     if( pxQueue->pxQueueSetContainer != NULL )
00593                     {
00594                         if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )
00595                         {
00596                             /* The queue is a member of a queue set, and posting
00597                             to the queue set caused a higher priority task to
00598                             unblock. A context switch is required. */
00599                             queueYIELD_IF_USING_PREEMPTION();
00600                         }
00601                     }
00602                     else
00603                     {
00604                         /* If there was a task waiting for data to arrive on the
00605                         queue then unblock it now. */
00606                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
00607                         {
00608                             if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
00609                             {
00610                                 /* The unblocked task has a priority higher than
00611                                 our own so yield immediately.  Yes it is ok to
00612                                 do this from within the critical section - the
00613                                 kernel takes care of that. */
00614                                 queueYIELD_IF_USING_PREEMPTION();
00615                             }
00616                         }
00617                     }
00618                 }
00619                 #else /* configUSE_QUEUE_SETS */
00620                 {
00621                     /* If there was a task waiting for data to arrive on the
00622                     queue then unblock it now. */
00623                     if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
00624                     {
00625                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
00626                         {
00627                             /* The unblocked task has a priority higher than
00628                             our own so yield immediately.  Yes it is ok to do
00629                             this from within the critical section - the kernel
00630                             takes care of that. */
00631                             queueYIELD_IF_USING_PREEMPTION();
00632                         }
00633                     }
00634                 }
00635                 #endif /* configUSE_QUEUE_SETS */
00636 
00637                 taskEXIT_CRITICAL();
00638 
00639                 /* Return to the original privilege level before exiting the
00640                 function. */
00641                 return pdPASS;
00642             }
00643             else
00644             {
00645                 if( xTicksToWait == ( portTickType ) 0 )
00646                 {
00647                     /* The queue was full and no block time is specified (or
00648                     the block time has expired) so leave now. */
00649                     taskEXIT_CRITICAL();
00650 
00651                     /* Return to the original privilege level before exiting
00652                     the function. */
00653                     traceQUEUE_SEND_FAILED( pxQueue );
00654                     return errQUEUE_FULL;
00655                 }
00656                 else if( xEntryTimeSet == pdFALSE )
00657                 {
00658                     /* The queue was full and a block time was specified so
00659                     configure the timeout structure. */
00660                     vTaskSetTimeOutState( &xTimeOut );
00661                     xEntryTimeSet = pdTRUE;
00662                 }
00663                 else
00664                 {
00665                     /* Entry time was already set. */
00666                 }
00667             }
00668         }
00669         taskEXIT_CRITICAL();
00670 
00671         /* Interrupts and other tasks can send to and receive from the queue
00672         now the critical section has been exited. */
00673 
00674         vTaskSuspendAll();
00675         prvLockQueue( pxQueue );
00676 
00677         /* Update the timeout state to see if it has expired yet. */
00678         if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
00679         {
00680             if( prvIsQueueFull( pxQueue ) != pdFALSE )
00681             {
00682                 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
00683                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
00684 
00685                 /* Unlocking the queue means queue events can effect the
00686                 event list.  It is possible that interrupts occurring now
00687                 remove this task from the event list again - but as the
00688                 scheduler is suspended the task will go onto the pending
00689                 ready last instead of the actual ready list. */
00690                 prvUnlockQueue( pxQueue );
00691 
00692                 /* Resuming the scheduler will move tasks from the pending
00693                 ready list into the ready list - so it is feasible that this
00694                 task is already in a ready list before it yields - in which
00695                 case the yield will not cause a context switch unless there
00696                 is also a higher priority task in the pending ready list. */
00697                 if( xTaskResumeAll() == pdFALSE )
00698                 {
00699                     portYIELD_WITHIN_API();
00700                 }
00701             }
00702             else
00703             {
00704                 /* Try again. */
00705                 prvUnlockQueue( pxQueue );
00706                 ( void ) xTaskResumeAll();
00707             }
00708         }
00709         else
00710         {
00711             /* The timeout has expired. */
00712             prvUnlockQueue( pxQueue );
00713             ( void ) xTaskResumeAll();
00714 
00715             /* Return to the original privilege level before exiting the
00716             function. */
00717             traceQUEUE_SEND_FAILED( pxQueue );
00718             return errQUEUE_FULL;
00719         }
00720     }
00721 }
00722 /*-----------------------------------------------------------*/
00723 
00724 #if ( configUSE_ALTERNATIVE_API == 1 )
00725 
00726     signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
00727     {
00728     signed portBASE_TYPE xEntryTimeSet = pdFALSE;
00729     xTimeOutType xTimeOut;
00730     xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
00731 
00732         configASSERT( pxQueue );
00733         configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
00734 
00735         for( ;; )
00736         {
00737             taskENTER_CRITICAL();
00738             {
00739                 /* Is there room on the queue now?  To be running we must be
00740                 the highest priority task wanting to access the queue. */
00741                 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
00742                 {
00743                     traceQUEUE_SEND( pxQueue );
00744                     prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
00745 
00746                     /* If there was a task waiting for data to arrive on the
00747                     queue then unblock it now. */
00748                     if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
00749                     {
00750                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
00751                         {
00752                             /* The unblocked task has a priority higher than
00753                             our own so yield immediately. */
00754                             portYIELD_WITHIN_API();
00755                         }
00756                     }
00757 
00758                     taskEXIT_CRITICAL();
00759                     return pdPASS;
00760                 }
00761                 else
00762                 {
00763                     if( xTicksToWait == ( portTickType ) 0 )
00764                     {
00765                         taskEXIT_CRITICAL();
00766                         return errQUEUE_FULL;
00767                     }
00768                     else if( xEntryTimeSet == pdFALSE )
00769                     {
00770                         vTaskSetTimeOutState( &xTimeOut );
00771                         xEntryTimeSet = pdTRUE;
00772                     }
00773                 }
00774             }
00775             taskEXIT_CRITICAL();
00776 
00777             taskENTER_CRITICAL();
00778             {
00779                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
00780                 {
00781                     if( prvIsQueueFull( pxQueue ) != pdFALSE )
00782                     {
00783                         traceBLOCKING_ON_QUEUE_SEND( pxQueue );
00784                         vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
00785                         portYIELD_WITHIN_API();
00786                     }
00787                 }
00788                 else
00789                 {
00790                     taskEXIT_CRITICAL();
00791                     traceQUEUE_SEND_FAILED( pxQueue );
00792                     return errQUEUE_FULL;
00793                 }
00794             }
00795             taskEXIT_CRITICAL();
00796         }
00797     }
00798 
00799 #endif /* configUSE_ALTERNATIVE_API */
00800 /*-----------------------------------------------------------*/
00801 
00802 #if ( configUSE_ALTERNATIVE_API == 1 )
00803 
00804     signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
00805     {
00806     signed portBASE_TYPE xEntryTimeSet = pdFALSE;
00807     xTimeOutType xTimeOut;
00808     signed char *pcOriginalReadPosition;
00809     xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
00810 
00811         configASSERT( pxQueue );
00812         configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
00813 
00814         for( ;; )
00815         {
00816             taskENTER_CRITICAL();
00817             {
00818                 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
00819                 {
00820                     /* Remember our read position in case we are just peeking. */
00821                     pcOriginalReadPosition = pxQueue->u.pcReadFrom;
00822 
00823                     prvCopyDataFromQueue( pxQueue, pvBuffer );
00824 
00825                     if( xJustPeeking == pdFALSE )
00826                     {
00827                         traceQUEUE_RECEIVE( pxQueue );
00828 
00829                         /* Data is actually being removed (not just peeked). */
00830                         --( pxQueue->uxMessagesWaiting );
00831 
00832                         #if ( configUSE_MUTEXES == 1 )
00833                         {
00834                             if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
00835                             {
00836                                 /* Record the information required to implement
00837                                 priority inheritance should it become necessary. */
00838                                 pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle();
00839                             }
00840                         }
00841                         #endif
00842 
00843                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
00844                         {
00845                             if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
00846                             {
00847                                 portYIELD_WITHIN_API();
00848                             }
00849                         }
00850                     }
00851                     else
00852                     {
00853                         traceQUEUE_PEEK( pxQueue );
00854 
00855                         /* We are not removing the data, so reset our read
00856                         pointer. */
00857                         pxQueue->u.pcReadFrom = pcOriginalReadPosition;
00858 
00859                         /* The data is being left in the queue, so see if there are
00860                         any other tasks waiting for the data. */
00861                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
00862                         {
00863                             /* Tasks that are removed from the event list will get added to
00864                             the pending ready list as the scheduler is still suspended. */
00865                             if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
00866                             {
00867                                 /* The task waiting has a higher priority than this task. */
00868                                 portYIELD_WITHIN_API();
00869                             }
00870                         }
00871 
00872                     }
00873 
00874                     taskEXIT_CRITICAL();
00875                     return pdPASS;
00876                 }
00877                 else
00878                 {
00879                     if( xTicksToWait == ( portTickType ) 0 )
00880                     {
00881                         taskEXIT_CRITICAL();
00882                         traceQUEUE_RECEIVE_FAILED( pxQueue );
00883                         return errQUEUE_EMPTY;
00884                     }
00885                     else if( xEntryTimeSet == pdFALSE )
00886                     {
00887                         vTaskSetTimeOutState( &xTimeOut );
00888                         xEntryTimeSet = pdTRUE;
00889                     }
00890                 }
00891             }
00892             taskEXIT_CRITICAL();
00893 
00894             taskENTER_CRITICAL();
00895             {
00896                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
00897                 {
00898                     if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
00899                     {
00900                         traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
00901 
00902                         #if ( configUSE_MUTEXES == 1 )
00903                         {
00904                             if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
00905                             {
00906                                 portENTER_CRITICAL();
00907                                 {
00908                                     vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
00909                                 }
00910                                 portEXIT_CRITICAL();
00911                             }
00912                         }
00913                         #endif
00914 
00915                         vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
00916                         portYIELD_WITHIN_API();
00917                     }
00918                 }
00919                 else
00920                 {
00921                     taskEXIT_CRITICAL();
00922                     traceQUEUE_RECEIVE_FAILED( pxQueue );
00923                     return errQUEUE_EMPTY;
00924                 }
00925             }
00926             taskEXIT_CRITICAL();
00927         }
00928     }
00929 
00930 
00931 #endif /* configUSE_ALTERNATIVE_API */
00932 /*-----------------------------------------------------------*/
00933 
00934 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle xQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )
00935 {
00936 signed portBASE_TYPE xReturn;
00937 unsigned portBASE_TYPE uxSavedInterruptStatus;
00938 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
00939 
00940     configASSERT( pxQueue );
00941     configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
00942     configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
00943 
00944     /* RTOS ports that support interrupt nesting have the concept of a maximum
00945     system call (or maximum API call) interrupt priority.  Interrupts that are
00946     above the maximum system call priority are keep permanently enabled, even
00947     when the RTOS kernel is in a critical section, but cannot make any calls to
00948     FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h
00949     then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
00950     failure if a FreeRTOS API function is called from an interrupt that has been
00951     assigned a priority above the configured maximum system call priority.
00952     Only FreeRTOS functions that end in FromISR can be called from interrupts
00953     that have been assigned a priority at or (logically) below the maximum
00954     system call interrupt priority.  FreeRTOS maintains a separate interrupt
00955     safe API to ensure interrupt entry is as fast and as simple as possible.
00956     More information (albeit Cortex-M specific) is provided on the following
00957     link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
00958     portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
00959 
00960     /* Similar to xQueueGenericSend, except we don't block if there is no room
00961     in the queue.  Also we don't directly wake a task that was blocked on a
00962     queue read, instead we return a flag to say whether a context switch is
00963     required or not (i.e. has a task with a higher priority than us been woken
00964     by this post). */
00965     uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
00966     {
00967         if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
00968         {
00969             traceQUEUE_SEND_FROM_ISR( pxQueue );
00970 
00971             prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
00972 
00973             /* If the queue is locked we do not alter the event list.  This will
00974             be done when the queue is unlocked later. */
00975             if( pxQueue->xTxLock == queueUNLOCKED )
00976             {
00977                 #if ( configUSE_QUEUE_SETS == 1 )
00978                 {
00979                     if( pxQueue->pxQueueSetContainer != NULL )
00980                     {
00981                         if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) == pdTRUE )
00982                         {
00983                             /* The queue is a member of a queue set, and posting
00984                             to the queue set caused a higher priority task to
00985                             unblock.  A context switch is required. */
00986                             if( pxHigherPriorityTaskWoken != NULL )
00987                             {
00988                                 *pxHigherPriorityTaskWoken = pdTRUE;
00989                             }
00990                         }
00991                     }
00992                     else
00993                     {
00994                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
00995                         {
00996                             if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
00997                             {
00998                                 /* The task waiting has a higher priority so record that a
00999                                 context switch is required. */
01000                                 if( pxHigherPriorityTaskWoken != NULL )
01001                                 {
01002                                     *pxHigherPriorityTaskWoken = pdTRUE;
01003                                 }
01004                             }
01005                         }
01006                     }
01007                 }
01008                 #else /* configUSE_QUEUE_SETS */
01009                 {
01010                     if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
01011                     {
01012                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
01013                         {
01014                             /* The task waiting has a higher priority so record that a
01015                             context switch is required. */
01016                             if( pxHigherPriorityTaskWoken != NULL )
01017                             {
01018                                 *pxHigherPriorityTaskWoken = pdTRUE;
01019                             }
01020                         }
01021                     }
01022                 }
01023                 #endif /* configUSE_QUEUE_SETS */
01024             }
01025             else
01026             {
01027                 /* Increment the lock count so the task that unlocks the queue
01028                 knows that data was posted while it was locked. */
01029                 ++( pxQueue->xTxLock );
01030             }
01031 
01032             xReturn = pdPASS;
01033         }
01034         else
01035         {
01036             traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
01037             xReturn = errQUEUE_FULL;
01038         }
01039     }
01040     portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
01041 
01042     return xReturn;
01043 }
01044 /*-----------------------------------------------------------*/
01045 
01046 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle xQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
01047 {
01048 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
01049 xTimeOutType xTimeOut;
01050 signed char *pcOriginalReadPosition;
01051 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
01052 
01053     configASSERT( pxQueue );
01054     configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
01055 
01056     /* This function relaxes the coding standard somewhat to allow return
01057     statements within the function itself.  This is done in the interest
01058     of execution time efficiency. */
01059 
01060     for( ;; )
01061     {
01062         taskENTER_CRITICAL();
01063         {
01064             /* Is there data in the queue now?  To be running we must be
01065             the highest priority task wanting to access the queue. */
01066             if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
01067             {
01068                 /* Remember the read position in case the queue is only being
01069                 peeked. */
01070                 pcOriginalReadPosition = pxQueue->u.pcReadFrom;
01071 
01072                 prvCopyDataFromQueue( pxQueue, pvBuffer );
01073 
01074                 if( xJustPeeking == pdFALSE )
01075                 {
01076                     traceQUEUE_RECEIVE( pxQueue );
01077 
01078                     /* Actually removing data, not just peeking. */
01079                     --( pxQueue->uxMessagesWaiting );
01080 
01081                     #if ( configUSE_MUTEXES == 1 )
01082                     {
01083                         if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
01084                         {
01085                             /* Record the information required to implement
01086                             priority inheritance should it become necessary. */
01087                             pxQueue->pxMutexHolder = ( signed char * ) xTaskGetCurrentTaskHandle(); /*lint !e961 Cast is not redundant as xTaskHandle is a typedef. */
01088                         }
01089                     }
01090                     #endif
01091 
01092                     if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
01093                     {
01094                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
01095                         {
01096                             queueYIELD_IF_USING_PREEMPTION();
01097                         }
01098                     }
01099                 }
01100                 else
01101                 {
01102                     traceQUEUE_PEEK( pxQueue );
01103 
01104                     /* The data is not being removed, so reset the read
01105                     pointer. */
01106                     pxQueue->u.pcReadFrom = pcOriginalReadPosition;
01107 
01108                     /* The data is being left in the queue, so see if there are
01109                     any other tasks waiting for the data. */
01110                     if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
01111                     {
01112                         /* Tasks that are removed from the event list will get added to
01113                         the pending ready list as the scheduler is still suspended. */
01114                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
01115                         {
01116                             /* The task waiting has a higher priority than this task. */
01117                             queueYIELD_IF_USING_PREEMPTION();
01118                         }
01119                     }
01120                 }
01121 
01122                 taskEXIT_CRITICAL();
01123                 return pdPASS;
01124             }
01125             else
01126             {
01127                 if( xTicksToWait == ( portTickType ) 0 )
01128                 {
01129                     /* The queue was empty and no block time is specified (or
01130                     the block time has expired) so leave now. */
01131                     taskEXIT_CRITICAL();
01132                     traceQUEUE_RECEIVE_FAILED( pxQueue );
01133                     return errQUEUE_EMPTY;
01134                 }
01135                 else if( xEntryTimeSet == pdFALSE )
01136                 {
01137                     /* The queue was empty and a block time was specified so
01138                     configure the timeout structure. */
01139                     vTaskSetTimeOutState( &xTimeOut );
01140                     xEntryTimeSet = pdTRUE;
01141                 }
01142                 else
01143                 {
01144                     /* Entry time was already set. */
01145                 }
01146             }
01147         }
01148         taskEXIT_CRITICAL();
01149 
01150         /* Interrupts and other tasks can send to and receive from the queue
01151         now the critical section has been exited. */
01152 
01153         vTaskSuspendAll();
01154         prvLockQueue( pxQueue );
01155 
01156         /* Update the timeout state to see if it has expired yet. */
01157         if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
01158         {
01159             if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
01160             {
01161                 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
01162 
01163                 #if ( configUSE_MUTEXES == 1 )
01164                 {
01165                     if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
01166                     {
01167                         portENTER_CRITICAL();
01168                         {
01169                             vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
01170                         }
01171                         portEXIT_CRITICAL();
01172                     }
01173                 }
01174                 #endif
01175 
01176                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
01177                 prvUnlockQueue( pxQueue );
01178                 if( xTaskResumeAll() == pdFALSE )
01179                 {
01180                     portYIELD_WITHIN_API();
01181                 }
01182             }
01183             else
01184             {
01185                 /* Try again. */
01186                 prvUnlockQueue( pxQueue );
01187                 ( void ) xTaskResumeAll();
01188             }
01189         }
01190         else
01191         {
01192             prvUnlockQueue( pxQueue );
01193             ( void ) xTaskResumeAll();
01194             traceQUEUE_RECEIVE_FAILED( pxQueue );
01195             return errQUEUE_EMPTY;
01196         }
01197     }
01198 }
01199 /*-----------------------------------------------------------*/
01200 
01201 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle xQueue, void * const pvBuffer, signed portBASE_TYPE *pxHigherPriorityTaskWoken )
01202 {
01203 signed portBASE_TYPE xReturn;
01204 unsigned portBASE_TYPE uxSavedInterruptStatus;
01205 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
01206 
01207     configASSERT( pxQueue );
01208     configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
01209 
01210     /* RTOS ports that support interrupt nesting have the concept of a maximum
01211     system call (or maximum API call) interrupt priority.  Interrupts that are
01212     above the maximum system call priority are keep permanently enabled, even
01213     when the RTOS kernel is in a critical section, but cannot make any calls to
01214     FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h
01215     then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
01216     failure if a FreeRTOS API function is called from an interrupt that has been
01217     assigned a priority above the configured maximum system call priority.
01218     Only FreeRTOS functions that end in FromISR can be called from interrupts
01219     that have been assigned a priority at or (logically) below the maximum
01220     system call interrupt priority.  FreeRTOS maintains a separate interrupt
01221     safe API to ensure interrupt entry is as fast and as simple as possible.
01222     More information (albeit Cortex-M specific) is provided on the following
01223     link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
01224     portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
01225 
01226     uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
01227     {
01228         /* Cannot block in an ISR, so check there is data available. */
01229         if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
01230         {
01231             traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
01232 
01233             prvCopyDataFromQueue( pxQueue, pvBuffer );
01234             --( pxQueue->uxMessagesWaiting );
01235 
01236             /* If the queue is locked the event list will not be modified.
01237             Instead update the lock count so the task that unlocks the queue
01238             will know that an ISR has removed data while the queue was
01239             locked. */
01240             if( pxQueue->xRxLock == queueUNLOCKED )
01241             {
01242                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
01243                 {
01244                     if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
01245                     {
01246                         /* The task waiting has a higher priority than us so
01247                         force a context switch. */
01248                         if( pxHigherPriorityTaskWoken != NULL )
01249                         {
01250                             *pxHigherPriorityTaskWoken = pdTRUE;
01251                         }
01252                     }
01253                 }
01254             }
01255             else
01256             {
01257                 /* Increment the lock count so the task that unlocks the queue
01258                 knows that data was removed while it was locked. */
01259                 ++( pxQueue->xRxLock );
01260             }
01261 
01262             xReturn = pdPASS;
01263         }
01264         else
01265         {
01266             xReturn = pdFAIL;
01267             traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
01268         }
01269     }
01270     portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
01271 
01272     return xReturn;
01273 }
01274 /*-----------------------------------------------------------*/
01275 
01276 signed portBASE_TYPE xQueuePeekFromISR( xQueueHandle xQueue,  void * const pvBuffer )
01277 {
01278 signed portBASE_TYPE xReturn;
01279 unsigned portBASE_TYPE uxSavedInterruptStatus;
01280 signed char *pcOriginalReadPosition;
01281 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
01282 
01283     configASSERT( pxQueue );
01284     configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
01285 
01286     /* RTOS ports that support interrupt nesting have the concept of a maximum
01287     system call (or maximum API call) interrupt priority.  Interrupts that are
01288     above the maximum system call priority are keep permanently enabled, even
01289     when the RTOS kernel is in a critical section, but cannot make any calls to
01290     FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h
01291     then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
01292     failure if a FreeRTOS API function is called from an interrupt that has been
01293     assigned a priority above the configured maximum system call priority.
01294     Only FreeRTOS functions that end in FromISR can be called from interrupts
01295     that have been assigned a priority at or (logically) below the maximum
01296     system call interrupt priority.  FreeRTOS maintains a separate interrupt
01297     safe API to ensure interrupt entry is as fast and as simple as possible.
01298     More information (albeit Cortex-M specific) is provided on the following
01299     link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
01300     portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
01301 
01302     uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
01303     {
01304         /* Cannot block in an ISR, so check there is data available. */
01305         if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
01306         {
01307             traceQUEUE_PEEK_FROM_ISR( pxQueue );
01308 
01309             /* Remember the read position so it can be reset as nothing is
01310             actually being removed from the queue. */
01311             pcOriginalReadPosition = pxQueue->u.pcReadFrom;
01312             prvCopyDataFromQueue( pxQueue, pvBuffer );
01313             pxQueue->u.pcReadFrom = pcOriginalReadPosition;
01314 
01315             xReturn = pdPASS;
01316         }
01317         else
01318         {
01319             xReturn = pdFAIL;
01320             traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue );
01321         }
01322     }
01323     portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
01324 
01325     return xReturn;
01326 }
01327 /*-----------------------------------------------------------*/
01328 
01329 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle xQueue )
01330 {
01331 unsigned portBASE_TYPE uxReturn;
01332 
01333     configASSERT( xQueue );
01334 
01335     taskENTER_CRITICAL();
01336         uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting;
01337     taskEXIT_CRITICAL();
01338 
01339     return uxReturn;
01340 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
01341 /*-----------------------------------------------------------*/
01342 
01343 unsigned portBASE_TYPE uxQueueSpacesAvailable( const xQueueHandle xQueue )
01344 {
01345 unsigned portBASE_TYPE uxReturn;
01346 xQUEUE *pxQueue;
01347 
01348     pxQueue = ( xQUEUE * ) xQueue;
01349     configASSERT( pxQueue );
01350 
01351     taskENTER_CRITICAL();
01352         uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting;
01353     taskEXIT_CRITICAL();
01354 
01355     return uxReturn;
01356 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
01357 /*-----------------------------------------------------------*/
01358 
01359 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle xQueue )
01360 {
01361 unsigned portBASE_TYPE uxReturn;
01362 
01363     configASSERT( xQueue );
01364 
01365     uxReturn = ( ( xQUEUE * ) xQueue )->uxMessagesWaiting;
01366 
01367     return uxReturn;
01368 } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
01369 /*-----------------------------------------------------------*/
01370 
01371 void vQueueDelete( xQueueHandle xQueue )
01372 {
01373 xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
01374 
01375     configASSERT( pxQueue );
01376 
01377     traceQUEUE_DELETE( pxQueue );
01378     #if ( configQUEUE_REGISTRY_SIZE > 0 )
01379     {
01380         vQueueUnregisterQueue( pxQueue );
01381     }
01382     #endif
01383     vPortFree( pxQueue->pcHead );
01384     vPortFree( pxQueue );
01385 }
01386 /*-----------------------------------------------------------*/
01387 
01388 #if ( configUSE_TRACE_FACILITY == 1 )
01389 
01390     unsigned char ucQueueGetQueueNumber( xQueueHandle xQueue )
01391     {
01392         return ( ( xQUEUE * ) xQueue )->ucQueueNumber;
01393     }
01394 
01395 #endif /* configUSE_TRACE_FACILITY */
01396 /*-----------------------------------------------------------*/
01397 
01398 #if ( configUSE_TRACE_FACILITY == 1 )
01399 
01400     void vQueueSetQueueNumber( xQueueHandle xQueue, unsigned char ucQueueNumber )
01401     {
01402         ( ( xQUEUE * ) xQueue )->ucQueueNumber = ucQueueNumber;
01403     }
01404 
01405 #endif /* configUSE_TRACE_FACILITY */
01406 /*-----------------------------------------------------------*/
01407 
01408 #if ( configUSE_TRACE_FACILITY == 1 )
01409 
01410     unsigned char ucQueueGetQueueType( xQueueHandle xQueue )
01411     {
01412         return ( ( xQUEUE * ) xQueue )->ucQueueType;
01413     }
01414 
01415 #endif /* configUSE_TRACE_FACILITY */
01416 /*-----------------------------------------------------------*/
01417 
01418 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )
01419 {
01420     if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )
01421     {
01422         #if ( configUSE_MUTEXES == 1 )
01423         {
01424             if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
01425             {
01426                 /* The mutex is no longer being held. */
01427                 vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
01428                 pxQueue->pxMutexHolder = NULL;
01429             }
01430         }
01431         #endif /* configUSE_MUTEXES */
01432     }
01433     else if( xPosition == queueSEND_TO_BACK )
01434     {
01435         ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. */
01436         pxQueue->pcWriteTo += pxQueue->uxItemSize;
01437         if( pxQueue->pcWriteTo >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */
01438         {
01439             pxQueue->pcWriteTo = pxQueue->pcHead;
01440         }
01441     }
01442     else
01443     {
01444         ( void ) memcpy( ( void * ) pxQueue->u.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
01445         pxQueue->u.pcReadFrom -= pxQueue->uxItemSize;
01446         if( pxQueue->u.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */
01447         {
01448             pxQueue->u.pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
01449         }
01450 
01451         if( xPosition == queueOVERWRITE )
01452         {
01453             if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
01454             {
01455                 /* An item is not being added but overwritten, so subtract
01456                 one from the recorded number of items in the queue so when
01457                 one is added again below the number of recorded items remains
01458                 correct. */
01459                 --( pxQueue->uxMessagesWaiting );
01460             }
01461         }
01462     }
01463 
01464     ++( pxQueue->uxMessagesWaiting );
01465 }
01466 /*-----------------------------------------------------------*/
01467 
01468 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, void * const pvBuffer )
01469 {
01470     if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
01471     {
01472         pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
01473         if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */
01474         {
01475             pxQueue->u.pcReadFrom = pxQueue->pcHead;
01476         }
01477         ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports.  Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. */
01478     }
01479 }
01480 /*-----------------------------------------------------------*/
01481 
01482 static void prvUnlockQueue( xQUEUE *pxQueue )
01483 {
01484     /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
01485 
01486     /* The lock counts contains the number of extra data items placed or
01487     removed from the queue while the queue was locked.  When a queue is
01488     locked items can be added or removed, but the event lists cannot be
01489     updated. */
01490     taskENTER_CRITICAL();
01491     {
01492         /* See if data was added to the queue while it was locked. */
01493         while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )
01494         {
01495             /* Data was posted while the queue was locked.  Are any tasks
01496             blocked waiting for data to become available? */
01497             #if ( configUSE_QUEUE_SETS == 1 )
01498             {
01499                 if( pxQueue->pxQueueSetContainer != NULL )
01500                 {
01501                     if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) == pdTRUE )
01502                     {
01503                         /* The queue is a member of a queue set, and posting to
01504                         the queue set caused a higher priority task to unblock.
01505                         A context switch is required. */
01506                         vTaskMissedYield();
01507                     }
01508                 }
01509                 else
01510                 {
01511                     /* Tasks that are removed from the event list will get added to
01512                     the pending ready list as the scheduler is still suspended. */
01513                     if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
01514                     {
01515                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
01516                         {
01517                             /* The task waiting has a higher priority so record that a
01518                             context switch is required. */
01519                             vTaskMissedYield();
01520                         }
01521                     }
01522                     else
01523                     {
01524                         break;
01525                     }
01526                 }
01527             }
01528             #else /* configUSE_QUEUE_SETS */
01529             {
01530                 /* Tasks that are removed from the event list will get added to
01531                 the pending ready list as the scheduler is still suspended. */
01532                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
01533                 {
01534                     if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
01535                     {
01536                         /* The task waiting has a higher priority so record that a
01537                         context switch is required. */
01538                         vTaskMissedYield();
01539                     }
01540                 }
01541                 else
01542                 {
01543                     break;
01544                 }
01545             }
01546             #endif /* configUSE_QUEUE_SETS */
01547 
01548             --( pxQueue->xTxLock );
01549         }
01550 
01551         pxQueue->xTxLock = queueUNLOCKED;
01552     }
01553     taskEXIT_CRITICAL();
01554 
01555     /* Do the same for the Rx lock. */
01556     taskENTER_CRITICAL();
01557     {
01558         while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )
01559         {
01560             if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
01561             {
01562                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
01563                 {
01564                     vTaskMissedYield();
01565                 }
01566 
01567                 --( pxQueue->xRxLock );
01568             }
01569             else
01570             {
01571                 break;
01572             }
01573         }
01574 
01575         pxQueue->xRxLock = queueUNLOCKED;
01576     }
01577     taskEXIT_CRITICAL();
01578 }
01579 /*-----------------------------------------------------------*/
01580 
01581 static signed portBASE_TYPE prvIsQueueEmpty( const xQUEUE *pxQueue )
01582 {
01583 signed portBASE_TYPE xReturn;
01584 
01585     taskENTER_CRITICAL();
01586     {
01587         if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE )  0 )
01588         {
01589             xReturn = pdTRUE;
01590         }
01591         else
01592         {
01593             xReturn = pdFALSE;
01594         }
01595     }
01596     taskEXIT_CRITICAL();
01597 
01598     return xReturn;
01599 }
01600 /*-----------------------------------------------------------*/
01601 
01602 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle xQueue )
01603 {
01604 signed portBASE_TYPE xReturn;
01605 
01606     configASSERT( xQueue );
01607     if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
01608     {
01609         xReturn = pdTRUE;
01610     }
01611     else
01612     {
01613         xReturn = pdFALSE;
01614     }
01615 
01616     return xReturn;
01617 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
01618 /*-----------------------------------------------------------*/
01619 
01620 static signed portBASE_TYPE prvIsQueueFull( const xQUEUE *pxQueue )
01621 {
01622 signed portBASE_TYPE xReturn;
01623 
01624     taskENTER_CRITICAL();
01625     {
01626         if( pxQueue->uxMessagesWaiting == pxQueue->uxLength )
01627         {
01628             xReturn = pdTRUE;
01629         }
01630         else
01631         {
01632             xReturn = pdFALSE;
01633         }
01634     }
01635     taskEXIT_CRITICAL();
01636 
01637     return xReturn;
01638 }
01639 /*-----------------------------------------------------------*/
01640 
01641 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle xQueue )
01642 {
01643 signed portBASE_TYPE xReturn;
01644 
01645     configASSERT( xQueue );
01646     if( ( ( xQUEUE * ) xQueue )->uxMessagesWaiting == ( ( xQUEUE * ) xQueue )->uxLength )
01647     {
01648         xReturn = pdTRUE;
01649     }
01650     else
01651     {
01652         xReturn = pdFALSE;
01653     }
01654 
01655     return xReturn;
01656 } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
01657 /*-----------------------------------------------------------*/
01658 
01659 #if ( configUSE_CO_ROUTINES == 1 )
01660 
01661     signed portBASE_TYPE xQueueCRSend( xQueueHandle xQueue, const void *pvItemToQueue, portTickType xTicksToWait )
01662     {
01663     signed portBASE_TYPE xReturn;
01664     xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
01665 
01666         /* If the queue is already full we may have to block.  A critical section
01667         is required to prevent an interrupt removing something from the queue
01668         between the check to see if the queue is full and blocking on the queue. */
01669         portDISABLE_INTERRUPTS();
01670         {
01671             if( prvIsQueueFull( pxQueue ) != pdFALSE )
01672             {
01673                 /* The queue is full - do we want to block or just leave without
01674                 posting? */
01675                 if( xTicksToWait > ( portTickType ) 0 )
01676                 {
01677                     /* As this is called from a coroutine we cannot block directly, but
01678                     return indicating that we need to block. */
01679                     vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
01680                     portENABLE_INTERRUPTS();
01681                     return errQUEUE_BLOCKED;
01682                 }
01683                 else
01684                 {
01685                     portENABLE_INTERRUPTS();
01686                     return errQUEUE_FULL;
01687                 }
01688             }
01689         }
01690         portENABLE_INTERRUPTS();
01691 
01692         portDISABLE_INTERRUPTS();
01693         {
01694             if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
01695             {
01696                 /* There is room in the queue, copy the data into the queue. */
01697                 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
01698                 xReturn = pdPASS;
01699 
01700                 /* Were any co-routines waiting for data to become available? */
01701                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
01702                 {
01703                     /* In this instance the co-routine could be placed directly
01704                     into the ready list as we are within a critical section.
01705                     Instead the same pending ready list mechanism is used as if
01706                     the event were caused from within an interrupt. */
01707                     if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
01708                     {
01709                         /* The co-routine waiting has a higher priority so record
01710                         that a yield might be appropriate. */
01711                         xReturn = errQUEUE_YIELD;
01712                     }
01713                 }
01714             }
01715             else
01716             {
01717                 xReturn = errQUEUE_FULL;
01718             }
01719         }
01720         portENABLE_INTERRUPTS();
01721 
01722         return xReturn;
01723     }
01724 
01725 #endif /* configUSE_CO_ROUTINES */
01726 /*-----------------------------------------------------------*/
01727 
01728 #if ( configUSE_CO_ROUTINES == 1 )
01729 
01730     signed portBASE_TYPE xQueueCRReceive( xQueueHandle xQueue, void *pvBuffer, portTickType xTicksToWait )
01731     {
01732     signed portBASE_TYPE xReturn;
01733     xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
01734 
01735         /* If the queue is already empty we may have to block.  A critical section
01736         is required to prevent an interrupt adding something to the queue
01737         between the check to see if the queue is empty and blocking on the queue. */
01738         portDISABLE_INTERRUPTS();
01739         {
01740             if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
01741             {
01742                 /* There are no messages in the queue, do we want to block or just
01743                 leave with nothing? */
01744                 if( xTicksToWait > ( portTickType ) 0 )
01745                 {
01746                     /* As this is a co-routine we cannot block directly, but return
01747                     indicating that we need to block. */
01748                     vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
01749                     portENABLE_INTERRUPTS();
01750                     return errQUEUE_BLOCKED;
01751                 }
01752                 else
01753                 {
01754                     portENABLE_INTERRUPTS();
01755                     return errQUEUE_FULL;
01756                 }
01757             }
01758         }
01759         portENABLE_INTERRUPTS();
01760 
01761         portDISABLE_INTERRUPTS();
01762         {
01763             if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
01764             {
01765                 /* Data is available from the queue. */
01766                 pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
01767                 if( pxQueue->u.pcReadFrom >= pxQueue->pcTail )
01768                 {
01769                     pxQueue->u.pcReadFrom = pxQueue->pcHead;
01770                 }
01771                 --( pxQueue->uxMessagesWaiting );
01772                 ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
01773 
01774                 xReturn = pdPASS;
01775 
01776                 /* Were any co-routines waiting for space to become available? */
01777                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
01778                 {
01779                     /* In this instance the co-routine could be placed directly
01780                     into the ready list as we are within a critical section.
01781                     Instead the same pending ready list mechanism is used as if
01782                     the event were caused from within an interrupt. */
01783                     if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
01784                     {
01785                         xReturn = errQUEUE_YIELD;
01786                     }
01787                 }
01788             }
01789             else
01790             {
01791                 xReturn = pdFAIL;
01792             }
01793         }
01794         portENABLE_INTERRUPTS();
01795 
01796         return xReturn;
01797     }
01798 
01799 #endif /* configUSE_CO_ROUTINES */
01800 /*-----------------------------------------------------------*/
01801 
01802 #if ( configUSE_CO_ROUTINES == 1 )
01803 
01804     signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle xQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
01805     {
01806     xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
01807 
01808         /* Cannot block within an ISR so if there is no space on the queue then
01809         exit without doing anything. */
01810         if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
01811         {
01812             prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
01813 
01814             /* We only want to wake one co-routine per ISR, so check that a
01815             co-routine has not already been woken. */
01816             if( xCoRoutinePreviouslyWoken == pdFALSE )
01817             {
01818                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
01819                 {
01820                     if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
01821                     {
01822                         return pdTRUE;
01823                     }
01824                 }
01825             }
01826         }
01827 
01828         return xCoRoutinePreviouslyWoken;
01829     }
01830 
01831 #endif /* configUSE_CO_ROUTINES */
01832 /*-----------------------------------------------------------*/
01833 
01834 #if ( configUSE_CO_ROUTINES == 1 )
01835 
01836     signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle xQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )
01837     {
01838     signed portBASE_TYPE xReturn;
01839     xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
01840 
01841         /* We cannot block from an ISR, so check there is data available. If
01842         not then just leave without doing anything. */
01843         if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
01844         {
01845             /* Copy the data from the queue. */
01846             pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
01847             if( pxQueue->u.pcReadFrom >= pxQueue->pcTail )
01848             {
01849                 pxQueue->u.pcReadFrom = pxQueue->pcHead;
01850             }
01851             --( pxQueue->uxMessagesWaiting );
01852             ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
01853 
01854             if( ( *pxCoRoutineWoken ) == pdFALSE )
01855             {
01856                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
01857                 {
01858                     if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
01859                     {
01860                         *pxCoRoutineWoken = pdTRUE;
01861                     }
01862                 }
01863             }
01864 
01865             xReturn = pdPASS;
01866         }
01867         else
01868         {
01869             xReturn = pdFAIL;
01870         }
01871 
01872         return xReturn;
01873     }
01874 
01875 #endif /* configUSE_CO_ROUTINES */
01876 /*-----------------------------------------------------------*/
01877 
01878 #if ( configQUEUE_REGISTRY_SIZE > 0 )
01879 
01880     void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )
01881     {
01882     unsigned portBASE_TYPE ux;
01883 
01884         /* See if there is an empty space in the registry.  A NULL name denotes
01885         a free slot. */
01886         for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
01887         {
01888             if( xQueueRegistry[ ux ].pcQueueName == NULL )
01889             {
01890                 /* Store the information on this queue. */
01891                 xQueueRegistry[ ux ].pcQueueName = pcQueueName;
01892                 xQueueRegistry[ ux ].xHandle = xQueue;
01893                 break;
01894             }
01895         }
01896     }
01897 
01898 #endif /* configQUEUE_REGISTRY_SIZE */
01899 /*-----------------------------------------------------------*/
01900 
01901 #if ( configQUEUE_REGISTRY_SIZE > 0 )
01902 
01903     void vQueueUnregisterQueue( xQueueHandle xQueue )
01904     {
01905     unsigned portBASE_TYPE ux;
01906 
01907         /* See if the handle of the queue being unregistered in actually in the
01908         registry. */
01909         for( ux = ( unsigned portBASE_TYPE ) 0U; ux < ( unsigned portBASE_TYPE ) configQUEUE_REGISTRY_SIZE; ux++ )
01910         {
01911             if( xQueueRegistry[ ux ].xHandle == xQueue )
01912             {
01913                 /* Set the name to NULL to show that this slot if free again. */
01914                 xQueueRegistry[ ux ].pcQueueName = NULL;
01915                 break;
01916             }
01917         }
01918 
01919     } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
01920 
01921 #endif /* configQUEUE_REGISTRY_SIZE */
01922 /*-----------------------------------------------------------*/
01923 
01924 #if ( configUSE_TIMERS == 1 )
01925 
01926     void vQueueWaitForMessageRestricted( xQueueHandle xQueue, portTickType xTicksToWait )
01927     {
01928     xQUEUE * const pxQueue = ( xQUEUE * ) xQueue;
01929 
01930         /* This function should not be called by application code hence the
01931         'Restricted' in its name.  It is not part of the public API.  It is
01932         designed for use by kernel code, and has special calling requirements.
01933         It can result in vListInsert() being called on a list that can only
01934         possibly ever have one item in it, so the list will be fast, but even
01935         so it should be called with the scheduler locked and not from a critical
01936         section. */
01937 
01938         /* Only do anything if there are no messages in the queue.  This function
01939         will not actually cause the task to block, just place it on a blocked
01940         list.  It will not block until the scheduler is unlocked - at which
01941         time a yield will be performed.  If an item is added to the queue while
01942         the queue is locked, and the calling task blocks on the queue, then the
01943         calling task will be immediately unblocked when the queue is unlocked. */
01944         prvLockQueue( pxQueue );
01945         if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0U )
01946         {
01947             /* There is nothing in the queue, block for the specified period. */
01948             vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
01949         }
01950         prvUnlockQueue( pxQueue );
01951     }
01952 
01953 #endif /* configUSE_TIMERS */
01954 /*-----------------------------------------------------------*/
01955 
01956 #if ( configUSE_QUEUE_SETS == 1 )
01957 
01958     xQueueSetHandle xQueueCreateSet( unsigned portBASE_TYPE uxEventQueueLength )
01959     {
01960     xQueueSetHandle pxQueue;
01961 
01962         pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( xQUEUE * ), queueQUEUE_TYPE_SET );
01963 
01964         return pxQueue;
01965     }
01966 
01967 #endif /* configUSE_QUEUE_SETS */
01968 /*-----------------------------------------------------------*/
01969 
01970 #if ( configUSE_QUEUE_SETS == 1 )
01971 
01972     portBASE_TYPE xQueueAddToSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )
01973     {
01974     portBASE_TYPE xReturn;
01975 
01976         if( ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL )
01977         {
01978             /* Cannot add a queue/semaphore to more than one queue set. */
01979             xReturn = pdFAIL;
01980         }
01981         else if( ( ( xQUEUE * ) xQueueOrSemaphore )->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 )
01982         {
01983             /* Cannot add a queue/semaphore to a queue set if there are already
01984             items in the queue/semaphore. */
01985             xReturn = pdFAIL;
01986         }
01987         else
01988         {
01989             taskENTER_CRITICAL();
01990             {
01991                 ( ( xQUEUE * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet;
01992             }
01993             taskEXIT_CRITICAL();
01994             xReturn = pdPASS;
01995         }
01996 
01997         return xReturn;
01998     }
01999 
02000 #endif /* configUSE_QUEUE_SETS */
02001 /*-----------------------------------------------------------*/
02002 
02003 #if ( configUSE_QUEUE_SETS == 1 )
02004 
02005     portBASE_TYPE xQueueRemoveFromSet( xQueueSetMemberHandle xQueueOrSemaphore, xQueueSetHandle xQueueSet )
02006     {
02007     portBASE_TYPE xReturn;
02008     xQUEUE * const pxQueueOrSemaphore = ( xQUEUE * ) xQueueOrSemaphore;
02009 
02010         if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet )
02011         {
02012             /* The queue was not a member of the set. */
02013             xReturn = pdFAIL;
02014         }
02015         else if( pxQueueOrSemaphore->uxMessagesWaiting != ( unsigned portBASE_TYPE ) 0 )
02016         {
02017             /* It is dangerous to remove a queue from a set when the queue is
02018             not empty because the queue set will still hold pending events for
02019             the queue. */
02020             xReturn = pdFAIL;
02021         }
02022         else
02023         {
02024             taskENTER_CRITICAL();
02025             {
02026                 /* The queue is no longer contained in the set. */
02027                 pxQueueOrSemaphore->pxQueueSetContainer = NULL;
02028             }
02029             taskEXIT_CRITICAL();
02030             xReturn = pdPASS;
02031         }
02032 
02033         return xReturn;
02034     } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */
02035 
02036 #endif /* configUSE_QUEUE_SETS */
02037 /*-----------------------------------------------------------*/
02038 
02039 #if ( configUSE_QUEUE_SETS == 1 )
02040 
02041     xQueueSetMemberHandle xQueueSelectFromSet( xQueueSetHandle xQueueSet, portTickType xBlockTimeTicks )
02042     {
02043     xQueueSetMemberHandle xReturn = NULL;
02044 
02045         ( void ) xQueueGenericReceive( ( xQueueHandle ) xQueueSet, &xReturn, xBlockTimeTicks, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */
02046         return xReturn;
02047     }
02048 
02049 #endif /* configUSE_QUEUE_SETS */
02050 /*-----------------------------------------------------------*/
02051 
02052 #if ( configUSE_QUEUE_SETS == 1 )
02053 
02054     xQueueSetMemberHandle xQueueSelectFromSetFromISR( xQueueSetHandle xQueueSet )
02055     {
02056     xQueueSetMemberHandle xReturn = NULL;
02057 
02058         ( void ) xQueueReceiveFromISR( ( xQueueHandle ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */
02059         return xReturn;
02060     }
02061 
02062 #endif /* configUSE_QUEUE_SETS */
02063 /*-----------------------------------------------------------*/
02064 
02065 #if ( configUSE_QUEUE_SETS == 1 )
02066 
02067     static portBASE_TYPE prvNotifyQueueSetContainer( const xQUEUE * const pxQueue, portBASE_TYPE xCopyPosition )
02068     {
02069     xQUEUE *pxQueueSetContainer = pxQueue->pxQueueSetContainer;
02070     portBASE_TYPE xReturn = pdFALSE;
02071 
02072         configASSERT( pxQueueSetContainer );
02073         configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength );
02074 
02075         if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength )
02076         {
02077             traceQUEUE_SEND( pxQueueSetContainer );
02078             /* The data copies is the handle of the queue that contains data. */
02079             prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition );
02080             if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE )
02081             {
02082                 if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE )
02083                 {
02084                     /* The task waiting has a higher priority */
02085                     xReturn = pdTRUE;
02086                 }
02087             }
02088         }
02089 
02090         return xReturn;
02091     }
02092 
02093 #endif /* configUSE_QUEUE_SETS */
02094 
02095 
02096 
02097 
02098 
02099 
02100 
02101 
02102 
02103 
02104 
02105