FreeRTOS Real Time Operating System, Modified from Kenji Arai's initial port. See freertos.org for full documentation.

Fork of FreeRTOS_on_mbed_v1 by Kenji Arai

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers queue.c Source File

queue.c

00001 /*
00002     FreeRTOS V6.0.3 - Copyright (C) 2010 Real Time Engineers Ltd.
00003 
00004     ***************************************************************************
00005     *                                                                         *
00006     * If you are:                                                             *
00007     *                                                                         *
00008     *    + New to FreeRTOS,                                                   *
00009     *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
00010     *    + Looking for basic training,                                        *
00011     *    + Wanting to improve your FreeRTOS skills and productivity           *
00012     *                                                                         *
00013     * then take a look at the FreeRTOS eBook                                  *
00014     *                                                                         *
00015     *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
00016     *                  http://www.FreeRTOS.org/Documentation                  *
00017     *                                                                         *
00018     * A pdf reference manual is also available.  Both are usually delivered   *
00019     * to your inbox within 20 minutes to two hours when purchased between 8am *
00020     * and 8pm GMT (although please allow up to 24 hours in case of            *
00021     * exceptional circumstances).  Thank you for your support!                *
00022     *                                                                         *
00023     ***************************************************************************
00024 
00025     This file is part of the FreeRTOS distribution.
00026 
00027     FreeRTOS is free software; you can redistribute it and/or modify it under
00028     the terms of the GNU General Public License (version 2) as published by the
00029     Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
00030     ***NOTE*** The exception to the GPL is included to allow you to distribute
00031     a combined work that includes FreeRTOS without being obliged to provide the
00032     source code for proprietary components outside of the FreeRTOS kernel.
00033     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
00034     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00035     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
00036     more details. You should have received a copy of the GNU General Public 
00037     License and the FreeRTOS license exception along with FreeRTOS; if not it 
00038     can be viewed here: http://www.freertos.org/a00114.html and also obtained 
00039     by writing to Richard Barry, contact details for whom are available on the
00040     FreeRTOS WEB site.
00041 
00042     1 tab == 4 spaces!
00043 
00044     http://www.FreeRTOS.org - Documentation, latest information, license and
00045     contact details.
00046 
00047     http://www.SafeRTOS.com - A version that is certified for use in safety
00048     critical systems.
00049 
00050     http://www.OpenRTOS.com - Commercial support, development, porting,
00051     licensing and training services.
00052 */
00053 
00054 #include <stdlib.h>
00055 #include <string.h>
00056 
00057 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
00058 all the API functions to use the MPU wrappers.  That should only be done when
00059 task.h is included from an application file. */
00060 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
00061 
00062 #include "FreeRTOS.h"
00063 #include "task.h"
00064 #include "croutine.h"
00065 
00066 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
00067 
00068 /*-----------------------------------------------------------
00069  * PUBLIC LIST API documented in list.h
00070  *----------------------------------------------------------*/
00071 
00072 /* Constants used with the cRxLock and cTxLock structure members. */
00073 #define queueUNLOCKED                    ( ( signed portBASE_TYPE ) -1 )
00074 #define queueLOCKED_UNMODIFIED            ( ( signed portBASE_TYPE ) 0 )
00075 
00076 #define queueERRONEOUS_UNBLOCK            ( -1 )
00077 
00078 /* For internal use only. */
00079 #define    queueSEND_TO_BACK                ( 0 )
00080 #define    queueSEND_TO_FRONT                ( 1 )
00081 
00082 /* Effectively make a union out of the xQUEUE structure. */
00083 #define pxMutexHolder                    pcTail
00084 #define uxQueueType                        pcHead
00085 #define uxRecursiveCallCount            pcReadFrom
00086 #define queueQUEUE_IS_MUTEX                NULL
00087 
00088 /* Semaphores do not actually store or copy data, so have an items size of
00089 zero. */
00090 #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( 0 )
00091 #define queueDONT_BLOCK                     ( ( portTickType ) 0 )
00092 #define queueMUTEX_GIVE_BLOCK_TIME         ( ( portTickType ) 0 )
00093 
00094 #ifdef __cplusplus
00095 extern "C" {
00096 #endif
00097 /*
00098  * Definition of the queue used by the scheduler.
00099  * Items are queued by copy, not reference.
00100  */
00101 typedef struct QueueDefinition
00102 {
00103     signed char *pcHead;                /*< Points to the beginning of the queue storage area. */
00104     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. */
00105 
00106     signed char *pcWriteTo;                /*< Points to the free next place in the storage area. */
00107     signed char *pcReadFrom;            /*< Points to the last place that a queued item was read from. */
00108 
00109     xList xTasksWaitingToSend;                /*< List of tasks that are blocked waiting to post onto this queue.  Stored in priority order. */
00110     xList xTasksWaitingToReceive;            /*< List of tasks that are blocked waiting to read from this queue.  Stored in priority order. */
00111 
00112     volatile unsigned portBASE_TYPE uxMessagesWaiting;/*< The number of items currently in the queue. */
00113     unsigned portBASE_TYPE uxLength;        /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */
00114     unsigned portBASE_TYPE uxItemSize;        /*< The size of each items that the queue will hold. */
00115 
00116     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. */
00117     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. */
00118 
00119 } xQUEUE;
00120 /*-----------------------------------------------------------*/
00121 
00122 /*
00123  * Inside this file xQueueHandle is a pointer to a xQUEUE structure.
00124  * To keep the definition private the API header file defines it as a
00125  * pointer to void.
00126  */
00127 typedef xQUEUE * xQueueHandle;
00128 
00129 #if 0
00130 /*
00131  * Prototypes for public functions are included here so we don't have to
00132  * include the API header file (as it defines xQueueHandle differently).  These
00133  * functions are documented in the API header file.
00134  */
00135 xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ) PRIVILEGED_FUNCTION;
00136 signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
00137 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
00138 void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
00139 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
00140 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;
00141 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;
00142 xQueueHandle xQueueCreateMutex( void ) PRIVILEGED_FUNCTION;
00143 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) PRIVILEGED_FUNCTION;
00144 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) PRIVILEGED_FUNCTION;
00145 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ) PRIVILEGED_FUNCTION;
00146 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
00147 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;
00148 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
00149 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
00150 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
00151 
00152 /*
00153  * Co-routine queue functions differ from task queue functions.  Co-routines are
00154  * an optional component.
00155  */
00156 #if configUSE_CO_ROUTINES == 1
00157     signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) PRIVILEGED_FUNCTION;
00158     signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;
00159     signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
00160     signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
00161 #endif
00162 #else
00163 /*
00164  * Prototypes for public functions are included here so we don't have to
00165  * include the API header file (as it defines xQueueHandle differently).  These
00166  * functions are documented in the API header file.
00167  */
00168 xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize );
00169 signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );
00170 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue );
00171 void vQueueDelete( xQueueHandle xQueue );
00172 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition );
00173 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );
00174 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken );
00175 xQueueHandle xQueueCreateMutex( void );
00176 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount );
00177 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime );
00178 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex );
00179 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );
00180 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );
00181 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue );
00182 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue );
00183 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue );
00184 
00185 /*
00186  * Co-routine queue functions differ from task queue functions.  Co-routines are
00187  * an optional component.
00188  */
00189 #if configUSE_CO_ROUTINES == 1
00190     signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken );
00191     signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken );
00192     signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait );
00193     signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait );
00194 #endif
00195 #endif
00196 /*
00197  * The queue registry is just a means for kernel aware debuggers to locate
00198  * queue structures.  It has no other purpose so is an optional component.
00199  */
00200 //#if configQUEUE_REGISTRY_SIZE > 0
00201 
00202     /* The type stored within the queue registry array.  This allows a name
00203     to be assigned to each queue making kernel aware debugging a little
00204     more user friendly. */
00205     typedef struct QUEUE_REGISTRY_ITEM
00206     {
00207         signed char *pcQueueName;
00208         xQueueHandle xHandle;
00209     } xQueueRegistryItem;
00210 
00211     /* The queue registry is simply an array of xQueueRegistryItem structures.
00212     The pcQueueName member of a structure being NULL is indicative of the
00213     array position being vacant. */
00214     xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
00215 
00216     /* Removes a queue from the registry by simply setting the pcQueueName
00217     member to NULL. */
00218     static void vQueueUnregisterQueue( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
00219     //void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName ) PRIVILEGED_FUNCTION;
00220     extern void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName );
00221 //#endif
00222 
00223 /*
00224  * Unlocks a queue locked by a call to prvLockQueue.  Locking a queue does not
00225  * prevent an ISR from adding or removing items to the queue, but does prevent
00226  * an ISR from removing tasks from the queue event lists.  If an ISR finds a
00227  * queue is locked it will instead increment the appropriate queue lock count
00228  * to indicate that a task may require unblocking.  When the queue in unlocked
00229  * these lock counts are inspected, and the appropriate action taken.
00230  */
00231 static void prvUnlockQueue( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
00232 
00233 /*
00234  * Uses a critical section to determine if there is any data in a queue.
00235  *
00236  * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
00237  */
00238 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
00239 
00240 /*
00241  * Uses a critical section to determine if there is any space in a queue.
00242  *
00243  * @return pdTRUE if there is no space, otherwise pdFALSE;
00244  */
00245 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
00246 
00247 /*
00248  * Copies an item into the queue, either at the front of the queue or the
00249  * back of the queue.
00250  */
00251 #if 0
00252 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION;
00253 #else
00254 void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition );
00255 #endif
00256 /*
00257  * Copies an item out of a queue.
00258  */
00259 // Modified by  Kenji Arai / JH1PJL, October 31st,2010
00260 #if 0
00261 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer ) PRIVILEGED_FUNCTION;
00262 #else
00263 void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer );
00264 #endif
00265 /*-----------------------------------------------------------*/
00266 
00267 /*
00268  * Macro to mark a queue as locked.  Locking a queue prevents an ISR from
00269  * accessing the queue event lists.
00270  */
00271 #define prvLockQueue( pxQueue )                            \
00272 {                                                        \
00273     taskENTER_CRITICAL();                                \
00274     {                                                    \
00275         if( pxQueue->xRxLock == queueUNLOCKED )            \
00276         {                                                \
00277             pxQueue->xRxLock = queueLOCKED_UNMODIFIED;    \
00278         }                                                \
00279         if( pxQueue->xTxLock == queueUNLOCKED )            \
00280         {                                                \
00281             pxQueue->xTxLock = queueLOCKED_UNMODIFIED;    \
00282         }                                                \
00283     }                                                    \
00284     taskEXIT_CRITICAL();                                \
00285 }
00286 /*-----------------------------------------------------------*/
00287 
00288 #ifdef __cplusplus
00289 }
00290 #endif
00291 /*-----------------------------------------------------------
00292  * PUBLIC QUEUE MANAGEMENT API documented in queue.h
00293  *----------------------------------------------------------*/
00294 
00295 xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize )
00296 {
00297 xQUEUE *pxNewQueue;
00298 size_t xQueueSizeInBytes;
00299 
00300     /* Allocate the new queue structure. */
00301     if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )
00302     {
00303         pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
00304         if( pxNewQueue != NULL )
00305         {
00306             /* Create the list of pointers to queue items.  The queue is one byte
00307             longer than asked for to make wrap checking easier/faster. */
00308             xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1;
00309 
00310             pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes );
00311             if( pxNewQueue->pcHead != NULL )
00312             {
00313                 /* Initialise the queue members as described above where the
00314                 queue type is defined. */
00315                 pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize );
00316                 pxNewQueue->uxMessagesWaiting = 0;
00317                 pxNewQueue->pcWriteTo = pxNewQueue->pcHead;
00318                 pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - 1 ) * uxItemSize );
00319                 pxNewQueue->uxLength = uxQueueLength;
00320                 pxNewQueue->uxItemSize = uxItemSize;
00321                 pxNewQueue->xRxLock = queueUNLOCKED;
00322                 pxNewQueue->xTxLock = queueUNLOCKED;
00323 
00324                 /* Likewise ensure the event queues start with the correct state. */
00325                 vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
00326                 vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
00327 
00328                 traceQUEUE_CREATE( pxNewQueue );
00329                 return  pxNewQueue;
00330             }
00331             else
00332             {
00333                 traceQUEUE_CREATE_FAILED();
00334                 vPortFree( pxNewQueue );
00335             }
00336         }
00337     }
00338 
00339     /* Will only reach here if we could not allocate enough memory or no memory
00340     was required. */
00341     return NULL;
00342 }
00343 /*-----------------------------------------------------------*/
00344 
00345 #if ( configUSE_MUTEXES == 1 )
00346 
00347     xQueueHandle xQueueCreateMutex( void )
00348     {
00349     xQUEUE *pxNewQueue;
00350 
00351         /* Allocate the new queue structure. */
00352         pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
00353         if( pxNewQueue != NULL )
00354         {
00355             /* Information required for priority inheritance. */
00356             pxNewQueue->pxMutexHolder = NULL;
00357             pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
00358 
00359             /* Queues used as a mutex no data is actually copied into or out
00360             of the queue. */
00361             pxNewQueue->pcWriteTo = NULL;
00362             pxNewQueue->pcReadFrom = NULL;
00363 
00364             /* Each mutex has a length of 1 (like a binary semaphore) and
00365             an item size of 0 as nothing is actually copied into or out
00366             of the mutex. */
00367             pxNewQueue->uxMessagesWaiting = 0;
00368             pxNewQueue->uxLength = 1;
00369             pxNewQueue->uxItemSize = 0;
00370             pxNewQueue->xRxLock = queueUNLOCKED;
00371             pxNewQueue->xTxLock = queueUNLOCKED;
00372 
00373             /* Ensure the event queues start with the correct state. */
00374             vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
00375             vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
00376 
00377             /* Start with the semaphore in the expected state. */
00378             xQueueGenericSend( pxNewQueue, NULL, 0, queueSEND_TO_BACK );
00379 
00380             traceCREATE_MUTEX( pxNewQueue );
00381         }
00382         else
00383         {
00384             traceCREATE_MUTEX_FAILED();
00385         }
00386 
00387         return pxNewQueue;
00388     }
00389 
00390 #endif /* configUSE_MUTEXES */
00391 /*-----------------------------------------------------------*/
00392 
00393 #if configUSE_RECURSIVE_MUTEXES == 1
00394 
00395     portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex )
00396     {
00397     portBASE_TYPE xReturn;
00398 
00399         /* If this is the task that holds the mutex then pxMutexHolder will not
00400         change outside of this task.  If this task does not hold the mutex then
00401         pxMutexHolder can never coincidentally equal the tasks handle, and as
00402         this is the only condition we are interested in it does not matter if
00403         pxMutexHolder is accessed simultaneously by another task.  Therefore no
00404         mutual exclusion is required to test the pxMutexHolder variable. */
00405         if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
00406         {
00407             traceGIVE_MUTEX_RECURSIVE( pxMutex );
00408 
00409             /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to
00410             the task handle, therefore no underflow check is required.  Also,
00411             uxRecursiveCallCount is only modified by the mutex holder, and as
00412             there can only be one, no mutual exclusion is required to modify the
00413             uxRecursiveCallCount member. */
00414             ( pxMutex->uxRecursiveCallCount )--;
00415 
00416             /* Have we unwound the call count? */
00417             if( pxMutex->uxRecursiveCallCount == 0 )
00418             {
00419                 /* Return the mutex.  This will automatically unblock any other
00420                 task that might be waiting to access the mutex. */
00421                 xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
00422             }
00423 
00424             xReturn = pdPASS;
00425         }
00426         else
00427         {
00428             /* We cannot give the mutex because we are not the holder. */
00429             xReturn = pdFAIL;
00430 
00431             traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
00432         }
00433 
00434         return xReturn;
00435     }
00436 
00437 #endif /* configUSE_RECURSIVE_MUTEXES */
00438 /*-----------------------------------------------------------*/
00439 
00440 #if configUSE_RECURSIVE_MUTEXES == 1
00441 
00442     portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime )
00443     {
00444     portBASE_TYPE xReturn;
00445 
00446         /* Comments regarding mutual exclusion as per those within
00447         xQueueGiveMutexRecursive(). */
00448 
00449         traceTAKE_MUTEX_RECURSIVE( pxMutex );
00450 
00451         if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
00452         {
00453             ( pxMutex->uxRecursiveCallCount )++;
00454             xReturn = pdPASS;
00455         }
00456         else
00457         {
00458             xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );
00459 
00460             /* pdPASS will only be returned if we successfully obtained the mutex,
00461             we may have blocked to reach here. */
00462             if( xReturn == pdPASS )
00463             {
00464                 ( pxMutex->uxRecursiveCallCount )++;
00465             }
00466         }
00467 
00468         return xReturn;
00469     }
00470 
00471 #endif /* configUSE_RECURSIVE_MUTEXES */
00472 /*-----------------------------------------------------------*/
00473 
00474 #if configUSE_COUNTING_SEMAPHORES == 1
00475 
00476     xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount )
00477     {
00478     xQueueHandle pxHandle;
00479 
00480         pxHandle = xQueueCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH );
00481 
00482         if( pxHandle != NULL )
00483         {
00484             pxHandle->uxMessagesWaiting = uxInitialCount;
00485 
00486             traceCREATE_COUNTING_SEMAPHORE();
00487         }
00488         else
00489         {
00490             traceCREATE_COUNTING_SEMAPHORE_FAILED();
00491         }
00492 
00493         return pxHandle;
00494     }
00495 
00496 #endif /* configUSE_COUNTING_SEMAPHORES */
00497 /*-----------------------------------------------------------*/
00498 
00499 signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
00500 {
00501 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
00502 xTimeOutType xTimeOut;
00503 
00504     /* This function relaxes the coding standard somewhat to allow return
00505     statements within the function itself.  This is done in the interest
00506     of execution time efficiency. */
00507     for( ;; )
00508     {
00509         taskENTER_CRITICAL();
00510         {
00511             /* Is there room on the queue now?  To be running we must be
00512             the highest priority task wanting to access the queue. */
00513             if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
00514             {
00515                 traceQUEUE_SEND( pxQueue );
00516                 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
00517 
00518                 /* If there was a task waiting for data to arrive on the
00519                 queue then unblock it now. */
00520                 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
00521                 {
00522                     if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
00523                     {
00524                         /* The unblocked task has a priority higher than
00525                         our own so yield immediately.  Yes it is ok to do
00526                         this from within the critical section - the kernel
00527                         takes care of that. */
00528                         portYIELD_WITHIN_API();
00529                     }
00530                 }
00531 
00532                 taskEXIT_CRITICAL();
00533 
00534                 /* Return to the original privilege level before exiting the
00535                 function. */
00536                 return pdPASS;
00537             }
00538             else
00539             {
00540                 if( xTicksToWait == ( portTickType ) 0 )
00541                 {
00542                     /* The queue was full and no block time is specified (or
00543                     the block time has expired) so leave now. */
00544                     taskEXIT_CRITICAL();
00545 
00546                     /* Return to the original privilege level before exiting
00547                     the function. */
00548                     traceQUEUE_SEND_FAILED( pxQueue );
00549                     return errQUEUE_FULL;
00550                 }
00551                 else if( xEntryTimeSet == pdFALSE )
00552                 {
00553                     /* The queue was full and a block time was specified so
00554                     configure the timeout structure. */
00555                     vTaskSetTimeOutState( &xTimeOut );
00556                     xEntryTimeSet = pdTRUE;
00557                 }
00558             }
00559         }
00560         taskEXIT_CRITICAL();
00561 
00562         /* Interrupts and other tasks can send to and receive from the queue
00563         now the critical section has been exited. */
00564 
00565         vTaskSuspendAll();
00566         prvLockQueue( pxQueue );
00567 
00568         /* Update the timeout state to see if it has expired yet. */
00569         if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
00570         {
00571             if( prvIsQueueFull( pxQueue ) )
00572             {
00573                 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
00574                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
00575 
00576                 /* Unlocking the queue means queue events can effect the
00577                 event list.  It is possible    that interrupts occurring now
00578                 remove this task from the event    list again - but as the
00579                 scheduler is suspended the task will go onto the pending
00580                 ready last instead of the actual ready list. */
00581                 prvUnlockQueue( pxQueue );
00582 
00583                 /* Resuming the scheduler will move tasks from the pending
00584                 ready list into the ready list - so it is feasible that this
00585                 task is already in a ready list before it yields - in which
00586                 case the yield will not cause a context switch unless there
00587                 is also a higher priority task in the pending ready list. */
00588                 if( !xTaskResumeAll() )
00589                 {
00590                     portYIELD_WITHIN_API();
00591                 }
00592             }
00593             else
00594             {
00595                 /* Try again. */
00596                 prvUnlockQueue( pxQueue );
00597                 ( void ) xTaskResumeAll();
00598             }
00599         }
00600         else
00601         {
00602             /* The timeout has expired. */
00603             prvUnlockQueue( pxQueue );
00604             ( void ) xTaskResumeAll();
00605 
00606             /* Return to the original privilege level before exiting the
00607             function. */
00608             traceQUEUE_SEND_FAILED( pxQueue );
00609             return errQUEUE_FULL;
00610         }
00611     }
00612 }
00613 /*-----------------------------------------------------------*/
00614 
00615 #if configUSE_ALTERNATIVE_API == 1
00616 
00617     signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
00618     {
00619     signed portBASE_TYPE xEntryTimeSet = pdFALSE;
00620     xTimeOutType xTimeOut;
00621 
00622         for( ;; )
00623         {
00624             taskENTER_CRITICAL();
00625             {
00626                 /* Is there room on the queue now?  To be running we must be
00627                 the highest priority task wanting to access the queue. */
00628                 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
00629                 {
00630                     traceQUEUE_SEND( pxQueue );
00631                     prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
00632 
00633                     /* If there was a task waiting for data to arrive on the
00634                     queue then unblock it now. */
00635                     if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
00636                     {
00637                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
00638                         {
00639                             /* The unblocked task has a priority higher than
00640                             our own so yield immediately. */
00641                             portYIELD_WITHIN_API();
00642                         }
00643                     }
00644 
00645                     taskEXIT_CRITICAL();
00646                     return pdPASS;
00647                 }
00648                 else
00649                 {
00650                     if( xTicksToWait == ( portTickType ) 0 )
00651                     {
00652                         taskEXIT_CRITICAL();
00653                         return errQUEUE_FULL;
00654                     }
00655                     else if( xEntryTimeSet == pdFALSE )
00656                     {
00657                         vTaskSetTimeOutState( &xTimeOut );
00658                         xEntryTimeSet = pdTRUE;
00659                     }
00660                 }
00661             }
00662             taskEXIT_CRITICAL();
00663 
00664             taskENTER_CRITICAL();
00665             {
00666                 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
00667                 {
00668                     if( prvIsQueueFull( pxQueue ) )
00669                     {
00670                         traceBLOCKING_ON_QUEUE_SEND( pxQueue );
00671                         vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
00672                         portYIELD_WITHIN_API();
00673                     }
00674                 }
00675                 else
00676                 {
00677                     taskEXIT_CRITICAL();
00678                     traceQUEUE_SEND_FAILED( pxQueue );
00679                     return errQUEUE_FULL;
00680                 }
00681             }
00682             taskEXIT_CRITICAL();
00683         }
00684     }
00685 
00686 #endif /* configUSE_ALTERNATIVE_API */
00687 /*-----------------------------------------------------------*/
00688 
00689 #if configUSE_ALTERNATIVE_API == 1
00690 
00691     signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
00692     {
00693     signed portBASE_TYPE xEntryTimeSet = pdFALSE;
00694     xTimeOutType xTimeOut;
00695     signed char *pcOriginalReadPosition;
00696 
00697         for( ;; )
00698         {
00699             taskENTER_CRITICAL();
00700             {
00701                 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
00702                 {
00703                     /* Remember our read position in case we are just peeking. */
00704                     pcOriginalReadPosition = pxQueue->pcReadFrom;
00705 
00706                     prvCopyDataFromQueue( pxQueue, pvBuffer );
00707 
00708                     if( xJustPeeking == pdFALSE )
00709                     {
00710                         traceQUEUE_RECEIVE( pxQueue );
00711 
00712                         /* We are actually removing data. */
00713                         --( pxQueue->uxMessagesWaiting );
00714 
00715                         #if ( configUSE_MUTEXES == 1 )
00716                         {
00717                             if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
00718                             {
00719                                 /* Record the information required to implement
00720                                 priority inheritance should it become necessary. */
00721                                 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
00722                             }
00723                         }
00724                         #endif
00725 
00726                         if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
00727                         {
00728                             if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
00729                             {
00730                                 portYIELD_WITHIN_API();
00731                             }
00732                         }
00733                     }
00734                     else
00735                     {
00736                         traceQUEUE_PEEK( pxQueue );
00737 
00738                         /* We are not removing the data, so reset our read
00739                         pointer. */
00740                         pxQueue->pcReadFrom = pcOriginalReadPosition;
00741 
00742                         /* The data is being left in the queue, so see if there are
00743                         any other tasks waiting for the data. */
00744                         if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
00745                         {
00746                             /* Tasks that are removed from the event list will get added to
00747                             the pending ready list as the scheduler is still suspended. */
00748                             if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
00749                             {
00750                                 /* The task waiting has a higher priority than this task. */
00751                                 portYIELD_WITHIN_API();
00752                             }
00753                         }
00754 
00755                     }
00756 
00757                     taskEXIT_CRITICAL();
00758                     return pdPASS;
00759                 }
00760                 else
00761                 {
00762                     if( xTicksToWait == ( portTickType ) 0 )
00763                     {
00764                         taskEXIT_CRITICAL();
00765                         traceQUEUE_RECEIVE_FAILED( pxQueue );
00766                         return errQUEUE_EMPTY;
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( prvIsQueueEmpty( pxQueue ) )
00782                     {
00783                         traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
00784 
00785                         #if ( configUSE_MUTEXES == 1 )
00786                         {
00787                             if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
00788                             {
00789                                 portENTER_CRITICAL();
00790                                     vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
00791                                 portEXIT_CRITICAL();
00792                             }
00793                         }
00794                         #endif
00795 
00796                         vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
00797                         portYIELD_WITHIN_API();
00798                     }
00799                 }
00800                 else
00801                 {
00802                     taskEXIT_CRITICAL();
00803                     traceQUEUE_RECEIVE_FAILED( pxQueue );
00804                     return errQUEUE_EMPTY;
00805                 }
00806             }
00807             taskEXIT_CRITICAL();
00808         }
00809     }
00810 
00811 
00812 #endif /* configUSE_ALTERNATIVE_API */
00813 /*-----------------------------------------------------------*/
00814 
00815 // Modified by  Kenji Arai / JH1PJL, October 30th,2010
00816 // move to port_asm.c
00817 #if 0
00818 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )
00819 {
00820 signed portBASE_TYPE xReturn;
00821 unsigned portBASE_TYPE uxSavedInterruptStatus;
00822 
00823     /* Similar to xQueueGenericSend, except we don't block if there is no room
00824     in the queue.  Also we don't directly wake a task that was blocked on a
00825     queue read, instead we return a flag to say whether a context switch is
00826     required or not (i.e. has a task with a higher priority than us been woken
00827     by this    post). */
00828     uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
00829     {
00830         if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
00831         {
00832             traceQUEUE_SEND_FROM_ISR( pxQueue );
00833 
00834             prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
00835 
00836             /* If the queue is locked we do not alter the event list.  This will
00837             be done when the queue is unlocked later. */
00838             if( pxQueue->xTxLock == queueUNLOCKED )
00839             {
00840                 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
00841                 {
00842                     if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
00843                     {
00844                         /* The task waiting has a higher priority so record that a
00845                         context    switch is required. */
00846                         *pxHigherPriorityTaskWoken = pdTRUE;
00847                     }
00848                 }
00849             }
00850             else
00851             {
00852                 /* Increment the lock count so the task that unlocks the queue
00853                 knows that data was posted while it was locked. */
00854                 ++( pxQueue->xTxLock );
00855             }
00856 
00857             xReturn = pdPASS;
00858         }
00859         else
00860         {
00861             traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
00862             xReturn = errQUEUE_FULL;
00863         }
00864     }
00865     portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
00866 
00867     return xReturn;
00868 }
00869 /*-----------------------------------------------------------*/
00870 #endif
00871 
00872 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
00873 {
00874 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
00875 xTimeOutType xTimeOut;
00876 signed char *pcOriginalReadPosition;
00877 
00878     /* This function relaxes the coding standard somewhat to allow return
00879     statements within the function itself.  This is done in the interest
00880     of execution time efficiency. */
00881 
00882     for( ;; )
00883     {
00884         taskENTER_CRITICAL();
00885         {
00886             /* Is there data in the queue now?  To be running we must be
00887             the highest priority task wanting to access the queue. */
00888             if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
00889             {
00890                 /* Remember our read position in case we are just peeking. */
00891                 pcOriginalReadPosition = pxQueue->pcReadFrom;
00892 
00893                 prvCopyDataFromQueue( pxQueue, pvBuffer );
00894 
00895                 if( xJustPeeking == pdFALSE )
00896                 {
00897                     traceQUEUE_RECEIVE( pxQueue );
00898 
00899                     /* We are actually removing data. */
00900                     --( pxQueue->uxMessagesWaiting );
00901 
00902                     #if ( configUSE_MUTEXES == 1 )
00903                     {
00904                         if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
00905                         {
00906                             /* Record the information required to implement
00907                             priority inheritance should it become necessary. */
00908                             // Modified by  Kenji Arai / JH1PJL, October 31st,2010
00909                             pxQueue->pxMutexHolder = (signed char *) xTaskGetCurrentTaskHandle();
00910                         }
00911                     }
00912                     #endif
00913 
00914                     if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
00915                     {
00916                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
00917                         {
00918                             portYIELD_WITHIN_API();
00919                         }
00920                     }
00921                 }
00922                 else
00923                 {
00924                     traceQUEUE_PEEK( pxQueue );
00925 
00926                     /* We are not removing the data, so reset our read
00927                     pointer. */
00928                     pxQueue->pcReadFrom = pcOriginalReadPosition;
00929 
00930                     /* The data is being left in the queue, so see if there are
00931                     any other tasks waiting for the data. */
00932                     if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
00933                     {
00934                         /* Tasks that are removed from the event list will get added to
00935                         the pending ready list as the scheduler is still suspended. */
00936                         if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
00937                         {
00938                             /* The task waiting has a higher priority than this task. */
00939                             portYIELD_WITHIN_API();
00940                         }
00941                     }
00942 
00943                 }
00944 
00945                 taskEXIT_CRITICAL();
00946                 return pdPASS;
00947             }
00948             else
00949             {
00950                 if( xTicksToWait == ( portTickType ) 0 )
00951                 {
00952                     /* The queue was empty and no block time is specified (or
00953                     the block time has expired) so leave now. */
00954                     taskEXIT_CRITICAL();
00955                     traceQUEUE_RECEIVE_FAILED( pxQueue );
00956                     return errQUEUE_EMPTY;
00957                 }
00958                 else if( xEntryTimeSet == pdFALSE )
00959                 {
00960                     /* The queue was empty and a block time was specified so
00961                     configure the timeout structure. */
00962                     vTaskSetTimeOutState( &xTimeOut );
00963                     xEntryTimeSet = pdTRUE;
00964                 }
00965             }
00966         }
00967         taskEXIT_CRITICAL();
00968 
00969         /* Interrupts and other tasks can send to and receive from the queue
00970         now the critical section has been exited. */
00971 
00972         vTaskSuspendAll();
00973         prvLockQueue( pxQueue );
00974 
00975         /* Update the timeout state to see if it has expired yet. */
00976         if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
00977         {
00978             if( prvIsQueueEmpty( pxQueue ) )
00979             {
00980                 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
00981 
00982                 #if ( configUSE_MUTEXES == 1 )
00983                 {
00984                     if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
00985                     {
00986                         portENTER_CRITICAL();
00987                         {
00988                             // Modified by  Kenji Arai / JH1PJL, October 31st,2010
00989                             //vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
00990                             vTaskPriorityInherit( ( xTaskHandle * ) pxQueue->pxMutexHolder );
00991                         }
00992                         portEXIT_CRITICAL();
00993                     }
00994                 }
00995                 #endif
00996 
00997                 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
00998                 prvUnlockQueue( pxQueue );
00999                 if( !xTaskResumeAll() )
01000                 {
01001                     portYIELD_WITHIN_API();
01002                 }
01003             }
01004             else
01005             {
01006                 /* Try again. */
01007                 prvUnlockQueue( pxQueue );
01008                 ( void ) xTaskResumeAll();
01009             }
01010         }
01011         else
01012         {
01013             prvUnlockQueue( pxQueue );
01014             ( void ) xTaskResumeAll();
01015             traceQUEUE_RECEIVE_FAILED( pxQueue );
01016             return errQUEUE_EMPTY;
01017         }
01018     }
01019 }
01020 /*-----------------------------------------------------------*/
01021 
01022 // Modified by  Kenji Arai / JH1PJL, October 30th,2010
01023 // move to port_asm.c
01024 #if 0
01025 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )
01026 {
01027 signed portBASE_TYPE xReturn;
01028 unsigned portBASE_TYPE uxSavedInterruptStatus;
01029 
01030     uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
01031     {
01032         /* We cannot block from an ISR, so check there is data available. */
01033         if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
01034         {
01035             traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
01036 
01037             prvCopyDataFromQueue( pxQueue, pvBuffer );
01038             --( pxQueue->uxMessagesWaiting );
01039 
01040             /* If the queue is locked we will not modify the event list.  Instead
01041             we update the lock count so the task that unlocks the queue will know
01042             that an ISR has removed data while the queue was locked. */
01043             if( pxQueue->xRxLock == queueUNLOCKED )
01044             {
01045                 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
01046                 {
01047                     if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
01048                     {
01049                         /* The task waiting has a higher priority than us so
01050                         force a context switch. */
01051                         *pxTaskWoken = pdTRUE;
01052                     }
01053                 }
01054             }
01055             else
01056             {
01057                 /* Increment the lock count so the task that unlocks the queue
01058                 knows that data was removed while it was locked. */
01059                 ++( pxQueue->xRxLock );
01060             }
01061 
01062             xReturn = pdPASS;
01063         }
01064         else
01065         {
01066             xReturn = pdFAIL;
01067             traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
01068         }
01069     }
01070     portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
01071 
01072     return xReturn;
01073 }
01074 /*-----------------------------------------------------------*/
01075 #endif
01076 
01077 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue )
01078 {
01079 unsigned portBASE_TYPE uxReturn;
01080 
01081     taskENTER_CRITICAL();
01082         uxReturn = pxQueue->uxMessagesWaiting;
01083     taskEXIT_CRITICAL();
01084 
01085     return uxReturn;
01086 }
01087 /*-----------------------------------------------------------*/
01088 
01089 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue )
01090 {
01091 unsigned portBASE_TYPE uxReturn;
01092 
01093     uxReturn = pxQueue->uxMessagesWaiting;
01094 
01095     return uxReturn;
01096 }
01097 /*-----------------------------------------------------------*/
01098 
01099 void vQueueDelete( xQueueHandle pxQueue )
01100 {
01101     traceQUEUE_DELETE( pxQueue );
01102     vQueueUnregisterQueue( pxQueue );
01103     vPortFree( pxQueue->pcHead );
01104     vPortFree( pxQueue );
01105 }
01106 /*-----------------------------------------------------------*/
01107 
01108 // Modified by  Kenji Arai / JH1PJL, October 31st,2010
01109 #if 0
01110 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )
01111 #else
01112 void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )
01113 #endif
01114 {
01115     if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )
01116     {
01117         #if ( configUSE_MUTEXES == 1 )
01118         {
01119             if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
01120             {
01121                 /* The mutex is no longer being held. */
01122                 // Modified by  Kenji Arai / JH1PJL, October 31st,2010
01123                 //vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
01124                 vTaskPriorityDisinherit( ( xTaskHandle * ) pxQueue->pxMutexHolder );
01125                 pxQueue->pxMutexHolder = NULL;
01126             }
01127         }
01128         #endif
01129     }
01130     else if( xPosition == queueSEND_TO_BACK )
01131     {
01132         memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
01133         pxQueue->pcWriteTo += pxQueue->uxItemSize;
01134         if( pxQueue->pcWriteTo >= pxQueue->pcTail )
01135         {
01136             pxQueue->pcWriteTo = pxQueue->pcHead;
01137         }
01138     }
01139     else
01140     {
01141         memcpy( ( void * ) pxQueue->pcReadFrom, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
01142         pxQueue->pcReadFrom -= pxQueue->uxItemSize;
01143         if( pxQueue->pcReadFrom < pxQueue->pcHead )
01144         {
01145             pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
01146         }
01147     }
01148 
01149     ++( pxQueue->uxMessagesWaiting );
01150 }
01151 /*-----------------------------------------------------------*/
01152 
01153 // Modified by  Kenji Arai / JH1PJL, October 31st,2010
01154 #if 0
01155 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
01156 #else
01157 void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
01158 #endif
01159 {
01160     if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
01161     {
01162         pxQueue->pcReadFrom += pxQueue->uxItemSize;
01163         if( pxQueue->pcReadFrom >= pxQueue->pcTail )
01164         {
01165             pxQueue->pcReadFrom = pxQueue->pcHead;
01166         }
01167         memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
01168     }
01169 }
01170 /*-----------------------------------------------------------*/
01171 
01172 // Modified by  Kenji Arai / JH1PJL, October 31st,2010
01173 #if 0
01174 static void prvUnlockQueue( xQueueHandle pxQueue )
01175 #else
01176 void prvUnlockQueue( xQueueHandle pxQueue )
01177 #endif
01178 {
01179     /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
01180 
01181     /* The lock counts contains the number of extra data items placed or
01182     removed from the queue while the queue was locked.  When a queue is
01183     locked items can be added or removed, but the event lists cannot be
01184     updated. */
01185     taskENTER_CRITICAL();
01186     {
01187         /* See if data was added to the queue while it was locked. */
01188         while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )
01189         {
01190             /* Data was posted while the queue was locked.  Are any tasks
01191             blocked waiting for data to become available? */
01192             if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
01193             {
01194                 /* Tasks that are removed from the event list will get added to
01195                 the pending ready list as the scheduler is still suspended. */
01196                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
01197                 {
01198                     /* The task waiting has a higher priority so record that a
01199                     context    switch is required. */
01200                     vTaskMissedYield();
01201                 }
01202 
01203                 --( pxQueue->xTxLock );
01204             }
01205             else
01206             {
01207                 break;
01208             }
01209         }
01210 
01211         pxQueue->xTxLock = queueUNLOCKED;
01212     }
01213     taskEXIT_CRITICAL();
01214 
01215     /* Do the same for the Rx lock. */
01216     taskENTER_CRITICAL();
01217     {
01218         while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )
01219         {
01220             if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
01221             {
01222                 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
01223                 {
01224                     vTaskMissedYield();
01225                 }
01226 
01227                 --( pxQueue->xRxLock );
01228             }
01229             else
01230             {
01231                 break;
01232             }
01233         }
01234 
01235         pxQueue->xRxLock = queueUNLOCKED;
01236     }
01237     taskEXIT_CRITICAL();
01238 }
01239 /*-----------------------------------------------------------*/
01240 
01241 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue )
01242 {
01243 signed portBASE_TYPE xReturn;
01244 
01245     taskENTER_CRITICAL();
01246         xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
01247     taskEXIT_CRITICAL();
01248 
01249     return xReturn;
01250 }
01251 /*-----------------------------------------------------------*/
01252 
01253 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue )
01254 {
01255 signed portBASE_TYPE xReturn;
01256 
01257     xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
01258 
01259     return xReturn;
01260 }
01261 /*-----------------------------------------------------------*/
01262 
01263 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue )
01264 {
01265 signed portBASE_TYPE xReturn;
01266 
01267     taskENTER_CRITICAL();
01268         xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
01269     taskEXIT_CRITICAL();
01270 
01271     return xReturn;
01272 }
01273 /*-----------------------------------------------------------*/
01274 
01275 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue )
01276 {
01277 signed portBASE_TYPE xReturn;
01278 
01279     xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
01280 
01281     return xReturn;
01282 }
01283 /*-----------------------------------------------------------*/
01284 
01285 #if configUSE_CO_ROUTINES == 1
01286 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )
01287 {
01288 signed portBASE_TYPE xReturn;
01289 
01290     /* If the queue is already full we may have to block.  A critical section
01291     is required to prevent an interrupt removing something from the queue
01292     between the check to see if the queue is full and blocking on the queue. */
01293     portDISABLE_INTERRUPTS();
01294     {
01295         if( prvIsQueueFull( pxQueue ) )
01296         {
01297             /* The queue is full - do we want to block or just leave without
01298             posting? */
01299             if( xTicksToWait > ( portTickType ) 0 )
01300             {
01301                 /* As this is called from a coroutine we cannot block directly, but
01302                 return indicating that we need to block. */
01303                 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
01304                 portENABLE_INTERRUPTS();
01305                 return errQUEUE_BLOCKED;
01306             }
01307             else
01308             {
01309                 portENABLE_INTERRUPTS();
01310                 return errQUEUE_FULL;
01311             }
01312         }
01313     }
01314     portENABLE_INTERRUPTS();
01315 
01316     portNOP();
01317 
01318     portDISABLE_INTERRUPTS();
01319     {
01320         if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
01321         {
01322             /* There is room in the queue, copy the data into the queue. */
01323             prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
01324             xReturn = pdPASS;
01325 
01326             /* Were any co-routines waiting for data to become available? */
01327             if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
01328             {
01329                 /* In this instance the co-routine could be placed directly
01330                 into the ready list as we are within a critical section.
01331                 Instead the same pending ready list mechanism is used as if
01332                 the event were caused from within an interrupt. */
01333                 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
01334                 {
01335                     /* The co-routine waiting has a higher priority so record
01336                     that a yield might be appropriate. */
01337                     xReturn = errQUEUE_YIELD;
01338                 }
01339             }
01340         }
01341         else
01342         {
01343             xReturn = errQUEUE_FULL;
01344         }
01345     }
01346     portENABLE_INTERRUPTS();
01347 
01348     return xReturn;
01349 }
01350 #endif
01351 /*-----------------------------------------------------------*/
01352 
01353 #if configUSE_CO_ROUTINES == 1
01354 signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )
01355 {
01356 signed portBASE_TYPE xReturn;
01357 
01358     /* If the queue is already empty we may have to block.  A critical section
01359     is required to prevent an interrupt adding something to the queue
01360     between the check to see if the queue is empty and blocking on the queue. */
01361     portDISABLE_INTERRUPTS();
01362     {
01363         if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
01364         {
01365             /* There are no messages in the queue, do we want to block or just
01366             leave with nothing? */
01367             if( xTicksToWait > ( portTickType ) 0 )
01368             {
01369                 /* As this is a co-routine we cannot block directly, but return
01370                 indicating that we need to block. */
01371                 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
01372                 portENABLE_INTERRUPTS();
01373                 return errQUEUE_BLOCKED;
01374             }
01375             else
01376             {
01377                 portENABLE_INTERRUPTS();
01378                 return errQUEUE_FULL;
01379             }
01380         }
01381     }
01382     portENABLE_INTERRUPTS();
01383 
01384     portNOP();
01385 
01386     portDISABLE_INTERRUPTS();
01387     {
01388         if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
01389         {
01390             /* Data is available from the queue. */
01391             pxQueue->pcReadFrom += pxQueue->uxItemSize;
01392             if( pxQueue->pcReadFrom >= pxQueue->pcTail )
01393             {
01394                 pxQueue->pcReadFrom = pxQueue->pcHead;
01395             }
01396             --( pxQueue->uxMessagesWaiting );
01397             memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
01398 
01399             xReturn = pdPASS;
01400 
01401             /* Were any co-routines waiting for space to become available? */
01402             if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
01403             {
01404                 /* In this instance the co-routine could be placed directly
01405                 into the ready list as we are within a critical section.
01406                 Instead the same pending ready list mechanism is used as if
01407                 the event were caused from within an interrupt. */
01408                 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
01409                 {
01410                     xReturn = errQUEUE_YIELD;
01411                 }
01412             }
01413         }
01414         else
01415         {
01416             xReturn = pdFAIL;
01417         }
01418     }
01419     portENABLE_INTERRUPTS();
01420 
01421     return xReturn;
01422 }
01423 #endif
01424 /*-----------------------------------------------------------*/
01425 
01426 
01427 
01428 #if configUSE_CO_ROUTINES == 1
01429 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
01430 {
01431     /* Cannot block within an ISR so if there is no space on the queue then
01432     exit without doing anything. */
01433     if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
01434     {
01435         prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
01436 
01437         /* We only want to wake one co-routine per ISR, so check that a
01438         co-routine has not already been woken. */
01439         if( !xCoRoutinePreviouslyWoken )
01440         {
01441             if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
01442             {
01443                 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
01444                 {
01445                     return pdTRUE;
01446                 }
01447             }
01448         }
01449     }
01450 
01451     return xCoRoutinePreviouslyWoken;
01452 }
01453 #endif
01454 /*-----------------------------------------------------------*/
01455 
01456 #if configUSE_CO_ROUTINES == 1
01457 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )
01458 {
01459 signed portBASE_TYPE xReturn;
01460 
01461     /* We cannot block from an ISR, so check there is data available. If
01462     not then just leave without doing anything. */
01463     if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
01464     {
01465         /* Copy the data from the queue. */
01466         pxQueue->pcReadFrom += pxQueue->uxItemSize;
01467         if( pxQueue->pcReadFrom >= pxQueue->pcTail )
01468         {
01469             pxQueue->pcReadFrom = pxQueue->pcHead;
01470         }
01471         --( pxQueue->uxMessagesWaiting );
01472         memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
01473 
01474         if( !( *pxCoRoutineWoken ) )
01475         {
01476             if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
01477             {
01478                 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
01479                 {
01480                     *pxCoRoutineWoken = pdTRUE;
01481                 }
01482             }
01483         }
01484 
01485         xReturn = pdPASS;
01486     }
01487     else
01488     {
01489         xReturn = pdFAIL;
01490     }
01491 
01492     return xReturn;
01493 }
01494 #endif
01495 /*-----------------------------------------------------------*/
01496 
01497 //#if configQUEUE_REGISTRY_SIZE > 0
01498 
01499     void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )
01500     {
01501     unsigned portBASE_TYPE ux;
01502 
01503         /* See if there is an empty space in the registry.  A NULL name denotes
01504         a free slot. */
01505         for( ux = 0; ux < configQUEUE_REGISTRY_SIZE; ux++ )
01506         {
01507             if( xQueueRegistry[ ux ].pcQueueName == NULL )
01508             {
01509                 /* Store the information on this queue. */
01510                 xQueueRegistry[ ux ].pcQueueName = pcQueueName;
01511                 xQueueRegistry[ ux ].xHandle = xQueue;
01512                 break;
01513             }
01514         }
01515     }
01516 
01517 //#endif
01518     /*-----------------------------------------------------------*/
01519 
01520 #if configQUEUE_REGISTRY_SIZE > 0
01521 
01522     static void vQueueUnregisterQueue( xQueueHandle xQueue )
01523     {
01524     unsigned portBASE_TYPE ux;
01525 
01526         /* See if the handle of the queue being unregistered in actually in the
01527         registry. */
01528         for( ux = 0; ux < configQUEUE_REGISTRY_SIZE; ux++ )
01529         {
01530             if( xQueueRegistry[ ux ].xHandle == xQueue )
01531             {
01532                 /* Set the name to NULL to show that this slot if free again. */
01533                 xQueueRegistry[ ux ].pcQueueName = NULL;
01534                 break;
01535             }
01536         }
01537 
01538     }
01539 
01540 #endif
01541