Rohit Grover / FreeRTOS

Dependents:   Nucleo freertos_test FreeRTOS_test freertos_bluetooth ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tasks.c Source File

tasks.c

00001 /*
00002     FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.
00003     All rights reserved
00004 
00005     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
00006 
00007     ***************************************************************************
00008      *                                                                       *
00009      *    FreeRTOS provides completely free yet professionally developed,    *
00010      *    robust, strictly quality controlled, supported, and cross          *
00011      *    platform software that has become a de facto standard.             *
00012      *                                                                       *
00013      *    Help yourself get started quickly and support the FreeRTOS         *
00014      *    project by purchasing a FreeRTOS tutorial book, reference          *
00015      *    manual, or both from: http://www.FreeRTOS.org/Documentation        *
00016      *                                                                       *
00017      *    Thank you!                                                         *
00018      *                                                                       *
00019     ***************************************************************************
00020 
00021     This file is part of the FreeRTOS distribution.
00022 
00023     FreeRTOS is free software; you can redistribute it and/or modify it under
00024     the terms of the GNU General Public License (version 2) as published by the
00025     Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
00026 
00027     >>! NOTE: The modification to the GPL is included to allow you to distribute
00028     >>! a combined work that includes FreeRTOS without being obliged to provide
00029     >>! the source code for proprietary components outside of the FreeRTOS
00030     >>! kernel.
00031 
00032     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
00033     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00034     FOR A PARTICULAR PURPOSE.  Full license text is available from the following
00035     link: http://www.freertos.org/a00114.html
00036 
00037     1 tab == 4 spaces!
00038 
00039     ***************************************************************************
00040      *                                                                       *
00041      *    Having a problem?  Start by reading the FAQ "My application does   *
00042      *    not run, what could be wrong?"                                     *
00043      *                                                                       *
00044      *    http://www.FreeRTOS.org/FAQHelp.html                               *
00045      *                                                                       *
00046     ***************************************************************************
00047 
00048     http://www.FreeRTOS.org - Documentation, books, training, latest versions,
00049     license and Real Time Engineers Ltd. contact details.
00050 
00051     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
00052     including FreeRTOS+Trace - an indispensable productivity tool, a DOS
00053     compatible FAT file system, and our tiny thread aware UDP/IP stack.
00054 
00055     http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
00056     Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS
00057     licenses offer ticketed support, indemnification and middleware.
00058 
00059     http://www.SafeRTOS.com - High Integrity Systems also provide a safety
00060     engineered and independently SIL3 certified version for use in safety and
00061     mission critical applications that require provable dependability.
00062 
00063     1 tab == 4 spaces!
00064 */
00065 
00066 /* Standard includes. */
00067 #include <stdlib.h>
00068 #include <string.h>
00069 
00070 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
00071 all the API functions to use the MPU wrappers.  That should only be done when
00072 task.h is included from an application file. */
00073 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
00074 
00075 /* FreeRTOS includes. */
00076 #include "FreeRTOS.h"
00077 #include "task.h"
00078 #include "timers.h"
00079 #include "StackMacros.h"
00080 
00081 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the
00082 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
00083 header files above, but not in this file, in order to generate the correct
00084 privileged Vs unprivileged linkage and placement. */
00085 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
00086 
00087 #if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 )
00088     /* At the bottom of this file are two optional functions that can be used
00089     to generate human readable text from the raw data generated by the
00090     uxTaskGetSystemState() function.  Note the formatting functions are provided
00091     for convenience only, and are NOT considered part of the kernel. */
00092     #include <stdio.h>
00093 #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
00094 
00095 /* Sanity check the configuration. */
00096 #if configUSE_TICKLESS_IDLE != 0
00097     #if INCLUDE_vTaskSuspend != 1
00098         #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0
00099     #endif /* INCLUDE_vTaskSuspend */
00100 #endif /* configUSE_TICKLESS_IDLE */
00101 
00102 /*
00103  * Defines the size, in words, of the stack allocated to the idle task.
00104  */
00105 #define tskIDLE_STACK_SIZE  configMINIMAL_STACK_SIZE
00106 
00107 #if( configUSE_PREEMPTION == 0 )
00108     /* If the cooperative scheduler is being used then a yield should not be
00109     performed just because a higher priority task has been woken. */
00110     #define taskYIELD_IF_USING_PREEMPTION()
00111 #else
00112     #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
00113 #endif
00114 
00115 /*
00116  * Task control block.  A task control block (TCB) is allocated for each task,
00117  * and stores task state information, including a pointer to the task's context
00118  * (the task's run time environment, including register values)
00119  */
00120 typedef struct tskTaskControlBlock
00121 {
00122     volatile portSTACK_TYPE *pxTopOfStack;      /*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
00123 
00124     #if ( portUSING_MPU_WRAPPERS == 1 )
00125         xMPU_SETTINGS xMPUSettings;             /*< The MPU settings are defined as part of the port layer.  THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
00126     #endif
00127 
00128     xListItem               xGenericListItem;   /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
00129     xListItem               xEventListItem;     /*< Used to reference a task from an event list. */
00130     unsigned portBASE_TYPE  uxPriority;         /*< The priority of the task.  0 is the lowest priority. */
00131     portSTACK_TYPE          *pxStack;           /*< Points to the start of the stack. */
00132     signed char             pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created.  Facilitates debugging only. */
00133 
00134     #if ( portSTACK_GROWTH > 0 )
00135         portSTACK_TYPE *pxEndOfStack;           /*< Points to the end of the stack on architectures where the stack grows up from low memory. */
00136     #endif
00137 
00138     #if ( portCRITICAL_NESTING_IN_TCB == 1 )
00139         unsigned portBASE_TYPE uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
00140     #endif
00141 
00142     #if ( configUSE_TRACE_FACILITY == 1 )
00143         unsigned portBASE_TYPE  uxTCBNumber;    /*< Stores a number that increments each time a TCB is created.  It allows debuggers to determine when a task has been deleted and then recreated. */
00144         unsigned portBASE_TYPE  uxTaskNumber;   /*< Stores a number specifically for use by third party trace code. */
00145     #endif
00146 
00147     #if ( configUSE_MUTEXES == 1 )
00148         unsigned portBASE_TYPE uxBasePriority;  /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
00149     #endif
00150 
00151     #if ( configUSE_APPLICATION_TASK_TAG == 1 )
00152         pdTASK_HOOK_CODE pxTaskTag;
00153     #endif
00154 
00155     #if ( configGENERATE_RUN_TIME_STATS == 1 )
00156         unsigned long ulRunTimeCounter;         /*< Stores the amount of time the task has spent in the Running state. */
00157     #endif
00158 
00159     #if ( configUSE_NEWLIB_REENTRANT == 1 )
00160         /* Allocate a Newlib reent structure that is specific to this task.
00161         Note Newlib support has been included by popular demand, but is not
00162         used by the FreeRTOS maintainers themselves.  FreeRTOS is not
00163         responsible for resulting newlib operation.  User must be familiar with
00164         newlib and must provide system-wide implementations of the necessary
00165         stubs. Be warned that (at the time of writing) the current newlib design
00166         implements a system-wide malloc() that must be provided with locks. */
00167         struct _reent xNewLib_reent;
00168     #endif
00169 
00170 } tskTCB;
00171 
00172 
00173 /*
00174  * Some kernel aware debuggers require the data the debugger needs access to to
00175  * be global, rather than file scope.
00176  */
00177 #ifdef portREMOVE_STATIC_QUALIFIER
00178     #define static
00179 #endif
00180 
00181 /*lint -e956 A manual analysis and inspection has been used to determine which
00182 static variables must be declared volatile. */
00183 
00184 PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL;
00185 
00186 /* Lists for ready and blocked tasks. --------------------*/
00187 PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */
00188 PRIVILEGED_DATA static xList xDelayedTaskList1;                         /*< Delayed tasks. */
00189 PRIVILEGED_DATA static xList xDelayedTaskList2;                         /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
00190 PRIVILEGED_DATA static xList * volatile pxDelayedTaskList;              /*< Points to the delayed task list currently being used. */
00191 PRIVILEGED_DATA static xList * volatile pxOverflowDelayedTaskList;      /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */
00192 PRIVILEGED_DATA static xList xPendingReadyList;                         /*< Tasks that have been readied while the scheduler was suspended.  They will be moved to the ready list when the scheduler is resumed. */
00193 
00194 #if ( INCLUDE_vTaskDelete == 1 )
00195 
00196     PRIVILEGED_DATA static xList xTasksWaitingTermination;              /*< Tasks that have been deleted - but the their memory not yet freed. */
00197     PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTasksDeleted = ( unsigned portBASE_TYPE ) 0U;
00198 
00199 #endif
00200 
00201 #if ( INCLUDE_vTaskSuspend == 1 )
00202 
00203     PRIVILEGED_DATA static xList xSuspendedTaskList;                    /*< Tasks that are currently suspended. */
00204 
00205 #endif
00206 
00207 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
00208 
00209     PRIVILEGED_DATA static xTaskHandle xIdleTaskHandle = NULL;          /*< Holds the handle of the idle task.  The idle task is created automatically when the scheduler is started. */
00210 
00211 #endif
00212 
00213 /* Other file private variables. --------------------------------*/
00214 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks   = ( unsigned portBASE_TYPE ) 0U;
00215 PRIVILEGED_DATA static volatile portTickType xTickCount                         = ( portTickType ) 0U;
00216 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTopReadyPriority       = tskIDLE_PRIORITY;
00217 PRIVILEGED_DATA static volatile signed portBASE_TYPE xSchedulerRunning          = pdFALSE;
00218 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended     = ( unsigned portBASE_TYPE ) pdFALSE;
00219 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxPendedTicks            = ( unsigned portBASE_TYPE ) 0U;
00220 PRIVILEGED_DATA static volatile portBASE_TYPE xYieldPending                     = pdFALSE;
00221 PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows                   = ( portBASE_TYPE ) 0;
00222 PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber                      = ( unsigned portBASE_TYPE ) 0U;
00223 PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime               = portMAX_DELAY;
00224 
00225 #if ( configGENERATE_RUN_TIME_STATS == 1 )
00226 
00227     PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL;    /*< Holds the value of a timer/counter the last time a task was switched in. */
00228     PRIVILEGED_DATA static unsigned long ulTotalRunTime = 0UL;          /*< Holds the total amount of execution time as defined by the run time counter clock. */
00229 
00230 #endif
00231 
00232 /*lint +e956 */
00233 
00234 /* Debugging and trace facilities private variables and macros. ------------*/
00235 
00236 /*
00237  * The value used to fill the stack of a task when the task is created.  This
00238  * is used purely for checking the high water mark for tasks.
00239  */
00240 #define tskSTACK_FILL_BYTE  ( 0xa5U )
00241 
00242 /*
00243  * Macros used by vListTask to indicate which state a task is in.
00244  */
00245 #define tskBLOCKED_CHAR     ( ( signed char ) 'B' )
00246 #define tskREADY_CHAR       ( ( signed char ) 'R' )
00247 #define tskDELETED_CHAR     ( ( signed char ) 'D' )
00248 #define tskSUSPENDED_CHAR   ( ( signed char ) 'S' )
00249 
00250 /*-----------------------------------------------------------*/
00251 
00252 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
00253 
00254     /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
00255     performed in a generic way that is not optimised to any particular
00256     microcontroller architecture. */
00257 
00258     /* uxTopReadyPriority holds the priority of the highest priority ready
00259     state task. */
00260     #define taskRECORD_READY_PRIORITY( uxPriority )                                                                     \
00261     {                                                                                                                   \
00262         if( ( uxPriority ) > uxTopReadyPriority )                                                                       \
00263         {                                                                                                               \
00264             uxTopReadyPriority = ( uxPriority );                                                                        \
00265         }                                                                                                               \
00266     } /* taskRECORD_READY_PRIORITY */
00267 
00268     /*-----------------------------------------------------------*/
00269 
00270     #define taskSELECT_HIGHEST_PRIORITY_TASK()                                                                          \
00271     {                                                                                                                   \
00272         /* Find the highest priority queue that contains ready tasks. */                                                \
00273         while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) )                                      \
00274         {                                                                                                               \
00275             configASSERT( uxTopReadyPriority );                                                                         \
00276             --uxTopReadyPriority;                                                                                       \
00277         }                                                                                                               \
00278                                                                                                                         \
00279         /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of                                        \
00280         the same priority get an equal share of the processor time. */                                                  \
00281         listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) );                      \
00282     } /* taskSELECT_HIGHEST_PRIORITY_TASK */
00283 
00284     /*-----------------------------------------------------------*/
00285 
00286     /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
00287     they are only required when a port optimised method of task selection is
00288     being used. */
00289     #define taskRESET_READY_PRIORITY( uxPriority )
00290     #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
00291 
00292 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
00293 
00294     /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
00295     performed in a way that is tailored to the particular microcontroller
00296     architecture being used. */
00297 
00298     /* A port optimised version is provided.  Call the port defined macros. */
00299     #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
00300 
00301     /*-----------------------------------------------------------*/
00302 
00303     #define taskSELECT_HIGHEST_PRIORITY_TASK()                                                      \
00304     {                                                                                               \
00305     unsigned portBASE_TYPE uxTopPriority;                                                           \
00306                                                                                                     \
00307         /* Find the highest priority queue that contains ready tasks. */                            \
00308         portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );                              \
00309         configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 );     \
00310         listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );       \
00311     } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
00312 
00313     /*-----------------------------------------------------------*/
00314 
00315     /* A port optimised version is provided, call it only if the TCB being reset
00316     is being referenced from a ready list.  If it is referenced from a delayed
00317     or suspended list then it won't be in a ready list. */
00318     #define taskRESET_READY_PRIORITY( uxPriority )                                                  \
00319     {                                                                                               \
00320         if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == 0 )              \
00321         {                                                                                           \
00322             portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) );                     \
00323         }                                                                                           \
00324     }
00325 
00326 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
00327 
00328 /*-----------------------------------------------------------*/
00329 
00330 /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
00331 count overflows. */
00332 #define taskSWITCH_DELAYED_LISTS()                                                                  \
00333 {                                                                                                   \
00334     xList *pxTemp;                                                                                  \
00335                                                                                                     \
00336     /* The delayed tasks list should be empty when the lists are switched. */                       \
00337     configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) );                                     \
00338                                                                                                     \
00339     pxTemp = pxDelayedTaskList;                                                                     \
00340     pxDelayedTaskList = pxOverflowDelayedTaskList;                                                  \
00341     pxOverflowDelayedTaskList = pxTemp;                                                             \
00342     xNumOfOverflows++;                                                                              \
00343                                                                                                     \
00344     if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )                                         \
00345     {                                                                                               \
00346         /* The new current delayed list is empty.  Set                                              \
00347         xNextTaskUnblockTime to the maximum possible value so it is                                 \
00348         extremely unlikely that the                                                                 \
00349         if( xTickCount >= xNextTaskUnblockTime ) test will pass until                               \
00350         there is an item in the delayed list. */                                                    \
00351         xNextTaskUnblockTime = portMAX_DELAY;                                                       \
00352     }                                                                                               \
00353     else                                                                                            \
00354     {                                                                                               \
00355         /* The new current delayed list is not empty, get the value of                              \
00356         the item at the head of the delayed list.  This is the time at                              \
00357         which the task at the head of the delayed list should be removed                            \
00358         from the Blocked state. */                                                                  \
00359         pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );                      \
00360         xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );             \
00361     }                                                                                               \
00362 }
00363 
00364 /*-----------------------------------------------------------*/
00365 
00366 /*
00367  * Place the task represented by pxTCB into the appropriate ready list for
00368  * the task.  It is inserted at the end of the list.
00369  */
00370 #define prvAddTaskToReadyList( pxTCB )                                                                              \
00371     traceMOVED_TASK_TO_READY_STATE( pxTCB )                                                                         \
00372     taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority );                                                             \
00373     vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) )
00374 /*-----------------------------------------------------------*/
00375 
00376 /*
00377  * Several functions take an xTaskHandle parameter that can optionally be NULL,
00378  * where NULL is used to indicate that the handle of the currently executing
00379  * task should be used in place of the parameter.  This macro simply checks to
00380  * see if the parameter is NULL and returns a pointer to the appropriate TCB.
00381  */
00382 #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( tskTCB * ) pxCurrentTCB : ( tskTCB * ) ( pxHandle ) )
00383 
00384 /* Callback function prototypes. --------------------------*/
00385 extern void vApplicationStackOverflowHook( xTaskHandle xTask, signed char *pcTaskName );
00386 extern void vApplicationTickHook( void );
00387 
00388 /* File private functions. --------------------------------*/
00389 
00390 /*
00391  * Utility to ready a TCB for a given task.  Mainly just copies the parameters
00392  * into the TCB structure.
00393  */
00394 static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) PRIVILEGED_FUNCTION;
00395 
00396 /*
00397  * Utility to ready all the lists used by the scheduler.  This is called
00398  * automatically upon the creation of the first task.
00399  */
00400 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
00401 
00402 /*
00403  * The idle task, which as all tasks is implemented as a never ending loop.
00404  * The idle task is automatically created and added to the ready lists upon
00405  * creation of the first user task.
00406  *
00407  * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
00408  * language extensions.  The equivalent prototype for this function is:
00409  *
00410  * void prvIdleTask( void *pvParameters );
00411  *
00412  */
00413 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
00414 
00415 /*
00416  * Utility to free all memory allocated by the scheduler to hold a TCB,
00417  * including the stack pointed to by the TCB.
00418  *
00419  * This does not free memory allocated by the task itself (i.e. memory
00420  * allocated by calls to pvPortMalloc from within the tasks application code).
00421  */
00422 #if ( INCLUDE_vTaskDelete == 1 )
00423 
00424     static void prvDeleteTCB( tskTCB *pxTCB ) PRIVILEGED_FUNCTION;
00425 
00426 #endif
00427 
00428 /*
00429  * Used only by the idle task.  This checks to see if anything has been placed
00430  * in the list of tasks waiting to be deleted.  If so the task is cleaned up
00431  * and its TCB deleted.
00432  */
00433 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
00434 
00435 /*
00436  * The currently executing task is entering the Blocked state.  Add the task to
00437  * either the current or the overflow delayed task list.
00438  */
00439 static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake ) PRIVILEGED_FUNCTION;
00440 
00441 /*
00442  * Allocates memory from the heap for a TCB and associated stack.  Checks the
00443  * allocation was successful.
00444  */
00445 static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) PRIVILEGED_FUNCTION;
00446 
00447 /*
00448  * Fills an xTaskStatusType structure with information on each task that is
00449  * referenced from the pxList list (which may be a ready list, a delayed list,
00450  * a suspended list, etc.).
00451  *
00452  * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
00453  * NORMAL APPLICATION CODE.
00454  */
00455 #if ( configUSE_TRACE_FACILITY == 1 )
00456 
00457     static unsigned portBASE_TYPE prvListTaskWithinSingleList( xTaskStatusType *pxTaskStatusArray, xList *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;
00458 
00459 #endif
00460 
00461 /*
00462  * When a task is created, the stack of the task is filled with a known value.
00463  * This function determines the 'high water mark' of the task stack by
00464  * determining how much of the stack remains at the original preset value.
00465  */
00466 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
00467 
00468     static unsigned short prvTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) PRIVILEGED_FUNCTION;
00469 
00470 #endif
00471 
00472 /*
00473  * Return the amount of time, in ticks, that will pass before the kernel will
00474  * next move a task from the Blocked state to the Running state.
00475  *
00476  * This conditional compilation should use inequality to 0, not equality to 1.
00477  * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
00478  * defined low power mode implementations require configUSE_TICKLESS_IDLE to be
00479  * set to a value other than 1.
00480  */
00481 #if ( configUSE_TICKLESS_IDLE != 0 )
00482 
00483     static portTickType prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
00484 
00485 #endif
00486 
00487 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 )
00488 {
00489 signed portBASE_TYPE xReturn;
00490 tskTCB * pxNewTCB;
00491 
00492     configASSERT( pxTaskCode );
00493     configASSERT( ( ( uxPriority & ( ~portPRIVILEGE_BIT ) ) < configMAX_PRIORITIES ) );
00494 
00495     /* Allocate the memory required by the TCB and stack for the new task,
00496     checking that the allocation was successful. */
00497     pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer );
00498 
00499     if( pxNewTCB != NULL )
00500     {
00501         portSTACK_TYPE *pxTopOfStack;
00502 
00503         #if( portUSING_MPU_WRAPPERS == 1 )
00504             /* Should the task be created in privileged mode? */
00505             portBASE_TYPE xRunPrivileged;
00506             if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
00507             {
00508                 xRunPrivileged = pdTRUE;
00509             }
00510             else
00511             {
00512                 xRunPrivileged = pdFALSE;
00513             }
00514             uxPriority &= ~portPRIVILEGE_BIT;
00515         #endif /* portUSING_MPU_WRAPPERS == 1 */
00516 
00517         /* Calculate the top of stack address.  This depends on whether the
00518         stack grows from high memory to low (as per the 80x86) or visa versa.
00519         portSTACK_GROWTH is used to make the result positive or negative as
00520         required by the port. */
00521         #if( portSTACK_GROWTH < 0 )
00522         {
00523             pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( unsigned short ) 1 );
00524             pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK  ) ); /*lint !e923 MISRA exception.  Avoiding casts between pointers and integers is not practical.  Size differences accounted for using portPOINTER_SIZE_TYPE type. */
00525 
00526             /* Check the alignment of the calculated top of stack is correct. */
00527             configASSERT( ( ( ( unsigned long ) pxTopOfStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
00528         }
00529         #else /* portSTACK_GROWTH */
00530         {
00531             pxTopOfStack = pxNewTCB->pxStack;
00532 
00533             /* Check the alignment of the stack buffer is correct. */
00534             configASSERT( ( ( ( unsigned long ) pxNewTCB->pxStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
00535 
00536             /* If we want to use stack checking on architectures that use
00537             a positive stack growth direction then we also need to store the
00538             other extreme of the stack space. */
00539             pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
00540         }
00541         #endif /* portSTACK_GROWTH */
00542 
00543         /* Setup the newly allocated TCB with the initial state of the task. */
00544         prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth );
00545 
00546         /* Initialize the TCB stack to look as if the task was already running,
00547         but had been interrupted by the scheduler.  The return address is set
00548         to the start of the task function. Once the stack has been initialised
00549         the top of stack variable is updated. */
00550         #if( portUSING_MPU_WRAPPERS == 1 )
00551         {
00552             pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
00553         }
00554         #else /* portUSING_MPU_WRAPPERS */
00555         {
00556             pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
00557         }
00558         #endif /* portUSING_MPU_WRAPPERS */
00559 
00560         if( ( void * ) pxCreatedTask != NULL )
00561         {
00562             /* Pass the TCB out - in an anonymous way.  The calling function/
00563             task can use this as a handle to delete the task later if
00564             required.*/
00565             *pxCreatedTask = ( xTaskHandle ) pxNewTCB;
00566         }
00567 
00568         /* Ensure interrupts don't access the task lists while they are being
00569         updated. */
00570         taskENTER_CRITICAL();
00571         {
00572             uxCurrentNumberOfTasks++;
00573             if( pxCurrentTCB == NULL )
00574             {
00575                 /* There are no other tasks, or all the other tasks are in
00576                 the suspended state - make this the current task. */
00577                 pxCurrentTCB =  pxNewTCB;
00578 
00579                 if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 )
00580                 {
00581                     /* This is the first task to be created so do the preliminary
00582                     initialisation required.  We will not recover if this call
00583                     fails, but we will report the failure. */
00584                     prvInitialiseTaskLists();
00585                 }
00586             }
00587             else
00588             {
00589                 /* If the scheduler is not already running, make this task the
00590                 current task if it is the highest priority task to be created
00591                 so far. */
00592                 if( xSchedulerRunning == pdFALSE )
00593                 {
00594                     if( pxCurrentTCB->uxPriority <= uxPriority )
00595                     {
00596                         pxCurrentTCB = pxNewTCB;
00597                     }
00598                 }
00599             }
00600 
00601             uxTaskNumber++;
00602 
00603             #if ( configUSE_TRACE_FACILITY == 1 )
00604             {
00605                 /* Add a counter into the TCB for tracing only. */
00606                 pxNewTCB->uxTCBNumber = uxTaskNumber;
00607             }
00608             #endif /* configUSE_TRACE_FACILITY */
00609             traceTASK_CREATE( pxNewTCB );
00610 
00611             prvAddTaskToReadyList( pxNewTCB );
00612 
00613             xReturn = pdPASS;
00614             portSETUP_TCB( pxNewTCB );
00615         }
00616         taskEXIT_CRITICAL();
00617     }
00618     else
00619     {
00620         xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
00621         traceTASK_CREATE_FAILED();
00622     }
00623 
00624     if( xReturn == pdPASS )
00625     {
00626         if( xSchedulerRunning != pdFALSE )
00627         {
00628             /* If the created task is of a higher priority than the current task
00629             then it should run now. */
00630             if( pxCurrentTCB->uxPriority < uxPriority )
00631             {
00632                 taskYIELD_IF_USING_PREEMPTION();
00633             }
00634         }
00635     }
00636 
00637     return xReturn;
00638 }
00639 /*-----------------------------------------------------------*/
00640 
00641 #if ( INCLUDE_vTaskDelete == 1 )
00642 
00643     void vTaskDelete( xTaskHandle xTaskToDelete )
00644     {
00645     tskTCB *pxTCB;
00646 
00647         taskENTER_CRITICAL();
00648         {
00649             /* If null is passed in here then we are deleting ourselves. */
00650             pxTCB = prvGetTCBFromHandle( xTaskToDelete );
00651 
00652             /* Remove task from the ready list and place in the termination list.
00653             This will stop the task from be scheduled.  The idle task will check
00654             the termination list and free up any memory allocated by the
00655             scheduler for the TCB and stack. */
00656             if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
00657             {
00658                 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
00659             }
00660 
00661             /* Is the task waiting on an event also? */
00662             if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
00663             {
00664                 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
00665             }
00666 
00667             vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );
00668 
00669             /* Increment the ucTasksDeleted variable so the idle task knows
00670             there is a task that has been deleted and that it should therefore
00671             check the xTasksWaitingTermination list. */
00672             ++uxTasksDeleted;
00673 
00674             /* Increment the uxTaskNumberVariable also so kernel aware debuggers
00675             can detect that the task lists need re-generating. */
00676             uxTaskNumber++;
00677 
00678             traceTASK_DELETE( pxTCB );
00679         }
00680         taskEXIT_CRITICAL();
00681 
00682         /* Force a reschedule if we have just deleted the current task. */
00683         if( xSchedulerRunning != pdFALSE )
00684         {
00685             if( pxTCB == pxCurrentTCB )
00686             {
00687                 portYIELD_WITHIN_API();
00688             }
00689         }
00690     }
00691 
00692 #endif /* INCLUDE_vTaskDelete */
00693 /*-----------------------------------------------------------*/
00694 
00695 #if ( INCLUDE_vTaskDelayUntil == 1 )
00696 
00697     void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement )
00698     {
00699     portTickType xTimeToWake;
00700     portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE;
00701 
00702         configASSERT( pxPreviousWakeTime );
00703         configASSERT( ( xTimeIncrement > 0U ) );
00704 
00705         vTaskSuspendAll();
00706         {
00707             /* Minor optimisation.  The tick count cannot change in this
00708             block. */
00709             const portTickType xConstTickCount = xTickCount;
00710 
00711             /* Generate the tick time at which the task wants to wake. */
00712             xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
00713 
00714             if( xConstTickCount < *pxPreviousWakeTime )
00715             {
00716                 /* The tick count has overflowed since this function was
00717                 lasted called.  In this case the only time we should ever
00718                 actually delay is if the wake time has also overflowed,
00719                 and the wake time is greater than the tick time.  When this
00720                 is the case it is as if neither time had overflowed. */
00721                 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
00722                 {
00723                     xShouldDelay = pdTRUE;
00724                 }
00725             }
00726             else
00727             {
00728                 /* The tick time has not overflowed.  In this case we will
00729                 delay if either the wake time has overflowed, and/or the
00730                 tick time is less than the wake time. */
00731                 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
00732                 {
00733                     xShouldDelay = pdTRUE;
00734                 }
00735             }
00736 
00737             /* Update the wake time ready for the next call. */
00738             *pxPreviousWakeTime = xTimeToWake;
00739 
00740             if( xShouldDelay != pdFALSE )
00741             {
00742                 traceTASK_DELAY_UNTIL();
00743 
00744                 /* We must remove ourselves from the ready list before adding
00745                 ourselves to the blocked list as the same list item is used for
00746                 both lists. */
00747                 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
00748                 {
00749                     /* The current task must be in a ready list, so there is
00750                     no need to check, and the port reset macro can be called
00751                     directly. */
00752                     portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
00753                 }
00754 
00755                 prvAddCurrentTaskToDelayedList( xTimeToWake );
00756             }
00757         }
00758         xAlreadyYielded = xTaskResumeAll();
00759 
00760         /* Force a reschedule if xTaskResumeAll has not already done so, we may
00761         have put ourselves to sleep. */
00762         if( xAlreadyYielded == pdFALSE )
00763         {
00764             portYIELD_WITHIN_API();
00765         }
00766     }
00767 
00768 #endif /* INCLUDE_vTaskDelayUntil */
00769 /*-----------------------------------------------------------*/
00770 
00771 #if ( INCLUDE_vTaskDelay == 1 )
00772 
00773     void vTaskDelay( portTickType xTicksToDelay )
00774     {
00775     portTickType xTimeToWake;
00776     signed portBASE_TYPE xAlreadyYielded = pdFALSE;
00777 
00778         /* A delay time of zero just forces a reschedule. */
00779         if( xTicksToDelay > ( portTickType ) 0U )
00780         {
00781             vTaskSuspendAll();
00782             {
00783                 traceTASK_DELAY();
00784 
00785                 /* A task that is removed from the event list while the
00786                 scheduler is suspended will not get placed in the ready
00787                 list or removed from the blocked list until the scheduler
00788                 is resumed.
00789 
00790                 This task cannot be in an event list as it is the currently
00791                 executing task. */
00792 
00793                 /* Calculate the time to wake - this may overflow but this is
00794                 not a problem. */
00795                 xTimeToWake = xTickCount + xTicksToDelay;
00796 
00797                 /* We must remove ourselves from the ready list before adding
00798                 ourselves to the blocked list as the same list item is used for
00799                 both lists. */
00800                 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
00801                 {
00802                     /* The current task must be in a ready list, so there is
00803                     no need to check, and the port reset macro can be called
00804                     directly. */
00805                     portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
00806                 }
00807                 prvAddCurrentTaskToDelayedList( xTimeToWake );
00808             }
00809             xAlreadyYielded = xTaskResumeAll();
00810         }
00811 
00812         /* Force a reschedule if xTaskResumeAll has not already done so, we may
00813         have put ourselves to sleep. */
00814         if( xAlreadyYielded == pdFALSE )
00815         {
00816             portYIELD_WITHIN_API();
00817         }
00818     }
00819 
00820 #endif /* INCLUDE_vTaskDelay */
00821 /*-----------------------------------------------------------*/
00822 
00823 #if ( INCLUDE_eTaskGetState == 1 )
00824 
00825     eTaskState eTaskGetState( xTaskHandle xTask )
00826     {
00827     eTaskState eReturn;
00828     xList *pxStateList;
00829     const tskTCB * const pxTCB = ( tskTCB * ) xTask;
00830 
00831         if( pxTCB == pxCurrentTCB )
00832         {
00833             /* The task calling this function is querying its own state. */
00834             eReturn = eRunning;
00835         }
00836         else
00837         {
00838             taskENTER_CRITICAL();
00839             {
00840                 pxStateList = ( xList * ) listLIST_ITEM_CONTAINER( &( pxTCB->xGenericListItem ) );
00841             }
00842             taskEXIT_CRITICAL();
00843 
00844             if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) )
00845             {
00846                 /* The task being queried is referenced from one of the Blocked
00847                 lists. */
00848                 eReturn = eBlocked;
00849             }
00850 
00851             #if ( INCLUDE_vTaskSuspend == 1 )
00852                 else if( pxStateList == &xSuspendedTaskList )
00853                 {
00854                     /* The task being queried is referenced from the suspended
00855                     list.  Is it genuinely suspended or is it block
00856                     indefinitely? */
00857                     if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
00858                     {
00859                         eReturn = eSuspended;
00860                     }
00861                     else
00862                     {
00863                         eReturn = eBlocked;
00864                     }
00865                 }
00866             #endif
00867 
00868             #if ( INCLUDE_vTaskDelete == 1 )
00869                 else if( pxStateList == &xTasksWaitingTermination )
00870                 {
00871                     /* The task being queried is referenced from the deleted
00872                     tasks list. */
00873                     eReturn = eDeleted;
00874                 }
00875             #endif
00876 
00877             else
00878             {
00879                 /* If the task is not in any other state, it must be in the
00880                 Ready (including pending ready) state. */
00881                 eReturn = eReady;
00882             }
00883         }
00884 
00885         return eReturn;
00886     }
00887 
00888 #endif /* INCLUDE_eTaskGetState */
00889 /*-----------------------------------------------------------*/
00890 
00891 #if ( INCLUDE_uxTaskPriorityGet == 1 )
00892 
00893     unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle xTask )
00894     {
00895     tskTCB *pxTCB;
00896     unsigned portBASE_TYPE uxReturn;
00897 
00898         taskENTER_CRITICAL();
00899         {
00900             /* If null is passed in here then we are changing the
00901             priority of the calling function. */
00902             pxTCB = prvGetTCBFromHandle( xTask );
00903             uxReturn = pxTCB->uxPriority;
00904         }
00905         taskEXIT_CRITICAL();
00906 
00907         return uxReturn;
00908     }
00909 
00910 #endif /* INCLUDE_uxTaskPriorityGet */
00911 /*-----------------------------------------------------------*/
00912 
00913 #if ( INCLUDE_vTaskPrioritySet == 1 )
00914 
00915     void vTaskPrioritySet( xTaskHandle xTask, unsigned portBASE_TYPE uxNewPriority )
00916     {
00917     tskTCB *pxTCB;
00918     unsigned portBASE_TYPE uxCurrentBasePriority, uxPriorityUsedOnEntry;
00919     portBASE_TYPE xYieldRequired = pdFALSE;
00920 
00921         configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
00922 
00923         /* Ensure the new priority is valid. */
00924         if( uxNewPriority >= ( unsigned portBASE_TYPE ) configMAX_PRIORITIES )
00925         {
00926             uxNewPriority = ( unsigned portBASE_TYPE ) configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U;
00927         }
00928 
00929         taskENTER_CRITICAL();
00930         {
00931             /* If null is passed in here then it is the priority of the calling
00932             task that is being changed. */
00933             pxTCB = prvGetTCBFromHandle( xTask );
00934 
00935             traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
00936 
00937             #if ( configUSE_MUTEXES == 1 )
00938             {
00939                 uxCurrentBasePriority = pxTCB->uxBasePriority;
00940             }
00941             #else
00942             {
00943                 uxCurrentBasePriority = pxTCB->uxPriority;
00944             }
00945             #endif
00946 
00947             if( uxCurrentBasePriority != uxNewPriority )
00948             {
00949                 /* The priority change may have readied a task of higher
00950                 priority than the calling task. */
00951                 if( uxNewPriority > uxCurrentBasePriority )
00952                 {
00953                     if( pxTCB != pxCurrentTCB )
00954                     {
00955                         /* The priority of a task other than the currently
00956                         running task is being raised.  Is the priority being
00957                         raised above that of the running task? */
00958                         if( uxNewPriority >= pxCurrentTCB->uxPriority )
00959                         {
00960                             xYieldRequired = pdTRUE;
00961                         }
00962                     }
00963                     else
00964                     {
00965                         /* The priority of the running task is being raised,
00966                         but the running task must already be the highest
00967                         priority task able to run so no yield is required. */
00968                     }
00969                 }
00970                 else if( pxTCB == pxCurrentTCB )
00971                 {
00972                     /* Setting the priority of the running task down means
00973                     there may now be another task of higher priority that
00974                     is ready to execute. */
00975                     xYieldRequired = pdTRUE;
00976                 }
00977                 else
00978                 {
00979                     /* Setting the priority of any other task down does not
00980                     require a yield as the running task must be above the
00981                     new priority of the task being modified. */
00982                 }
00983 
00984                 /* Remember the ready list the task might be referenced from
00985                 before its uxPriority member is changed so the
00986                 taskRESET_READY_PRIORITY() macro can function correctly. */
00987                 uxPriorityUsedOnEntry = pxTCB->uxPriority;
00988 
00989                 #if ( configUSE_MUTEXES == 1 )
00990                 {
00991                     /* Only change the priority being used if the task is not
00992                     currently using an inherited priority. */
00993                     if( pxTCB->uxBasePriority == pxTCB->uxPriority )
00994                     {
00995                         pxTCB->uxPriority = uxNewPriority;
00996                     }
00997 
00998                     /* The base priority gets set whatever. */
00999                     pxTCB->uxBasePriority = uxNewPriority;
01000                 }
01001                 #else
01002                 {
01003                     pxTCB->uxPriority = uxNewPriority;
01004                 }
01005                 #endif
01006 
01007                 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( portTickType ) configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
01008 
01009                 /* If the task is in the blocked or suspended list we need do
01010                 nothing more than change it's priority variable. However, if
01011                 the task is in a ready list it needs to be removed and placed
01012                 in the list appropriate to its new priority. */
01013                 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
01014                 {
01015                     /* The task is currently in its ready list - remove before adding
01016                     it to it's new ready list.  As we are in a critical section we
01017                     can do this even if the scheduler is suspended. */
01018                     if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
01019                     {
01020                         /* It is known that the task is in its ready list so
01021                         there is no need to check again and the port level
01022                         reset macro can be called directly. */
01023                         portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
01024                     }
01025                     prvAddTaskToReadyList( pxTCB );
01026                 }
01027 
01028                 if( xYieldRequired == pdTRUE )
01029                 {
01030                     taskYIELD_IF_USING_PREEMPTION();
01031                 }
01032 
01033                 /* Remove compiler warning about unused variables when the port
01034                 optimised task selection is not being used. */
01035                 ( void ) uxPriorityUsedOnEntry;
01036             }
01037         }
01038         taskEXIT_CRITICAL();
01039     }
01040 
01041 #endif /* INCLUDE_vTaskPrioritySet */
01042 /*-----------------------------------------------------------*/
01043 
01044 #if ( INCLUDE_vTaskSuspend == 1 )
01045 
01046     void vTaskSuspend( xTaskHandle xTaskToSuspend )
01047     {
01048     tskTCB *pxTCB;
01049 
01050         taskENTER_CRITICAL();
01051         {
01052             /* If null is passed in here then it is the running task that is
01053             being suspended. */
01054             pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
01055 
01056             traceTASK_SUSPEND( pxTCB );
01057 
01058             /* Remove task from the ready/delayed list and place in the suspended list. */
01059             if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
01060             {
01061                 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
01062             }
01063 
01064             /* Is the task waiting on an event also? */
01065             if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
01066             {
01067                 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
01068             }
01069 
01070             vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) );
01071         }
01072         taskEXIT_CRITICAL();
01073 
01074         if( pxTCB == pxCurrentTCB )
01075         {
01076             if( xSchedulerRunning != pdFALSE )
01077             {
01078                 /* The current task has just been suspended. */
01079                 portYIELD_WITHIN_API();
01080             }
01081             else
01082             {
01083                 /* The scheduler is not running, but the task that was pointed
01084                 to by pxCurrentTCB has just been suspended and pxCurrentTCB
01085                 must be adjusted to point to a different task. */
01086                 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )
01087                 {
01088                     /* No other tasks are ready, so set pxCurrentTCB back to
01089                     NULL so when the next task is created pxCurrentTCB will
01090                     be set to point to it no matter what its relative priority
01091                     is. */
01092                     pxCurrentTCB = NULL;
01093                 }
01094                 else
01095                 {
01096                     vTaskSwitchContext();
01097                 }
01098             }
01099         }
01100     }
01101 
01102 #endif /* INCLUDE_vTaskSuspend */
01103 /*-----------------------------------------------------------*/
01104 
01105 #if ( INCLUDE_vTaskSuspend == 1 )
01106 
01107     signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask )
01108     {
01109     portBASE_TYPE xReturn = pdFALSE;
01110     const tskTCB * const pxTCB = ( tskTCB * ) xTask;
01111 
01112         /* It does not make sense to check if the calling task is suspended. */
01113         configASSERT( xTask );
01114 
01115         /* Is the task we are attempting to resume actually in the
01116         suspended list? */
01117         if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
01118         {
01119             /* Has the task already been resumed from within an ISR? */
01120             if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
01121             {
01122                 /* Is it in the suspended list because it is in the
01123                 Suspended state?  It is possible to be in the suspended
01124                 list because it is blocked on a task with no timeout
01125                 specified. */
01126                 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )
01127                 {
01128                     xReturn = pdTRUE;
01129                 }
01130             }
01131         }
01132 
01133         return xReturn;
01134     } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
01135 
01136 #endif /* INCLUDE_vTaskSuspend */
01137 /*-----------------------------------------------------------*/
01138 
01139 #if ( INCLUDE_vTaskSuspend == 1 )
01140 
01141     void vTaskResume( xTaskHandle xTaskToResume )
01142     {
01143     tskTCB * const pxTCB = ( tskTCB * ) xTaskToResume;
01144 
01145         /* It does not make sense to resume the calling task. */
01146         configASSERT( xTaskToResume );
01147 
01148         /* The parameter cannot be NULL as it is impossible to resume the
01149         currently executing task. */
01150         if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
01151         {
01152             taskENTER_CRITICAL();
01153             {
01154                 if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
01155                 {
01156                     traceTASK_RESUME( pxTCB );
01157 
01158                     /* As we are in a critical section we can access the ready
01159                     lists even if the scheduler is suspended. */
01160                     ( void ) uxListRemove(  &( pxTCB->xGenericListItem ) );
01161                     prvAddTaskToReadyList( pxTCB );
01162 
01163                     /* We may have just resumed a higher priority task. */
01164                     if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
01165                     {
01166                         /* This yield may not cause the task just resumed to run,
01167                         but will leave the lists in the correct state for the
01168                         next yield. */
01169                         taskYIELD_IF_USING_PREEMPTION();
01170                     }
01171                 }
01172             }
01173             taskEXIT_CRITICAL();
01174         }
01175     }
01176 
01177 #endif /* INCLUDE_vTaskSuspend */
01178 
01179 /*-----------------------------------------------------------*/
01180 
01181 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
01182 
01183     portBASE_TYPE xTaskResumeFromISR( xTaskHandle xTaskToResume )
01184     {
01185     portBASE_TYPE xYieldRequired = pdFALSE;
01186     tskTCB * const pxTCB = ( tskTCB * ) xTaskToResume;
01187     unsigned portBASE_TYPE uxSavedInterruptStatus;
01188 
01189         configASSERT( xTaskToResume );
01190 
01191         /* RTOS ports that support interrupt nesting have the concept of a
01192         maximum system call (or maximum API call) interrupt priority.
01193         Interrupts that are above the maximum system call priority are keep
01194         permanently enabled, even when the RTOS kernel is in a critical section,
01195         but cannot make any calls to FreeRTOS API functions.  If configASSERT()
01196         is defined in FreeRTOSConfig.h then
01197         portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
01198         failure if a FreeRTOS API function is called from an interrupt that has
01199         been assigned a priority above the configured maximum system call
01200         priority.  Only FreeRTOS functions that end in FromISR can be called
01201         from interrupts that have been assigned a priority at or (logically)
01202         below the maximum system call interrupt priority.  FreeRTOS maintains a
01203         separate interrupt safe API to ensure interrupt entry is as fast and as
01204         simple as possible.  More information (albeit Cortex-M specific) is
01205         provided on the following link:
01206         http://www.freertos.org/RTOS-Cortex-M3-M4.html */
01207         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
01208 
01209         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
01210         {
01211             if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
01212             {
01213                 traceTASK_RESUME_FROM_ISR( pxTCB );
01214 
01215                 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
01216                 {
01217                     if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
01218                     {
01219                         xYieldRequired = pdTRUE;
01220                     }
01221 
01222                     ( void ) uxListRemove(  &( pxTCB->xGenericListItem ) );
01223                     prvAddTaskToReadyList( pxTCB );
01224                 }
01225                 else
01226                 {
01227                     /* We cannot access the delayed or ready lists, so will hold this
01228                     task pending until the scheduler is resumed, at which point a
01229                     yield will be performed if necessary. */
01230                     vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
01231                 }
01232             }
01233         }
01234         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
01235 
01236         return xYieldRequired;
01237     }
01238 
01239 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
01240 /*-----------------------------------------------------------*/
01241 
01242 void vTaskStartScheduler( void )
01243 {
01244 portBASE_TYPE xReturn;
01245 
01246     /* Add the idle task at the lowest priority. */
01247     #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
01248     {
01249         /* Create the idle task, storing its handle in xIdleTaskHandle so it can
01250         be returned by the xTaskGetIdleTaskHandle() function. */
01251         xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
01252     }
01253     #else
01254     {
01255         /* Create the idle task without storing its handle. */
01256         xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), NULL );  /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
01257     }
01258     #endif /* INCLUDE_xTaskGetIdleTaskHandle */
01259 
01260     #if ( configUSE_TIMERS == 1 )
01261     {
01262         if( xReturn == pdPASS )
01263         {
01264             xReturn = xTimerCreateTimerTask();
01265         }
01266     }
01267     #endif /* configUSE_TIMERS */
01268 
01269     if( xReturn == pdPASS )
01270     {
01271         /* Interrupts are turned off here, to ensure a tick does not occur
01272         before or during the call to xPortStartScheduler().  The stacks of
01273         the created tasks contain a status word with interrupts switched on
01274         so interrupts will automatically get re-enabled when the first task
01275         starts to run. */
01276         portDISABLE_INTERRUPTS();
01277 
01278         #if ( configUSE_NEWLIB_REENTRANT == 1 )
01279         {
01280             /* Switch Newlib's _impure_ptr variable to point to the _reent
01281             structure specific to the task that will run first. */
01282             _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
01283         }
01284         #endif /* configUSE_NEWLIB_REENTRANT */
01285 
01286         xSchedulerRunning = pdTRUE;
01287         xTickCount = ( portTickType ) 0U;
01288 
01289         /* If configGENERATE_RUN_TIME_STATS is defined then the following
01290         macro must be defined to configure the timer/counter used to generate
01291         the run time counter time base. */
01292         portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
01293 
01294         /* Setting up the timer tick is hardware specific and thus in the
01295         portable interface. */
01296         if( xPortStartScheduler() != pdFALSE )
01297         {
01298             /* Should not reach here as if the scheduler is running the
01299             function will not return. */
01300         }
01301         else
01302         {
01303             /* Should only reach here if a task calls xTaskEndScheduler(). */
01304         }
01305     }
01306     else
01307     {
01308         /* This line will only be reached if the kernel could not be started,
01309         because there was not enough FreeRTOS heap to create the idle task
01310         or the timer task. */
01311         configASSERT( xReturn );
01312     }
01313 }
01314 /*-----------------------------------------------------------*/
01315 
01316 void vTaskEndScheduler( void )
01317 {
01318     /* Stop the scheduler interrupts and call the portable scheduler end
01319     routine so the original ISRs can be restored if necessary.  The port
01320     layer must ensure interrupts enable bit is left in the correct state. */
01321     portDISABLE_INTERRUPTS();
01322     xSchedulerRunning = pdFALSE;
01323     vPortEndScheduler();
01324 }
01325 /*----------------------------------------------------------*/
01326 
01327 void vTaskSuspendAll( void )
01328 {
01329     /* A critical section is not required as the variable is of type
01330     portBASE_TYPE. */
01331     ++uxSchedulerSuspended;
01332 }
01333 /*----------------------------------------------------------*/
01334 
01335 #if ( configUSE_TICKLESS_IDLE != 0 )
01336 
01337     static portTickType prvGetExpectedIdleTime( void )
01338     {
01339     portTickType xReturn;
01340 
01341         if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
01342         {
01343             xReturn = 0;
01344         }
01345         else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
01346         {
01347             /* There are other idle priority tasks in the ready state.  If
01348             time slicing is used then the very next tick interrupt must be
01349             processed. */
01350             xReturn = 0;
01351         }
01352         else
01353         {
01354             xReturn = xNextTaskUnblockTime - xTickCount;
01355         }
01356 
01357         return xReturn;
01358     }
01359 
01360 #endif /* configUSE_TICKLESS_IDLE */
01361 /*----------------------------------------------------------*/
01362 
01363 signed portBASE_TYPE xTaskResumeAll( void )
01364 {
01365 tskTCB *pxTCB;
01366 portBASE_TYPE xAlreadyYielded = pdFALSE;
01367 
01368     /* If uxSchedulerSuspended is zero then this function does not match a
01369     previous call to vTaskSuspendAll(). */
01370     configASSERT( uxSchedulerSuspended );
01371 
01372     /* It is possible that an ISR caused a task to be removed from an event
01373     list while the scheduler was suspended.  If this was the case then the
01374     removed task will have been added to the xPendingReadyList.  Once the
01375     scheduler has been resumed it is safe to move all the pending ready
01376     tasks from this list into their appropriate ready list. */
01377     taskENTER_CRITICAL();
01378     {
01379         --uxSchedulerSuspended;
01380 
01381         if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
01382         {
01383             if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0U )
01384             {
01385                 /* Move any readied tasks from the pending list into the
01386                 appropriate ready list. */
01387                 while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
01388                 {
01389                     pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );
01390                     ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
01391                     ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
01392                     prvAddTaskToReadyList( pxTCB );
01393 
01394                     /* If we have moved a task that has a priority higher than
01395                     the current task then we should yield. */
01396                     if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
01397                     {
01398                         xYieldPending = pdTRUE;
01399                     }
01400                 }
01401 
01402                 /* If any ticks occurred while the scheduler was suspended then
01403                 they should be processed now.  This ensures the tick count does not
01404                 slip, and that any delayed tasks are resumed at the correct time. */
01405                 if( uxPendedTicks > ( unsigned portBASE_TYPE ) 0U )
01406                 {
01407                     while( uxPendedTicks > ( unsigned portBASE_TYPE ) 0U )
01408                     {
01409                         if( xTaskIncrementTick() != pdFALSE )
01410                         {
01411                             xYieldPending = pdTRUE;
01412                         }
01413                         --uxPendedTicks;
01414                     }
01415                 }
01416 
01417                 if( xYieldPending == pdTRUE )
01418                 {
01419                     #if( configUSE_PREEMPTION != 0 )
01420                     {
01421                         xAlreadyYielded = pdTRUE;
01422                     }
01423                     #endif
01424                     taskYIELD_IF_USING_PREEMPTION();
01425                 }
01426             }
01427         }
01428     }
01429     taskEXIT_CRITICAL();
01430 
01431     return xAlreadyYielded;
01432 }
01433 /*-----------------------------------------------------------*/
01434 
01435 portTickType xTaskGetTickCount( void )
01436 {
01437 portTickType xTicks;
01438 
01439     /* Critical section required if running on a 16 bit processor. */
01440     taskENTER_CRITICAL();
01441     {
01442         xTicks = xTickCount;
01443     }
01444     taskEXIT_CRITICAL();
01445 
01446     return xTicks;
01447 }
01448 /*-----------------------------------------------------------*/
01449 
01450 portTickType xTaskGetTickCountFromISR( void )
01451 {
01452 portTickType xReturn;
01453 unsigned portBASE_TYPE uxSavedInterruptStatus;
01454 
01455     /* RTOS ports that support interrupt nesting have the concept of a maximum
01456     system call (or maximum API call) interrupt priority.  Interrupts that are
01457     above the maximum system call priority are keep permanently enabled, even
01458     when the RTOS kernel is in a critical section, but cannot make any calls to
01459     FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h
01460     then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
01461     failure if a FreeRTOS API function is called from an interrupt that has been
01462     assigned a priority above the configured maximum system call priority.
01463     Only FreeRTOS functions that end in FromISR can be called from interrupts
01464     that have been assigned a priority at or (logically) below the maximum
01465     system call interrupt priority.  FreeRTOS maintains a separate interrupt
01466     safe API to ensure interrupt entry is as fast and as simple as possible.
01467     More information (albeit Cortex-M specific) is provided on the following
01468     link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
01469     portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
01470 
01471     uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
01472     xReturn = xTickCount;
01473     portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
01474 
01475     return xReturn;
01476 }
01477 /*-----------------------------------------------------------*/
01478 
01479 unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
01480 {
01481     /* A critical section is not required because the variables are of type
01482     portBASE_TYPE. */
01483     return uxCurrentNumberOfTasks;
01484 }
01485 /*-----------------------------------------------------------*/
01486 
01487 #if ( INCLUDE_pcTaskGetTaskName == 1 )
01488 
01489     signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery )
01490     {
01491     tskTCB *pxTCB;
01492 
01493         /* If null is passed in here then the name of the calling task is being queried. */
01494         pxTCB = prvGetTCBFromHandle( xTaskToQuery );
01495         configASSERT( pxTCB );
01496         return &( pxTCB->pcTaskName[ 0 ] );
01497     }
01498 
01499 #endif /* INCLUDE_pcTaskGetTaskName */
01500 /*-----------------------------------------------------------*/
01501 
01502 #if ( configUSE_TRACE_FACILITY == 1 )
01503 
01504     unsigned portBASE_TYPE uxTaskGetSystemState( xTaskStatusType *pxTaskStatusArray, unsigned portBASE_TYPE uxArraySize, unsigned long *pulTotalRunTime )
01505     {
01506     unsigned portBASE_TYPE uxTask = 0, uxQueue = configMAX_PRIORITIES;
01507 
01508         vTaskSuspendAll();
01509         {
01510             /* Is there a space in the array for each task in the system? */
01511             if( uxArraySize >= uxCurrentNumberOfTasks )
01512             {
01513                 /* Fill in an xTaskStatusType structure with information on each
01514                 task in the Ready state. */
01515                 do
01516                 {
01517                     uxQueue--;
01518                     uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
01519 
01520                 } while( uxQueue > ( unsigned portBASE_TYPE ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
01521 
01522                 /* Fill in an xTaskStatusType structure with information on each
01523                 task in the Blocked state. */
01524                 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( xList * ) pxDelayedTaskList, eBlocked );
01525                 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( xList * ) pxOverflowDelayedTaskList, eBlocked );
01526 
01527                 #if( INCLUDE_vTaskDelete == 1 )
01528                 {
01529                     /* Fill in an xTaskStatusType structure with information on
01530                     each task that has been deleted but not yet cleaned up. */
01531                     uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
01532                 }
01533                 #endif
01534 
01535                 #if ( INCLUDE_vTaskSuspend == 1 )
01536                 {
01537                     /* Fill in an xTaskStatusType structure with information on
01538                     each task in the Suspended state. */
01539                     uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
01540                 }
01541                 #endif
01542 
01543                 #if ( configGENERATE_RUN_TIME_STATS == 1)
01544                 {
01545                     if( pulTotalRunTime != NULL )
01546                     {
01547                         #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
01548                             portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
01549                         #else
01550                             *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
01551                         #endif
01552                     }
01553                 }
01554                 #else
01555                 {
01556                     if( pulTotalRunTime != NULL )
01557                     {
01558                         *pulTotalRunTime = 0;
01559                     }
01560                 }
01561                 #endif
01562             }
01563         }
01564         ( void ) xTaskResumeAll();
01565 
01566         return uxTask;
01567     }
01568 
01569 #endif /* configUSE_TRACE_FACILITY */
01570 /*----------------------------------------------------------*/
01571 
01572 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
01573 
01574     xTaskHandle xTaskGetIdleTaskHandle( void )
01575     {
01576         /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
01577         started, then xIdleTaskHandle will be NULL. */
01578         configASSERT( ( xIdleTaskHandle != NULL ) );
01579         return xIdleTaskHandle;
01580     }
01581 
01582 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
01583 /*----------------------------------------------------------*/
01584 
01585 /* This conditional compilation should use inequality to 0, not equality to 1.
01586 This is to ensure vTaskStepTick() is available when user defined low power mode
01587 implementations require configUSE_TICKLESS_IDLE to be set to a value other than
01588 1. */
01589 #if ( configUSE_TICKLESS_IDLE != 0 )
01590 
01591     void vTaskStepTick( portTickType xTicksToJump )
01592     {
01593         /* Correct the tick count value after a period during which the tick
01594         was suppressed.  Note this does *not* call the tick hook function for
01595         each stepped tick. */
01596         configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
01597         xTickCount += xTicksToJump;
01598         traceINCREASE_TICK_COUNT( xTicksToJump );
01599     }
01600 
01601 #endif /* configUSE_TICKLESS_IDLE */
01602 /*----------------------------------------------------------*/
01603 
01604 portBASE_TYPE xTaskIncrementTick( void )
01605 {
01606 tskTCB * pxTCB;
01607 portTickType xItemValue;
01608 portBASE_TYPE xSwitchRequired = pdFALSE;
01609 
01610     /* Called by the portable layer each time a tick interrupt occurs.
01611     Increments the tick then checks to see if the new tick value will cause any
01612     tasks to be unblocked. */
01613     traceTASK_INCREMENT_TICK( xTickCount );
01614     if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
01615     {
01616         /* Increment the RTOS tick, switching the delayed and overflowed
01617         delayed lists if it wraps to 0. */
01618         ++xTickCount;
01619 
01620         {
01621             /* Minor optimisation.  The tick count cannot change in this
01622             block. */
01623             const portTickType xConstTickCount = xTickCount;
01624 
01625             if( xConstTickCount == ( portTickType ) 0U )
01626             {
01627                 taskSWITCH_DELAYED_LISTS();
01628             }
01629 
01630             /* See if this tick has made a timeout expire.  Tasks are stored in the
01631             queue in the order of their wake time - meaning once one tasks has been
01632             found whose block time has not expired there is no need not look any
01633             further down the list. */
01634             if( xConstTickCount >= xNextTaskUnblockTime )
01635             {
01636                 for( ;; )
01637                 {
01638                     if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
01639                     {
01640                         /* The delayed list is empty.  Set xNextTaskUnblockTime to
01641                         the maximum possible value so it is extremely unlikely that
01642                         the if( xTickCount >= xNextTaskUnblockTime ) test will pass
01643                         next time through. */
01644                         xNextTaskUnblockTime = portMAX_DELAY;
01645                         break;
01646                     }
01647                     else
01648                     {
01649                         /* The delayed list is not empty, get the value of the item
01650                         at the head of the delayed list.  This is the time at which
01651                         the task at the head of the delayed list must be removed
01652                         from the Blocked state. */
01653                         pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
01654                         xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
01655 
01656                         if( xConstTickCount < xItemValue )
01657                         {
01658                             /* It is not time to unblock this item yet, but the item
01659                             value is the time at which the task at the head of the
01660                             blocked list must be removed from the Blocked state -
01661                             so record the item value in xNextTaskUnblockTime. */
01662                             xNextTaskUnblockTime = xItemValue;
01663                             break;
01664                         }
01665 
01666                         /* It is time to remove the item from the Blocked state. */
01667                         ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
01668 
01669                         /* Is the task waiting on an event also?  If so remove it
01670                         from the event list. */
01671                         if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
01672                         {
01673                             ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
01674                         }
01675 
01676                         /* Place the unblocked task into the appropriate ready
01677                         list. */
01678                         prvAddTaskToReadyList( pxTCB );
01679 
01680                         /* A task being unblocked cannot cause an immediate context
01681                         switch if preemption is turned off. */
01682                         #if (  configUSE_PREEMPTION == 1 )
01683                         {
01684                             /* Preemption is on, but a context switch should only
01685                             be performed if the unblocked task has a priority that
01686                             is equal to or higher than the currently executing
01687                             task. */
01688                             if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
01689                             {
01690                                 xSwitchRequired = pdTRUE;
01691                             }
01692                         }
01693                         #endif /* configUSE_PREEMPTION */
01694                     }
01695                 }
01696             }
01697         }
01698 
01699         /* Tasks of equal priority to the currently running task will share
01700         processing time (time slice) if preemption is on, and the application
01701         writer has not explicitly turned time slicing off. */
01702         #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
01703         {
01704             if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( unsigned portBASE_TYPE ) 1 )
01705             {
01706                 xSwitchRequired = pdTRUE;
01707             }
01708         }
01709         #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
01710 
01711         #if ( configUSE_TICK_HOOK == 1 )
01712         {
01713             /* Guard against the tick hook being called when the pended tick
01714             count is being unwound (when the scheduler is being unlocked). */
01715             if( uxPendedTicks == ( unsigned portBASE_TYPE ) 0U )
01716             {
01717                 vApplicationTickHook();
01718             }
01719         }
01720         #endif /* configUSE_TICK_HOOK */
01721     }
01722     else
01723     {
01724         ++uxPendedTicks;
01725 
01726         /* The tick hook gets called at regular intervals, even if the
01727         scheduler is locked. */
01728         #if ( configUSE_TICK_HOOK == 1 )
01729         {
01730             vApplicationTickHook();
01731         }
01732         #endif
01733     }
01734 
01735     #if ( configUSE_PREEMPTION == 1 )
01736     {
01737         if( xYieldPending != pdFALSE )
01738         {
01739             xSwitchRequired = pdTRUE;
01740         }
01741     }
01742     #endif /* configUSE_PREEMPTION */
01743 
01744     return xSwitchRequired;
01745 }
01746 /*-----------------------------------------------------------*/
01747 
01748 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
01749 
01750     void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction )
01751     {
01752     tskTCB *xTCB;
01753 
01754         /* If xTask is NULL then we are setting our own task hook. */
01755         if( xTask == NULL )
01756         {
01757             xTCB = ( tskTCB * ) pxCurrentTCB;
01758         }
01759         else
01760         {
01761             xTCB = ( tskTCB * ) xTask;
01762         }
01763 
01764         /* Save the hook function in the TCB.  A critical section is required as
01765         the value can be accessed from an interrupt. */
01766         taskENTER_CRITICAL();
01767             xTCB->pxTaskTag = pxHookFunction;
01768         taskEXIT_CRITICAL();
01769     }
01770 
01771 #endif /* configUSE_APPLICATION_TASK_TAG */
01772 /*-----------------------------------------------------------*/
01773 
01774 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
01775 
01776     pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask )
01777     {
01778     tskTCB *xTCB;
01779     pdTASK_HOOK_CODE xReturn;
01780 
01781         /* If xTask is NULL then we are setting our own task hook. */
01782         if( xTask == NULL )
01783         {
01784             xTCB = ( tskTCB * ) pxCurrentTCB;
01785         }
01786         else
01787         {
01788             xTCB = ( tskTCB * ) xTask;
01789         }
01790 
01791         /* Save the hook function in the TCB.  A critical section is required as
01792         the value can be accessed from an interrupt. */
01793         taskENTER_CRITICAL();
01794             xReturn = xTCB->pxTaskTag;
01795         taskEXIT_CRITICAL();
01796 
01797         return xReturn;
01798     }
01799 
01800 #endif /* configUSE_APPLICATION_TASK_TAG */
01801 /*-----------------------------------------------------------*/
01802 
01803 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
01804 
01805     portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter )
01806     {
01807     tskTCB *xTCB;
01808     portBASE_TYPE xReturn;
01809 
01810         /* If xTask is NULL then we are calling our own task hook. */
01811         if( xTask == NULL )
01812         {
01813             xTCB = ( tskTCB * ) pxCurrentTCB;
01814         }
01815         else
01816         {
01817             xTCB = ( tskTCB * ) xTask;
01818         }
01819 
01820         if( xTCB->pxTaskTag != NULL )
01821         {
01822             xReturn = xTCB->pxTaskTag( pvParameter );
01823         }
01824         else
01825         {
01826             xReturn = pdFAIL;
01827         }
01828 
01829         return xReturn;
01830     }
01831 
01832 #endif /* configUSE_APPLICATION_TASK_TAG */
01833 /*-----------------------------------------------------------*/
01834 
01835 void vTaskSwitchContext( void )
01836 {
01837     if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE )
01838     {
01839         /* The scheduler is currently suspended - do not allow a context
01840         switch. */
01841         xYieldPending = pdTRUE;
01842     }
01843     else
01844     {
01845         xYieldPending = pdFALSE;
01846         traceTASK_SWITCHED_OUT();
01847 
01848         #if ( configGENERATE_RUN_TIME_STATS == 1 )
01849         {
01850                 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
01851                     portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
01852                 #else
01853                     ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
01854                 #endif
01855 
01856                 /* Add the amount of time the task has been running to the
01857                 accumulated time so far.  The time the task started running was
01858                 stored in ulTaskSwitchedInTime.  Note that there is no overflow
01859                 protection here so count values are only valid until the timer
01860                 overflows.  The guard against negative values is to protect
01861                 against suspect run time stat counter implementations - which
01862                 are provided by the application, not the kernel. */
01863                 if( ulTotalRunTime > ulTaskSwitchedInTime )
01864                 {
01865                     pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
01866                 }
01867                 ulTaskSwitchedInTime = ulTotalRunTime;
01868         }
01869         #endif /* configGENERATE_RUN_TIME_STATS */
01870 
01871         taskFIRST_CHECK_FOR_STACK_OVERFLOW();
01872         taskSECOND_CHECK_FOR_STACK_OVERFLOW();
01873 
01874         taskSELECT_HIGHEST_PRIORITY_TASK();
01875 
01876         traceTASK_SWITCHED_IN();
01877 
01878         #if ( configUSE_NEWLIB_REENTRANT == 1 )
01879         {
01880             /* Switch Newlib's _impure_ptr variable to point to the _reent
01881             structure specific to this task. */
01882             _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
01883         }
01884         #endif /* configUSE_NEWLIB_REENTRANT */
01885     }
01886 }
01887 /*-----------------------------------------------------------*/
01888 
01889 void vTaskPlaceOnEventList( xList * const pxEventList, portTickType xTicksToWait )
01890 {
01891 portTickType xTimeToWake;
01892 
01893     configASSERT( pxEventList );
01894 
01895     /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
01896     SCHEDULER SUSPENDED. */
01897 
01898     /* Place the event list item of the TCB in the appropriate event list.
01899     This is placed in the list in priority order so the highest priority task
01900     is the first to be woken by the event. */
01901     vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
01902 
01903     /* We must remove ourselves from the ready list before adding ourselves
01904     to the blocked list as the same list item is used for both lists.  We have
01905     exclusive access to the ready lists as the scheduler is locked. */
01906     if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
01907     {
01908         /* The current task must be in a ready list, so there is no need to
01909         check, and the port reset macro can be called directly. */
01910         portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
01911     }
01912 
01913     #if ( INCLUDE_vTaskSuspend == 1 )
01914     {
01915         if( xTicksToWait == portMAX_DELAY )
01916         {
01917             /* Add ourselves to the suspended task list instead of a delayed task
01918             list to ensure we are not woken by a timing event.  We will block
01919             indefinitely. */
01920             vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
01921         }
01922         else
01923         {
01924             /* Calculate the time at which the task should be woken if the event does
01925             not occur.  This may overflow but this doesn't matter. */
01926             xTimeToWake = xTickCount + xTicksToWait;
01927             prvAddCurrentTaskToDelayedList( xTimeToWake );
01928         }
01929     }
01930     #else /* INCLUDE_vTaskSuspend */
01931     {
01932             /* Calculate the time at which the task should be woken if the event does
01933             not occur.  This may overflow but this doesn't matter. */
01934             xTimeToWake = xTickCount + xTicksToWait;
01935             prvAddCurrentTaskToDelayedList( xTimeToWake );
01936     }
01937     #endif /* INCLUDE_vTaskSuspend */
01938 }
01939 /*-----------------------------------------------------------*/
01940 
01941 #if configUSE_TIMERS == 1
01942 
01943     void vTaskPlaceOnEventListRestricted( xList * const pxEventList, portTickType xTicksToWait )
01944     {
01945     portTickType xTimeToWake;
01946 
01947         configASSERT( pxEventList );
01948 
01949         /* This function should not be called by application code hence the
01950         'Restricted' in its name.  It is not part of the public API.  It is
01951         designed for use by kernel code, and has special calling requirements -
01952         it should be called from a critical section. */
01953 
01954 
01955         /* Place the event list item of the TCB in the appropriate event list.
01956         In this case it is assume that this is the only task that is going to
01957         be waiting on this event list, so the faster vListInsertEnd() function
01958         can be used in place of vListInsert. */
01959         vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
01960 
01961         /* We must remove this task from the ready list before adding it to the
01962         blocked list as the same list item is used for both lists.  This
01963         function is called form a critical section. */
01964         if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
01965         {
01966             /* The current task must be in a ready list, so there is no need to
01967             check, and the port reset macro can be called directly. */
01968             portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
01969         }
01970 
01971         /* Calculate the time at which the task should be woken if the event does
01972         not occur.  This may overflow but this doesn't matter. */
01973         xTimeToWake = xTickCount + xTicksToWait;
01974 
01975         traceTASK_DELAY_UNTIL();
01976         prvAddCurrentTaskToDelayedList( xTimeToWake );
01977     }
01978 
01979 #endif /* configUSE_TIMERS */
01980 /*-----------------------------------------------------------*/
01981 
01982 signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList )
01983 {
01984 tskTCB *pxUnblockedTCB;
01985 portBASE_TYPE xReturn;
01986 
01987     /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
01988     SCHEDULER SUSPENDED.  It can also be called from within an ISR. */
01989 
01990     /* The event list is sorted in priority order, so we can remove the
01991     first in the list, remove the TCB from the delayed list, and add
01992     it to the ready list.
01993 
01994     If an event is for a queue that is locked then this function will never
01995     get called - the lock count on the queue will get modified instead.  This
01996     means we can always expect exclusive access to the event list here.
01997 
01998     This function assumes that a check has already been made to ensure that
01999     pxEventList is not empty. */
02000     pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
02001     configASSERT( pxUnblockedTCB );
02002     ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
02003 
02004     if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
02005     {
02006         ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
02007         prvAddTaskToReadyList( pxUnblockedTCB );
02008     }
02009     else
02010     {
02011         /* We cannot access the delayed or ready lists, so will hold this
02012         task pending until the scheduler is resumed. */
02013         vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
02014     }
02015 
02016     if( pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority )
02017     {
02018         /* Return true if the task removed from the event list has
02019         a higher priority than the calling task.  This allows
02020         the calling task to know if it should force a context
02021         switch now. */
02022         xReturn = pdTRUE;
02023 
02024         /* Mark that a yield is pending in case the user is not using the
02025         "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
02026         xYieldPending = pdTRUE;
02027     }
02028     else
02029     {
02030         xReturn = pdFALSE;
02031     }
02032 
02033     return xReturn;
02034 }
02035 /*-----------------------------------------------------------*/
02036 
02037 void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut )
02038 {
02039     configASSERT( pxTimeOut );
02040     pxTimeOut->xOverflowCount = xNumOfOverflows;
02041     pxTimeOut->xTimeOnEntering = xTickCount;
02042 }
02043 /*-----------------------------------------------------------*/
02044 
02045 portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait )
02046 {
02047 portBASE_TYPE xReturn;
02048 
02049     configASSERT( pxTimeOut );
02050     configASSERT( pxTicksToWait );
02051 
02052     taskENTER_CRITICAL();
02053     {
02054         /* Minor optimisation.  The tick count cannot change in this block. */
02055         const portTickType xConstTickCount = xTickCount;
02056 
02057         #if ( INCLUDE_vTaskSuspend == 1 )
02058             /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is
02059             the maximum block time then the task should block indefinitely, and
02060             therefore never time out. */
02061             if( *pxTicksToWait == portMAX_DELAY )
02062             {
02063                 xReturn = pdFALSE;
02064             }
02065             else /* We are not blocking indefinitely, perform the checks below. */
02066         #endif
02067 
02068         if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
02069         {
02070             /* The tick count is greater than the time at which vTaskSetTimeout()
02071             was called, but has also overflowed since vTaskSetTimeOut() was called.
02072             It must have wrapped all the way around and gone past us again. This
02073             passed since vTaskSetTimeout() was called. */
02074             xReturn = pdTRUE;
02075         }
02076         else if( ( xConstTickCount - pxTimeOut->xTimeOnEntering ) < *pxTicksToWait )
02077         {
02078             /* Not a genuine timeout. Adjust parameters for time remaining. */
02079             *pxTicksToWait -= ( xConstTickCount -  pxTimeOut->xTimeOnEntering );
02080             vTaskSetTimeOutState( pxTimeOut );
02081             xReturn = pdFALSE;
02082         }
02083         else
02084         {
02085             xReturn = pdTRUE;
02086         }
02087     }
02088     taskEXIT_CRITICAL();
02089 
02090     return xReturn;
02091 }
02092 /*-----------------------------------------------------------*/
02093 
02094 void vTaskMissedYield( void )
02095 {
02096     xYieldPending = pdTRUE;
02097 }
02098 /*-----------------------------------------------------------*/
02099 
02100 #if ( configUSE_TRACE_FACILITY == 1 )
02101 
02102     unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask )
02103     {
02104     unsigned portBASE_TYPE uxReturn;
02105     tskTCB *pxTCB;
02106 
02107         if( xTask != NULL )
02108         {
02109             pxTCB = ( tskTCB * ) xTask;
02110             uxReturn = pxTCB->uxTaskNumber;
02111         }
02112         else
02113         {
02114             uxReturn = 0U;
02115         }
02116 
02117         return uxReturn;
02118     }
02119 
02120 #endif /* configUSE_TRACE_FACILITY */
02121 /*-----------------------------------------------------------*/
02122 
02123 #if ( configUSE_TRACE_FACILITY == 1 )
02124 
02125     void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle )
02126     {
02127     tskTCB *pxTCB;
02128 
02129         if( xTask != NULL )
02130         {
02131             pxTCB = ( tskTCB * ) xTask;
02132             pxTCB->uxTaskNumber = uxHandle;
02133         }
02134     }
02135 
02136 #endif /* configUSE_TRACE_FACILITY */
02137 
02138 /*
02139  * -----------------------------------------------------------
02140  * The Idle task.
02141  * ----------------------------------------------------------
02142  *
02143  * The portTASK_FUNCTION() macro is used to allow port/compiler specific
02144  * language extensions.  The equivalent prototype for this function is:
02145  *
02146  * void prvIdleTask( void *pvParameters );
02147  *
02148  */
02149 static portTASK_FUNCTION( prvIdleTask, pvParameters )
02150 {
02151     /* Stop warnings. */
02152     ( void ) pvParameters;
02153 
02154     for( ;; )
02155     {
02156         /* See if any tasks have been deleted. */
02157         prvCheckTasksWaitingTermination();
02158 
02159         #if ( configUSE_PREEMPTION == 0 )
02160         {
02161             /* If we are not using preemption we keep forcing a task switch to
02162             see if any other task has become available.  If we are using
02163             preemption we don't need to do this as any task becoming available
02164             will automatically get the processor anyway. */
02165             taskYIELD();
02166         }
02167         #endif /* configUSE_PREEMPTION */
02168 
02169         #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
02170         {
02171             /* When using preemption tasks of equal priority will be
02172             timesliced.  If a task that is sharing the idle priority is ready
02173             to run then the idle task should yield before the end of the
02174             timeslice.
02175 
02176             A critical region is not required here as we are just reading from
02177             the list, and an occasional incorrect value will not matter.  If
02178             the ready list at the idle priority contains more than one task
02179             then a task other than the idle task is ready to execute. */
02180             if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( unsigned portBASE_TYPE ) 1 )
02181             {
02182                 taskYIELD();
02183             }
02184         }
02185         #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
02186 
02187         #if ( configUSE_IDLE_HOOK == 1 )
02188         {
02189             extern void vApplicationIdleHook( void );
02190 
02191             /* Call the user defined function from within the idle task.  This
02192             allows the application designer to add background functionality
02193             without the overhead of a separate task.
02194             NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
02195             CALL A FUNCTION THAT MIGHT BLOCK. */
02196             vApplicationIdleHook();
02197         }
02198         #endif /* configUSE_IDLE_HOOK */
02199 
02200         /* This conditional compilation should use inequality to 0, not equality
02201         to 1.  This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
02202         user defined low power mode implementations require
02203         configUSE_TICKLESS_IDLE to be set to a value other than 1. */
02204         #if ( configUSE_TICKLESS_IDLE != 0 )
02205         {
02206         portTickType xExpectedIdleTime;
02207 
02208             /* It is not desirable to suspend then resume the scheduler on
02209             each iteration of the idle task.  Therefore, a preliminary
02210             test of the expected idle time is performed without the
02211             scheduler suspended.  The result here is not necessarily
02212             valid. */
02213             xExpectedIdleTime = prvGetExpectedIdleTime();
02214 
02215             if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
02216             {
02217                 vTaskSuspendAll();
02218                 {
02219                     /* Now the scheduler is suspended, the expected idle
02220                     time can be sampled again, and this time its value can
02221                     be used. */
02222                     configASSERT( xNextTaskUnblockTime >= xTickCount );
02223                     xExpectedIdleTime = prvGetExpectedIdleTime();
02224 
02225                     if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
02226                     {
02227                         traceLOW_POWER_IDLE_BEGIN();
02228                         portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
02229                         traceLOW_POWER_IDLE_END();
02230                     }
02231                 }
02232                 ( void ) xTaskResumeAll();
02233             }
02234         }
02235         #endif /* configUSE_TICKLESS_IDLE */
02236     }
02237 }
02238 /*-----------------------------------------------------------*/
02239 
02240 #if configUSE_TICKLESS_IDLE != 0
02241 
02242     eSleepModeStatus eTaskConfirmSleepModeStatus( void )
02243     {
02244     eSleepModeStatus eReturn = eStandardSleep;
02245 
02246         if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
02247         {
02248             /* A task was made ready while the scheduler was suspended. */
02249             eReturn = eAbortSleep;
02250         }
02251         else if( xYieldPending != pdFALSE )
02252         {
02253             /* A yield was pended while the scheduler was suspended. */
02254             eReturn = eAbortSleep;
02255         }
02256         else
02257         {
02258             #if configUSE_TIMERS == 0
02259             {
02260                 /* The idle task exists in addition to the application tasks. */
02261                 const unsigned portBASE_TYPE uxNonApplicationTasks = 1;
02262 
02263                 /* If timers are not being used and all the tasks are in the
02264                 suspended list (which might mean they have an infinite block
02265                 time rather than actually being suspended) then it is safe to
02266                 turn all clocks off and just wait for external interrupts. */
02267                 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
02268                 {
02269                     eReturn = eNoTasksWaitingTimeout;
02270                 }
02271             }
02272             #endif /* configUSE_TIMERS */
02273         }
02274 
02275         return eReturn;
02276     }
02277 #endif /* configUSE_TICKLESS_IDLE */
02278 /*-----------------------------------------------------------*/
02279 
02280 static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth )
02281 {
02282 unsigned portBASE_TYPE x;
02283 
02284     /* Store the task name in the TCB. */
02285     for( x = ( unsigned portBASE_TYPE ) 0; x < ( unsigned portBASE_TYPE ) configMAX_TASK_NAME_LEN; x++ )
02286     {
02287         pxTCB->pcTaskName[ x ] = pcName[ x ];
02288 
02289         /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
02290         configMAX_TASK_NAME_LEN characters just in case the memory after the
02291         string is not accessible (extremely unlikely). */
02292         if( pcName[ x ] == 0x00 )
02293         {
02294             break;
02295         }
02296     }
02297 
02298     /* Ensure the name string is terminated in the case that the string length
02299     was greater or equal to configMAX_TASK_NAME_LEN. */
02300     pxTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = ( signed char ) '\0';
02301 
02302     /* This is used as an array index so must ensure it's not too large.  First
02303     remove the privilege bit if one is present. */
02304     if( uxPriority >= ( unsigned portBASE_TYPE ) configMAX_PRIORITIES )
02305     {
02306         uxPriority = ( unsigned portBASE_TYPE ) configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U;
02307     }
02308 
02309     pxTCB->uxPriority = uxPriority;
02310     #if ( configUSE_MUTEXES == 1 )
02311     {
02312         pxTCB->uxBasePriority = uxPriority;
02313     }
02314     #endif /* configUSE_MUTEXES */
02315 
02316     vListInitialiseItem( &( pxTCB->xGenericListItem ) );
02317     vListInitialiseItem( &( pxTCB->xEventListItem ) );
02318 
02319     /* Set the pxTCB as a link back from the xListItem.  This is so we can get
02320     back to the containing TCB from a generic item in a list. */
02321     listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB );
02322 
02323     /* Event lists are always in priority order. */
02324     listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( portTickType ) configMAX_PRIORITIES - ( portTickType ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
02325     listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB );
02326 
02327     #if ( portCRITICAL_NESTING_IN_TCB == 1 )
02328     {
02329         pxTCB->uxCriticalNesting = ( unsigned portBASE_TYPE ) 0U;
02330     }
02331     #endif /* portCRITICAL_NESTING_IN_TCB */
02332 
02333     #if ( configUSE_APPLICATION_TASK_TAG == 1 )
02334     {
02335         pxTCB->pxTaskTag = NULL;
02336     }
02337     #endif /* configUSE_APPLICATION_TASK_TAG */
02338 
02339     #if ( configGENERATE_RUN_TIME_STATS == 1 )
02340     {
02341         pxTCB->ulRunTimeCounter = 0UL;
02342     }
02343     #endif /* configGENERATE_RUN_TIME_STATS */
02344 
02345     #if ( portUSING_MPU_WRAPPERS == 1 )
02346     {
02347         vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth );
02348     }
02349     #else /* portUSING_MPU_WRAPPERS */
02350     {
02351         ( void ) xRegions;
02352         ( void ) usStackDepth;
02353     }
02354     #endif /* portUSING_MPU_WRAPPERS */
02355 
02356     #if ( configUSE_NEWLIB_REENTRANT == 1 )
02357     {
02358         /* Initialise this task's Newlib reent structure. */
02359         _REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) );
02360     }
02361     #endif /* configUSE_NEWLIB_REENTRANT */
02362 }
02363 /*-----------------------------------------------------------*/
02364 
02365 #if ( portUSING_MPU_WRAPPERS == 1 )
02366 
02367     void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions )
02368     {
02369     tskTCB *pxTCB;
02370 
02371         /* If null is passed in here then we are deleting ourselves. */
02372         pxTCB = prvGetTCBFromHandle( xTaskToModify );
02373 
02374         vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
02375     }
02376 
02377 #endif /* portUSING_MPU_WRAPPERS */
02378 /*-----------------------------------------------------------*/
02379 
02380 static void prvInitialiseTaskLists( void )
02381 {
02382 unsigned portBASE_TYPE uxPriority;
02383 
02384     for( uxPriority = ( unsigned portBASE_TYPE ) 0U; uxPriority < ( unsigned portBASE_TYPE ) configMAX_PRIORITIES; uxPriority++ )
02385     {
02386         vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
02387     }
02388 
02389     vListInitialise( &xDelayedTaskList1 );
02390     vListInitialise( &xDelayedTaskList2 );
02391     vListInitialise( &xPendingReadyList );
02392 
02393     #if ( INCLUDE_vTaskDelete == 1 )
02394     {
02395         vListInitialise( &xTasksWaitingTermination );
02396     }
02397     #endif /* INCLUDE_vTaskDelete */
02398 
02399     #if ( INCLUDE_vTaskSuspend == 1 )
02400     {
02401         vListInitialise( &xSuspendedTaskList );
02402     }
02403     #endif /* INCLUDE_vTaskSuspend */
02404 
02405     /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
02406     using list2. */
02407     pxDelayedTaskList = &xDelayedTaskList1;
02408     pxOverflowDelayedTaskList = &xDelayedTaskList2;
02409 }
02410 /*-----------------------------------------------------------*/
02411 
02412 static void prvCheckTasksWaitingTermination( void )
02413 {
02414     #if ( INCLUDE_vTaskDelete == 1 )
02415     {
02416         portBASE_TYPE xListIsEmpty;
02417 
02418         /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
02419         too often in the idle task. */
02420         while( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0U )
02421         {
02422             vTaskSuspendAll();
02423                 xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
02424             ( void ) xTaskResumeAll();
02425 
02426             if( xListIsEmpty == pdFALSE )
02427             {
02428                 tskTCB *pxTCB;
02429 
02430                 taskENTER_CRITICAL();
02431                 {
02432                     pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
02433                     ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
02434                     --uxCurrentNumberOfTasks;
02435                     --uxTasksDeleted;
02436                 }
02437                 taskEXIT_CRITICAL();
02438 
02439                 prvDeleteTCB( pxTCB );
02440             }
02441         }
02442     }
02443     #endif /* vTaskDelete */
02444 }
02445 /*-----------------------------------------------------------*/
02446 
02447 static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake )
02448 {
02449     /* The list item will be inserted in wake time order. */
02450     listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
02451 
02452     if( xTimeToWake < xTickCount )
02453     {
02454         /* Wake time has overflowed.  Place this item in the overflow list. */
02455         vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
02456     }
02457     else
02458     {
02459         /* The wake time has not overflowed, so we can use the current block list. */
02460         vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
02461 
02462         /* If the task entering the blocked state was placed at the head of the
02463         list of blocked tasks then xNextTaskUnblockTime needs to be updated
02464         too. */
02465         if( xTimeToWake < xNextTaskUnblockTime )
02466         {
02467             xNextTaskUnblockTime = xTimeToWake;
02468         }
02469     }
02470 }
02471 /*-----------------------------------------------------------*/
02472 
02473 static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer )
02474 {
02475 tskTCB *pxNewTCB;
02476 
02477     /* Allocate space for the TCB.  Where the memory comes from depends on
02478     the implementation of the port malloc function. */
02479     pxNewTCB = ( tskTCB * ) pvPortMalloc( sizeof( tskTCB ) );
02480 
02481     if( pxNewTCB != NULL )
02482     {
02483         /* Allocate space for the stack used by the task being created.
02484         The base of the stack memory stored in the TCB so the task can
02485         be deleted later if required. */
02486         pxNewTCB->pxStack = ( portSTACK_TYPE * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( portSTACK_TYPE ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
02487 
02488         if( pxNewTCB->pxStack == NULL )
02489         {
02490             /* Could not allocate the stack.  Delete the allocated TCB. */
02491             vPortFree( pxNewTCB );
02492             pxNewTCB = NULL;
02493         }
02494         else
02495         {
02496             /* Just to help debugging. */
02497             ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( portSTACK_TYPE ) );
02498         }
02499     }
02500 
02501     return pxNewTCB;
02502 }
02503 /*-----------------------------------------------------------*/
02504 
02505 #if ( configUSE_TRACE_FACILITY == 1 )
02506 
02507     static unsigned portBASE_TYPE prvListTaskWithinSingleList( xTaskStatusType *pxTaskStatusArray, xList *pxList, eTaskState eState )
02508     {
02509     volatile tskTCB *pxNextTCB, *pxFirstTCB;
02510     unsigned portBASE_TYPE uxTask = 0;
02511 
02512         if( listCURRENT_LIST_LENGTH( pxList ) > ( unsigned portBASE_TYPE ) 0 )
02513         {
02514             listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
02515 
02516             /* Populate an xTaskStatusType structure within the
02517             pxTaskStatusArray array for each task that is referenced from
02518             pxList.  See the definition of xTaskStatusType in task.h for the
02519             meaning of each xTaskStatusType structure member. */
02520             do
02521             {
02522                 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
02523 
02524                 pxTaskStatusArray[ uxTask ].xHandle = ( xTaskHandle ) pxNextTCB;
02525                 pxTaskStatusArray[ uxTask ].pcTaskName = ( const signed char * ) &( pxNextTCB->pcTaskName [ 0 ] );
02526                 pxTaskStatusArray[ uxTask ].xTaskNumber = pxNextTCB->uxTCBNumber;
02527                 pxTaskStatusArray[ uxTask ].eCurrentState = eState;
02528                 pxTaskStatusArray[ uxTask ].uxCurrentPriority = pxNextTCB->uxPriority;
02529 
02530                 #if ( configUSE_MUTEXES == 1 )
02531                 {
02532                     pxTaskStatusArray[ uxTask ].uxBasePriority = pxNextTCB->uxBasePriority;
02533                 }
02534                 #else
02535                 {
02536                     pxTaskStatusArray[ uxTask ].uxBasePriority = 0;
02537                 }
02538                 #endif
02539 
02540                 #if ( configGENERATE_RUN_TIME_STATS == 1 )
02541                 {
02542                     pxTaskStatusArray[ uxTask ].ulRunTimeCounter = pxNextTCB->ulRunTimeCounter;
02543                 }
02544                 #else
02545                 {
02546                     pxTaskStatusArray[ uxTask ].ulRunTimeCounter = 0;
02547                 }
02548                 #endif
02549 
02550                 #if ( portSTACK_GROWTH > 0 )
02551                 {
02552                     pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxEndOfStack );
02553                 }
02554                 #else
02555                 {
02556                     pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack );
02557                 }
02558                 #endif
02559 
02560                 uxTask++;
02561 
02562             } while( pxNextTCB != pxFirstTCB );
02563         }
02564 
02565         return uxTask;
02566     }
02567 
02568 #endif /* configUSE_TRACE_FACILITY */
02569 /*-----------------------------------------------------------*/
02570 
02571 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
02572 
02573     static unsigned short prvTaskCheckFreeStackSpace( const unsigned char * pucStackByte )
02574     {
02575     unsigned short usCount = 0U;
02576 
02577         while( *pucStackByte == tskSTACK_FILL_BYTE )
02578         {
02579             pucStackByte -= portSTACK_GROWTH;
02580             usCount++;
02581         }
02582 
02583         usCount /= sizeof( portSTACK_TYPE );
02584 
02585         return usCount;
02586     }
02587 
02588 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */
02589 /*-----------------------------------------------------------*/
02590 
02591 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
02592 
02593     unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask )
02594     {
02595     tskTCB *pxTCB;
02596     unsigned char *pcEndOfStack;
02597     unsigned portBASE_TYPE uxReturn;
02598 
02599         pxTCB = prvGetTCBFromHandle( xTask );
02600 
02601         #if portSTACK_GROWTH < 0
02602         {
02603             pcEndOfStack = ( unsigned char * ) pxTCB->pxStack;
02604         }
02605         #else
02606         {
02607             pcEndOfStack = ( unsigned char * ) pxTCB->pxEndOfStack;
02608         }
02609         #endif
02610 
02611         uxReturn = ( unsigned portBASE_TYPE ) prvTaskCheckFreeStackSpace( pcEndOfStack );
02612 
02613         return uxReturn;
02614     }
02615 
02616 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
02617 /*-----------------------------------------------------------*/
02618 
02619 #if ( INCLUDE_vTaskDelete == 1 )
02620 
02621     static void prvDeleteTCB( tskTCB *pxTCB )
02622     {
02623         /* This call is required specifically for the TriCore port.  It must be
02624         above the vPortFree() calls.  The call is also used by ports/demos that
02625         want to allocate and clean RAM statically. */
02626         portCLEAN_UP_TCB( pxTCB );
02627 
02628         /* Free up the memory allocated by the scheduler for the task.  It is up to
02629         the task to free any memory allocated at the application level. */
02630         vPortFreeAligned( pxTCB->pxStack );
02631         vPortFree( pxTCB );
02632     }
02633 
02634 #endif /* INCLUDE_vTaskDelete */
02635 /*-----------------------------------------------------------*/
02636 
02637 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
02638 
02639     xTaskHandle xTaskGetCurrentTaskHandle( void )
02640     {
02641     xTaskHandle xReturn;
02642 
02643         /* A critical section is not required as this is not called from
02644         an interrupt and the current TCB will always be the same for any
02645         individual execution thread. */
02646         xReturn = pxCurrentTCB;
02647 
02648         return xReturn;
02649     }
02650 
02651 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
02652 /*-----------------------------------------------------------*/
02653 
02654 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
02655 
02656     portBASE_TYPE xTaskGetSchedulerState( void )
02657     {
02658     portBASE_TYPE xReturn;
02659 
02660         if( xSchedulerRunning == pdFALSE )
02661         {
02662             xReturn = taskSCHEDULER_NOT_STARTED;
02663         }
02664         else
02665         {
02666             if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
02667             {
02668                 xReturn = taskSCHEDULER_RUNNING;
02669             }
02670             else
02671             {
02672                 xReturn = taskSCHEDULER_SUSPENDED;
02673             }
02674         }
02675 
02676         return xReturn;
02677     }
02678 
02679 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
02680 /*-----------------------------------------------------------*/
02681 
02682 #if ( configUSE_MUTEXES == 1 )
02683 
02684     void vTaskPriorityInherit( xTaskHandle const pxMutexHolder )
02685     {
02686     tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;
02687 
02688         /* If the mutex was given back by an interrupt while the queue was
02689         locked then the mutex holder might now be NULL. */
02690         if( pxMutexHolder != NULL )
02691         {
02692             if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
02693             {
02694                 /* Adjust the mutex holder state to account for its new priority. */
02695                 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( portTickType ) configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
02696 
02697                 /* If the task being modified is in the ready state it will need to
02698                 be moved into a new list. */
02699                 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
02700                 {
02701                     if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
02702                     {
02703                         taskRESET_READY_PRIORITY( pxTCB->uxPriority );
02704                     }
02705 
02706                     /* Inherit the priority before being moved into the new list. */
02707                     pxTCB->uxPriority = pxCurrentTCB->uxPriority;
02708                     prvAddTaskToReadyList( pxTCB );
02709                 }
02710                 else
02711                 {
02712                     /* Just inherit the priority. */
02713                     pxTCB->uxPriority = pxCurrentTCB->uxPriority;
02714                 }
02715 
02716                 traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );
02717             }
02718         }
02719     }
02720 
02721 #endif /* configUSE_MUTEXES */
02722 /*-----------------------------------------------------------*/
02723 
02724 #if ( configUSE_MUTEXES == 1 )
02725 
02726     void vTaskPriorityDisinherit( xTaskHandle const pxMutexHolder )
02727     {
02728     tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;
02729 
02730         if( pxMutexHolder != NULL )
02731         {
02732             if( pxTCB->uxPriority != pxTCB->uxBasePriority )
02733             {
02734                 /* We must be the running task to be able to give the mutex back.
02735                 Remove ourselves from the ready list we currently appear in. */
02736                 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
02737                 {
02738                     taskRESET_READY_PRIORITY( pxTCB->uxPriority );
02739                 }
02740 
02741                 /* Disinherit the priority before adding the task into the new
02742                 ready list. */
02743                 traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
02744                 pxTCB->uxPriority = pxTCB->uxBasePriority;
02745                 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( portTickType ) configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
02746                 prvAddTaskToReadyList( pxTCB );
02747             }
02748         }
02749     }
02750 
02751 #endif /* configUSE_MUTEXES */
02752 /*-----------------------------------------------------------*/
02753 
02754 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
02755 
02756     void vTaskEnterCritical( void )
02757     {
02758         portDISABLE_INTERRUPTS();
02759 
02760         if( xSchedulerRunning != pdFALSE )
02761         {
02762             ( pxCurrentTCB->uxCriticalNesting )++;
02763         }
02764     }
02765 
02766 #endif /* portCRITICAL_NESTING_IN_TCB */
02767 /*-----------------------------------------------------------*/
02768 
02769 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
02770 
02771     void vTaskExitCritical( void )
02772     {
02773         if( xSchedulerRunning != pdFALSE )
02774         {
02775             if( pxCurrentTCB->uxCriticalNesting > 0U )
02776             {
02777                 ( pxCurrentTCB->uxCriticalNesting )--;
02778 
02779                 if( pxCurrentTCB->uxCriticalNesting == 0U )
02780                 {
02781                     portENABLE_INTERRUPTS();
02782                 }
02783             }
02784         }
02785     }
02786 
02787 #endif /* portCRITICAL_NESTING_IN_TCB */
02788 /*-----------------------------------------------------------*/
02789 
02790 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) )
02791 
02792     void vTaskList( signed char *pcWriteBuffer )
02793     {
02794     xTaskStatusType *pxTaskStatusArray;
02795     volatile unsigned portBASE_TYPE uxArraySize, x;
02796     char cStatus;
02797 
02798         /*
02799          * PLEASE NOTE:
02800          *
02801          * This function is provided for convenience only, and is used by many
02802          * of the demo applications.  Do not consider it to be part of the
02803          * scheduler.
02804          *
02805          * vTaskList() calls uxTaskGetSystemState(), then formats part of the
02806          * uxTaskGetSystemState() output into a human readable table that
02807          * displays task names, states and stack usage.
02808          *
02809          * vTaskList() has a dependency on the sprintf() C library function that
02810          * might bloat the code size, use a lot of stack, and provide different
02811          * results on different platforms.  An alternative, tiny, third party,
02812          * and limited functionality implementation of sprintf() is provided in
02813          * many of the FreeRTOS/Demo sub-directories in a file called
02814          * printf-stdarg.c (note printf-stdarg.c does not provide a full
02815          * snprintf() implementation!).
02816          *
02817          * It is recommended that production systems call uxTaskGetSystemState()
02818          * directly to get access to raw stats data, rather than indirectly
02819          * through a call to vTaskList().
02820          */
02821 
02822 
02823         /* Make sure the write buffer does not contain a string. */
02824         *pcWriteBuffer = 0x00;
02825 
02826         /* Take a snapshot of the number of tasks in case it changes while this
02827         function is executing. */
02828         uxArraySize = uxCurrentNumberOfTasks;
02829 
02830         /* Allocate an array index for each task. */
02831         pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( xTaskStatusType ) );
02832 
02833         if( pxTaskStatusArray != NULL )
02834         {
02835             /* Generate the (binary) data. */
02836             uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
02837 
02838             /* Create a human readable table from the binary data. */
02839             for( x = 0; x < uxArraySize; x++ )
02840             {
02841                 switch( pxTaskStatusArray[ x ].eCurrentState )
02842                 {
02843                 case eReady:        cStatus = tskREADY_CHAR;
02844                                     break;
02845 
02846                 case eBlocked:      cStatus = tskBLOCKED_CHAR;
02847                                     break;
02848 
02849                 case eSuspended:    cStatus = tskSUSPENDED_CHAR;
02850                                     break;
02851 
02852                 case eDeleted:      cStatus = tskDELETED_CHAR;
02853                                     break;
02854 
02855                 default:            /* Should not get here, but it is included
02856                                     to prevent static checking errors. */
02857                                     cStatus = 0x00;
02858                                     break;
02859                 }
02860 
02861                 sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxTaskStatusArray[ x ].pcTaskName, cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber );
02862                 pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
02863             }
02864 
02865             /* Free the array again. */
02866             vPortFree( pxTaskStatusArray );
02867         }
02868     }
02869 
02870 #endif /* configUSE_TRACE_FACILITY */
02871 /*----------------------------------------------------------*/
02872 
02873 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) )
02874 
02875     void vTaskGetRunTimeStats( signed char *pcWriteBuffer )
02876     {
02877     xTaskStatusType *pxTaskStatusArray;
02878     volatile unsigned portBASE_TYPE uxArraySize, x;
02879     unsigned long ulTotalTime, ulStatsAsPercentage;
02880 
02881         /*
02882          * PLEASE NOTE:
02883          *
02884          * This function is provided for convenience only, and is used by many
02885          * of the demo applications.  Do not consider it to be part of the
02886          * scheduler.
02887          *
02888          * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part
02889          * of the uxTaskGetSystemState() output into a human readable table that
02890          * displays the amount of time each task has spent in the Running state
02891          * in both absolute and percentage terms.
02892          *
02893          * vTaskGetRunTimeStats() has a dependency on the sprintf() C library
02894          * function that might bloat the code size, use a lot of stack, and
02895          * provide different results on different platforms.  An alternative,
02896          * tiny, third party, and limited functionality implementation of
02897          * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in
02898          * a file called printf-stdarg.c (note printf-stdarg.c does not provide
02899          * a full snprintf() implementation!).
02900          *
02901          * It is recommended that production systems call uxTaskGetSystemState()
02902          * directly to get access to raw stats data, rather than indirectly
02903          * through a call to vTaskGetRunTimeStats().
02904          */
02905 
02906         /* Make sure the write buffer does not contain a string. */
02907         *pcWriteBuffer = 0x00;
02908 
02909         /* Take a snapshot of the number of tasks in case it changes while this
02910         function is executing. */
02911         uxArraySize = uxCurrentNumberOfTasks;
02912 
02913         /* Allocate an array index for each task. */
02914         pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( xTaskStatusType ) );
02915 
02916         if( pxTaskStatusArray != NULL )
02917         {
02918             /* Generate the (binary) data. */
02919             uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
02920 
02921             /* For percentage calculations. */
02922             ulTotalTime /= 100UL;
02923 
02924             /* Avoid divide by zero errors. */
02925             if( ulTotalTime > 0 )
02926             {
02927                 /* Create a human readable table from the binary data. */
02928                 for( x = 0; x < uxArraySize; x++ )
02929                 {
02930                     /* What percentage of the total run time has the task used?
02931                     This will always be rounded down to the nearest integer.
02932                     ulTotalRunTimeDiv100 has already been divided by 100. */
02933                     ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
02934 
02935                     if( ulStatsAsPercentage > 0UL )
02936                     {
02937                         #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
02938                         {
02939                             sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
02940                         }
02941                         #else
02942                         {
02943                             /* sizeof( int ) == sizeof( long ) so a smaller
02944                             printf() library can be used. */
02945                             sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%u\t\t%u%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );
02946                         }
02947                         #endif
02948                     }
02949                     else
02950                     {
02951                         /* If the percentage is zero here then the task has
02952                         consumed less than 1% of the total run time. */
02953                         #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
02954                         {
02955                             sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );
02956                         }
02957                         #else
02958                         {
02959                             /* sizeof( int ) == sizeof( long ) so a smaller
02960                             printf() library can be used. */
02961                             sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%u\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter );
02962                         }
02963                         #endif
02964                     }
02965 
02966                     pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
02967                 }
02968             }
02969 
02970             /* Free the array again. */
02971             vPortFree( pxTaskStatusArray );
02972         }
02973     }
02974 
02975 #endif /* configGENERATE_RUN_TIME_STATS */
02976 
02977 
02978