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
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
Generated on Fri Jul 15 2022 10:21:25 by
1.7.2
