00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #include <stdlib.h>
00055 #include <string.h>
00056
00057
00058
00059
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
00070
00071
00072
00073 #define queueUNLOCKED ( ( signed portBASE_TYPE ) -1 )
00074 #define queueLOCKED_UNMODIFIED ( ( signed portBASE_TYPE ) 0 )
00075
00076 #define queueERRONEOUS_UNBLOCK ( -1 )
00077
00078
00079 #define queueSEND_TO_BACK ( 0 )
00080 #define queueSEND_TO_FRONT ( 1 )
00081
00082
00083 #define pxMutexHolder pcTail
00084 #define uxQueueType pcHead
00085 #define uxRecursiveCallCount pcReadFrom
00086 #define queueQUEUE_IS_MUTEX NULL
00087
00088
00089
00090 #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( 0 )
00091 #define queueDONT_BLOCK ( ( portTickType ) 0 )
00092 #define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0 )
00093
00094
00095
00096
00097
00098 typedef struct QueueDefinition
00099 {
00100 signed char *pcHead;
00101 signed char *pcTail;
00102
00103 signed char *pcWriteTo;
00104 signed char *pcReadFrom;
00105
00106 xList xTasksWaitingToSend;
00107 xList xTasksWaitingToReceive;
00108
00109 volatile unsigned portBASE_TYPE uxMessagesWaiting;
00110 unsigned portBASE_TYPE uxLength;
00111 unsigned portBASE_TYPE uxItemSize;
00112
00113 signed portBASE_TYPE xRxLock;
00114 signed portBASE_TYPE xTxLock;
00115
00116 } xQUEUE;
00117
00118
00119
00120
00121
00122
00123
00124 typedef xQUEUE * xQueueHandle;
00125
00126
00127
00128
00129
00130
00131 xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize ) PRIVILEGED_FUNCTION;
00132 signed portBASE_TYPE xQueueGenericSend( xQueueHandle xQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
00133 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
00134 void vQueueDelete( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
00135 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
00136 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;
00137 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;
00138 xQueueHandle xQueueCreateMutex( void ) PRIVILEGED_FUNCTION;
00139 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount ) PRIVILEGED_FUNCTION;
00140 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime ) PRIVILEGED_FUNCTION;
00141 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex ) PRIVILEGED_FUNCTION;
00142 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition ) PRIVILEGED_FUNCTION;
00143 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking ) PRIVILEGED_FUNCTION;
00144 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
00145 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
00146 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
00147
00148
00149
00150
00151
00152 #if configUSE_CO_ROUTINES == 1
00153 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken ) PRIVILEGED_FUNCTION;
00154 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxTaskWoken ) PRIVILEGED_FUNCTION;
00155 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
00156 signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;
00157 #endif
00158
00159
00160
00161
00162
00163 #if configQUEUE_REGISTRY_SIZE > 0
00164
00165
00166
00167
00168 typedef struct QUEUE_REGISTRY_ITEM
00169 {
00170 signed char *pcQueueName;
00171 xQueueHandle xHandle;
00172 } xQueueRegistryItem;
00173
00174
00175
00176
00177 xQueueRegistryItem xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
00178
00179
00180
00181 static void vQueueUnregisterQueue( xQueueHandle xQueue ) PRIVILEGED_FUNCTION;
00182 void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName ) PRIVILEGED_FUNCTION;
00183 #endif
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 static void prvUnlockQueue( xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
00194
00195
00196
00197
00198
00199
00200 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
00201
00202
00203
00204
00205
00206
00207 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue ) PRIVILEGED_FUNCTION;
00208
00209
00210
00211
00212
00213 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition ) PRIVILEGED_FUNCTION;
00214
00215
00216
00217
00218 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer ) PRIVILEGED_FUNCTION;
00219
00220
00221
00222
00223
00224
00225 #define prvLockQueue( pxQueue ) \
00226 { \
00227 taskENTER_CRITICAL(); \
00228 { \
00229 if( pxQueue->xRxLock == queueUNLOCKED ) \
00230 { \
00231 pxQueue->xRxLock = queueLOCKED_UNMODIFIED; \
00232 } \
00233 if( pxQueue->xTxLock == queueUNLOCKED ) \
00234 { \
00235 pxQueue->xTxLock = queueLOCKED_UNMODIFIED; \
00236 } \
00237 } \
00238 taskEXIT_CRITICAL(); \
00239 }
00240
00241
00242
00243
00244
00245
00246
00247 xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize )
00248 {
00249 xQUEUE *pxNewQueue;
00250 size_t xQueueSizeInBytes;
00251
00252
00253 if( uxQueueLength > ( unsigned portBASE_TYPE ) 0 )
00254 {
00255 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
00256 if( pxNewQueue != NULL )
00257 {
00258
00259
00260 xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ) + ( size_t ) 1;
00261
00262 pxNewQueue->pcHead = ( signed char * ) pvPortMalloc( xQueueSizeInBytes );
00263 if( pxNewQueue->pcHead != NULL )
00264 {
00265
00266
00267 pxNewQueue->pcTail = pxNewQueue->pcHead + ( uxQueueLength * uxItemSize );
00268 pxNewQueue->uxMessagesWaiting = 0;
00269 pxNewQueue->pcWriteTo = pxNewQueue->pcHead;
00270 pxNewQueue->pcReadFrom = pxNewQueue->pcHead + ( ( uxQueueLength - 1 ) * uxItemSize );
00271 pxNewQueue->uxLength = uxQueueLength;
00272 pxNewQueue->uxItemSize = uxItemSize;
00273 pxNewQueue->xRxLock = queueUNLOCKED;
00274 pxNewQueue->xTxLock = queueUNLOCKED;
00275
00276
00277 vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
00278 vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
00279
00280 traceQUEUE_CREATE( pxNewQueue );
00281 return pxNewQueue;
00282 }
00283 else
00284 {
00285 traceQUEUE_CREATE_FAILED();
00286 vPortFree( pxNewQueue );
00287 }
00288 }
00289 }
00290
00291
00292
00293 return NULL;
00294 }
00295
00296
00297 #if ( configUSE_MUTEXES == 1 )
00298
00299 xQueueHandle xQueueCreateMutex( void )
00300 {
00301 xQUEUE *pxNewQueue;
00302
00303
00304 pxNewQueue = ( xQUEUE * ) pvPortMalloc( sizeof( xQUEUE ) );
00305 if( pxNewQueue != NULL )
00306 {
00307
00308 pxNewQueue->pxMutexHolder = NULL;
00309 pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
00310
00311
00312
00313 pxNewQueue->pcWriteTo = NULL;
00314 pxNewQueue->pcReadFrom = NULL;
00315
00316
00317
00318
00319 pxNewQueue->uxMessagesWaiting = 0;
00320 pxNewQueue->uxLength = 1;
00321 pxNewQueue->uxItemSize = 0;
00322 pxNewQueue->xRxLock = queueUNLOCKED;
00323 pxNewQueue->xTxLock = queueUNLOCKED;
00324
00325
00326 vListInitialise( &( pxNewQueue->xTasksWaitingToSend ) );
00327 vListInitialise( &( pxNewQueue->xTasksWaitingToReceive ) );
00328
00329
00330 xQueueGenericSend( pxNewQueue, NULL, 0, queueSEND_TO_BACK );
00331
00332 traceCREATE_MUTEX( pxNewQueue );
00333 }
00334 else
00335 {
00336 traceCREATE_MUTEX_FAILED();
00337 }
00338
00339 return pxNewQueue;
00340 }
00341
00342 #endif
00343
00344
00345 #if configUSE_RECURSIVE_MUTEXES == 1
00346
00347 portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex )
00348 {
00349 portBASE_TYPE xReturn;
00350
00351
00352
00353
00354
00355
00356
00357 if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
00358 {
00359 traceGIVE_MUTEX_RECURSIVE( pxMutex );
00360
00361
00362
00363
00364
00365
00366 ( pxMutex->uxRecursiveCallCount )--;
00367
00368
00369 if( pxMutex->uxRecursiveCallCount == 0 )
00370 {
00371
00372
00373 xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
00374 }
00375
00376 xReturn = pdPASS;
00377 }
00378 else
00379 {
00380
00381 xReturn = pdFAIL;
00382
00383 traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
00384 }
00385
00386 return xReturn;
00387 }
00388
00389 #endif
00390
00391
00392 #if configUSE_RECURSIVE_MUTEXES == 1
00393
00394 portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime )
00395 {
00396 portBASE_TYPE xReturn;
00397
00398
00399
00400
00401 traceTAKE_MUTEX_RECURSIVE( pxMutex );
00402
00403 if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
00404 {
00405 ( pxMutex->uxRecursiveCallCount )++;
00406 xReturn = pdPASS;
00407 }
00408 else
00409 {
00410 xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );
00411
00412
00413
00414 if( xReturn == pdPASS )
00415 {
00416 ( pxMutex->uxRecursiveCallCount )++;
00417 }
00418 }
00419
00420 return xReturn;
00421 }
00422
00423 #endif
00424
00425
00426 #if configUSE_COUNTING_SEMAPHORES == 1
00427
00428 xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount )
00429 {
00430 xQueueHandle pxHandle;
00431
00432 pxHandle = xQueueCreate( ( unsigned portBASE_TYPE ) uxCountValue, queueSEMAPHORE_QUEUE_ITEM_LENGTH );
00433
00434 if( pxHandle != NULL )
00435 {
00436 pxHandle->uxMessagesWaiting = uxInitialCount;
00437
00438 traceCREATE_COUNTING_SEMAPHORE();
00439 }
00440 else
00441 {
00442 traceCREATE_COUNTING_SEMAPHORE_FAILED();
00443 }
00444
00445 return pxHandle;
00446 }
00447
00448 #endif
00449
00450
00451 signed portBASE_TYPE xQueueGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
00452 {
00453 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
00454 xTimeOutType xTimeOut;
00455
00456
00457
00458
00459 for( ;; )
00460 {
00461 taskENTER_CRITICAL();
00462 {
00463
00464
00465 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
00466 {
00467 traceQUEUE_SEND( pxQueue );
00468 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
00469
00470
00471
00472 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
00473 {
00474 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
00475 {
00476
00477
00478
00479
00480 portYIELD_WITHIN_API();
00481 }
00482 }
00483
00484 taskEXIT_CRITICAL();
00485
00486
00487
00488 return pdPASS;
00489 }
00490 else
00491 {
00492 if( xTicksToWait == ( portTickType ) 0 )
00493 {
00494
00495
00496 taskEXIT_CRITICAL();
00497
00498
00499
00500 traceQUEUE_SEND_FAILED( pxQueue );
00501 return errQUEUE_FULL;
00502 }
00503 else if( xEntryTimeSet == pdFALSE )
00504 {
00505
00506
00507 vTaskSetTimeOutState( &xTimeOut );
00508 xEntryTimeSet = pdTRUE;
00509 }
00510 }
00511 }
00512 taskEXIT_CRITICAL();
00513
00514
00515
00516
00517 vTaskSuspendAll();
00518 prvLockQueue( pxQueue );
00519
00520
00521 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
00522 {
00523 if( prvIsQueueFull( pxQueue ) )
00524 {
00525 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
00526 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
00527
00528
00529
00530
00531
00532
00533 prvUnlockQueue( pxQueue );
00534
00535
00536
00537
00538
00539
00540 if( !xTaskResumeAll() )
00541 {
00542 portYIELD_WITHIN_API();
00543 }
00544 }
00545 else
00546 {
00547
00548 prvUnlockQueue( pxQueue );
00549 ( void ) xTaskResumeAll();
00550 }
00551 }
00552 else
00553 {
00554
00555 prvUnlockQueue( pxQueue );
00556 ( void ) xTaskResumeAll();
00557
00558
00559
00560 traceQUEUE_SEND_FAILED( pxQueue );
00561 return errQUEUE_FULL;
00562 }
00563 }
00564 }
00565
00566
00567 #if configUSE_ALTERNATIVE_API == 1
00568
00569 signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition )
00570 {
00571 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
00572 xTimeOutType xTimeOut;
00573
00574 for( ;; )
00575 {
00576 taskENTER_CRITICAL();
00577 {
00578
00579
00580 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
00581 {
00582 traceQUEUE_SEND( pxQueue );
00583 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
00584
00585
00586
00587 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
00588 {
00589 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) == pdTRUE )
00590 {
00591
00592
00593 portYIELD_WITHIN_API();
00594 }
00595 }
00596
00597 taskEXIT_CRITICAL();
00598 return pdPASS;
00599 }
00600 else
00601 {
00602 if( xTicksToWait == ( portTickType ) 0 )
00603 {
00604 taskEXIT_CRITICAL();
00605 return errQUEUE_FULL;
00606 }
00607 else if( xEntryTimeSet == pdFALSE )
00608 {
00609 vTaskSetTimeOutState( &xTimeOut );
00610 xEntryTimeSet = pdTRUE;
00611 }
00612 }
00613 }
00614 taskEXIT_CRITICAL();
00615
00616 taskENTER_CRITICAL();
00617 {
00618 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
00619 {
00620 if( prvIsQueueFull( pxQueue ) )
00621 {
00622 traceBLOCKING_ON_QUEUE_SEND( pxQueue );
00623 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
00624 portYIELD_WITHIN_API();
00625 }
00626 }
00627 else
00628 {
00629 taskEXIT_CRITICAL();
00630 traceQUEUE_SEND_FAILED( pxQueue );
00631 return errQUEUE_FULL;
00632 }
00633 }
00634 taskEXIT_CRITICAL();
00635 }
00636 }
00637
00638 #endif
00639
00640
00641 #if configUSE_ALTERNATIVE_API == 1
00642
00643 signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
00644 {
00645 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
00646 xTimeOutType xTimeOut;
00647 signed char *pcOriginalReadPosition;
00648
00649 for( ;; )
00650 {
00651 taskENTER_CRITICAL();
00652 {
00653 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
00654 {
00655
00656 pcOriginalReadPosition = pxQueue->pcReadFrom;
00657
00658 prvCopyDataFromQueue( pxQueue, pvBuffer );
00659
00660 if( xJustPeeking == pdFALSE )
00661 {
00662 traceQUEUE_RECEIVE( pxQueue );
00663
00664
00665 --( pxQueue->uxMessagesWaiting );
00666
00667 #if ( configUSE_MUTEXES == 1 )
00668 {
00669 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
00670 {
00671
00672
00673 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
00674 }
00675 }
00676 #endif
00677
00678 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
00679 {
00680 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
00681 {
00682 portYIELD_WITHIN_API();
00683 }
00684 }
00685 }
00686 else
00687 {
00688 traceQUEUE_PEEK( pxQueue );
00689
00690
00691
00692 pxQueue->pcReadFrom = pcOriginalReadPosition;
00693
00694
00695
00696 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
00697 {
00698
00699
00700 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
00701 {
00702
00703 portYIELD_WITHIN_API();
00704 }
00705 }
00706
00707 }
00708
00709 taskEXIT_CRITICAL();
00710 return pdPASS;
00711 }
00712 else
00713 {
00714 if( xTicksToWait == ( portTickType ) 0 )
00715 {
00716 taskEXIT_CRITICAL();
00717 traceQUEUE_RECEIVE_FAILED( pxQueue );
00718 return errQUEUE_EMPTY;
00719 }
00720 else if( xEntryTimeSet == pdFALSE )
00721 {
00722 vTaskSetTimeOutState( &xTimeOut );
00723 xEntryTimeSet = pdTRUE;
00724 }
00725 }
00726 }
00727 taskEXIT_CRITICAL();
00728
00729 taskENTER_CRITICAL();
00730 {
00731 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
00732 {
00733 if( prvIsQueueEmpty( pxQueue ) )
00734 {
00735 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
00736
00737 #if ( configUSE_MUTEXES == 1 )
00738 {
00739 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
00740 {
00741 portENTER_CRITICAL();
00742 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
00743 portEXIT_CRITICAL();
00744 }
00745 }
00746 #endif
00747
00748 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
00749 portYIELD_WITHIN_API();
00750 }
00751 }
00752 else
00753 {
00754 taskEXIT_CRITICAL();
00755 traceQUEUE_RECEIVE_FAILED( pxQueue );
00756 return errQUEUE_EMPTY;
00757 }
00758 }
00759 taskEXIT_CRITICAL();
00760 }
00761 }
00762
00763
00764 #endif
00765
00766
00767 signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )
00768 {
00769 signed portBASE_TYPE xReturn;
00770 unsigned portBASE_TYPE uxSavedInterruptStatus;
00771
00772
00773
00774
00775
00776
00777 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
00778 {
00779 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
00780 {
00781 traceQUEUE_SEND_FROM_ISR( pxQueue );
00782
00783 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
00784
00785
00786
00787 if( pxQueue->xTxLock == queueUNLOCKED )
00788 {
00789 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
00790 {
00791 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
00792 {
00793
00794
00795 *pxHigherPriorityTaskWoken = pdTRUE;
00796 }
00797 }
00798 }
00799 else
00800 {
00801
00802
00803 ++( pxQueue->xTxLock );
00804 }
00805
00806 xReturn = pdPASS;
00807 }
00808 else
00809 {
00810 traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
00811 xReturn = errQUEUE_FULL;
00812 }
00813 }
00814 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
00815
00816 return xReturn;
00817 }
00818
00819
00820 signed portBASE_TYPE xQueueGenericReceive( xQueueHandle pxQueue, void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking )
00821 {
00822 signed portBASE_TYPE xEntryTimeSet = pdFALSE;
00823 xTimeOutType xTimeOut;
00824 signed char *pcOriginalReadPosition;
00825
00826
00827
00828
00829
00830 for( ;; )
00831 {
00832 taskENTER_CRITICAL();
00833 {
00834
00835
00836 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
00837 {
00838
00839 pcOriginalReadPosition = pxQueue->pcReadFrom;
00840
00841 prvCopyDataFromQueue( pxQueue, pvBuffer );
00842
00843 if( xJustPeeking == pdFALSE )
00844 {
00845 traceQUEUE_RECEIVE( pxQueue );
00846
00847
00848 --( pxQueue->uxMessagesWaiting );
00849
00850 #if ( configUSE_MUTEXES == 1 )
00851 {
00852 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
00853 {
00854
00855
00856 pxQueue->pxMutexHolder = xTaskGetCurrentTaskHandle();
00857 }
00858 }
00859 #endif
00860
00861 if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
00862 {
00863 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) == pdTRUE )
00864 {
00865 portYIELD_WITHIN_API();
00866 }
00867 }
00868 }
00869 else
00870 {
00871 traceQUEUE_PEEK( pxQueue );
00872
00873
00874
00875 pxQueue->pcReadFrom = pcOriginalReadPosition;
00876
00877
00878
00879 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
00880 {
00881
00882
00883 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
00884 {
00885
00886 portYIELD_WITHIN_API();
00887 }
00888 }
00889
00890 }
00891
00892 taskEXIT_CRITICAL();
00893 return pdPASS;
00894 }
00895 else
00896 {
00897 if( xTicksToWait == ( portTickType ) 0 )
00898 {
00899
00900
00901 taskEXIT_CRITICAL();
00902 traceQUEUE_RECEIVE_FAILED( pxQueue );
00903 return errQUEUE_EMPTY;
00904 }
00905 else if( xEntryTimeSet == pdFALSE )
00906 {
00907
00908
00909 vTaskSetTimeOutState( &xTimeOut );
00910 xEntryTimeSet = pdTRUE;
00911 }
00912 }
00913 }
00914 taskEXIT_CRITICAL();
00915
00916
00917
00918
00919 vTaskSuspendAll();
00920 prvLockQueue( pxQueue );
00921
00922
00923 if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
00924 {
00925 if( prvIsQueueEmpty( pxQueue ) )
00926 {
00927 traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
00928
00929 #if ( configUSE_MUTEXES == 1 )
00930 {
00931 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
00932 {
00933 portENTER_CRITICAL();
00934 {
00935 vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
00936 }
00937 portEXIT_CRITICAL();
00938 }
00939 }
00940 #endif
00941
00942 vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
00943 prvUnlockQueue( pxQueue );
00944 if( !xTaskResumeAll() )
00945 {
00946 portYIELD_WITHIN_API();
00947 }
00948 }
00949 else
00950 {
00951
00952 prvUnlockQueue( pxQueue );
00953 ( void ) xTaskResumeAll();
00954 }
00955 }
00956 else
00957 {
00958 prvUnlockQueue( pxQueue );
00959 ( void ) xTaskResumeAll();
00960 traceQUEUE_RECEIVE_FAILED( pxQueue );
00961 return errQUEUE_EMPTY;
00962 }
00963 }
00964 }
00965
00966
00967 signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken )
00968 {
00969 signed portBASE_TYPE xReturn;
00970 unsigned portBASE_TYPE uxSavedInterruptStatus;
00971
00972 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
00973 {
00974
00975 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
00976 {
00977 traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
00978
00979 prvCopyDataFromQueue( pxQueue, pvBuffer );
00980 --( pxQueue->uxMessagesWaiting );
00981
00982
00983
00984
00985 if( pxQueue->xRxLock == queueUNLOCKED )
00986 {
00987 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
00988 {
00989 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
00990 {
00991
00992
00993 *pxTaskWoken = pdTRUE;
00994 }
00995 }
00996 }
00997 else
00998 {
00999
01000
01001 ++( pxQueue->xRxLock );
01002 }
01003
01004 xReturn = pdPASS;
01005 }
01006 else
01007 {
01008 xReturn = pdFAIL;
01009 traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
01010 }
01011 }
01012 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
01013
01014 return xReturn;
01015 }
01016
01017
01018 unsigned portBASE_TYPE uxQueueMessagesWaiting( const xQueueHandle pxQueue )
01019 {
01020 unsigned portBASE_TYPE uxReturn;
01021
01022 taskENTER_CRITICAL();
01023 uxReturn = pxQueue->uxMessagesWaiting;
01024 taskEXIT_CRITICAL();
01025
01026 return uxReturn;
01027 }
01028
01029
01030 unsigned portBASE_TYPE uxQueueMessagesWaitingFromISR( const xQueueHandle pxQueue )
01031 {
01032 unsigned portBASE_TYPE uxReturn;
01033
01034 uxReturn = pxQueue->uxMessagesWaiting;
01035
01036 return uxReturn;
01037 }
01038
01039
01040 void vQueueDelete( xQueueHandle pxQueue )
01041 {
01042 traceQUEUE_DELETE( pxQueue );
01043 vQueueUnregisterQueue( pxQueue );
01044 vPortFree( pxQueue->pcHead );
01045 vPortFree( pxQueue );
01046 }
01047
01048
01049 static void prvCopyDataToQueue( xQUEUE *pxQueue, const void *pvItemToQueue, portBASE_TYPE xPosition )
01050 {
01051 if( pxQueue->uxItemSize == ( unsigned portBASE_TYPE ) 0 )
01052 {
01053 #if ( configUSE_MUTEXES == 1 )
01054 {
01055 if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
01056 {
01057
01058 vTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
01059 pxQueue->pxMutexHolder = NULL;
01060 }
01061 }
01062 #endif
01063 }
01064 else if( xPosition == queueSEND_TO_BACK )
01065 {
01066 memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
01067 pxQueue->pcWriteTo += pxQueue->uxItemSize;
01068 if( pxQueue->pcWriteTo >= pxQueue->pcTail )
01069 {
01070 pxQueue->pcWriteTo = pxQueue->pcHead;
01071 }
01072 }
01073 else
01074 {
01075 memcpy( ( void * ) pxQueue->pcReadFrom, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );
01076 pxQueue->pcReadFrom -= pxQueue->uxItemSize;
01077 if( pxQueue->pcReadFrom < pxQueue->pcHead )
01078 {
01079 pxQueue->pcReadFrom = ( pxQueue->pcTail - pxQueue->uxItemSize );
01080 }
01081 }
01082
01083 ++( pxQueue->uxMessagesWaiting );
01084 }
01085
01086
01087 static void prvCopyDataFromQueue( xQUEUE * const pxQueue, const void *pvBuffer )
01088 {
01089 if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
01090 {
01091 pxQueue->pcReadFrom += pxQueue->uxItemSize;
01092 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
01093 {
01094 pxQueue->pcReadFrom = pxQueue->pcHead;
01095 }
01096 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
01097 }
01098 }
01099
01100
01101 static void prvUnlockQueue( xQueueHandle pxQueue )
01102 {
01103
01104
01105
01106
01107
01108
01109 taskENTER_CRITICAL();
01110 {
01111
01112 while( pxQueue->xTxLock > queueLOCKED_UNMODIFIED )
01113 {
01114
01115
01116 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
01117 {
01118
01119
01120 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
01121 {
01122
01123
01124 vTaskMissedYield();
01125 }
01126
01127 --( pxQueue->xTxLock );
01128 }
01129 else
01130 {
01131 break;
01132 }
01133 }
01134
01135 pxQueue->xTxLock = queueUNLOCKED;
01136 }
01137 taskEXIT_CRITICAL();
01138
01139
01140 taskENTER_CRITICAL();
01141 {
01142 while( pxQueue->xRxLock > queueLOCKED_UNMODIFIED )
01143 {
01144 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
01145 {
01146 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
01147 {
01148 vTaskMissedYield();
01149 }
01150
01151 --( pxQueue->xRxLock );
01152 }
01153 else
01154 {
01155 break;
01156 }
01157 }
01158
01159 pxQueue->xRxLock = queueUNLOCKED;
01160 }
01161 taskEXIT_CRITICAL();
01162 }
01163
01164
01165 static signed portBASE_TYPE prvIsQueueEmpty( const xQueueHandle pxQueue )
01166 {
01167 signed portBASE_TYPE xReturn;
01168
01169 taskENTER_CRITICAL();
01170 xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
01171 taskEXIT_CRITICAL();
01172
01173 return xReturn;
01174 }
01175
01176
01177 signed portBASE_TYPE xQueueIsQueueEmptyFromISR( const xQueueHandle pxQueue )
01178 {
01179 signed portBASE_TYPE xReturn;
01180
01181 xReturn = ( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 );
01182
01183 return xReturn;
01184 }
01185
01186
01187 static signed portBASE_TYPE prvIsQueueFull( const xQueueHandle pxQueue )
01188 {
01189 signed portBASE_TYPE xReturn;
01190
01191 taskENTER_CRITICAL();
01192 xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
01193 taskEXIT_CRITICAL();
01194
01195 return xReturn;
01196 }
01197
01198
01199 signed portBASE_TYPE xQueueIsQueueFullFromISR( const xQueueHandle pxQueue )
01200 {
01201 signed portBASE_TYPE xReturn;
01202
01203 xReturn = ( pxQueue->uxMessagesWaiting == pxQueue->uxLength );
01204
01205 return xReturn;
01206 }
01207
01208
01209 #if configUSE_CO_ROUTINES == 1
01210 signed portBASE_TYPE xQueueCRSend( xQueueHandle pxQueue, const void *pvItemToQueue, portTickType xTicksToWait )
01211 {
01212 signed portBASE_TYPE xReturn;
01213
01214
01215
01216
01217 portDISABLE_INTERRUPTS();
01218 {
01219 if( prvIsQueueFull( pxQueue ) )
01220 {
01221
01222
01223 if( xTicksToWait > ( portTickType ) 0 )
01224 {
01225
01226
01227 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) );
01228 portENABLE_INTERRUPTS();
01229 return errQUEUE_BLOCKED;
01230 }
01231 else
01232 {
01233 portENABLE_INTERRUPTS();
01234 return errQUEUE_FULL;
01235 }
01236 }
01237 }
01238 portENABLE_INTERRUPTS();
01239
01240 portNOP();
01241
01242 portDISABLE_INTERRUPTS();
01243 {
01244 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
01245 {
01246
01247 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
01248 xReturn = pdPASS;
01249
01250
01251 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
01252 {
01253
01254
01255
01256
01257 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
01258 {
01259
01260
01261 xReturn = errQUEUE_YIELD;
01262 }
01263 }
01264 }
01265 else
01266 {
01267 xReturn = errQUEUE_FULL;
01268 }
01269 }
01270 portENABLE_INTERRUPTS();
01271
01272 return xReturn;
01273 }
01274 #endif
01275
01276
01277 #if configUSE_CO_ROUTINES == 1
01278 signed portBASE_TYPE xQueueCRReceive( xQueueHandle pxQueue, void *pvBuffer, portTickType xTicksToWait )
01279 {
01280 signed portBASE_TYPE xReturn;
01281
01282
01283
01284
01285 portDISABLE_INTERRUPTS();
01286 {
01287 if( pxQueue->uxMessagesWaiting == ( unsigned portBASE_TYPE ) 0 )
01288 {
01289
01290
01291 if( xTicksToWait > ( portTickType ) 0 )
01292 {
01293
01294
01295 vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) );
01296 portENABLE_INTERRUPTS();
01297 return errQUEUE_BLOCKED;
01298 }
01299 else
01300 {
01301 portENABLE_INTERRUPTS();
01302 return errQUEUE_FULL;
01303 }
01304 }
01305 }
01306 portENABLE_INTERRUPTS();
01307
01308 portNOP();
01309
01310 portDISABLE_INTERRUPTS();
01311 {
01312 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
01313 {
01314
01315 pxQueue->pcReadFrom += pxQueue->uxItemSize;
01316 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
01317 {
01318 pxQueue->pcReadFrom = pxQueue->pcHead;
01319 }
01320 --( pxQueue->uxMessagesWaiting );
01321 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
01322
01323 xReturn = pdPASS;
01324
01325
01326 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
01327 {
01328
01329
01330
01331
01332 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
01333 {
01334 xReturn = errQUEUE_YIELD;
01335 }
01336 }
01337 }
01338 else
01339 {
01340 xReturn = pdFAIL;
01341 }
01342 }
01343 portENABLE_INTERRUPTS();
01344
01345 return xReturn;
01346 }
01347 #endif
01348
01349
01350
01351
01352 #if configUSE_CO_ROUTINES == 1
01353 signed portBASE_TYPE xQueueCRSendFromISR( xQueueHandle pxQueue, const void *pvItemToQueue, signed portBASE_TYPE xCoRoutinePreviouslyWoken )
01354 {
01355
01356
01357 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
01358 {
01359 prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK );
01360
01361
01362
01363 if( !xCoRoutinePreviouslyWoken )
01364 {
01365 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
01366 {
01367 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
01368 {
01369 return pdTRUE;
01370 }
01371 }
01372 }
01373 }
01374
01375 return xCoRoutinePreviouslyWoken;
01376 }
01377 #endif
01378
01379
01380 #if configUSE_CO_ROUTINES == 1
01381 signed portBASE_TYPE xQueueCRReceiveFromISR( xQueueHandle pxQueue, void *pvBuffer, signed portBASE_TYPE *pxCoRoutineWoken )
01382 {
01383 signed portBASE_TYPE xReturn;
01384
01385
01386
01387 if( pxQueue->uxMessagesWaiting > ( unsigned portBASE_TYPE ) 0 )
01388 {
01389
01390 pxQueue->pcReadFrom += pxQueue->uxItemSize;
01391 if( pxQueue->pcReadFrom >= pxQueue->pcTail )
01392 {
01393 pxQueue->pcReadFrom = pxQueue->pcHead;
01394 }
01395 --( pxQueue->uxMessagesWaiting );
01396 memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->pcReadFrom, ( unsigned ) pxQueue->uxItemSize );
01397
01398 if( !( *pxCoRoutineWoken ) )
01399 {
01400 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) )
01401 {
01402 if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
01403 {
01404 *pxCoRoutineWoken = pdTRUE;
01405 }
01406 }
01407 }
01408
01409 xReturn = pdPASS;
01410 }
01411 else
01412 {
01413 xReturn = pdFAIL;
01414 }
01415
01416 return xReturn;
01417 }
01418 #endif
01419
01420
01421 #if configQUEUE_REGISTRY_SIZE > 0
01422
01423 void vQueueAddToRegistry( xQueueHandle xQueue, signed char *pcQueueName )
01424 {
01425 unsigned portBASE_TYPE ux;
01426
01427
01428
01429 for( ux = 0; ux < configQUEUE_REGISTRY_SIZE; ux++ )
01430 {
01431 if( xQueueRegistry[ ux ].pcQueueName == NULL )
01432 {
01433
01434 xQueueRegistry[ ux ].pcQueueName = pcQueueName;
01435 xQueueRegistry[ ux ].xHandle = xQueue;
01436 break;
01437 }
01438 }
01439 }
01440
01441 #endif
01442
01443
01444 #if configQUEUE_REGISTRY_SIZE > 0
01445
01446 static void vQueueUnregisterQueue( xQueueHandle xQueue )
01447 {
01448 unsigned portBASE_TYPE ux;
01449
01450
01451
01452 for( ux = 0; ux < configQUEUE_REGISTRY_SIZE; ux++ )
01453 {
01454 if( xQueueRegistry[ ux ].xHandle == xQueue )
01455 {
01456
01457 xQueueRegistry[ ux ].pcQueueName = NULL;
01458 break;
01459 }
01460 }
01461
01462 }
01463
01464 #endif
01465