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
00055 #include <stdio.h>
00056 #include <stdlib.h>
00057 #include <string.h>
00058
00059
00060
00061
00062 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
00063
00064 #include "FreeRTOS.h"
00065 #include "task.h"
00066 #include "StackMacros.h"
00067
00068 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
00069
00070
00071
00072
00073 #define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE
00074
00075 #define tskIDLE_PRIORITY ( ( unsigned portBASE_TYPE ) 0 )
00076
00077
00078
00079
00080
00081 typedef struct tskTaskControlBlock
00082 {
00083 volatile portSTACK_TYPE *pxTopOfStack;
00084
00085 #if ( portUSING_MPU_WRAPPERS == 1 )
00086 xMPU_SETTINGS xMPUSettings;
00087 #endif
00088
00089 xListItem xGenericListItem;
00090 xListItem xEventListItem;
00091 unsigned portBASE_TYPE uxPriority;
00092 portSTACK_TYPE *pxStack;
00093 signed char pcTaskName[ configMAX_TASK_NAME_LEN ];
00094
00095 #if ( portSTACK_GROWTH > 0 )
00096 portSTACK_TYPE *pxEndOfStack;
00097 #endif
00098
00099 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
00100 unsigned portBASE_TYPE uxCriticalNesting;
00101 #endif
00102
00103 #if ( configUSE_TRACE_FACILITY == 1 )
00104 unsigned portBASE_TYPE uxTCBNumber;
00105 #endif
00106
00107 #if ( configUSE_MUTEXES == 1 )
00108 unsigned portBASE_TYPE uxBasePriority;
00109 #endif
00110
00111 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
00112 pdTASK_HOOK_CODE pxTaskTag;
00113 #endif
00114
00115 #if ( configGENERATE_RUN_TIME_STATS == 1 )
00116 unsigned long ulRunTimeCounter;
00117 #endif
00118
00119 } tskTCB;
00120
00121
00122
00123
00124
00125
00126 #ifdef portREMOVE_STATIC_QUALIFIER
00127 #define static
00128 #endif
00129
00130
00131 PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL;
00132
00133
00134
00135 PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ];
00136 PRIVILEGED_DATA static xList xDelayedTaskList1;
00137 PRIVILEGED_DATA static xList xDelayedTaskList2;
00138 PRIVILEGED_DATA static xList * volatile pxDelayedTaskList ;
00139 PRIVILEGED_DATA static xList * volatile pxOverflowDelayedTaskList;
00140 PRIVILEGED_DATA static xList xPendingReadyList;
00141
00142 #if ( INCLUDE_vTaskDelete == 1 )
00143
00144 PRIVILEGED_DATA static volatile xList xTasksWaitingTermination;
00145 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTasksDeleted = ( unsigned portBASE_TYPE ) 0;
00146
00147 #endif
00148
00149 #if ( INCLUDE_vTaskSuspend == 1 )
00150
00151 PRIVILEGED_DATA static xList xSuspendedTaskList;
00152
00153 #endif
00154
00155
00156 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0;
00157 PRIVILEGED_DATA static volatile portTickType xTickCount = ( portTickType ) 0;
00158 PRIVILEGED_DATA static unsigned portBASE_TYPE uxTopUsedPriority = tskIDLE_PRIORITY;
00159 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTopReadyPriority = tskIDLE_PRIORITY;
00160 PRIVILEGED_DATA static volatile signed portBASE_TYPE xSchedulerRunning = pdFALSE;
00161 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended = ( unsigned portBASE_TYPE ) pdFALSE;
00162 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxMissedTicks = ( unsigned portBASE_TYPE ) 0;
00163 PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE;
00164 PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0;
00165 PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0;
00166
00167 #if ( configGENERATE_RUN_TIME_STATS == 1 )
00168
00169 PRIVILEGED_DATA static char pcStatsString[ 50 ] ;
00170 PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL;
00171 static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime ) PRIVILEGED_FUNCTION;
00172
00173 #endif
00174
00175
00176
00177
00178
00179
00180
00181 #define tskSTACK_FILL_BYTE ( 0xa5 )
00182
00183
00184
00185
00186 #define tskBLOCKED_CHAR ( ( signed char ) 'B' )
00187 #define tskREADY_CHAR ( ( signed char ) 'R' )
00188 #define tskDELETED_CHAR ( ( signed char ) 'D' )
00189 #define tskSUSPENDED_CHAR ( ( signed char ) 'S' )
00190
00191
00192
00193
00194 #if ( configUSE_TRACE_FACILITY == 1 )
00195
00196 #define tskSIZE_OF_EACH_TRACE_LINE ( ( unsigned long ) ( sizeof( unsigned long ) + sizeof( unsigned long ) ) )
00197 PRIVILEGED_DATA static volatile signed char * volatile pcTraceBuffer;
00198 PRIVILEGED_DATA static signed char *pcTraceBufferStart;
00199 PRIVILEGED_DATA static signed char *pcTraceBufferEnd;
00200 PRIVILEGED_DATA static signed portBASE_TYPE xTracing = pdFALSE;
00201 static unsigned portBASE_TYPE uxPreviousTask = 255;
00202 PRIVILEGED_DATA static char pcStatusString[ 50 ];
00203
00204 #endif
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 #if ( configUSE_TRACE_FACILITY == 1 )
00215
00216 #define vWriteTraceToBuffer() \
00217 { \
00218 if( xTracing ) \
00219 { \
00220 if( uxPreviousTask != pxCurrentTCB->uxTCBNumber ) \
00221 { \
00222 if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \
00223 { \
00224 uxPreviousTask = pxCurrentTCB->uxTCBNumber; \
00225 *( unsigned long * ) pcTraceBuffer = ( unsigned long ) xTickCount; \
00226 pcTraceBuffer += sizeof( unsigned long ); \
00227 *( unsigned long * ) pcTraceBuffer = ( unsigned long ) uxPreviousTask; \
00228 pcTraceBuffer += sizeof( unsigned long ); \
00229 } \
00230 else \
00231 { \
00232 xTracing = pdFALSE; \
00233 } \
00234 } \
00235 } \
00236 }
00237
00238 #else
00239
00240 #define vWriteTraceToBuffer()
00241
00242 #endif
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 #define prvAddTaskToReadyQueue( pxTCB ) \
00253 { \
00254 if( pxTCB->uxPriority > uxTopReadyPriority ) \
00255 { \
00256 uxTopReadyPriority = pxTCB->uxPriority; \
00257 } \
00258 vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ); \
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 #define prvCheckDelayedTasks() \
00271 { \
00272 register tskTCB *pxTCB; \
00273 \
00274 while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL ) \
00275 { \
00276 if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) ) \
00277 { \
00278 break; \
00279 } \
00280 vListRemove( &( pxTCB->xGenericListItem ) ); \
00281 \
00282 if( pxTCB->xEventListItem.pvContainer ) \
00283 { \
00284 vListRemove( &( pxTCB->xEventListItem ) ); \
00285 } \
00286 prvAddTaskToReadyQueue( pxTCB ); \
00287 } \
00288 }
00289
00290
00291
00292
00293
00294
00295
00296
00297 #define prvGetTCBFromHandle( pxHandle ) ( ( pxHandle == NULL ) ? ( tskTCB * ) pxCurrentTCB : ( tskTCB * ) pxHandle )
00298
00299
00300
00301
00302
00303
00304
00305
00306 static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) PRIVILEGED_FUNCTION;
00307
00308
00309
00310
00311
00312 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
00326
00327
00328
00329
00330
00331
00332
00333
00334 #if ( ( INCLUDE_vTaskDelete == 1 ) || ( INCLUDE_vTaskCleanUpResources == 1 ) )
00335
00336 static void prvDeleteTCB( tskTCB *pxTCB ) PRIVILEGED_FUNCTION;
00337
00338 #endif
00339
00340
00341
00342
00343
00344
00345 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
00346
00347
00348
00349
00350
00351 static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) PRIVILEGED_FUNCTION;
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362 #if ( configUSE_TRACE_FACILITY == 1 )
00363
00364 static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus ) PRIVILEGED_FUNCTION;
00365
00366 #endif
00367
00368
00369
00370
00371
00372
00373 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
00374
00375 static unsigned short usTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) PRIVILEGED_FUNCTION;
00376
00377 #endif
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions )
00389 {
00390 signed portBASE_TYPE xReturn;
00391 tskTCB * pxNewTCB;
00392 portBASE_TYPE xRunPrivileged;
00393
00394
00395
00396 pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer );
00397
00398 if( pxNewTCB != NULL )
00399 {
00400 portSTACK_TYPE *pxTopOfStack;
00401
00402
00403 if( ( uxPriority & portPRIVILEGE_BIT ) != 0x00 )
00404 {
00405 xRunPrivileged = pdTRUE;
00406 }
00407 else
00408 {
00409 xRunPrivileged = pdFALSE;
00410 }
00411 uxPriority &= ~portPRIVILEGE_BIT;
00412
00413
00414
00415
00416
00417 #if( portSTACK_GROWTH < 0 )
00418 {
00419 pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
00420 pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( unsigned long ) pxTopOfStack ) & ( ( unsigned long ) ~portBYTE_ALIGNMENT_MASK ) );
00421 }
00422 #else
00423 {
00424 pxTopOfStack = pxNewTCB->pxStack;
00425
00426
00427
00428
00429 pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
00430 }
00431 #endif
00432
00433
00434 prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth );
00435
00436
00437
00438
00439
00440 #if( portUSING_MPU_WRAPPERS == 1 )
00441 {
00442 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
00443 }
00444 #else
00445 {
00446 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
00447 ( void ) xRunPrivileged;
00448 }
00449 #endif
00450
00451
00452
00453 portENTER_CRITICAL();
00454 {
00455 uxCurrentNumberOfTasks++;
00456 if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 )
00457 {
00458
00459 pxCurrentTCB = pxNewTCB;
00460
00461
00462
00463
00464 prvInitialiseTaskLists();
00465 }
00466 else
00467 {
00468
00469
00470
00471 if( xSchedulerRunning == pdFALSE )
00472 {
00473 if( pxCurrentTCB->uxPriority <= uxPriority )
00474 {
00475 pxCurrentTCB = pxNewTCB;
00476 }
00477 }
00478 }
00479
00480
00481
00482 if( pxNewTCB->uxPriority > uxTopUsedPriority )
00483 {
00484 uxTopUsedPriority = pxNewTCB->uxPriority;
00485 }
00486
00487 #if ( configUSE_TRACE_FACILITY == 1 )
00488 {
00489
00490 pxNewTCB->uxTCBNumber = uxTaskNumber;
00491 }
00492 #endif
00493 uxTaskNumber++;
00494
00495 prvAddTaskToReadyQueue( pxNewTCB );
00496
00497 xReturn = pdPASS;
00498 traceTASK_CREATE( pxNewTCB );
00499 }
00500 portEXIT_CRITICAL();
00501 }
00502 else
00503 {
00504 xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
00505 traceTASK_CREATE_FAILED( pxNewTCB );
00506 }
00507
00508 if( xReturn == pdPASS )
00509 {
00510 if( ( void * ) pxCreatedTask != NULL )
00511 {
00512
00513
00514
00515 *pxCreatedTask = ( xTaskHandle ) pxNewTCB;
00516 }
00517
00518 if( xSchedulerRunning != pdFALSE )
00519 {
00520
00521
00522 if( pxCurrentTCB->uxPriority < uxPriority )
00523 {
00524 portYIELD_WITHIN_API();
00525 }
00526 }
00527 }
00528
00529 return xReturn;
00530 }
00531
00532
00533 #if ( INCLUDE_vTaskDelete == 1 )
00534
00535 void vTaskDelete( xTaskHandle pxTaskToDelete )
00536 {
00537 tskTCB *pxTCB;
00538
00539 portENTER_CRITICAL();
00540 {
00541
00542
00543 if( pxTaskToDelete == pxCurrentTCB )
00544 {
00545 pxTaskToDelete = NULL;
00546 }
00547
00548
00549 pxTCB = prvGetTCBFromHandle( pxTaskToDelete );
00550
00551
00552
00553
00554
00555 vListRemove( &( pxTCB->xGenericListItem ) );
00556
00557
00558 if( pxTCB->xEventListItem.pvContainer )
00559 {
00560 vListRemove( &( pxTCB->xEventListItem ) );
00561 }
00562
00563 vListInsertEnd( ( xList * ) &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );
00564
00565
00566
00567
00568 ++uxTasksDeleted;
00569
00570
00571
00572 uxTaskNumber++;
00573
00574 traceTASK_DELETE( pxTCB );
00575 }
00576 portEXIT_CRITICAL();
00577
00578
00579 if( xSchedulerRunning != pdFALSE )
00580 {
00581 if( ( void * ) pxTaskToDelete == NULL )
00582 {
00583 portYIELD_WITHIN_API();
00584 }
00585 }
00586 }
00587
00588 #endif
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599 #if ( INCLUDE_vTaskDelayUntil == 1 )
00600
00601 void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement )
00602 {
00603 portTickType xTimeToWake;
00604 portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE;
00605
00606 vTaskSuspendAll();
00607 {
00608
00609 xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
00610
00611 if( xTickCount < *pxPreviousWakeTime )
00612 {
00613
00614
00615
00616
00617
00618 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xTickCount ) )
00619 {
00620 xShouldDelay = pdTRUE;
00621 }
00622 }
00623 else
00624 {
00625
00626
00627
00628 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xTickCount ) )
00629 {
00630 xShouldDelay = pdTRUE;
00631 }
00632 }
00633
00634
00635 *pxPreviousWakeTime = xTimeToWake;
00636
00637 if( xShouldDelay )
00638 {
00639 traceTASK_DELAY_UNTIL();
00640
00641
00642
00643
00644 vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
00645
00646
00647 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
00648
00649 if( xTimeToWake < xTickCount )
00650 {
00651
00652
00653 vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
00654 }
00655 else
00656 {
00657
00658
00659 vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
00660 }
00661 }
00662 }
00663 xAlreadyYielded = xTaskResumeAll();
00664
00665
00666
00667 if( !xAlreadyYielded )
00668 {
00669 portYIELD_WITHIN_API();
00670 }
00671 }
00672
00673 #endif
00674
00675
00676 #if ( INCLUDE_vTaskDelay == 1 )
00677
00678 void vTaskDelay( portTickType xTicksToDelay )
00679 {
00680 portTickType xTimeToWake;
00681 signed portBASE_TYPE xAlreadyYielded = pdFALSE;
00682
00683
00684 if( xTicksToDelay > ( portTickType ) 0 )
00685 {
00686 vTaskSuspendAll();
00687 {
00688 traceTASK_DELAY();
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700 xTimeToWake = xTickCount + xTicksToDelay;
00701
00702
00703
00704
00705 vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
00706
00707
00708 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
00709
00710 if( xTimeToWake < xTickCount )
00711 {
00712
00713
00714 vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
00715 }
00716 else
00717 {
00718
00719
00720 vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
00721 }
00722 }
00723 xAlreadyYielded = xTaskResumeAll();
00724 }
00725
00726
00727
00728 if( !xAlreadyYielded )
00729 {
00730 portYIELD_WITHIN_API();
00731 }
00732 }
00733
00734 #endif
00735
00736
00737 #if ( INCLUDE_uxTaskPriorityGet == 1 )
00738
00739 unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask )
00740 {
00741 tskTCB *pxTCB;
00742 unsigned portBASE_TYPE uxReturn;
00743
00744 portENTER_CRITICAL();
00745 {
00746
00747
00748 pxTCB = prvGetTCBFromHandle( pxTask );
00749 uxReturn = pxTCB->uxPriority;
00750 }
00751 portEXIT_CRITICAL();
00752
00753 return uxReturn;
00754 }
00755
00756 #endif
00757
00758
00759 #if ( INCLUDE_vTaskPrioritySet == 1 )
00760
00761 void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority )
00762 {
00763 tskTCB *pxTCB;
00764 unsigned portBASE_TYPE uxCurrentPriority, xYieldRequired = pdFALSE;
00765
00766
00767 if( uxNewPriority >= configMAX_PRIORITIES )
00768 {
00769 uxNewPriority = configMAX_PRIORITIES - 1;
00770 }
00771
00772 portENTER_CRITICAL();
00773 {
00774 if( pxTask == pxCurrentTCB )
00775 {
00776 pxTask = NULL;
00777 }
00778
00779
00780
00781 pxTCB = prvGetTCBFromHandle( pxTask );
00782
00783 traceTASK_PRIORITY_SET( pxTask, uxNewPriority );
00784
00785 #if ( configUSE_MUTEXES == 1 )
00786 {
00787 uxCurrentPriority = pxTCB->uxBasePriority;
00788 }
00789 #else
00790 {
00791 uxCurrentPriority = pxTCB->uxPriority;
00792 }
00793 #endif
00794
00795 if( uxCurrentPriority != uxNewPriority )
00796 {
00797
00798
00799 if( uxNewPriority > uxCurrentPriority )
00800 {
00801 if( pxTask != NULL )
00802 {
00803
00804
00805
00806
00807 xYieldRequired = pdTRUE;
00808 }
00809 }
00810 else if( pxTask == NULL )
00811 {
00812
00813
00814 xYieldRequired = pdTRUE;
00815 }
00816
00817
00818
00819 #if ( configUSE_MUTEXES == 1 )
00820 {
00821
00822
00823 if( pxTCB->uxBasePriority == pxTCB->uxPriority )
00824 {
00825 pxTCB->uxPriority = uxNewPriority;
00826 }
00827
00828
00829 pxTCB->uxBasePriority = uxNewPriority;
00830 }
00831 #else
00832 {
00833 pxTCB->uxPriority = uxNewPriority;
00834 }
00835 #endif
00836
00837 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) );
00838
00839
00840
00841
00842
00843 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxCurrentPriority ] ), &( pxTCB->xGenericListItem ) ) )
00844 {
00845
00846
00847
00848 vListRemove( &( pxTCB->xGenericListItem ) );
00849 prvAddTaskToReadyQueue( pxTCB );
00850 }
00851
00852 if( xYieldRequired == pdTRUE )
00853 {
00854 portYIELD_WITHIN_API();
00855 }
00856 }
00857 }
00858 portEXIT_CRITICAL();
00859 }
00860
00861 #endif
00862
00863
00864 #if ( INCLUDE_vTaskSuspend == 1 )
00865
00866 void vTaskSuspend( xTaskHandle pxTaskToSuspend )
00867 {
00868 tskTCB *pxTCB;
00869
00870 portENTER_CRITICAL();
00871 {
00872
00873
00874 if( pxTaskToSuspend == pxCurrentTCB )
00875 {
00876 pxTaskToSuspend = NULL;
00877 }
00878
00879
00880 pxTCB = prvGetTCBFromHandle( pxTaskToSuspend );
00881
00882 traceTASK_SUSPEND( pxTCB );
00883
00884
00885 vListRemove( &( pxTCB->xGenericListItem ) );
00886
00887
00888 if( pxTCB->xEventListItem.pvContainer )
00889 {
00890 vListRemove( &( pxTCB->xEventListItem ) );
00891 }
00892
00893 vListInsertEnd( ( xList * ) &xSuspendedTaskList, &( pxTCB->xGenericListItem ) );
00894 }
00895 portEXIT_CRITICAL();
00896
00897
00898 if( ( void * ) pxTaskToSuspend == NULL )
00899 {
00900 portYIELD_WITHIN_API();
00901 }
00902 }
00903
00904 #endif
00905
00906
00907 #if ( INCLUDE_vTaskSuspend == 1 )
00908
00909 signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask )
00910 {
00911 portBASE_TYPE xReturn = pdFALSE;
00912 const tskTCB * const pxTCB = ( tskTCB * ) xTask;
00913
00914
00915
00916 if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
00917 {
00918
00919 if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE )
00920 {
00921
00922
00923
00924
00925 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) == pdTRUE )
00926 {
00927 xReturn = pdTRUE;
00928 }
00929 }
00930 }
00931
00932 return xReturn;
00933 }
00934
00935 #endif
00936
00937
00938 #if ( INCLUDE_vTaskSuspend == 1 )
00939
00940 void vTaskResume( xTaskHandle pxTaskToResume )
00941 {
00942 tskTCB *pxTCB;
00943
00944
00945
00946 pxTCB = ( tskTCB * ) pxTaskToResume;
00947
00948
00949
00950 if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
00951 {
00952 portENTER_CRITICAL();
00953 {
00954 if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
00955 {
00956 traceTASK_RESUME( pxTCB );
00957
00958
00959
00960 vListRemove( &( pxTCB->xGenericListItem ) );
00961 prvAddTaskToReadyQueue( pxTCB );
00962
00963
00964 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
00965 {
00966
00967
00968 portYIELD_WITHIN_API();
00969 }
00970 }
00971 }
00972 portEXIT_CRITICAL();
00973 }
00974 }
00975
00976 #endif
00977
00978
00979
00980 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
00981
00982 portBASE_TYPE xTaskResumeFromISR( xTaskHandle pxTaskToResume )
00983 {
00984 portBASE_TYPE xYieldRequired = pdFALSE;
00985 tskTCB *pxTCB;
00986
00987 pxTCB = ( tskTCB * ) pxTaskToResume;
00988
00989 if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
00990 {
00991 traceTASK_RESUME_FROM_ISR( pxTCB );
00992
00993 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
00994 {
00995 xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority );
00996 vListRemove( &( pxTCB->xGenericListItem ) );
00997 prvAddTaskToReadyQueue( pxTCB );
00998 }
00999 else
01000 {
01001
01002
01003
01004 vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
01005 }
01006 }
01007
01008 return xYieldRequired;
01009 }
01010
01011 #endif
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021 void vTaskStartScheduler( void )
01022 {
01023 portBASE_TYPE xReturn;
01024
01025
01026 xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), ( xTaskHandle * ) NULL );
01027
01028 if( xReturn == pdPASS )
01029 {
01030
01031
01032
01033
01034
01035
01036
01037
01038 portDISABLE_INTERRUPTS();
01039
01040 xSchedulerRunning = pdTRUE;
01041 xTickCount = ( portTickType ) 0;
01042
01043
01044
01045
01046 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
01047
01048
01049
01050 if( xPortStartScheduler() )
01051 {
01052
01053
01054 }
01055 else
01056 {
01057
01058 }
01059 }
01060 }
01061
01062
01063 void vTaskEndScheduler( void )
01064 {
01065
01066
01067
01068 portDISABLE_INTERRUPTS();
01069 xSchedulerRunning = pdFALSE;
01070 vPortEndScheduler();
01071 }
01072
01073
01074 void vTaskSuspendAll( void )
01075 {
01076
01077
01078 ++uxSchedulerSuspended;
01079 }
01080
01081
01082 signed portBASE_TYPE xTaskResumeAll( void )
01083 {
01084 register tskTCB *pxTCB;
01085 signed portBASE_TYPE xAlreadyYielded = pdFALSE;
01086
01087
01088
01089
01090
01091
01092 portENTER_CRITICAL();
01093 {
01094 --uxSchedulerSuspended;
01095
01096 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
01097 {
01098 if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0 )
01099 {
01100 portBASE_TYPE xYieldRequired = pdFALSE;
01101
01102
01103
01104 while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xPendingReadyList ) ) ) != NULL )
01105 {
01106 vListRemove( &( pxTCB->xEventListItem ) );
01107 vListRemove( &( pxTCB->xGenericListItem ) );
01108 prvAddTaskToReadyQueue( pxTCB );
01109
01110
01111
01112 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
01113 {
01114 xYieldRequired = pdTRUE;
01115 }
01116 }
01117
01118
01119
01120
01121 if( uxMissedTicks > ( unsigned portBASE_TYPE ) 0 )
01122 {
01123 while( uxMissedTicks > ( unsigned portBASE_TYPE ) 0 )
01124 {
01125 vTaskIncrementTick();
01126 --uxMissedTicks;
01127 }
01128
01129
01130
01131
01132 #if configUSE_PREEMPTION == 1
01133 {
01134 xYieldRequired = pdTRUE;
01135 }
01136 #endif
01137 }
01138
01139 if( ( xYieldRequired == pdTRUE ) || ( xMissedYield == pdTRUE ) )
01140 {
01141 xAlreadyYielded = pdTRUE;
01142 xMissedYield = pdFALSE;
01143 portYIELD_WITHIN_API();
01144 }
01145 }
01146 }
01147 }
01148 portEXIT_CRITICAL();
01149
01150 return xAlreadyYielded;
01151 }
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164 portTickType xTaskGetTickCount( void )
01165 {
01166 portTickType xTicks;
01167
01168
01169 portENTER_CRITICAL();
01170 {
01171 xTicks = xTickCount;
01172 }
01173 portEXIT_CRITICAL();
01174
01175 return xTicks;
01176 }
01177
01178
01179 unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
01180 {
01181
01182
01183 return uxCurrentNumberOfTasks;
01184 }
01185
01186
01187 #if ( configUSE_TRACE_FACILITY == 1 )
01188
01189 void vTaskList( signed char *pcWriteBuffer )
01190 {
01191 unsigned portBASE_TYPE uxQueue;
01192
01193
01194
01195
01196 vTaskSuspendAll();
01197 {
01198
01199
01200
01201 pcWriteBuffer[ 0 ] = ( signed char ) 0x00;
01202 strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" );
01203
01204 uxQueue = uxTopUsedPriority + 1;
01205
01206 do
01207 {
01208 uxQueue--;
01209
01210 if( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) )
01211 {
01212 prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), tskREADY_CHAR );
01213 }
01214 }while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY );
01215
01216 if( !listLIST_IS_EMPTY( pxDelayedTaskList ) )
01217 {
01218 prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, tskBLOCKED_CHAR );
01219 }
01220
01221 if( !listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) )
01222 {
01223 prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, tskBLOCKED_CHAR );
01224 }
01225
01226 #if( INCLUDE_vTaskDelete == 1 )
01227 {
01228 if( !listLIST_IS_EMPTY( &xTasksWaitingTermination ) )
01229 {
01230 prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &xTasksWaitingTermination, tskDELETED_CHAR );
01231 }
01232 }
01233 #endif
01234
01235 #if ( INCLUDE_vTaskSuspend == 1 )
01236 {
01237 if( !listLIST_IS_EMPTY( &xSuspendedTaskList ) )
01238 {
01239 prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &xSuspendedTaskList, tskSUSPENDED_CHAR );
01240 }
01241 }
01242 #endif
01243 }
01244 xTaskResumeAll();
01245 }
01246
01247 #endif
01248
01249
01250 #if ( configGENERATE_RUN_TIME_STATS == 1 )
01251
01252 void vTaskGetRunTimeStats( signed char *pcWriteBuffer )
01253 {
01254 unsigned portBASE_TYPE uxQueue;
01255 unsigned long ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
01256
01257
01258
01259
01260 vTaskSuspendAll();
01261 {
01262
01263
01264
01265
01266 pcWriteBuffer[ 0 ] = ( signed char ) 0x00;
01267 strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" );
01268
01269 uxQueue = uxTopUsedPriority + 1;
01270
01271 do
01272 {
01273 uxQueue--;
01274
01275 if( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) )
01276 {
01277 prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), ulTotalRunTime );
01278 }
01279 }while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY );
01280
01281 if( !listLIST_IS_EMPTY( pxDelayedTaskList ) )
01282 {
01283 prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, ulTotalRunTime );
01284 }
01285
01286 if( !listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) )
01287 {
01288 prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, ulTotalRunTime );
01289 }
01290
01291 #if ( INCLUDE_vTaskDelete == 1 )
01292 {
01293 if( !listLIST_IS_EMPTY( &xTasksWaitingTermination ) )
01294 {
01295 prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &xTasksWaitingTermination, ulTotalRunTime );
01296 }
01297 }
01298 #endif
01299
01300 #if ( INCLUDE_vTaskSuspend == 1 )
01301 {
01302 if( !listLIST_IS_EMPTY( &xSuspendedTaskList ) )
01303 {
01304 prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &xSuspendedTaskList, ulTotalRunTime );
01305 }
01306 }
01307 #endif
01308 }
01309 xTaskResumeAll();
01310 }
01311
01312 #endif
01313
01314
01315 #if ( configUSE_TRACE_FACILITY == 1 )
01316
01317 void vTaskStartTrace( signed char * pcBuffer, unsigned long ulBufferSize )
01318 {
01319 portENTER_CRITICAL();
01320 {
01321 pcTraceBuffer = ( signed char * )pcBuffer;
01322 pcTraceBufferStart = pcBuffer;
01323 pcTraceBufferEnd = pcBuffer + ( ulBufferSize - tskSIZE_OF_EACH_TRACE_LINE );
01324 xTracing = pdTRUE;
01325 }
01326 portEXIT_CRITICAL();
01327 }
01328
01329 #endif
01330
01331
01332 #if ( configUSE_TRACE_FACILITY == 1 )
01333
01334 unsigned long ulTaskEndTrace( void )
01335 {
01336 unsigned long ulBufferLength;
01337
01338 portENTER_CRITICAL();
01339 xTracing = pdFALSE;
01340 portEXIT_CRITICAL();
01341
01342 ulBufferLength = ( unsigned long ) ( pcTraceBuffer - pcTraceBufferStart );
01343
01344 return ulBufferLength;
01345 }
01346
01347 #endif
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357 void vTaskIncrementTick( void )
01358 {
01359
01360
01361
01362 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
01363 {
01364 ++xTickCount;
01365 if( xTickCount == ( portTickType ) 0 )
01366 {
01367 xList *pxTemp;
01368
01369
01370
01371
01372 pxTemp = pxDelayedTaskList;
01373 pxDelayedTaskList = pxOverflowDelayedTaskList;
01374 pxOverflowDelayedTaskList = pxTemp;
01375 xNumOfOverflows++;
01376 }
01377
01378
01379 prvCheckDelayedTasks();
01380 }
01381 else
01382 {
01383 ++uxMissedTicks;
01384
01385
01386
01387 #if ( configUSE_TICK_HOOK == 1 )
01388 {
01389 extern void vApplicationTickHook( void );
01390
01391 vApplicationTickHook();
01392 }
01393 #endif
01394 }
01395
01396 #if ( configUSE_TICK_HOOK == 1 )
01397 {
01398 extern void vApplicationTickHook( void );
01399
01400
01401
01402 if( uxMissedTicks == 0 )
01403 {
01404 vApplicationTickHook();
01405 }
01406 }
01407 #endif
01408
01409 traceTASK_INCREMENT_TICK( xTickCount );
01410 }
01411
01412
01413 #if ( ( INCLUDE_vTaskCleanUpResources == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
01414
01415 void vTaskCleanUpResources( void )
01416 {
01417 unsigned short usQueue;
01418 volatile tskTCB *pxTCB;
01419
01420 usQueue = ( unsigned short ) uxTopUsedPriority + ( unsigned short ) 1;
01421
01422
01423 do
01424 {
01425 usQueue--;
01426
01427 while( !listLIST_IS_EMPTY( &( pxReadyTasksLists[ usQueue ] ) ) )
01428 {
01429 listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &( pxReadyTasksLists[ usQueue ] ) );
01430 vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );
01431
01432 prvDeleteTCB( ( tskTCB * ) pxTCB );
01433 }
01434 }while( usQueue > ( unsigned short ) tskIDLE_PRIORITY );
01435
01436
01437 while( !listLIST_IS_EMPTY( &xDelayedTaskList1 ) )
01438 {
01439 listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xDelayedTaskList1 );
01440 vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );
01441
01442 prvDeleteTCB( ( tskTCB * ) pxTCB );
01443 }
01444
01445
01446 while( !listLIST_IS_EMPTY( &xDelayedTaskList2 ) )
01447 {
01448 listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xDelayedTaskList2 );
01449 vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );
01450
01451 prvDeleteTCB( ( tskTCB * ) pxTCB );
01452 }
01453
01454 while( !listLIST_IS_EMPTY( &xSuspendedTaskList ) )
01455 {
01456 listGET_OWNER_OF_NEXT_ENTRY( pxTCB, &xSuspendedTaskList );
01457 vListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) );
01458
01459 prvDeleteTCB( ( tskTCB * ) pxTCB );
01460 }
01461 }
01462
01463 #endif
01464
01465
01466 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
01467
01468 void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxTagValue )
01469 {
01470 tskTCB *xTCB;
01471
01472
01473 if( xTask == NULL )
01474 {
01475 xTCB = ( tskTCB * ) pxCurrentTCB;
01476 }
01477 else
01478 {
01479 xTCB = ( tskTCB * ) xTask;
01480 }
01481
01482
01483
01484 portENTER_CRITICAL();
01485 xTCB->pxTaskTag = pxTagValue;
01486 portEXIT_CRITICAL();
01487 }
01488
01489 #endif
01490
01491
01492 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
01493
01494 pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask )
01495 {
01496 tskTCB *xTCB;
01497 pdTASK_HOOK_CODE xReturn;
01498
01499
01500 if( xTask == NULL )
01501 {
01502 xTCB = ( tskTCB * ) pxCurrentTCB;
01503 }
01504 else
01505 {
01506 xTCB = ( tskTCB * ) xTask;
01507 }
01508
01509
01510
01511 portENTER_CRITICAL();
01512 xReturn = xTCB->pxTaskTag;
01513 portEXIT_CRITICAL();
01514
01515 return xReturn;
01516 }
01517
01518 #endif
01519
01520
01521 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
01522
01523 portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter )
01524 {
01525 tskTCB *xTCB;
01526 portBASE_TYPE xReturn;
01527
01528
01529 if( xTask == NULL )
01530 {
01531 xTCB = ( tskTCB * ) pxCurrentTCB;
01532 }
01533 else
01534 {
01535 xTCB = ( tskTCB * ) xTask;
01536 }
01537
01538 if( xTCB->pxTaskTag != NULL )
01539 {
01540 xReturn = xTCB->pxTaskTag( pvParameter );
01541 }
01542 else
01543 {
01544 xReturn = pdFAIL;
01545 }
01546
01547 return xReturn;
01548 }
01549
01550 #endif
01551
01552
01553 void vTaskSwitchContext( void )
01554 {
01555 if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE )
01556 {
01557
01558
01559 xMissedYield = pdTRUE;
01560 return;
01561 }
01562
01563 traceTASK_SWITCHED_OUT();
01564
01565 #if ( configGENERATE_RUN_TIME_STATS == 1 )
01566 {
01567 unsigned long ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE();
01568
01569
01570
01571
01572
01573
01574 pxCurrentTCB->ulRunTimeCounter += ( ulTempCounter - ulTaskSwitchedInTime );
01575 ulTaskSwitchedInTime = ulTempCounter;
01576 }
01577 #endif
01578
01579 taskFIRST_CHECK_FOR_STACK_OVERFLOW();
01580 taskSECOND_CHECK_FOR_STACK_OVERFLOW();
01581
01582
01583 while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) )
01584 {
01585 --uxTopReadyPriority;
01586 }
01587
01588
01589
01590 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) );
01591
01592 traceTASK_SWITCHED_IN();
01593 vWriteTraceToBuffer();
01594 }
01595
01596
01597 void vTaskPlaceOnEventList( const xList * const pxEventList, portTickType xTicksToWait )
01598 {
01599 portTickType xTimeToWake;
01600
01601
01602
01603
01604
01605
01606
01607 vListInsert( ( xList * ) pxEventList, ( xListItem * ) &( pxCurrentTCB->xEventListItem ) );
01608
01609
01610
01611
01612 vListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
01613
01614
01615 #if ( INCLUDE_vTaskSuspend == 1 )
01616 {
01617 if( xTicksToWait == portMAX_DELAY )
01618 {
01619
01620
01621
01622 vListInsertEnd( ( xList * ) &xSuspendedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
01623 }
01624 else
01625 {
01626
01627
01628 xTimeToWake = xTickCount + xTicksToWait;
01629
01630 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
01631
01632 if( xTimeToWake < xTickCount )
01633 {
01634
01635 vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
01636 }
01637 else
01638 {
01639
01640 vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
01641 }
01642 }
01643 }
01644 #else
01645 {
01646
01647
01648 xTimeToWake = xTickCount + xTicksToWait;
01649
01650 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
01651
01652 if( xTimeToWake < xTickCount )
01653 {
01654
01655 vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
01656 }
01657 else
01658 {
01659
01660 vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
01661 }
01662 }
01663 #endif
01664 }
01665
01666
01667 signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList )
01668 {
01669 tskTCB *pxUnblockedTCB;
01670 portBASE_TYPE xReturn;
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682 pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
01683 vListRemove( &( pxUnblockedTCB->xEventListItem ) );
01684
01685 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
01686 {
01687 vListRemove( &( pxUnblockedTCB->xGenericListItem ) );
01688 prvAddTaskToReadyQueue( pxUnblockedTCB );
01689 }
01690 else
01691 {
01692
01693
01694 vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
01695 }
01696
01697 if( pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority )
01698 {
01699
01700
01701
01702
01703 xReturn = pdTRUE;
01704 }
01705 else
01706 {
01707 xReturn = pdFALSE;
01708 }
01709
01710 return xReturn;
01711 }
01712
01713
01714 void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut )
01715 {
01716 pxTimeOut->xOverflowCount = xNumOfOverflows;
01717 pxTimeOut->xTimeOnEntering = xTickCount;
01718 }
01719
01720
01721 portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait )
01722 {
01723 portBASE_TYPE xReturn;
01724
01725 portENTER_CRITICAL();
01726 {
01727 #if ( INCLUDE_vTaskSuspend == 1 )
01728
01729
01730
01731 if( *pxTicksToWait == portMAX_DELAY )
01732 {
01733 xReturn = pdFALSE;
01734 }
01735 else
01736 #endif
01737
01738 if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( ( portTickType ) xTickCount >= ( portTickType ) pxTimeOut->xTimeOnEntering ) )
01739 {
01740
01741
01742
01743
01744 xReturn = pdTRUE;
01745 }
01746 else if( ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ) < ( portTickType ) *pxTicksToWait )
01747 {
01748
01749 *pxTicksToWait -= ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering );
01750 vTaskSetTimeOutState( pxTimeOut );
01751 xReturn = pdFALSE;
01752 }
01753 else
01754 {
01755 xReturn = pdTRUE;
01756 }
01757 }
01758 portEXIT_CRITICAL();
01759
01760 return xReturn;
01761 }
01762
01763
01764 void vTaskMissedYield( void )
01765 {
01766 xMissedYield = pdTRUE;
01767 }
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780 static portTASK_FUNCTION( prvIdleTask, pvParameters )
01781 {
01782
01783 ( void ) pvParameters;
01784
01785 for( ;; )
01786 {
01787
01788 prvCheckTasksWaitingTermination();
01789
01790 #if ( configUSE_PREEMPTION == 0 )
01791 {
01792
01793
01794
01795
01796 taskYIELD();
01797 }
01798 #endif
01799
01800 #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
01801 {
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( unsigned portBASE_TYPE ) 1 )
01812 {
01813 taskYIELD();
01814 }
01815 }
01816 #endif
01817
01818 #if ( configUSE_IDLE_HOOK == 1 )
01819 {
01820 extern void vApplicationIdleHook( void );
01821
01822
01823
01824
01825
01826
01827 vApplicationIdleHook();
01828 }
01829 #endif
01830 }
01831 }
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845 static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth )
01846 {
01847
01848 #if configMAX_TASK_NAME_LEN > 1
01849 {
01850
01851 strncpy( ( char * ) pxTCB->pcTaskName, ( const char * ) pcName, ( unsigned short ) configMAX_TASK_NAME_LEN );
01852 }
01853 #endif
01854 pxTCB->pcTaskName[ ( unsigned short ) configMAX_TASK_NAME_LEN - ( unsigned short ) 1 ] = '\0';
01855
01856
01857
01858 if( uxPriority >= configMAX_PRIORITIES )
01859 {
01860 uxPriority = configMAX_PRIORITIES - 1;
01861 }
01862
01863 pxTCB->uxPriority = uxPriority;
01864 #if ( configUSE_MUTEXES == 1 )
01865 {
01866 pxTCB->uxBasePriority = uxPriority;
01867 }
01868 #endif
01869
01870 vListInitialiseItem( &( pxTCB->xGenericListItem ) );
01871 vListInitialiseItem( &( pxTCB->xEventListItem ) );
01872
01873
01874
01875 listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB );
01876
01877
01878 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxPriority );
01879 listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB );
01880
01881 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
01882 {
01883 pxTCB->uxCriticalNesting = ( unsigned portBASE_TYPE ) 0;
01884 }
01885 #endif
01886
01887 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
01888 {
01889 pxTCB->pxTaskTag = NULL;
01890 }
01891 #endif
01892
01893 #if ( configGENERATE_RUN_TIME_STATS == 1 )
01894 {
01895 pxTCB->ulRunTimeCounter = 0UL;
01896 }
01897 #endif
01898
01899 #if ( portUSING_MPU_WRAPPERS == 1 )
01900 {
01901 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth );
01902 }
01903 #else
01904 {
01905 ( void ) xRegions;
01906 ( void ) usStackDepth;
01907 }
01908 #endif
01909 }
01910
01911
01912 #if ( portUSING_MPU_WRAPPERS == 1 )
01913
01914 void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions )
01915 {
01916 tskTCB *pxTCB;
01917
01918 if( xTaskToModify == pxCurrentTCB )
01919 {
01920 xTaskToModify = NULL;
01921 }
01922
01923
01924 pxTCB = prvGetTCBFromHandle( xTaskToModify );
01925
01926 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
01927 }
01928
01929 #endif
01930
01931 static void prvInitialiseTaskLists( void )
01932 {
01933 unsigned portBASE_TYPE uxPriority;
01934
01935 for( uxPriority = 0; uxPriority < configMAX_PRIORITIES; uxPriority++ )
01936 {
01937 vListInitialise( ( xList * ) &( pxReadyTasksLists[ uxPriority ] ) );
01938 }
01939
01940 vListInitialise( ( xList * ) &xDelayedTaskList1 );
01941 vListInitialise( ( xList * ) &xDelayedTaskList2 );
01942 vListInitialise( ( xList * ) &xPendingReadyList );
01943
01944 #if ( INCLUDE_vTaskDelete == 1 )
01945 {
01946 vListInitialise( ( xList * ) &xTasksWaitingTermination );
01947 }
01948 #endif
01949
01950 #if ( INCLUDE_vTaskSuspend == 1 )
01951 {
01952 vListInitialise( ( xList * ) &xSuspendedTaskList );
01953 }
01954 #endif
01955
01956
01957
01958 pxDelayedTaskList = &xDelayedTaskList1;
01959 pxOverflowDelayedTaskList = &xDelayedTaskList2;
01960 }
01961
01962
01963 static void prvCheckTasksWaitingTermination( void )
01964 {
01965 #if ( INCLUDE_vTaskDelete == 1 )
01966 {
01967 portBASE_TYPE xListIsEmpty;
01968
01969
01970
01971 if( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0 )
01972 {
01973 vTaskSuspendAll();
01974 xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
01975 xTaskResumeAll();
01976
01977 if( !xListIsEmpty )
01978 {
01979 tskTCB *pxTCB;
01980
01981 portENTER_CRITICAL();
01982 {
01983 pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xTasksWaitingTermination ) );
01984 vListRemove( &( pxTCB->xGenericListItem ) );
01985 --uxCurrentNumberOfTasks;
01986 --uxTasksDeleted;
01987 }
01988 portEXIT_CRITICAL();
01989
01990 prvDeleteTCB( pxTCB );
01991 }
01992 }
01993 }
01994 #endif
01995 }
01996
01997
01998 static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer )
01999 {
02000 tskTCB *pxNewTCB;
02001
02002
02003
02004 pxNewTCB = ( tskTCB * ) pvPortMalloc( sizeof( tskTCB ) );
02005
02006 if( pxNewTCB != NULL )
02007 {
02008
02009
02010
02011 pxNewTCB->pxStack = ( portSTACK_TYPE * ) pvPortMallocAligned( ( ( ( size_t )usStackDepth ) * sizeof( portSTACK_TYPE ) ), puxStackBuffer );
02012
02013 if( pxNewTCB->pxStack == NULL )
02014 {
02015
02016 vPortFree( pxNewTCB );
02017 pxNewTCB = NULL;
02018 }
02019 else
02020 {
02021
02022 memset( pxNewTCB->pxStack, tskSTACK_FILL_BYTE, usStackDepth * sizeof( portSTACK_TYPE ) );
02023 }
02024 }
02025
02026 return pxNewTCB;
02027 }
02028
02029
02030 #if ( configUSE_TRACE_FACILITY == 1 )
02031
02032 static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus )
02033 {
02034 volatile tskTCB *pxNextTCB, *pxFirstTCB;
02035 unsigned short usStackRemaining;
02036
02037
02038 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
02039 do
02040 {
02041 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
02042 usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack );
02043 sprintf( pcStatusString, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxNextTCB->pcTaskName, cStatus, ( unsigned int ) pxNextTCB->uxPriority, usStackRemaining, ( unsigned int ) pxNextTCB->uxTCBNumber );
02044 strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatusString );
02045
02046 } while( pxNextTCB != pxFirstTCB );
02047 }
02048
02049 #endif
02050
02051
02052 #if ( configGENERATE_RUN_TIME_STATS == 1 )
02053
02054 static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime )
02055 {
02056 volatile tskTCB *pxNextTCB, *pxFirstTCB;
02057 unsigned long ulStatsAsPercentage;
02058
02059
02060 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
02061 do
02062 {
02063
02064 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
02065
02066
02067 if( ulTotalRunTime > 0UL )
02068 {
02069
02070 if( pxNextTCB->ulRunTimeCounter == 0 )
02071 {
02072
02073 sprintf( pcStatsString, ( char * ) "%s\t\t0\t\t0%%\r\n", pxNextTCB->pcTaskName );
02074 }
02075 else
02076 {
02077
02078
02079 ulStatsAsPercentage = ( 100UL * pxNextTCB->ulRunTimeCounter ) / ulTotalRunTime;
02080
02081 if( ulStatsAsPercentage > 0UL )
02082 {
02083 sprintf( pcStatsString, ( char * ) "%s\t\t%u\t\t%u%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );
02084 }
02085 else
02086 {
02087
02088
02089 sprintf( pcStatsString, ( char * ) "%s\t\t%u\t\t<1%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter );
02090 }
02091 }
02092
02093 strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatsString );
02094 }
02095
02096 } while( pxNextTCB != pxFirstTCB );
02097 }
02098
02099 #endif
02100
02101
02102 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
02103
02104 static unsigned short usTaskCheckFreeStackSpace( const unsigned char * pucStackByte )
02105 {
02106 register unsigned short usCount = 0;
02107
02108 while( *pucStackByte == tskSTACK_FILL_BYTE )
02109 {
02110 pucStackByte -= portSTACK_GROWTH;
02111 usCount++;
02112 }
02113
02114 usCount /= sizeof( portSTACK_TYPE );
02115
02116 return usCount;
02117 }
02118
02119 #endif
02120
02121
02122 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
02123
02124 unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask )
02125 {
02126 tskTCB *pxTCB;
02127 unsigned char *pcEndOfStack;
02128 unsigned portBASE_TYPE uxReturn;
02129
02130 pxTCB = prvGetTCBFromHandle( xTask );
02131
02132 #if portSTACK_GROWTH < 0
02133 {
02134 pcEndOfStack = ( unsigned char * ) pxTCB->pxStack;
02135 }
02136 #else
02137 {
02138 pcEndOfStack = ( unsigned char * ) pxTCB->pxEndOfStack;
02139 }
02140 #endif
02141
02142 uxReturn = ( unsigned portBASE_TYPE ) usTaskCheckFreeStackSpace( pcEndOfStack );
02143
02144 return uxReturn;
02145 }
02146
02147 #endif
02148
02149
02150 #if ( ( INCLUDE_vTaskDelete == 1 ) || ( INCLUDE_vTaskCleanUpResources == 1 ) )
02151
02152 static void prvDeleteTCB( tskTCB *pxTCB )
02153 {
02154
02155
02156 vPortFreeAligned( pxTCB->pxStack );
02157 vPortFree( pxTCB );
02158 }
02159
02160 #endif
02161
02162
02163
02164
02165 #if ( INCLUDE_xTaskGetCurrentTaskHandle == 1 )
02166
02167 xTaskHandle xTaskGetCurrentTaskHandle( void )
02168 {
02169 xTaskHandle xReturn;
02170
02171
02172
02173
02174 xReturn = pxCurrentTCB;
02175
02176 return xReturn;
02177 }
02178
02179 #endif
02180
02181
02182
02183 #if ( INCLUDE_xTaskGetSchedulerState == 1 )
02184
02185 portBASE_TYPE xTaskGetSchedulerState( void )
02186 {
02187 portBASE_TYPE xReturn;
02188
02189 if( xSchedulerRunning == pdFALSE )
02190 {
02191 xReturn = taskSCHEDULER_NOT_STARTED;
02192 }
02193 else
02194 {
02195 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
02196 {
02197 xReturn = taskSCHEDULER_RUNNING;
02198 }
02199 else
02200 {
02201 xReturn = taskSCHEDULER_SUSPENDED;
02202 }
02203 }
02204
02205 return xReturn;
02206 }
02207
02208 #endif
02209
02210
02211 #if ( configUSE_MUTEXES == 1 )
02212
02213 void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder )
02214 {
02215 tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;
02216
02217 if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
02218 {
02219
02220 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority );
02221
02222
02223
02224 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) )
02225 {
02226 vListRemove( &( pxTCB->xGenericListItem ) );
02227
02228
02229 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
02230 prvAddTaskToReadyQueue( pxTCB );
02231 }
02232 else
02233 {
02234
02235 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
02236 }
02237 }
02238 }
02239
02240 #endif
02241
02242
02243 #if ( configUSE_MUTEXES == 1 )
02244
02245 void vTaskPriorityDisinherit( xTaskHandle * const pxMutexHolder )
02246 {
02247 tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;
02248
02249 if( pxMutexHolder != NULL )
02250 {
02251 if( pxTCB->uxPriority != pxTCB->uxBasePriority )
02252 {
02253
02254
02255 vListRemove( &( pxTCB->xGenericListItem ) );
02256
02257
02258
02259 pxTCB->uxPriority = pxTCB->uxBasePriority;
02260 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority );
02261 prvAddTaskToReadyQueue( pxTCB );
02262 }
02263 }
02264 }
02265
02266 #endif
02267
02268
02269 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
02270
02271 void vTaskEnterCritical( void )
02272 {
02273 portDISABLE_INTERRUPTS();
02274
02275 if( xSchedulerRunning != pdFALSE )
02276 {
02277 pxCurrentTCB->uxCriticalNesting++;
02278 }
02279 }
02280
02281 #endif
02282
02283
02284 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
02285
02286 void vTaskExitCritical( void )
02287 {
02288 if( xSchedulerRunning != pdFALSE )
02289 {
02290 if( pxCurrentTCB->uxCriticalNesting > 0 )
02291 {
02292 pxCurrentTCB->uxCriticalNesting--;
02293
02294 if( pxCurrentTCB->uxCriticalNesting == 0 )
02295 {
02296 portENABLE_INTERRUPTS();
02297 }
02298 }
02299 }
02300 }
02301
02302 #endif
02303
02304
02305
02306
02307