TI's CC3100 websocket camera demo with Arducam mini ov5642 and freertos. Should work with other M3's. Work in progress test demo.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tasks.c Source File

tasks.c

00001 /*
00002     FreeRTOS V8.2.1 - Copyright (C) 2015 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     This file is part of the FreeRTOS distribution.
00008 
00009     FreeRTOS is free software; you can redistribute it and/or modify it under
00010     the terms of the GNU General Public License (version 2) as published by the
00011     Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
00012 
00013     ***************************************************************************
00014     >>!   NOTE: The modification to the GPL is included to allow you to     !<<
00015     >>!   distribute a combined work that includes FreeRTOS without being   !<<
00016     >>!   obliged to provide the source code for proprietary components     !<<
00017     >>!   outside of the FreeRTOS kernel.                                   !<<
00018     ***************************************************************************
00019 
00020     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
00021     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00022     FOR A PARTICULAR PURPOSE.  Full license text is available on the following
00023     link: http://www.freertos.org/a00114.html
00024 
00025     ***************************************************************************
00026      *                                                                       *
00027      *    FreeRTOS provides completely free yet professionally developed,    *
00028      *    robust, strictly quality controlled, supported, and cross          *
00029      *    platform software that is more than just the market leader, it     *
00030      *    is the industry's de facto standard.                               *
00031      *                                                                       *
00032      *    Help yourself get started quickly while simultaneously helping     *
00033      *    to support the FreeRTOS project by purchasing a FreeRTOS           *
00034      *    tutorial book, reference manual, or both:                          *
00035      *    http://www.FreeRTOS.org/Documentation                              *
00036      *                                                                       *
00037     ***************************************************************************
00038 
00039     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
00040     the FAQ page "My application does not run, what could be wrong?".  Have you
00041     defined configASSERT()?
00042 
00043     http://www.FreeRTOS.org/support - In return for receiving this top quality
00044     embedded software for free we request you assist our global community by
00045     participating in the support forum.
00046 
00047     http://www.FreeRTOS.org/training - Investing in training allows your team to
00048     be as productive as possible as early as possible.  Now you can receive
00049     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
00050     Ltd, and the world's leading authority on the world's leading RTOS.
00051 
00052     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
00053     including FreeRTOS+Trace - an indispensable productivity tool, a DOS
00054     compatible FAT file system, and our tiny thread aware UDP/IP stack.
00055 
00056     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
00057     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
00058 
00059     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
00060     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
00061     licenses offer ticketed support, indemnification and commercial middleware.
00062 
00063     http://www.SafeRTOS.com - High Integrity Systems also provide a safety
00064     engineered and independently SIL3 certified version for use in safety and
00065     mission critical applications that require provable dependability.
00066 
00067     1 tab == 4 spaces!
00068 */
00069 
00070 /* Standard includes. */
00071 #include <stdlib.h>
00072 #include <string.h>
00073 
00074 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
00075 all the API functions to use the MPU wrappers.  That should only be done when
00076 task.h is included from an application file. */
00077 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
00078 
00079 /* FreeRTOS includes. */
00080 #include "FreeRTOS.h"
00081 #include "task.h"
00082 #include "timers.h"
00083 #include "StackMacros.h"
00084 
00085 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the
00086 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
00087 header files above, but not in this file, in order to generate the correct
00088 privileged Vs unprivileged linkage and placement. */
00089 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
00090 
00091 /* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting
00092 functions but without including stdio.h here. */
00093 #if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 )
00094     /* At the bottom of this file are two optional functions that can be used
00095     to generate human readable text from the raw data generated by the
00096     uxTaskGetSystemState() function.  Note the formatting functions are provided
00097     for convenience only, and are NOT considered part of the kernel. */
00098     #include <stdio.h>
00099 #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
00100 
00101 /* Sanity check the configuration. */
00102 #if configUSE_TICKLESS_IDLE != 0
00103     #if INCLUDE_vTaskSuspend != 1
00104         #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0
00105     #endif /* INCLUDE_vTaskSuspend */
00106 #endif /* configUSE_TICKLESS_IDLE */
00107 
00108 /*
00109  * Defines the size, in words, of the stack allocated to the idle task.
00110  */
00111 #define tskIDLE_STACK_SIZE  configMINIMAL_STACK_SIZE
00112 
00113 #if( configUSE_PREEMPTION == 0 )
00114     /* If the cooperative scheduler is being used then a yield should not be
00115     performed just because a higher priority task has been woken. */
00116     #define taskYIELD_IF_USING_PREEMPTION()
00117 #else
00118     #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
00119 #endif
00120 
00121 /* Value that can be assigned to the eNotifyState member of the TCB. */
00122 typedef enum
00123 {
00124     eNotWaitingNotification = 0,
00125     eWaitingNotification,
00126     eNotified
00127 } eNotifyValue;
00128 
00129 /*
00130  * Task control block.  A task control block (TCB) is allocated for each task,
00131  * and stores task state information, including a pointer to the task's context
00132  * (the task's run time environment, including register values)
00133  */
00134 typedef struct tskTaskControlBlock
00135 {
00136     volatile StackType_t    *pxTopOfStack;  /*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
00137 
00138     #if ( portUSING_MPU_WRAPPERS == 1 )
00139         xMPU_SETTINGS   xMPUSettings;       /*< The MPU settings are defined as part of the port layer.  THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
00140         BaseType_t      xUsingStaticallyAllocatedStack; /* Set to pdTRUE if the stack is a statically allocated array, and pdFALSE if the stack is dynamically allocated. */
00141     #endif
00142 
00143     ListItem_t          xGenericListItem;   /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
00144     ListItem_t          xEventListItem;     /*< Used to reference a task from an event list. */
00145     UBaseType_t         uxPriority;         /*< The priority of the task.  0 is the lowest priority. */
00146     StackType_t         *pxStack;           /*< Points to the start of the stack. */
00147     char                pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created.  Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
00148 
00149     #if ( portSTACK_GROWTH > 0 )
00150         StackType_t     *pxEndOfStack;      /*< Points to the end of the stack on architectures where the stack grows up from low memory. */
00151     #endif
00152 
00153     #if ( portCRITICAL_NESTING_IN_TCB == 1 )
00154         UBaseType_t     uxCriticalNesting;  /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
00155     #endif
00156 
00157     #if ( configUSE_TRACE_FACILITY == 1 )
00158         UBaseType_t     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. */
00159         UBaseType_t     uxTaskNumber;       /*< Stores a number specifically for use by third party trace code. */
00160     #endif
00161 
00162     #if ( configUSE_MUTEXES == 1 )
00163         UBaseType_t     uxBasePriority;     /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
00164         UBaseType_t     uxMutexesHeld;
00165     #endif
00166 
00167     #if ( configUSE_APPLICATION_TASK_TAG == 1 )
00168         TaskHookFunction_t pxTaskTag;
00169     #endif
00170 
00171     #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
00172         void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
00173     #endif
00174 
00175     #if ( configGENERATE_RUN_TIME_STATS == 1 )
00176         uint32_t        ulRunTimeCounter;   /*< Stores the amount of time the task has spent in the Running state. */
00177     #endif
00178 
00179     #if ( configUSE_NEWLIB_REENTRANT == 1 )
00180         /* Allocate a Newlib reent structure that is specific to this task.
00181         Note Newlib support has been included by popular demand, but is not
00182         used by the FreeRTOS maintainers themselves.  FreeRTOS is not
00183         responsible for resulting newlib operation.  User must be familiar with
00184         newlib and must provide system-wide implementations of the necessary
00185         stubs. Be warned that (at the time of writing) the current newlib design
00186         implements a system-wide malloc() that must be provided with locks. */
00187         struct  _reent xNewLib_reent;
00188     #endif
00189 
00190     #if ( configUSE_TASK_NOTIFICATIONS == 1 )
00191         volatile uint32_t ulNotifiedValue;
00192         volatile eNotifyValue eNotifyState;
00193     #endif
00194 
00195 } tskTCB;
00196 
00197 /* The old tskTCB name is maintained above then typedefed to the new TCB_t name
00198 below to enable the use of older kernel aware debuggers. */
00199 typedef tskTCB TCB_t;
00200 
00201 /*
00202  * Some kernel aware debuggers require the data the debugger needs access to to
00203  * be global, rather than file scope.
00204  */
00205 #ifdef portREMOVE_STATIC_QUALIFIER
00206     #define static
00207 #endif
00208 
00209 /*lint -e956 A manual analysis and inspection has been used to determine which
00210 static variables must be declared volatile. */
00211 
00212 PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
00213 
00214 /* Lists for ready and blocked tasks. --------------------*/
00215 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */
00216 PRIVILEGED_DATA static List_t xDelayedTaskList1;                        /*< Delayed tasks. */
00217 PRIVILEGED_DATA static List_t xDelayedTaskList2;                        /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
00218 PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList;             /*< Points to the delayed task list currently being used. */
00219 PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList;     /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */
00220 PRIVILEGED_DATA static List_t xPendingReadyList;                        /*< Tasks that have been readied while the scheduler was suspended.  They will be moved to the ready list when the scheduler is resumed. */
00221 
00222 #if ( INCLUDE_vTaskDelete == 1 )
00223 
00224     PRIVILEGED_DATA static List_t xTasksWaitingTermination;             /*< Tasks that have been deleted - but their memory not yet freed. */
00225     PRIVILEGED_DATA static volatile UBaseType_t uxTasksDeleted = ( UBaseType_t ) 0U;
00226 
00227 #endif
00228 
00229 #if ( INCLUDE_vTaskSuspend == 1 )
00230 
00231     PRIVILEGED_DATA static List_t xSuspendedTaskList;                   /*< Tasks that are currently suspended. */
00232 
00233 #endif
00234 
00235 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
00236 
00237     PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle = NULL;         /*< Holds the handle of the idle task.  The idle task is created automatically when the scheduler is started. */
00238 
00239 #endif
00240 
00241 /* Other file private variables. --------------------------------*/
00242 PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks  = ( UBaseType_t ) 0U;
00243 PRIVILEGED_DATA static volatile TickType_t xTickCount               = ( TickType_t ) 0U;
00244 PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority      = tskIDLE_PRIORITY;
00245 PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning        = pdFALSE;
00246 PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks           = ( UBaseType_t ) 0U;
00247 PRIVILEGED_DATA static volatile BaseType_t xYieldPending            = pdFALSE;
00248 PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows          = ( BaseType_t ) 0;
00249 PRIVILEGED_DATA static UBaseType_t uxTaskNumber                     = ( UBaseType_t ) 0U;
00250 PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime     = portMAX_DELAY;
00251 
00252 /* Context switches are held pending while the scheduler is suspended.  Also,
00253 interrupts must not manipulate the xGenericListItem of a TCB, or any of the
00254 lists the xGenericListItem can be referenced from, if the scheduler is suspended.
00255 If an interrupt needs to unblock a task while the scheduler is suspended then it
00256 moves the task's event list item into the xPendingReadyList, ready for the
00257 kernel to move the task from the pending ready list into the real ready list
00258 when the scheduler is unsuspended.  The pending ready list itself can only be
00259 accessed from a critical section. */
00260 PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended    = ( UBaseType_t ) pdFALSE;
00261 
00262 #if ( configGENERATE_RUN_TIME_STATS == 1 )
00263 
00264     PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
00265     PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL;       /*< Holds the total amount of execution time as defined by the run time counter clock. */
00266 
00267 #endif
00268 
00269 /*lint +e956 */
00270 
00271 /* Debugging and trace facilities private variables and macros. ------------*/
00272 
00273 /*
00274  * The value used to fill the stack of a task when the task is created.  This
00275  * is used purely for checking the high water mark for tasks.
00276  */
00277 #define tskSTACK_FILL_BYTE  ( 0xa5U )
00278 
00279 /*
00280  * Macros used by vListTask to indicate which state a task is in.
00281  */
00282 #define tskBLOCKED_CHAR     ( 'B' )
00283 #define tskREADY_CHAR       ( 'R' )
00284 #define tskDELETED_CHAR     ( 'D' )
00285 #define tskSUSPENDED_CHAR   ( 'S' )
00286 
00287 /*-----------------------------------------------------------*/
00288 
00289 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
00290 
00291     /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
00292     performed in a generic way that is not optimised to any particular
00293     microcontroller architecture. */
00294 
00295     /* uxTopReadyPriority holds the priority of the highest priority ready
00296     state task. */
00297     #define taskRECORD_READY_PRIORITY( uxPriority )                                                     \
00298     {                                                                                                   \
00299         if( ( uxPriority ) > uxTopReadyPriority )                                                       \
00300         {                                                                                               \
00301             uxTopReadyPriority = ( uxPriority );                                                        \
00302         }                                                                                               \
00303     } /* taskRECORD_READY_PRIORITY */
00304 
00305     /*-----------------------------------------------------------*/
00306 
00307     #define taskSELECT_HIGHEST_PRIORITY_TASK()                                                          \
00308     {                                                                                                   \
00309         /* Find the highest priority queue that contains ready tasks. */                                \
00310         while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) )                      \
00311         {                                                                                               \
00312             configASSERT( uxTopReadyPriority );                                                         \
00313             --uxTopReadyPriority;                                                                       \
00314         }                                                                                               \
00315                                                                                                         \
00316         /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of                        \
00317         the same priority get an equal share of the processor time. */                                  \
00318         listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) );      \
00319     } /* taskSELECT_HIGHEST_PRIORITY_TASK */
00320 
00321     /*-----------------------------------------------------------*/
00322 
00323     /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
00324     they are only required when a port optimised method of task selection is
00325     being used. */
00326     #define taskRESET_READY_PRIORITY( uxPriority )
00327     #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
00328 
00329 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
00330 
00331     /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
00332     performed in a way that is tailored to the particular microcontroller
00333     architecture being used. */
00334 
00335     /* A port optimised version is provided.  Call the port defined macros. */
00336     #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
00337 
00338     /*-----------------------------------------------------------*/
00339 
00340     #define taskSELECT_HIGHEST_PRIORITY_TASK()                                                      \
00341     {                                                                                               \
00342     UBaseType_t uxTopPriority;                                                                      \
00343                                                                                                     \
00344         /* Find the highest priority queue that contains ready tasks. */                            \
00345         portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );                              \
00346         configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 );     \
00347         listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );       \
00348     } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
00349 
00350     /*-----------------------------------------------------------*/
00351 
00352     /* A port optimised version is provided, call it only if the TCB being reset
00353     is being referenced from a ready list.  If it is referenced from a delayed
00354     or suspended list then it won't be in a ready list. */
00355     #define taskRESET_READY_PRIORITY( uxPriority )                                                      \
00356     {                                                                                                   \
00357         if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 )  \
00358         {                                                                                               \
00359             portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) );                         \
00360         }                                                                                               \
00361     }
00362 
00363 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
00364 
00365 /*-----------------------------------------------------------*/
00366 
00367 /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
00368 count overflows. */
00369 #define taskSWITCH_DELAYED_LISTS()                                                                  \
00370 {                                                                                                   \
00371     List_t *pxTemp;                                                                                 \
00372                                                                                                     \
00373     /* The delayed tasks list should be empty when the lists are switched. */                       \
00374     configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) );                                     \
00375                                                                                                     \
00376     pxTemp = pxDelayedTaskList;                                                                     \
00377     pxDelayedTaskList = pxOverflowDelayedTaskList;                                                  \
00378     pxOverflowDelayedTaskList = pxTemp;                                                             \
00379     xNumOfOverflows++;                                                                              \
00380     prvResetNextTaskUnblockTime();                                                                  \
00381 }
00382 
00383 /*-----------------------------------------------------------*/
00384 
00385 /*
00386  * Place the task represented by pxTCB into the appropriate ready list for
00387  * the task.  It is inserted at the end of the list.
00388  */
00389 #define prvAddTaskToReadyList( pxTCB )                                                              \
00390     traceMOVED_TASK_TO_READY_STATE( pxTCB );                                                        \
00391     taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority );                                             \
00392     vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) )
00393 /*-----------------------------------------------------------*/
00394 
00395 /*
00396  * Several functions take an TaskHandle_t parameter that can optionally be NULL,
00397  * where NULL is used to indicate that the handle of the currently executing
00398  * task should be used in place of the parameter.  This macro simply checks to
00399  * see if the parameter is NULL and returns a pointer to the appropriate TCB.
00400  */
00401 #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TCB_t * ) pxCurrentTCB : ( TCB_t * ) ( pxHandle ) )
00402 
00403 /* The item value of the event list item is normally used to hold the priority
00404 of the task to which it belongs (coded to allow it to be held in reverse
00405 priority order).  However, it is occasionally borrowed for other purposes.  It
00406 is important its value is not updated due to a task priority change while it is
00407 being used for another purpose.  The following bit definition is used to inform
00408 the scheduler that the value should not be changed - in which case it is the
00409 responsibility of whichever module is using the value to ensure it gets set back
00410 to its original value when it is released. */
00411 #if configUSE_16_BIT_TICKS == 1
00412     #define taskEVENT_LIST_ITEM_VALUE_IN_USE    0x8000U
00413 #else
00414     #define taskEVENT_LIST_ITEM_VALUE_IN_USE    0x80000000UL
00415 #endif
00416 
00417 /* Callback function prototypes. --------------------------*/
00418 #if configCHECK_FOR_STACK_OVERFLOW > 0
00419     extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName );
00420 #endif
00421 
00422 #if configUSE_TICK_HOOK > 0
00423     extern void vApplicationTickHook( void );
00424 #endif
00425 
00426 /* File private functions. --------------------------------*/
00427 
00428 /*
00429  * Utility to ready a TCB for a given task.  Mainly just copies the parameters
00430  * into the TCB structure.
00431  */
00432 static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
00433 
00434 /**
00435  * Utility task that simply returns pdTRUE if the task referenced by xTask is
00436  * currently in the Suspended state, or pdFALSE if the task referenced by xTask
00437  * is in any other state.
00438  */
00439 #if ( INCLUDE_vTaskSuspend == 1 )
00440     static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
00441 #endif /* INCLUDE_vTaskSuspend */
00442 
00443 /*
00444  * Utility to ready all the lists used by the scheduler.  This is called
00445  * automatically upon the creation of the first task.
00446  */
00447 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
00448 
00449 /*
00450  * The idle task, which as all tasks is implemented as a never ending loop.
00451  * The idle task is automatically created and added to the ready lists upon
00452  * creation of the first user task.
00453  *
00454  * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
00455  * language extensions.  The equivalent prototype for this function is:
00456  *
00457  * void prvIdleTask( void *pvParameters );
00458  *
00459  */
00460 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
00461 
00462 /*
00463  * Utility to free all memory allocated by the scheduler to hold a TCB,
00464  * including the stack pointed to by the TCB.
00465  *
00466  * This does not free memory allocated by the task itself (i.e. memory
00467  * allocated by calls to pvPortMalloc from within the tasks application code).
00468  */
00469 #if ( INCLUDE_vTaskDelete == 1 )
00470 
00471     static void prvDeleteTCB( TCB_t *pxTCB ) PRIVILEGED_FUNCTION;
00472 
00473 #endif
00474 
00475 /*
00476  * Used only by the idle task.  This checks to see if anything has been placed
00477  * in the list of tasks waiting to be deleted.  If so the task is cleaned up
00478  * and its TCB deleted.
00479  */
00480 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
00481 
00482 /*
00483  * The currently executing task is entering the Blocked state.  Add the task to
00484  * either the current or the overflow delayed task list.
00485  */
00486 static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake ) PRIVILEGED_FUNCTION;
00487 
00488 /*
00489  * Allocates memory from the heap for a TCB and associated stack.  Checks the
00490  * allocation was successful.
00491  */
00492 static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer ) PRIVILEGED_FUNCTION;
00493 
00494 /*
00495  * Fills an TaskStatus_t structure with information on each task that is
00496  * referenced from the pxList list (which may be a ready list, a delayed list,
00497  * a suspended list, etc.).
00498  *
00499  * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
00500  * NORMAL APPLICATION CODE.
00501  */
00502 #if ( configUSE_TRACE_FACILITY == 1 )
00503 
00504     static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;
00505 
00506 #endif
00507 
00508 /*
00509  * When a task is created, the stack of the task is filled with a known value.
00510  * This function determines the 'high water mark' of the task stack by
00511  * determining how much of the stack remains at the original preset value.
00512  */
00513 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
00514 
00515     static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
00516 
00517 #endif
00518 
00519 /*
00520  * Return the amount of time, in ticks, that will pass before the kernel will
00521  * next move a task from the Blocked state to the Running state.
00522  *
00523  * This conditional compilation should use inequality to 0, not equality to 1.
00524  * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
00525  * defined low power mode implementations require configUSE_TICKLESS_IDLE to be
00526  * set to a value other than 1.
00527  */
00528 #if ( configUSE_TICKLESS_IDLE != 0 )
00529 
00530     static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
00531 
00532 #endif
00533 
00534 /*
00535  * Set xNextTaskUnblockTime to the time at which the next Blocked state task
00536  * will exit the Blocked state.
00537  */
00538 static void prvResetNextTaskUnblockTime( void );
00539 
00540 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
00541 
00542     /*
00543      * Helper function used to pad task names with spaces when printing out
00544      * human readable tables of task information.
00545      */
00546     static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName );
00547 
00548 #endif
00549 /*-----------------------------------------------------------*/
00550 
00551 BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
00552 {
00553 BaseType_t xReturn;
00554 TCB_t * pxNewTCB;
00555 StackType_t *pxTopOfStack;
00556 
00557     configASSERT( pxTaskCode );
00558     configASSERT( ( ( uxPriority & ( UBaseType_t ) ( ~portPRIVILEGE_BIT ) ) < ( UBaseType_t ) configMAX_PRIORITIES ) );
00559 
00560     /* Allocate the memory required by the TCB and stack for the new task,
00561     checking that the allocation was successful. */
00562     pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer );
00563 
00564     if( pxNewTCB != NULL )
00565     {
00566         #if( portUSING_MPU_WRAPPERS == 1 )
00567             /* Should the task be created in privileged mode? */
00568             BaseType_t xRunPrivileged;
00569             if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
00570             {
00571                 xRunPrivileged = pdTRUE;
00572             }
00573             else
00574             {
00575                 xRunPrivileged = pdFALSE;
00576             }
00577             uxPriority &= ~portPRIVILEGE_BIT;
00578 
00579             if( puxStackBuffer != NULL )
00580             {
00581                 /* The application provided its own stack.  Note this so no
00582                 attempt is made to delete the stack should that task be
00583                 deleted. */
00584                 pxNewTCB->xUsingStaticallyAllocatedStack = pdTRUE;
00585             }
00586             else
00587             {
00588                 /* The stack was allocated dynamically.  Note this so it can be
00589                 deleted again if the task is deleted. */
00590                 pxNewTCB->xUsingStaticallyAllocatedStack = pdFALSE;
00591             }
00592         #endif /* portUSING_MPU_WRAPPERS == 1 */
00593 
00594         /* Calculate the top of stack address.  This depends on whether the
00595         stack grows from high memory to low (as per the 80x86) or vice versa.
00596         portSTACK_GROWTH is used to make the result positive or negative as
00597         required by the port. */
00598         #if( portSTACK_GROWTH < 0 )
00599         {
00600             pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( uint16_t ) 1 );
00601             pxTopOfStack = ( StackType_t * ) ( ( ( 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. */
00602 
00603             /* Check the alignment of the calculated top of stack is correct. */
00604             configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
00605         }
00606         #else /* portSTACK_GROWTH */
00607         {
00608             pxTopOfStack = pxNewTCB->pxStack;
00609 
00610             /* Check the alignment of the stack buffer is correct. */
00611             configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
00612 
00613             /* If we want to use stack checking on architectures that use
00614             a positive stack growth direction then we also need to store the
00615             other extreme of the stack space. */
00616             pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
00617         }
00618         #endif /* portSTACK_GROWTH */
00619 
00620         /* Setup the newly allocated TCB with the initial state of the task. */
00621         prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth );
00622 
00623         /* Initialize the TCB stack to look as if the task was already running,
00624         but had been interrupted by the scheduler.  The return address is set
00625         to the start of the task function. Once the stack has been initialised
00626         the top of stack variable is updated. */
00627         #if( portUSING_MPU_WRAPPERS == 1 )
00628         {
00629             pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
00630         }
00631         #else /* portUSING_MPU_WRAPPERS */
00632         {
00633             pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
00634         }
00635         #endif /* portUSING_MPU_WRAPPERS */
00636 
00637         if( ( void * ) pxCreatedTask != NULL )
00638         {
00639             /* Pass the TCB out - in an anonymous way.  The calling function/
00640             task can use this as a handle to delete the task later if
00641             required.*/
00642             *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
00643         }
00644         else
00645         {
00646             mtCOVERAGE_TEST_MARKER();
00647         }
00648 
00649         /* Ensure interrupts don't access the task lists while they are being
00650         updated. */
00651         taskENTER_CRITICAL();
00652         {
00653             uxCurrentNumberOfTasks++;
00654             if( pxCurrentTCB == NULL )
00655             {
00656                 /* There are no other tasks, or all the other tasks are in
00657                 the suspended state - make this the current task. */
00658                 pxCurrentTCB =  pxNewTCB;
00659 
00660                 if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
00661                 {
00662                     /* This is the first task to be created so do the preliminary
00663                     initialisation required.  We will not recover if this call
00664                     fails, but we will report the failure. */
00665                     prvInitialiseTaskLists();
00666                 }
00667                 else
00668                 {
00669                     mtCOVERAGE_TEST_MARKER();
00670                 }
00671             }
00672             else
00673             {
00674                 /* If the scheduler is not already running, make this task the
00675                 current task if it is the highest priority task to be created
00676                 so far. */
00677                 if( xSchedulerRunning == pdFALSE )
00678                 {
00679                     if( pxCurrentTCB->uxPriority <= uxPriority )
00680                     {
00681                         pxCurrentTCB = pxNewTCB;
00682                     }
00683                     else
00684                     {
00685                         mtCOVERAGE_TEST_MARKER();
00686                     }
00687                 }
00688                 else
00689                 {
00690                     mtCOVERAGE_TEST_MARKER();
00691                 }
00692             }
00693 
00694             uxTaskNumber++;
00695 
00696             #if ( configUSE_TRACE_FACILITY == 1 )
00697             {
00698                 /* Add a counter into the TCB for tracing only. */
00699                 pxNewTCB->uxTCBNumber = uxTaskNumber;
00700             }
00701             #endif /* configUSE_TRACE_FACILITY */
00702             traceTASK_CREATE( pxNewTCB );
00703 
00704             prvAddTaskToReadyList( pxNewTCB );
00705 
00706             xReturn = pdPASS;
00707             portSETUP_TCB( pxNewTCB );
00708         }
00709         taskEXIT_CRITICAL();
00710     }
00711     else
00712     {
00713         xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
00714         traceTASK_CREATE_FAILED();
00715     }
00716 
00717     if( xReturn == pdPASS )
00718     {
00719         if( xSchedulerRunning != pdFALSE )
00720         {
00721             /* If the created task is of a higher priority than the current task
00722             then it should run now. */
00723             if( pxCurrentTCB->uxPriority < uxPriority )
00724             {
00725                 taskYIELD_IF_USING_PREEMPTION();
00726             }
00727             else
00728             {
00729                 mtCOVERAGE_TEST_MARKER();
00730             }
00731         }
00732         else
00733         {
00734             mtCOVERAGE_TEST_MARKER();
00735         }
00736     }
00737 
00738     return xReturn;
00739 }
00740 /*-----------------------------------------------------------*/
00741 
00742 #if ( INCLUDE_vTaskDelete == 1 )
00743 
00744     void vTaskDelete( TaskHandle_t xTaskToDelete )
00745     {
00746     TCB_t *pxTCB;
00747 
00748         taskENTER_CRITICAL();
00749         {
00750             /* If null is passed in here then it is the calling task that is
00751             being deleted. */
00752             pxTCB = prvGetTCBFromHandle( xTaskToDelete );
00753 
00754             /* Remove task from the ready list and place in the termination list.
00755             This will stop the task from be scheduled.  The idle task will check
00756             the termination list and free up any memory allocated by the
00757             scheduler for the TCB and stack. */
00758             if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
00759             {
00760                 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
00761             }
00762             else
00763             {
00764                 mtCOVERAGE_TEST_MARKER();
00765             }
00766 
00767             /* Is the task waiting on an event also? */
00768             if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
00769             {
00770                 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
00771             }
00772             else
00773             {
00774                 mtCOVERAGE_TEST_MARKER();
00775             }
00776 
00777             vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );
00778 
00779             /* Increment the ucTasksDeleted variable so the idle task knows
00780             there is a task that has been deleted and that it should therefore
00781             check the xTasksWaitingTermination list. */
00782             ++uxTasksDeleted;
00783 
00784             /* Increment the uxTaskNumberVariable also so kernel aware debuggers
00785             can detect that the task lists need re-generating. */
00786             uxTaskNumber++;
00787 
00788             traceTASK_DELETE( pxTCB );
00789         }
00790         taskEXIT_CRITICAL();
00791 
00792         /* Force a reschedule if it is the currently running task that has just
00793         been deleted. */
00794         if( xSchedulerRunning != pdFALSE )
00795         {
00796             if( pxTCB == pxCurrentTCB )
00797             {
00798                 configASSERT( uxSchedulerSuspended == 0 );
00799 
00800                 /* The pre-delete hook is primarily for the Windows simulator,
00801                 in which Windows specific clean up operations are performed,
00802                 after which it is not possible to yield away from this task -
00803                 hence xYieldPending is used to latch that a context switch is
00804                 required. */
00805                 portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
00806                 portYIELD_WITHIN_API();
00807             }
00808             else
00809             {
00810                 /* Reset the next expected unblock time in case it referred to
00811                 the task that has just been deleted. */
00812                 taskENTER_CRITICAL();
00813                 {
00814                     prvResetNextTaskUnblockTime();
00815                 }
00816                 taskEXIT_CRITICAL();
00817             }
00818         }
00819     }
00820 
00821 #endif /* INCLUDE_vTaskDelete */
00822 /*-----------------------------------------------------------*/
00823 
00824 #if ( INCLUDE_vTaskDelayUntil == 1 )
00825 
00826     void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
00827     {
00828     TickType_t xTimeToWake;
00829     BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
00830 
00831         configASSERT( pxPreviousWakeTime );
00832         configASSERT( ( xTimeIncrement > 0U ) );
00833         configASSERT( uxSchedulerSuspended == 0 );
00834 
00835         vTaskSuspendAll();
00836         {
00837             /* Minor optimisation.  The tick count cannot change in this
00838             block. */
00839             const TickType_t xConstTickCount = xTickCount;
00840 
00841             /* Generate the tick time at which the task wants to wake. */
00842             xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
00843 
00844             if( xConstTickCount < *pxPreviousWakeTime )
00845             {
00846                 /* The tick count has overflowed since this function was
00847                 lasted called.  In this case the only time we should ever
00848                 actually delay is if the wake time has also overflowed,
00849                 and the wake time is greater than the tick time.  When this
00850                 is the case it is as if neither time had overflowed. */
00851                 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
00852                 {
00853                     xShouldDelay = pdTRUE;
00854                 }
00855                 else
00856                 {
00857                     mtCOVERAGE_TEST_MARKER();
00858                 }
00859             }
00860             else
00861             {
00862                 /* The tick time has not overflowed.  In this case we will
00863                 delay if either the wake time has overflowed, and/or the
00864                 tick time is less than the wake time. */
00865                 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
00866                 {
00867                     xShouldDelay = pdTRUE;
00868                 }
00869                 else
00870                 {
00871                     mtCOVERAGE_TEST_MARKER();
00872                 }
00873             }
00874 
00875             /* Update the wake time ready for the next call. */
00876             *pxPreviousWakeTime = xTimeToWake;
00877 
00878             if( xShouldDelay != pdFALSE )
00879             {
00880                 traceTASK_DELAY_UNTIL();
00881 
00882                 /* Remove the task from the ready list before adding it to the
00883                 blocked list as the same list item is used for both lists. */
00884                 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
00885                 {
00886                     /* The current task must be in a ready list, so there is
00887                     no need to check, and the port reset macro can be called
00888                     directly. */
00889                     portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
00890                 }
00891                 else
00892                 {
00893                     mtCOVERAGE_TEST_MARKER();
00894                 }
00895 
00896                 prvAddCurrentTaskToDelayedList( xTimeToWake );
00897             }
00898             else
00899             {
00900                 mtCOVERAGE_TEST_MARKER();
00901             }
00902         }
00903         xAlreadyYielded = xTaskResumeAll();
00904 
00905         /* Force a reschedule if xTaskResumeAll has not already done so, we may
00906         have put ourselves to sleep. */
00907         if( xAlreadyYielded == pdFALSE )
00908         {
00909             portYIELD_WITHIN_API();
00910         }
00911         else
00912         {
00913             mtCOVERAGE_TEST_MARKER();
00914         }
00915     }
00916 
00917 #endif /* INCLUDE_vTaskDelayUntil */
00918 /*-----------------------------------------------------------*/
00919 
00920 #if ( INCLUDE_vTaskDelay == 1 )
00921 
00922     void vTaskDelay( const TickType_t xTicksToDelay )
00923     {
00924     TickType_t xTimeToWake;
00925     BaseType_t xAlreadyYielded = pdFALSE;
00926 
00927 
00928         /* A delay time of zero just forces a reschedule. */
00929         if( xTicksToDelay > ( TickType_t ) 0U )
00930         {
00931             configASSERT( uxSchedulerSuspended == 0 );
00932             vTaskSuspendAll();
00933             {
00934                 traceTASK_DELAY();
00935 
00936                 /* A task that is removed from the event list while the
00937                 scheduler is suspended will not get placed in the ready
00938                 list or removed from the blocked list until the scheduler
00939                 is resumed.
00940 
00941                 This task cannot be in an event list as it is the currently
00942                 executing task. */
00943 
00944                 /* Calculate the time to wake - this may overflow but this is
00945                 not a problem. */
00946                 xTimeToWake = xTickCount + xTicksToDelay;
00947 
00948                 /* We must remove ourselves from the ready list before adding
00949                 ourselves to the blocked list as the same list item is used for
00950                 both lists. */
00951                 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
00952                 {
00953                     /* The current task must be in a ready list, so there is
00954                     no need to check, and the port reset macro can be called
00955                     directly. */
00956                     portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
00957                 }
00958                 else
00959                 {
00960                     mtCOVERAGE_TEST_MARKER();
00961                 }
00962                 prvAddCurrentTaskToDelayedList( xTimeToWake );
00963             }
00964             xAlreadyYielded = xTaskResumeAll();
00965         }
00966         else
00967         {
00968             mtCOVERAGE_TEST_MARKER();
00969         }
00970 
00971         /* Force a reschedule if xTaskResumeAll has not already done so, we may
00972         have put ourselves to sleep. */
00973         if( xAlreadyYielded == pdFALSE )
00974         {
00975             portYIELD_WITHIN_API();
00976         }
00977         else
00978         {
00979             mtCOVERAGE_TEST_MARKER();
00980         }
00981     }
00982 
00983 #endif /* INCLUDE_vTaskDelay */
00984 /*-----------------------------------------------------------*/
00985 
00986 #if ( INCLUDE_eTaskGetState == 1 )
00987 
00988     eTaskState eTaskGetState( TaskHandle_t xTask )
00989     {
00990     eTaskState eReturn;
00991     List_t *pxStateList;
00992     const TCB_t * const pxTCB = ( TCB_t * ) xTask;
00993 
00994         configASSERT( pxTCB );
00995 
00996         if( pxTCB == pxCurrentTCB )
00997         {
00998             /* The task calling this function is querying its own state. */
00999             eReturn = eRunning;
01000         }
01001         else
01002         {
01003             taskENTER_CRITICAL();
01004             {
01005                 pxStateList = ( List_t * ) listLIST_ITEM_CONTAINER( &( pxTCB->xGenericListItem ) );
01006             }
01007             taskEXIT_CRITICAL();
01008 
01009             if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) )
01010             {
01011                 /* The task being queried is referenced from one of the Blocked
01012                 lists. */
01013                 eReturn = eBlocked;
01014             }
01015 
01016             #if ( INCLUDE_vTaskSuspend == 1 )
01017                 else if( pxStateList == &xSuspendedTaskList )
01018                 {
01019                     /* The task being queried is referenced from the suspended
01020                     list.  Is it genuinely suspended or is it block
01021                     indefinitely? */
01022                     if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
01023                     {
01024                         eReturn = eSuspended;
01025                     }
01026                     else
01027                     {
01028                         eReturn = eBlocked;
01029                     }
01030                 }
01031             #endif
01032 
01033             #if ( INCLUDE_vTaskDelete == 1 )
01034                 else if( pxStateList == &xTasksWaitingTermination )
01035                 {
01036                     /* The task being queried is referenced from the deleted
01037                     tasks list. */
01038                     eReturn = eDeleted;
01039                 }
01040             #endif
01041 
01042             else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */
01043             {
01044                 /* If the task is not in any other state, it must be in the
01045                 Ready (including pending ready) state. */
01046                 eReturn = eReady;
01047             }
01048         }
01049 
01050         return eReturn;
01051     } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
01052 
01053 #endif /* INCLUDE_eTaskGetState */
01054 /*-----------------------------------------------------------*/
01055 
01056 #if ( INCLUDE_uxTaskPriorityGet == 1 )
01057 
01058     UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask )
01059     {
01060     TCB_t *pxTCB;
01061     UBaseType_t uxReturn;
01062 
01063         taskENTER_CRITICAL();
01064         {
01065             /* If null is passed in here then we are changing the
01066             priority of the calling function. */
01067             pxTCB = prvGetTCBFromHandle( xTask );
01068             uxReturn = pxTCB->uxPriority;
01069         }
01070         taskEXIT_CRITICAL();
01071 
01072         return uxReturn;
01073     }
01074 
01075 #endif /* INCLUDE_uxTaskPriorityGet */
01076 /*-----------------------------------------------------------*/
01077 
01078 #if ( INCLUDE_uxTaskPriorityGet == 1 )
01079 
01080     UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask )
01081     {
01082     TCB_t *pxTCB;
01083     UBaseType_t uxReturn, uxSavedInterruptState;
01084 
01085         /* RTOS ports that support interrupt nesting have the concept of a
01086         maximum system call (or maximum API call) interrupt priority.
01087         Interrupts that are above the maximum system call priority are keep
01088         permanently enabled, even when the RTOS kernel is in a critical section,
01089         but cannot make any calls to FreeRTOS API functions.  If configASSERT()
01090         is defined in FreeRTOSConfig.h then
01091         portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
01092         failure if a FreeRTOS API function is called from an interrupt that has
01093         been assigned a priority above the configured maximum system call
01094         priority.  Only FreeRTOS functions that end in FromISR can be called
01095         from interrupts that have been assigned a priority at or (logically)
01096         below the maximum system call interrupt priority.  FreeRTOS maintains a
01097         separate interrupt safe API to ensure interrupt entry is as fast and as
01098         simple as possible.  More information (albeit Cortex-M specific) is
01099         provided on the following link:
01100         http://www.freertos.org/RTOS-Cortex-M3-M4.html */
01101         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
01102 
01103         uxSavedInterruptState = portSET_INTERRUPT_MASK_FROM_ISR();
01104         {
01105             /* If null is passed in here then it is the priority of the calling
01106             task that is being queried. */
01107             pxTCB = prvGetTCBFromHandle( xTask );
01108             uxReturn = pxTCB->uxPriority;
01109         }
01110         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState );
01111 
01112         return uxReturn;
01113     }
01114 
01115 #endif /* INCLUDE_uxTaskPriorityGet */
01116 /*-----------------------------------------------------------*/
01117 
01118 #if ( INCLUDE_vTaskPrioritySet == 1 )
01119 
01120     void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )
01121     {
01122     TCB_t *pxTCB;
01123     UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;
01124     BaseType_t xYieldRequired = pdFALSE;
01125 
01126         configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
01127 
01128         /* Ensure the new priority is valid. */
01129         if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
01130         {
01131             uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
01132         }
01133         else
01134         {
01135             mtCOVERAGE_TEST_MARKER();
01136         }
01137 
01138         taskENTER_CRITICAL();
01139         {
01140             /* If null is passed in here then it is the priority of the calling
01141             task that is being changed. */
01142             pxTCB = prvGetTCBFromHandle( xTask );
01143 
01144             traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
01145 
01146             #if ( configUSE_MUTEXES == 1 )
01147             {
01148                 uxCurrentBasePriority = pxTCB->uxBasePriority;
01149             }
01150             #else
01151             {
01152                 uxCurrentBasePriority = pxTCB->uxPriority;
01153             }
01154             #endif
01155 
01156             if( uxCurrentBasePriority != uxNewPriority )
01157             {
01158                 /* The priority change may have readied a task of higher
01159                 priority than the calling task. */
01160                 if( uxNewPriority > uxCurrentBasePriority )
01161                 {
01162                     if( pxTCB != pxCurrentTCB )
01163                     {
01164                         /* The priority of a task other than the currently
01165                         running task is being raised.  Is the priority being
01166                         raised above that of the running task? */
01167                         if( uxNewPriority >= pxCurrentTCB->uxPriority )
01168                         {
01169                             xYieldRequired = pdTRUE;
01170                         }
01171                         else
01172                         {
01173                             mtCOVERAGE_TEST_MARKER();
01174                         }
01175                     }
01176                     else
01177                     {
01178                         /* The priority of the running task is being raised,
01179                         but the running task must already be the highest
01180                         priority task able to run so no yield is required. */
01181                     }
01182                 }
01183                 else if( pxTCB == pxCurrentTCB )
01184                 {
01185                     /* Setting the priority of the running task down means
01186                     there may now be another task of higher priority that
01187                     is ready to execute. */
01188                     xYieldRequired = pdTRUE;
01189                 }
01190                 else
01191                 {
01192                     /* Setting the priority of any other task down does not
01193                     require a yield as the running task must be above the
01194                     new priority of the task being modified. */
01195                 }
01196 
01197                 /* Remember the ready list the task might be referenced from
01198                 before its uxPriority member is changed so the
01199                 taskRESET_READY_PRIORITY() macro can function correctly. */
01200                 uxPriorityUsedOnEntry = pxTCB->uxPriority;
01201 
01202                 #if ( configUSE_MUTEXES == 1 )
01203                 {
01204                     /* Only change the priority being used if the task is not
01205                     currently using an inherited priority. */
01206                     if( pxTCB->uxBasePriority == pxTCB->uxPriority )
01207                     {
01208                         pxTCB->uxPriority = uxNewPriority;
01209                     }
01210                     else
01211                     {
01212                         mtCOVERAGE_TEST_MARKER();
01213                     }
01214 
01215                     /* The base priority gets set whatever. */
01216                     pxTCB->uxBasePriority = uxNewPriority;
01217                 }
01218                 #else
01219                 {
01220                     pxTCB->uxPriority = uxNewPriority;
01221                 }
01222                 #endif
01223 
01224                 /* Only reset the event list item value if the value is not
01225                 being used for anything else. */
01226                 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
01227                 {
01228                     listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
01229                 }
01230                 else
01231                 {
01232                     mtCOVERAGE_TEST_MARKER();
01233                 }
01234 
01235                 /* If the task is in the blocked or suspended list we need do
01236                 nothing more than change it's priority variable. However, if
01237                 the task is in a ready list it needs to be removed and placed
01238                 in the list appropriate to its new priority. */
01239                 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
01240                 {
01241                     /* The task is currently in its ready list - remove before adding
01242                     it to it's new ready list.  As we are in a critical section we
01243                     can do this even if the scheduler is suspended. */
01244                     if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
01245                     {
01246                         /* It is known that the task is in its ready list so
01247                         there is no need to check again and the port level
01248                         reset macro can be called directly. */
01249                         portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
01250                     }
01251                     else
01252                     {
01253                         mtCOVERAGE_TEST_MARKER();
01254                     }
01255                     prvAddTaskToReadyList( pxTCB );
01256                 }
01257                 else
01258                 {
01259                     mtCOVERAGE_TEST_MARKER();
01260                 }
01261 
01262                 if( xYieldRequired == pdTRUE )
01263                 {
01264                     taskYIELD_IF_USING_PREEMPTION();
01265                 }
01266                 else
01267                 {
01268                     mtCOVERAGE_TEST_MARKER();
01269                 }
01270 
01271                 /* Remove compiler warning about unused variables when the port
01272                 optimised task selection is not being used. */
01273                 ( void ) uxPriorityUsedOnEntry;
01274             }
01275         }
01276         taskEXIT_CRITICAL();
01277     }
01278 
01279 #endif /* INCLUDE_vTaskPrioritySet */
01280 /*-----------------------------------------------------------*/
01281 
01282 #if ( INCLUDE_vTaskSuspend == 1 )
01283 
01284     void vTaskSuspend( TaskHandle_t xTaskToSuspend )
01285     {
01286     TCB_t *pxTCB;
01287 
01288         taskENTER_CRITICAL();
01289         {
01290             /* If null is passed in here then it is the running task that is
01291             being suspended. */
01292             pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
01293 
01294             traceTASK_SUSPEND( pxTCB );
01295 
01296             /* Remove task from the ready/delayed list and place in the
01297             suspended list. */
01298             if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
01299             {
01300                 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
01301             }
01302             else
01303             {
01304                 mtCOVERAGE_TEST_MARKER();
01305             }
01306 
01307             /* Is the task waiting on an event also? */
01308             if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
01309             {
01310                 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
01311             }
01312             else
01313             {
01314                 mtCOVERAGE_TEST_MARKER();
01315             }
01316 
01317             vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) );
01318         }
01319         taskEXIT_CRITICAL();
01320 
01321         if( pxTCB == pxCurrentTCB )
01322         {
01323             if( xSchedulerRunning != pdFALSE )
01324             {
01325                 /* The current task has just been suspended. */
01326                 configASSERT( uxSchedulerSuspended == 0 );
01327                 portYIELD_WITHIN_API();
01328             }
01329             else
01330             {
01331                 /* The scheduler is not running, but the task that was pointed
01332                 to by pxCurrentTCB has just been suspended and pxCurrentTCB
01333                 must be adjusted to point to a different task. */
01334                 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )
01335                 {
01336                     /* No other tasks are ready, so set pxCurrentTCB back to
01337                     NULL so when the next task is created pxCurrentTCB will
01338                     be set to point to it no matter what its relative priority
01339                     is. */
01340                     pxCurrentTCB = NULL;
01341                 }
01342                 else
01343                 {
01344                     vTaskSwitchContext();
01345                 }
01346             }
01347         }
01348         else
01349         {
01350             if( xSchedulerRunning != pdFALSE )
01351             {
01352                 /* A task other than the currently running task was suspended,
01353                 reset the next expected unblock time in case it referred to the
01354                 task that is now in the Suspended state. */
01355                 taskENTER_CRITICAL();
01356                 {
01357                     prvResetNextTaskUnblockTime();
01358                 }
01359                 taskEXIT_CRITICAL();
01360             }
01361             else
01362             {
01363                 mtCOVERAGE_TEST_MARKER();
01364             }
01365         }
01366     }
01367 
01368 #endif /* INCLUDE_vTaskSuspend */
01369 /*-----------------------------------------------------------*/
01370 
01371 #if ( INCLUDE_vTaskSuspend == 1 )
01372 
01373     static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
01374     {
01375     BaseType_t xReturn = pdFALSE;
01376     const TCB_t * const pxTCB = ( TCB_t * ) xTask;
01377 
01378         /* Accesses xPendingReadyList so must be called from a critical
01379         section. */
01380 
01381         /* It does not make sense to check if the calling task is suspended. */
01382         configASSERT( xTask );
01383 
01384         /* Is the task being resumed actually in the suspended list? */
01385         if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
01386         {
01387             /* Has the task already been resumed from within an ISR? */
01388             if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
01389             {
01390                 /* Is it in the suspended list because it is in the Suspended
01391                 state, or because is is blocked with no timeout? */
01392                 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )
01393                 {
01394                     xReturn = pdTRUE;
01395                 }
01396                 else
01397                 {
01398                     mtCOVERAGE_TEST_MARKER();
01399                 }
01400             }
01401             else
01402             {
01403                 mtCOVERAGE_TEST_MARKER();
01404             }
01405         }
01406         else
01407         {
01408             mtCOVERAGE_TEST_MARKER();
01409         }
01410 
01411         return xReturn;
01412     } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
01413 
01414 #endif /* INCLUDE_vTaskSuspend */
01415 /*-----------------------------------------------------------*/
01416 
01417 #if ( INCLUDE_vTaskSuspend == 1 )
01418 
01419     void vTaskResume( TaskHandle_t xTaskToResume )
01420     {
01421     TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
01422 
01423         /* It does not make sense to resume the calling task. */
01424         configASSERT( xTaskToResume );
01425 
01426         /* The parameter cannot be NULL as it is impossible to resume the
01427         currently executing task. */
01428         if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
01429         {
01430             taskENTER_CRITICAL();
01431             {
01432                 if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE )
01433                 {
01434                     traceTASK_RESUME( pxTCB );
01435 
01436                     /* As we are in a critical section we can access the ready
01437                     lists even if the scheduler is suspended. */
01438                     ( void ) uxListRemove(  &( pxTCB->xGenericListItem ) );
01439                     prvAddTaskToReadyList( pxTCB );
01440 
01441                     /* We may have just resumed a higher priority task. */
01442                     if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
01443                     {
01444                         /* This yield may not cause the task just resumed to run,
01445                         but will leave the lists in the correct state for the
01446                         next yield. */
01447                         taskYIELD_IF_USING_PREEMPTION();
01448                     }
01449                     else
01450                     {
01451                         mtCOVERAGE_TEST_MARKER();
01452                     }
01453                 }
01454                 else
01455                 {
01456                     mtCOVERAGE_TEST_MARKER();
01457                 }
01458             }
01459             taskEXIT_CRITICAL();
01460         }
01461         else
01462         {
01463             mtCOVERAGE_TEST_MARKER();
01464         }
01465     }
01466 
01467 #endif /* INCLUDE_vTaskSuspend */
01468 
01469 /*-----------------------------------------------------------*/
01470 
01471 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
01472 
01473     BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
01474     {
01475     BaseType_t xYieldRequired = pdFALSE;
01476     TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
01477     UBaseType_t uxSavedInterruptStatus;
01478 
01479         configASSERT( xTaskToResume );
01480 
01481         /* RTOS ports that support interrupt nesting have the concept of a
01482         maximum system call (or maximum API call) interrupt priority.
01483         Interrupts that are above the maximum system call priority are keep
01484         permanently enabled, even when the RTOS kernel is in a critical section,
01485         but cannot make any calls to FreeRTOS API functions.  If configASSERT()
01486         is defined in FreeRTOSConfig.h then
01487         portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
01488         failure if a FreeRTOS API function is called from an interrupt that has
01489         been assigned a priority above the configured maximum system call
01490         priority.  Only FreeRTOS functions that end in FromISR can be called
01491         from interrupts that have been assigned a priority at or (logically)
01492         below the maximum system call interrupt priority.  FreeRTOS maintains a
01493         separate interrupt safe API to ensure interrupt entry is as fast and as
01494         simple as possible.  More information (albeit Cortex-M specific) is
01495         provided on the following link:
01496         http://www.freertos.org/RTOS-Cortex-M3-M4.html */
01497         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
01498 
01499         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
01500         {
01501             if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE )
01502             {
01503                 traceTASK_RESUME_FROM_ISR( pxTCB );
01504 
01505                 /* Check the ready lists can be accessed. */
01506                 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
01507                 {
01508                     /* Ready lists can be accessed so move the task from the
01509                     suspended list to the ready list directly. */
01510                     if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
01511                     {
01512                         xYieldRequired = pdTRUE;
01513                     }
01514                     else
01515                     {
01516                         mtCOVERAGE_TEST_MARKER();
01517                     }
01518 
01519                     ( void ) uxListRemove(  &( pxTCB->xGenericListItem ) );
01520                     prvAddTaskToReadyList( pxTCB );
01521                 }
01522                 else
01523                 {
01524                     /* The delayed or ready lists cannot be accessed so the task
01525                     is held in the pending ready list until the scheduler is
01526                     unsuspended. */
01527                     vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
01528                 }
01529             }
01530             else
01531             {
01532                 mtCOVERAGE_TEST_MARKER();
01533             }
01534         }
01535         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
01536 
01537         return xYieldRequired;
01538     }
01539 
01540 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
01541 /*-----------------------------------------------------------*/
01542 
01543 void vTaskStartScheduler( void )
01544 {
01545 BaseType_t xReturn;
01546 
01547     /* Add the idle task at the lowest priority. */
01548     #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
01549     {
01550         /* Create the idle task, storing its handle in xIdleTaskHandle so it can
01551         be returned by the xTaskGetIdleTaskHandle() function. */
01552         xReturn = xTaskCreate( prvIdleTask, "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. */
01553     }
01554     #else
01555     {
01556         /* Create the idle task without storing its handle. */
01557         xReturn = xTaskCreate( prvIdleTask, "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. */
01558     }
01559     #endif /* INCLUDE_xTaskGetIdleTaskHandle */
01560 
01561     #if ( configUSE_TIMERS == 1 )
01562     {
01563         if( xReturn == pdPASS )
01564         {
01565             xReturn = xTimerCreateTimerTask();
01566         }
01567         else
01568         {
01569             mtCOVERAGE_TEST_MARKER();
01570         }
01571     }
01572     #endif /* configUSE_TIMERS */
01573 
01574     if( xReturn == pdPASS )
01575     {
01576         /* Interrupts are turned off here, to ensure a tick does not occur
01577         before or during the call to xPortStartScheduler().  The stacks of
01578         the created tasks contain a status word with interrupts switched on
01579         so interrupts will automatically get re-enabled when the first task
01580         starts to run. */
01581         portDISABLE_INTERRUPTS();
01582 
01583         #if ( configUSE_NEWLIB_REENTRANT == 1 )
01584         {
01585             /* Switch Newlib's _impure_ptr variable to point to the _reent
01586             structure specific to the task that will run first. */
01587             _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
01588         }
01589         #endif /* configUSE_NEWLIB_REENTRANT */
01590 
01591         xSchedulerRunning = pdTRUE;
01592         xTickCount = ( TickType_t ) 0U;
01593 
01594         /* If configGENERATE_RUN_TIME_STATS is defined then the following
01595         macro must be defined to configure the timer/counter used to generate
01596         the run time counter time base. */
01597         portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
01598 
01599         /* Setting up the timer tick is hardware specific and thus in the
01600         portable interface. */
01601         if( xPortStartScheduler() != pdFALSE )
01602         {
01603             /* Should not reach here as if the scheduler is running the
01604             function will not return. */
01605         }
01606         else
01607         {
01608             /* Should only reach here if a task calls xTaskEndScheduler(). */
01609         }
01610     }
01611     else
01612     {
01613         /* This line will only be reached if the kernel could not be started,
01614         because there was not enough FreeRTOS heap to create the idle task
01615         or the timer task. */
01616         configASSERT( xReturn );
01617     }
01618 }
01619 /*-----------------------------------------------------------*/
01620 
01621 void vTaskEndScheduler( void )
01622 {
01623     /* Stop the scheduler interrupts and call the portable scheduler end
01624     routine so the original ISRs can be restored if necessary.  The port
01625     layer must ensure interrupts enable bit is left in the correct state. */
01626     portDISABLE_INTERRUPTS();
01627     xSchedulerRunning = pdFALSE;
01628     vPortEndScheduler();
01629 }
01630 /*----------------------------------------------------------*/
01631 
01632 void vTaskSuspendAll( void )
01633 {
01634     /* A critical section is not required as the variable is of type
01635     BaseType_t.  Please read Richard Barry's reply in the following link to a
01636     post in the FreeRTOS support forum before reporting this as a bug! -
01637     http://goo.gl/wu4acr */
01638     ++uxSchedulerSuspended;
01639 }
01640 /*----------------------------------------------------------*/
01641 
01642 #if ( configUSE_TICKLESS_IDLE != 0 )
01643 
01644     static TickType_t prvGetExpectedIdleTime( void )
01645     {
01646     TickType_t xReturn;
01647 
01648         if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
01649         {
01650             xReturn = 0;
01651         }
01652         else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
01653         {
01654             /* There are other idle priority tasks in the ready state.  If
01655             time slicing is used then the very next tick interrupt must be
01656             processed. */
01657             xReturn = 0;
01658         }
01659         else
01660         {
01661             xReturn = xNextTaskUnblockTime - xTickCount;
01662         }
01663 
01664         return xReturn;
01665     }
01666 
01667 #endif /* configUSE_TICKLESS_IDLE */
01668 /*----------------------------------------------------------*/
01669 
01670 BaseType_t xTaskResumeAll( void )
01671 {
01672 TCB_t *pxTCB;
01673 BaseType_t xAlreadyYielded = pdFALSE;
01674 
01675     /* If uxSchedulerSuspended is zero then this function does not match a
01676     previous call to vTaskSuspendAll(). */
01677     configASSERT( uxSchedulerSuspended );
01678 
01679     /* It is possible that an ISR caused a task to be removed from an event
01680     list while the scheduler was suspended.  If this was the case then the
01681     removed task will have been added to the xPendingReadyList.  Once the
01682     scheduler has been resumed it is safe to move all the pending ready
01683     tasks from this list into their appropriate ready list. */
01684     taskENTER_CRITICAL();
01685     {
01686         --uxSchedulerSuspended;
01687 
01688         if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
01689         {
01690             if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )
01691             {
01692                 /* Move any readied tasks from the pending list into the
01693                 appropriate ready list. */
01694                 while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
01695                 {
01696                     pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );
01697                     ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
01698                     ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
01699                     prvAddTaskToReadyList( pxTCB );
01700 
01701                     /* If the moved task has a priority higher than the current
01702                     task then a yield must be performed. */
01703                     if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
01704                     {
01705                         xYieldPending = pdTRUE;
01706                     }
01707                     else
01708                     {
01709                         mtCOVERAGE_TEST_MARKER();
01710                     }
01711                 }
01712 
01713                 /* If any ticks occurred while the scheduler was suspended then
01714                 they should be processed now.  This ensures the tick count does
01715                 not slip, and that any delayed tasks are resumed at the correct
01716                 time. */
01717                 if( uxPendedTicks > ( UBaseType_t ) 0U )
01718                 {
01719                     while( uxPendedTicks > ( UBaseType_t ) 0U )
01720                     {
01721                         if( xTaskIncrementTick() != pdFALSE )
01722                         {
01723                             xYieldPending = pdTRUE;
01724                         }
01725                         else
01726                         {
01727                             mtCOVERAGE_TEST_MARKER();
01728                         }
01729                         --uxPendedTicks;
01730                     }
01731                 }
01732                 else
01733                 {
01734                     mtCOVERAGE_TEST_MARKER();
01735                 }
01736 
01737                 if( xYieldPending == pdTRUE )
01738                 {
01739                     #if( configUSE_PREEMPTION != 0 )
01740                     {
01741                         xAlreadyYielded = pdTRUE;
01742                     }
01743                     #endif
01744                     taskYIELD_IF_USING_PREEMPTION();
01745                 }
01746                 else
01747                 {
01748                     mtCOVERAGE_TEST_MARKER();
01749                 }
01750             }
01751         }
01752         else
01753         {
01754             mtCOVERAGE_TEST_MARKER();
01755         }
01756     }
01757     taskEXIT_CRITICAL();
01758 
01759     return xAlreadyYielded;
01760 }
01761 /*-----------------------------------------------------------*/
01762 
01763 TickType_t xTaskGetTickCount( void )
01764 {
01765 TickType_t xTicks;
01766 
01767     /* Critical section required if running on a 16 bit processor. */
01768     portTICK_TYPE_ENTER_CRITICAL();
01769     {
01770         xTicks = xTickCount;
01771     }
01772     portTICK_TYPE_EXIT_CRITICAL();
01773 
01774     return xTicks;
01775 }
01776 /*-----------------------------------------------------------*/
01777 
01778 TickType_t xTaskGetTickCountFromISR( void )
01779 {
01780 TickType_t xReturn;
01781 UBaseType_t uxSavedInterruptStatus;
01782 
01783     /* RTOS ports that support interrupt nesting have the concept of a maximum
01784     system call (or maximum API call) interrupt priority.  Interrupts that are
01785     above the maximum system call priority are kept permanently enabled, even
01786     when the RTOS kernel is in a critical section, but cannot make any calls to
01787     FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h
01788     then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
01789     failure if a FreeRTOS API function is called from an interrupt that has been
01790     assigned a priority above the configured maximum system call priority.
01791     Only FreeRTOS functions that end in FromISR can be called from interrupts
01792     that have been assigned a priority at or (logically) below the maximum
01793     system call interrupt priority.  FreeRTOS maintains a separate interrupt
01794     safe API to ensure interrupt entry is as fast and as simple as possible.
01795     More information (albeit Cortex-M specific) is provided on the following
01796     link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
01797     portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
01798 
01799     uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR();
01800     {
01801         xReturn = xTickCount;
01802     }
01803     portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
01804 
01805     return xReturn;
01806 }
01807 /*-----------------------------------------------------------*/
01808 
01809 UBaseType_t uxTaskGetNumberOfTasks( void )
01810 {
01811     /* A critical section is not required because the variables are of type
01812     BaseType_t. */
01813     return uxCurrentNumberOfTasks;
01814 }
01815 /*-----------------------------------------------------------*/
01816 
01817 #if ( INCLUDE_pcTaskGetTaskName == 1 )
01818 
01819     char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
01820     {
01821     TCB_t *pxTCB;
01822 
01823         /* If null is passed in here then the name of the calling task is being queried. */
01824         pxTCB = prvGetTCBFromHandle( xTaskToQuery );
01825         configASSERT( pxTCB );
01826         return &( pxTCB->pcTaskName[ 0 ] );
01827     }
01828 
01829 #endif /* INCLUDE_pcTaskGetTaskName */
01830 /*-----------------------------------------------------------*/
01831 
01832 #if ( configUSE_TRACE_FACILITY == 1 )
01833 
01834     UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime )
01835     {
01836     UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
01837 
01838         vTaskSuspendAll();
01839         {
01840             /* Is there a space in the array for each task in the system? */
01841             if( uxArraySize >= uxCurrentNumberOfTasks )
01842             {
01843                 /* Fill in an TaskStatus_t structure with information on each
01844                 task in the Ready state. */
01845                 do
01846                 {
01847                     uxQueue--;
01848                     uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
01849 
01850                 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
01851 
01852                 /* Fill in an TaskStatus_t structure with information on each
01853                 task in the Blocked state. */
01854                 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );
01855                 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );
01856 
01857                 #if( INCLUDE_vTaskDelete == 1 )
01858                 {
01859                     /* Fill in an TaskStatus_t structure with information on
01860                     each task that has been deleted but not yet cleaned up. */
01861                     uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
01862                 }
01863                 #endif
01864 
01865                 #if ( INCLUDE_vTaskSuspend == 1 )
01866                 {
01867                     /* Fill in an TaskStatus_t structure with information on
01868                     each task in the Suspended state. */
01869                     uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
01870                 }
01871                 #endif
01872 
01873                 #if ( configGENERATE_RUN_TIME_STATS == 1)
01874                 {
01875                     if( pulTotalRunTime != NULL )
01876                     {
01877                         #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
01878                             portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
01879                         #else
01880                             *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
01881                         #endif
01882                     }
01883                 }
01884                 #else
01885                 {
01886                     if( pulTotalRunTime != NULL )
01887                     {
01888                         *pulTotalRunTime = 0;
01889                     }
01890                 }
01891                 #endif
01892             }
01893             else
01894             {
01895                 mtCOVERAGE_TEST_MARKER();
01896             }
01897         }
01898         ( void ) xTaskResumeAll();
01899 
01900         return uxTask;
01901     }
01902 
01903 #endif /* configUSE_TRACE_FACILITY */
01904 /*----------------------------------------------------------*/
01905 
01906 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
01907 
01908     TaskHandle_t xTaskGetIdleTaskHandle( void )
01909     {
01910         /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
01911         started, then xIdleTaskHandle will be NULL. */
01912         configASSERT( ( xIdleTaskHandle != NULL ) );
01913         return xIdleTaskHandle;
01914     }
01915 
01916 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
01917 /*----------------------------------------------------------*/
01918 
01919 /* This conditional compilation should use inequality to 0, not equality to 1.
01920 This is to ensure vTaskStepTick() is available when user defined low power mode
01921 implementations require configUSE_TICKLESS_IDLE to be set to a value other than
01922 1. */
01923 #if ( configUSE_TICKLESS_IDLE != 0 )
01924 
01925     void vTaskStepTick( const TickType_t xTicksToJump )
01926     {
01927         /* Correct the tick count value after a period during which the tick
01928         was suppressed.  Note this does *not* call the tick hook function for
01929         each stepped tick. */
01930         configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
01931         xTickCount += xTicksToJump;
01932         traceINCREASE_TICK_COUNT( xTicksToJump );
01933     }
01934 
01935 #endif /* configUSE_TICKLESS_IDLE */
01936 /*----------------------------------------------------------*/
01937 
01938 BaseType_t xTaskIncrementTick( void )
01939 {
01940 TCB_t * pxTCB;
01941 TickType_t xItemValue;
01942 BaseType_t xSwitchRequired = pdFALSE;
01943 
01944     /* Called by the portable layer each time a tick interrupt occurs.
01945     Increments the tick then checks to see if the new tick value will cause any
01946     tasks to be unblocked. */
01947     traceTASK_INCREMENT_TICK( xTickCount );
01948     if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
01949     {
01950         /* Increment the RTOS tick, switching the delayed and overflowed
01951         delayed lists if it wraps to 0. */
01952         ++xTickCount;
01953 
01954         {
01955             /* Minor optimisation.  The tick count cannot change in this
01956             block. */
01957             const TickType_t xConstTickCount = xTickCount;
01958 
01959             if( xConstTickCount == ( TickType_t ) 0U )
01960             {
01961                 taskSWITCH_DELAYED_LISTS();
01962             }
01963             else
01964             {
01965                 mtCOVERAGE_TEST_MARKER();
01966             }
01967 
01968             /* See if this tick has made a timeout expire.  Tasks are stored in
01969             the queue in the order of their wake time - meaning once one task
01970             has been found whose block time has not expired there is no need to
01971             look any further down the list. */
01972             if( xConstTickCount >= xNextTaskUnblockTime )
01973             {
01974                 for( ;; )
01975                 {
01976                     if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
01977                     {
01978                         /* The delayed list is empty.  Set xNextTaskUnblockTime
01979                         to the maximum possible value so it is extremely
01980                         unlikely that the
01981                         if( xTickCount >= xNextTaskUnblockTime ) test will pass
01982                         next time through. */
01983                         xNextTaskUnblockTime = portMAX_DELAY;
01984                         break;
01985                     }
01986                     else
01987                     {
01988                         /* The delayed list is not empty, get the value of the
01989                         item at the head of the delayed list.  This is the time
01990                         at which the task at the head of the delayed list must
01991                         be removed from the Blocked state. */
01992                         pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
01993                         xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
01994 
01995                         if( xConstTickCount < xItemValue )
01996                         {
01997                             /* It is not time to unblock this item yet, but the
01998                             item value is the time at which the task at the head
01999                             of the blocked list must be removed from the Blocked
02000                             state - so record the item value in
02001                             xNextTaskUnblockTime. */
02002                             xNextTaskUnblockTime = xItemValue;
02003                             break;
02004                         }
02005                         else
02006                         {
02007                             mtCOVERAGE_TEST_MARKER();
02008                         }
02009 
02010                         /* It is time to remove the item from the Blocked state. */
02011                         ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
02012 
02013                         /* Is the task waiting on an event also?  If so remove
02014                         it from the event list. */
02015                         if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
02016                         {
02017                             ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
02018                         }
02019                         else
02020                         {
02021                             mtCOVERAGE_TEST_MARKER();
02022                         }
02023 
02024                         /* Place the unblocked task into the appropriate ready
02025                         list. */
02026                         prvAddTaskToReadyList( pxTCB );
02027 
02028                         /* A task being unblocked cannot cause an immediate
02029                         context switch if preemption is turned off. */
02030                         #if (  configUSE_PREEMPTION == 1 )
02031                         {
02032                             /* Preemption is on, but a context switch should
02033                             only be performed if the unblocked task has a
02034                             priority that is equal to or higher than the
02035                             currently executing task. */
02036                             if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
02037                             {
02038                                 xSwitchRequired = pdTRUE;
02039                             }
02040                             else
02041                             {
02042                                 mtCOVERAGE_TEST_MARKER();
02043                             }
02044                         }
02045                         #endif /* configUSE_PREEMPTION */
02046                     }
02047                 }
02048             }
02049         }
02050 
02051         /* Tasks of equal priority to the currently running task will share
02052         processing time (time slice) if preemption is on, and the application
02053         writer has not explicitly turned time slicing off. */
02054         #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
02055         {
02056             if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )
02057             {
02058                 xSwitchRequired = pdTRUE;
02059             }
02060             else
02061             {
02062                 mtCOVERAGE_TEST_MARKER();
02063             }
02064         }
02065         #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
02066 
02067         #if ( configUSE_TICK_HOOK == 1 )
02068         {
02069             /* Guard against the tick hook being called when the pended tick
02070             count is being unwound (when the scheduler is being unlocked). */
02071             if( uxPendedTicks == ( UBaseType_t ) 0U )
02072             {
02073                 vApplicationTickHook();
02074             }
02075             else
02076             {
02077                 mtCOVERAGE_TEST_MARKER();
02078             }
02079         }
02080         #endif /* configUSE_TICK_HOOK */
02081     }
02082     else
02083     {
02084         ++uxPendedTicks;
02085 
02086         /* The tick hook gets called at regular intervals, even if the
02087         scheduler is locked. */
02088         #if ( configUSE_TICK_HOOK == 1 )
02089         {
02090             vApplicationTickHook();
02091         }
02092         #endif
02093     }
02094 
02095     #if ( configUSE_PREEMPTION == 1 )
02096     {
02097         if( xYieldPending != pdFALSE )
02098         {
02099             xSwitchRequired = pdTRUE;
02100         }
02101         else
02102         {
02103             mtCOVERAGE_TEST_MARKER();
02104         }
02105     }
02106     #endif /* configUSE_PREEMPTION */
02107 
02108     return xSwitchRequired;
02109 }
02110 /*-----------------------------------------------------------*/
02111 
02112 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
02113 
02114     void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction )
02115     {
02116     TCB_t *xTCB;
02117 
02118         /* If xTask is NULL then it is the task hook of the calling task that is
02119         getting set. */
02120         if( xTask == NULL )
02121         {
02122             xTCB = ( TCB_t * ) pxCurrentTCB;
02123         }
02124         else
02125         {
02126             xTCB = ( TCB_t * ) xTask;
02127         }
02128 
02129         /* Save the hook function in the TCB.  A critical section is required as
02130         the value can be accessed from an interrupt. */
02131         taskENTER_CRITICAL();
02132             xTCB->pxTaskTag = pxHookFunction;
02133         taskEXIT_CRITICAL();
02134     }
02135 
02136 #endif /* configUSE_APPLICATION_TASK_TAG */
02137 /*-----------------------------------------------------------*/
02138 
02139 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
02140 
02141     TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
02142     {
02143     TCB_t *xTCB;
02144     TaskHookFunction_t xReturn;
02145 
02146         /* If xTask is NULL then we are setting our own task hook. */
02147         if( xTask == NULL )
02148         {
02149             xTCB = ( TCB_t * ) pxCurrentTCB;
02150         }
02151         else
02152         {
02153             xTCB = ( TCB_t * ) xTask;
02154         }
02155 
02156         /* Save the hook function in the TCB.  A critical section is required as
02157         the value can be accessed from an interrupt. */
02158         taskENTER_CRITICAL();
02159         {
02160             xReturn = xTCB->pxTaskTag;
02161         }
02162         taskEXIT_CRITICAL();
02163 
02164         return xReturn;
02165     }
02166 
02167 #endif /* configUSE_APPLICATION_TASK_TAG */
02168 /*-----------------------------------------------------------*/
02169 
02170 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
02171 
02172     BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter )
02173     {
02174     TCB_t *xTCB;
02175     BaseType_t xReturn;
02176 
02177         /* If xTask is NULL then we are calling our own task hook. */
02178         if( xTask == NULL )
02179         {
02180             xTCB = ( TCB_t * ) pxCurrentTCB;
02181         }
02182         else
02183         {
02184             xTCB = ( TCB_t * ) xTask;
02185         }
02186 
02187         if( xTCB->pxTaskTag != NULL )
02188         {
02189             xReturn = xTCB->pxTaskTag( pvParameter );
02190         }
02191         else
02192         {
02193             xReturn = pdFAIL;
02194         }
02195 
02196         return xReturn;
02197     }
02198 
02199 #endif /* configUSE_APPLICATION_TASK_TAG */
02200 /*-----------------------------------------------------------*/
02201 
02202 void vTaskSwitchContext( void )
02203 {
02204     if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )
02205     {
02206         /* The scheduler is currently suspended - do not allow a context
02207         switch. */
02208         xYieldPending = pdTRUE;
02209     }
02210     else
02211     {
02212         xYieldPending = pdFALSE;
02213         traceTASK_SWITCHED_OUT();
02214 
02215         #if ( configGENERATE_RUN_TIME_STATS == 1 )
02216         {
02217                 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
02218                     portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
02219                 #else
02220                     ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
02221                 #endif
02222 
02223                 /* Add the amount of time the task has been running to the
02224                 accumulated time so far.  The time the task started running was
02225                 stored in ulTaskSwitchedInTime.  Note that there is no overflow
02226                 protection here so count values are only valid until the timer
02227                 overflows.  The guard against negative values is to protect
02228                 against suspect run time stat counter implementations - which
02229                 are provided by the application, not the kernel. */
02230                 if( ulTotalRunTime > ulTaskSwitchedInTime )
02231                 {
02232                     pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
02233                 }
02234                 else
02235                 {
02236                     mtCOVERAGE_TEST_MARKER();
02237                 }
02238                 ulTaskSwitchedInTime = ulTotalRunTime;
02239         }
02240         #endif /* configGENERATE_RUN_TIME_STATS */
02241 
02242         /* Check for stack overflow, if configured. */
02243         taskFIRST_CHECK_FOR_STACK_OVERFLOW();
02244         taskSECOND_CHECK_FOR_STACK_OVERFLOW();
02245 
02246         /* Select a new task to run using either the generic C or port
02247         optimised asm code. */
02248         taskSELECT_HIGHEST_PRIORITY_TASK();
02249         traceTASK_SWITCHED_IN();
02250 
02251         #if ( configUSE_NEWLIB_REENTRANT == 1 )
02252         {
02253             /* Switch Newlib's _impure_ptr variable to point to the _reent
02254             structure specific to this task. */
02255             _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
02256         }
02257         #endif /* configUSE_NEWLIB_REENTRANT */
02258     }
02259 }
02260 /*-----------------------------------------------------------*/
02261 
02262 void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )
02263 {
02264 TickType_t xTimeToWake;
02265 
02266     configASSERT( pxEventList );
02267 
02268     /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
02269     SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
02270 
02271     /* Place the event list item of the TCB in the appropriate event list.
02272     This is placed in the list in priority order so the highest priority task
02273     is the first to be woken by the event.  The queue that contains the event
02274     list is locked, preventing simultaneous access from interrupts. */
02275     vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
02276 
02277     /* The task must be removed from from the ready list before it is added to
02278     the blocked list as the same list item is used for both lists.  Exclusive
02279     access to the ready lists guaranteed because the scheduler is locked. */
02280     if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
02281     {
02282         /* The current task must be in a ready list, so there is no need to
02283         check, and the port reset macro can be called directly. */
02284         portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
02285     }
02286     else
02287     {
02288         mtCOVERAGE_TEST_MARKER();
02289     }
02290 
02291     #if ( INCLUDE_vTaskSuspend == 1 )
02292     {
02293         if( xTicksToWait == portMAX_DELAY )
02294         {
02295             /* Add the task to the suspended task list instead of a delayed task
02296             list to ensure the task is not woken by a timing event.  It will
02297             block indefinitely. */
02298             vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
02299         }
02300         else
02301         {
02302             /* Calculate the time at which the task should be woken if the event
02303             does not occur.  This may overflow but this doesn't matter, the
02304             scheduler will handle it. */
02305             xTimeToWake = xTickCount + xTicksToWait;
02306             prvAddCurrentTaskToDelayedList( xTimeToWake );
02307         }
02308     }
02309     #else /* INCLUDE_vTaskSuspend */
02310     {
02311             /* Calculate the time at which the task should be woken if the event does
02312             not occur.  This may overflow but this doesn't matter, the scheduler
02313             will handle it. */
02314             xTimeToWake = xTickCount + xTicksToWait;
02315             prvAddCurrentTaskToDelayedList( xTimeToWake );
02316     }
02317     #endif /* INCLUDE_vTaskSuspend */
02318 }
02319 /*-----------------------------------------------------------*/
02320 
02321 void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait )
02322 {
02323 TickType_t xTimeToWake;
02324 
02325     configASSERT( pxEventList );
02326 
02327     /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by
02328     the event groups implementation. */
02329     configASSERT( uxSchedulerSuspended != 0 );
02330 
02331     /* Store the item value in the event list item.  It is safe to access the
02332     event list item here as interrupts won't access the event list item of a
02333     task that is not in the Blocked state. */
02334     listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
02335 
02336     /* Place the event list item of the TCB at the end of the appropriate event
02337     list.  It is safe to access the event list here because it is part of an
02338     event group implementation - and interrupts don't access event groups
02339     directly (instead they access them indirectly by pending function calls to
02340     the task level). */
02341     vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
02342 
02343     /* The task must be removed from the ready list before it is added to the
02344     blocked list.  Exclusive access can be assured to the ready list as the
02345     scheduler is locked. */
02346     if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
02347     {
02348         /* The current task must be in a ready list, so there is no need to
02349         check, and the port reset macro can be called directly. */
02350         portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
02351     }
02352     else
02353     {
02354         mtCOVERAGE_TEST_MARKER();
02355     }
02356 
02357     #if ( INCLUDE_vTaskSuspend == 1 )
02358     {
02359         if( xTicksToWait == portMAX_DELAY )
02360         {
02361             /* Add the task to the suspended task list instead of a delayed task
02362             list to ensure it is not woken by a timing event.  It will block
02363             indefinitely. */
02364             vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
02365         }
02366         else
02367         {
02368             /* Calculate the time at which the task should be woken if the event
02369             does not occur.  This may overflow but this doesn't matter, the
02370             kernel will manage it correctly. */
02371             xTimeToWake = xTickCount + xTicksToWait;
02372             prvAddCurrentTaskToDelayedList( xTimeToWake );
02373         }
02374     }
02375     #else /* INCLUDE_vTaskSuspend */
02376     {
02377             /* Calculate the time at which the task should be woken if the event does
02378             not occur.  This may overflow but this doesn't matter, the kernel
02379             will manage it correctly. */
02380             xTimeToWake = xTickCount + xTicksToWait;
02381             prvAddCurrentTaskToDelayedList( xTimeToWake );
02382     }
02383     #endif /* INCLUDE_vTaskSuspend */
02384 }
02385 /*-----------------------------------------------------------*/
02386 
02387 #if configUSE_TIMERS == 1
02388 
02389     void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait )
02390     {
02391     TickType_t xTimeToWake;
02392 
02393         configASSERT( pxEventList );
02394 
02395         /* This function should not be called by application code hence the
02396         'Restricted' in its name.  It is not part of the public API.  It is
02397         designed for use by kernel code, and has special calling requirements -
02398         it should be called with the scheduler suspended. */
02399 
02400 
02401         /* Place the event list item of the TCB in the appropriate event list.
02402         In this case it is assume that this is the only task that is going to
02403         be waiting on this event list, so the faster vListInsertEnd() function
02404         can be used in place of vListInsert. */
02405         vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
02406 
02407         /* We must remove this task from the ready list before adding it to the
02408         blocked list as the same list item is used for both lists.  This
02409         function is called with the scheduler locked so interrupts will not
02410         access the lists at the same time. */
02411         if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
02412         {
02413             /* The current task must be in a ready list, so there is no need to
02414             check, and the port reset macro can be called directly. */
02415             portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
02416         }
02417         else
02418         {
02419             mtCOVERAGE_TEST_MARKER();
02420         }
02421 
02422         /* Calculate the time at which the task should be woken if the event does
02423         not occur.  This may overflow but this doesn't matter. */
02424         xTimeToWake = xTickCount + xTicksToWait;
02425 
02426         traceTASK_DELAY_UNTIL();
02427         prvAddCurrentTaskToDelayedList( xTimeToWake );
02428     }
02429 
02430 #endif /* configUSE_TIMERS */
02431 /*-----------------------------------------------------------*/
02432 
02433 BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
02434 {
02435 TCB_t *pxUnblockedTCB;
02436 BaseType_t xReturn;
02437 
02438     /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION.  It can also be
02439     called from a critical section within an ISR. */
02440 
02441     /* The event list is sorted in priority order, so the first in the list can
02442     be removed as it is known to be the highest priority.  Remove the TCB from
02443     the delayed list, and add it to the ready list.
02444 
02445     If an event is for a queue that is locked then this function will never
02446     get called - the lock count on the queue will get modified instead.  This
02447     means exclusive access to the event list is guaranteed here.
02448 
02449     This function assumes that a check has already been made to ensure that
02450     pxEventList is not empty. */
02451     pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
02452     configASSERT( pxUnblockedTCB );
02453     ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
02454 
02455     if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
02456     {
02457         ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
02458         prvAddTaskToReadyList( pxUnblockedTCB );
02459     }
02460     else
02461     {
02462         /* The delayed and ready lists cannot be accessed, so hold this task
02463         pending until the scheduler is resumed. */
02464         vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
02465     }
02466 
02467     if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
02468     {
02469         /* Return true if the task removed from the event list has a higher
02470         priority than the calling task.  This allows the calling task to know if
02471         it should force a context switch now. */
02472         xReturn = pdTRUE;
02473 
02474         /* Mark that a yield is pending in case the user is not using the
02475         "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
02476         xYieldPending = pdTRUE;
02477     }
02478     else
02479     {
02480         xReturn = pdFALSE;
02481     }
02482 
02483     #if( configUSE_TICKLESS_IDLE == 1 )
02484     {
02485         /* If a task is blocked on a kernel object then xNextTaskUnblockTime
02486         might be set to the blocked task's time out time.  If the task is
02487         unblocked for a reason other than a timeout xNextTaskUnblockTime is
02488         normally left unchanged, because it is automatically get reset to a new
02489         value when the tick count equals xNextTaskUnblockTime.  However if
02490         tickless idling is used it might be more important to enter sleep mode
02491         at the earliest possible time - so reset xNextTaskUnblockTime here to
02492         ensure it is updated at the earliest possible time. */
02493         prvResetNextTaskUnblockTime();
02494     }
02495     #endif
02496 
02497     return xReturn;
02498 }
02499 /*-----------------------------------------------------------*/
02500 
02501 BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )
02502 {
02503 TCB_t *pxUnblockedTCB;
02504 BaseType_t xReturn;
02505 
02506     /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by
02507     the event flags implementation. */
02508     configASSERT( uxSchedulerSuspended != pdFALSE );
02509 
02510     /* Store the new item value in the event list. */
02511     listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
02512 
02513     /* Remove the event list form the event flag.  Interrupts do not access
02514     event flags. */
02515     pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem );
02516     configASSERT( pxUnblockedTCB );
02517     ( void ) uxListRemove( pxEventListItem );
02518 
02519     /* Remove the task from the delayed list and add it to the ready list.  The
02520     scheduler is suspended so interrupts will not be accessing the ready
02521     lists. */
02522     ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
02523     prvAddTaskToReadyList( pxUnblockedTCB );
02524 
02525     if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
02526     {
02527         /* Return true if the task removed from the event list has
02528         a higher priority than the calling task.  This allows
02529         the calling task to know if it should force a context
02530         switch now. */
02531         xReturn = pdTRUE;
02532 
02533         /* Mark that a yield is pending in case the user is not using the
02534         "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
02535         xYieldPending = pdTRUE;
02536     }
02537     else
02538     {
02539         xReturn = pdFALSE;
02540     }
02541 
02542     return xReturn;
02543 }
02544 /*-----------------------------------------------------------*/
02545 
02546 void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
02547 {
02548     configASSERT( pxTimeOut );
02549     pxTimeOut->xOverflowCount = xNumOfOverflows;
02550     pxTimeOut->xTimeOnEntering = xTickCount;
02551 }
02552 /*-----------------------------------------------------------*/
02553 
02554 BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait )
02555 {
02556 BaseType_t xReturn;
02557 
02558     configASSERT( pxTimeOut );
02559     configASSERT( pxTicksToWait );
02560 
02561     taskENTER_CRITICAL();
02562     {
02563         /* Minor optimisation.  The tick count cannot change in this block. */
02564         const TickType_t xConstTickCount = xTickCount;
02565 
02566         #if ( INCLUDE_vTaskSuspend == 1 )
02567             /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is
02568             the maximum block time then the task should block indefinitely, and
02569             therefore never time out. */
02570             if( *pxTicksToWait == portMAX_DELAY )
02571             {
02572                 xReturn = pdFALSE;
02573             }
02574             else /* We are not blocking indefinitely, perform the checks below. */
02575         #endif
02576 
02577         if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
02578         {
02579             /* The tick count is greater than the time at which vTaskSetTimeout()
02580             was called, but has also overflowed since vTaskSetTimeOut() was called.
02581             It must have wrapped all the way around and gone past us again. This
02582             passed since vTaskSetTimeout() was called. */
02583             xReturn = pdTRUE;
02584         }
02585         else if( ( xConstTickCount - pxTimeOut->xTimeOnEntering ) < *pxTicksToWait )
02586         {
02587             /* Not a genuine timeout. Adjust parameters for time remaining. */
02588             *pxTicksToWait -= ( xConstTickCount -  pxTimeOut->xTimeOnEntering );
02589             vTaskSetTimeOutState( pxTimeOut );
02590             xReturn = pdFALSE;
02591         }
02592         else
02593         {
02594             xReturn = pdTRUE;
02595         }
02596     }
02597     taskEXIT_CRITICAL();
02598 
02599     return xReturn;
02600 }
02601 /*-----------------------------------------------------------*/
02602 
02603 void vTaskMissedYield( void )
02604 {
02605     xYieldPending = pdTRUE;
02606 }
02607 /*-----------------------------------------------------------*/
02608 
02609 #if ( configUSE_TRACE_FACILITY == 1 )
02610 
02611     UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )
02612     {
02613     UBaseType_t uxReturn;
02614     TCB_t *pxTCB;
02615 
02616         if( xTask != NULL )
02617         {
02618             pxTCB = ( TCB_t * ) xTask;
02619             uxReturn = pxTCB->uxTaskNumber;
02620         }
02621         else
02622         {
02623             uxReturn = 0U;
02624         }
02625 
02626         return uxReturn;
02627     }
02628 
02629 #endif /* configUSE_TRACE_FACILITY */
02630 /*-----------------------------------------------------------*/
02631 
02632 #if ( configUSE_TRACE_FACILITY == 1 )
02633 
02634     void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle )
02635     {
02636     TCB_t *pxTCB;
02637 
02638         if( xTask != NULL )
02639         {
02640             pxTCB = ( TCB_t * ) xTask;
02641             pxTCB->uxTaskNumber = uxHandle;
02642         }
02643     }
02644 
02645 #endif /* configUSE_TRACE_FACILITY */
02646 
02647 /*
02648  * -----------------------------------------------------------
02649  * The Idle task.
02650  * ----------------------------------------------------------
02651  *
02652  * The portTASK_FUNCTION() macro is used to allow port/compiler specific
02653  * language extensions.  The equivalent prototype for this function is:
02654  *
02655  * void prvIdleTask( void *pvParameters );
02656  *
02657  */
02658 static portTASK_FUNCTION( prvIdleTask, pvParameters )
02659 {
02660     /* Stop warnings. */
02661     ( void ) pvParameters;
02662 
02663     for( ;; )
02664     {
02665         /* See if any tasks have been deleted. */
02666         prvCheckTasksWaitingTermination();
02667 
02668         #if ( configUSE_PREEMPTION == 0 )
02669         {
02670             /* If we are not using preemption we keep forcing a task switch to
02671             see if any other task has become available.  If we are using
02672             preemption we don't need to do this as any task becoming available
02673             will automatically get the processor anyway. */
02674             taskYIELD();
02675         }
02676         #endif /* configUSE_PREEMPTION */
02677 
02678         #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
02679         {
02680             /* When using preemption tasks of equal priority will be
02681             timesliced.  If a task that is sharing the idle priority is ready
02682             to run then the idle task should yield before the end of the
02683             timeslice.
02684 
02685             A critical region is not required here as we are just reading from
02686             the list, and an occasional incorrect value will not matter.  If
02687             the ready list at the idle priority contains more than one task
02688             then a task other than the idle task is ready to execute. */
02689             if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )
02690             {
02691                 taskYIELD();
02692             }
02693             else
02694             {
02695                 mtCOVERAGE_TEST_MARKER();
02696             }
02697         }
02698         #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
02699 
02700         #if ( configUSE_IDLE_HOOK == 1 )
02701         {
02702             extern void vApplicationIdleHook( void );
02703 
02704             /* Call the user defined function from within the idle task.  This
02705             allows the application designer to add background functionality
02706             without the overhead of a separate task.
02707             NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
02708             CALL A FUNCTION THAT MIGHT BLOCK. */
02709             vApplicationIdleHook();
02710         }
02711         #endif /* configUSE_IDLE_HOOK */
02712 
02713         /* This conditional compilation should use inequality to 0, not equality
02714         to 1.  This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
02715         user defined low power mode implementations require
02716         configUSE_TICKLESS_IDLE to be set to a value other than 1. */
02717         #if ( configUSE_TICKLESS_IDLE != 0 )
02718         {
02719         TickType_t xExpectedIdleTime;
02720 
02721             /* It is not desirable to suspend then resume the scheduler on
02722             each iteration of the idle task.  Therefore, a preliminary
02723             test of the expected idle time is performed without the
02724             scheduler suspended.  The result here is not necessarily
02725             valid. */
02726             xExpectedIdleTime = prvGetExpectedIdleTime();
02727 
02728             if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
02729             {
02730                 vTaskSuspendAll();
02731                 {
02732                     /* Now the scheduler is suspended, the expected idle
02733                     time can be sampled again, and this time its value can
02734                     be used. */
02735                     configASSERT( xNextTaskUnblockTime >= xTickCount );
02736                     xExpectedIdleTime = prvGetExpectedIdleTime();
02737 
02738                     if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
02739                     {
02740                         traceLOW_POWER_IDLE_BEGIN();
02741                         portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
02742                         traceLOW_POWER_IDLE_END();
02743                     }
02744                     else
02745                     {
02746                         mtCOVERAGE_TEST_MARKER();
02747                     }
02748                 }
02749                 ( void ) xTaskResumeAll();
02750             }
02751             else
02752             {
02753                 mtCOVERAGE_TEST_MARKER();
02754             }
02755         }
02756         #endif /* configUSE_TICKLESS_IDLE */
02757     }
02758 }
02759 /*-----------------------------------------------------------*/
02760 
02761 #if configUSE_TICKLESS_IDLE != 0
02762 
02763     eSleepModeStatus eTaskConfirmSleepModeStatus( void )
02764     {
02765     eSleepModeStatus eReturn = eStandardSleep;
02766 
02767         if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
02768         {
02769             /* A task was made ready while the scheduler was suspended. */
02770             eReturn = eAbortSleep;
02771         }
02772         else if( xYieldPending != pdFALSE )
02773         {
02774             /* A yield was pended while the scheduler was suspended. */
02775             eReturn = eAbortSleep;
02776         }
02777         else
02778         {
02779             #if configUSE_TIMERS == 0
02780             {
02781                 /* The idle task exists in addition to the application tasks. */
02782                 const UBaseType_t uxNonApplicationTasks = 1;
02783 
02784                 /* If timers are not being used and all the tasks are in the
02785                 suspended list (which might mean they have an infinite block
02786                 time rather than actually being suspended) then it is safe to
02787                 turn all clocks off and just wait for external interrupts. */
02788                 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
02789                 {
02790                     eReturn = eNoTasksWaitingTimeout;
02791                 }
02792                 else
02793                 {
02794                     mtCOVERAGE_TEST_MARKER();
02795                 }
02796             }
02797             #endif /* configUSE_TIMERS */
02798         }
02799 
02800         return eReturn;
02801     }
02802 #endif /* configUSE_TICKLESS_IDLE */
02803 /*-----------------------------------------------------------*/
02804 
02805 static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
02806 {
02807 UBaseType_t x;
02808 
02809     /* Store the task name in the TCB. */
02810     for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
02811     {
02812         pxTCB->pcTaskName[ x ] = pcName[ x ];
02813 
02814         /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
02815         configMAX_TASK_NAME_LEN characters just in case the memory after the
02816         string is not accessible (extremely unlikely). */
02817         if( pcName[ x ] == 0x00 )
02818         {
02819             break;
02820         }
02821         else
02822         {
02823             mtCOVERAGE_TEST_MARKER();
02824         }
02825     }
02826 
02827     /* Ensure the name string is terminated in the case that the string length
02828     was greater or equal to configMAX_TASK_NAME_LEN. */
02829     pxTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
02830 
02831     /* This is used as an array index so must ensure it's not too large.  First
02832     remove the privilege bit if one is present. */
02833     if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
02834     {
02835         uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
02836     }
02837     else
02838     {
02839         mtCOVERAGE_TEST_MARKER();
02840     }
02841 
02842     pxTCB->uxPriority = uxPriority;
02843     #if ( configUSE_MUTEXES == 1 )
02844     {
02845         pxTCB->uxBasePriority = uxPriority;
02846         pxTCB->uxMutexesHeld = 0;
02847     }
02848     #endif /* configUSE_MUTEXES */
02849 
02850     vListInitialiseItem( &( pxTCB->xGenericListItem ) );
02851     vListInitialiseItem( &( pxTCB->xEventListItem ) );
02852 
02853     /* Set the pxTCB as a link back from the ListItem_t.  This is so we can get
02854     back to the containing TCB from a generic item in a list. */
02855     listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB );
02856 
02857     /* Event lists are always in priority order. */
02858     listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
02859     listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB );
02860 
02861     #if ( portCRITICAL_NESTING_IN_TCB == 1 )
02862     {
02863         pxTCB->uxCriticalNesting = ( UBaseType_t ) 0U;
02864     }
02865     #endif /* portCRITICAL_NESTING_IN_TCB */
02866 
02867     #if ( configUSE_APPLICATION_TASK_TAG == 1 )
02868     {
02869         pxTCB->pxTaskTag = NULL;
02870     }
02871     #endif /* configUSE_APPLICATION_TASK_TAG */
02872 
02873     #if ( configGENERATE_RUN_TIME_STATS == 1 )
02874     {
02875         pxTCB->ulRunTimeCounter = 0UL;
02876     }
02877     #endif /* configGENERATE_RUN_TIME_STATS */
02878 
02879     #if ( portUSING_MPU_WRAPPERS == 1 )
02880     {
02881         vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth );
02882     }
02883     #else /* portUSING_MPU_WRAPPERS */
02884     {
02885         ( void ) xRegions;
02886         ( void ) usStackDepth;
02887     }
02888     #endif /* portUSING_MPU_WRAPPERS */
02889 
02890     #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
02891     {
02892         for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ )
02893         {
02894             pxTCB->pvThreadLocalStoragePointers[ x ] = NULL;
02895         }
02896     }
02897     #endif
02898 
02899     #if ( configUSE_TASK_NOTIFICATIONS == 1 )
02900     {
02901         pxTCB->ulNotifiedValue = 0;
02902         pxTCB->eNotifyState = eNotWaitingNotification;
02903     }
02904     #endif
02905 
02906     #if ( configUSE_NEWLIB_REENTRANT == 1 )
02907     {
02908         /* Initialise this task's Newlib reent structure. */
02909         _REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) );
02910     }
02911     #endif /* configUSE_NEWLIB_REENTRANT */
02912 }
02913 /*-----------------------------------------------------------*/
02914 
02915 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
02916 
02917     void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue )
02918     {
02919     TCB_t *pxTCB;
02920 
02921         if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS )
02922         {
02923             pxTCB = prvGetTCBFromHandle( xTaskToSet );
02924             pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue;
02925         }
02926     }
02927 
02928 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
02929 /*-----------------------------------------------------------*/
02930 
02931 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
02932 
02933     void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex )
02934     {
02935     void *pvReturn = NULL;
02936     TCB_t *pxTCB;
02937 
02938         if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS )
02939         {
02940             pxTCB = prvGetTCBFromHandle( xTaskToQuery );
02941             pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ];
02942         }
02943         else
02944         {
02945             pvReturn = NULL;
02946         }
02947 
02948         return pvReturn;
02949     }
02950 
02951 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
02952 /*-----------------------------------------------------------*/
02953 
02954 #if ( portUSING_MPU_WRAPPERS == 1 )
02955 
02956     void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions )
02957     {
02958     TCB_t *pxTCB;
02959 
02960         /* If null is passed in here then we are deleting ourselves. */
02961         pxTCB = prvGetTCBFromHandle( xTaskToModify );
02962 
02963         vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
02964     }
02965 
02966 #endif /* portUSING_MPU_WRAPPERS */
02967 /*-----------------------------------------------------------*/
02968 
02969 static void prvInitialiseTaskLists( void )
02970 {
02971 UBaseType_t uxPriority;
02972 
02973     for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
02974     {
02975         vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
02976     }
02977 
02978     vListInitialise( &xDelayedTaskList1 );
02979     vListInitialise( &xDelayedTaskList2 );
02980     vListInitialise( &xPendingReadyList );
02981 
02982     #if ( INCLUDE_vTaskDelete == 1 )
02983     {
02984         vListInitialise( &xTasksWaitingTermination );
02985     }
02986     #endif /* INCLUDE_vTaskDelete */
02987 
02988     #if ( INCLUDE_vTaskSuspend == 1 )
02989     {
02990         vListInitialise( &xSuspendedTaskList );
02991     }
02992     #endif /* INCLUDE_vTaskSuspend */
02993 
02994     /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
02995     using list2. */
02996     pxDelayedTaskList = &xDelayedTaskList1;
02997     pxOverflowDelayedTaskList = &xDelayedTaskList2;
02998 }
02999 /*-----------------------------------------------------------*/
03000 
03001 static void prvCheckTasksWaitingTermination( void )
03002 {
03003     #if ( INCLUDE_vTaskDelete == 1 )
03004     {
03005         BaseType_t xListIsEmpty;
03006 
03007         /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
03008         too often in the idle task. */
03009         while( uxTasksDeleted > ( UBaseType_t ) 0U )
03010         {
03011             vTaskSuspendAll();
03012             {
03013                 xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
03014             }
03015             ( void ) xTaskResumeAll();
03016 
03017             if( xListIsEmpty == pdFALSE )
03018             {
03019                 TCB_t *pxTCB;
03020 
03021                 taskENTER_CRITICAL();
03022                 {
03023                     pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
03024                     ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
03025                     --uxCurrentNumberOfTasks;
03026                     --uxTasksDeleted;
03027                 }
03028                 taskEXIT_CRITICAL();
03029 
03030                 prvDeleteTCB( pxTCB );
03031             }
03032             else
03033             {
03034                 mtCOVERAGE_TEST_MARKER();
03035             }
03036         }
03037     }
03038     #endif /* vTaskDelete */
03039 }
03040 /*-----------------------------------------------------------*/
03041 
03042 static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake )
03043 {
03044     /* The list item will be inserted in wake time order. */
03045     listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
03046 
03047     if( xTimeToWake < xTickCount )
03048     {
03049         /* Wake time has overflowed.  Place this item in the overflow list. */
03050         vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
03051     }
03052     else
03053     {
03054         /* The wake time has not overflowed, so the current block list is used. */
03055         vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
03056 
03057         /* If the task entering the blocked state was placed at the head of the
03058         list of blocked tasks then xNextTaskUnblockTime needs to be updated
03059         too. */
03060         if( xTimeToWake < xNextTaskUnblockTime )
03061         {
03062             xNextTaskUnblockTime = xTimeToWake;
03063         }
03064         else
03065         {
03066             mtCOVERAGE_TEST_MARKER();
03067         }
03068     }
03069 }
03070 /*-----------------------------------------------------------*/
03071 
03072 static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer )
03073 {
03074 TCB_t *pxNewTCB;
03075 
03076     /* If the stack grows down then allocate the stack then the TCB so the stack
03077     does not grow into the TCB.  Likewise if the stack grows up then allocate
03078     the TCB then the stack. */
03079     #if( portSTACK_GROWTH > 0 )
03080     {
03081         /* Allocate space for the TCB.  Where the memory comes from depends on
03082         the implementation of the port malloc function. */
03083         pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
03084 
03085         if( pxNewTCB != NULL )
03086         {
03087             /* Allocate space for the stack used by the task being created.
03088             The base of the stack memory stored in the TCB so the task can
03089             be deleted later if required. */
03090             pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
03091 
03092             if( pxNewTCB->pxStack == NULL )
03093             {
03094                 /* Could not allocate the stack.  Delete the allocated TCB. */
03095                 vPortFree( pxNewTCB );
03096                 pxNewTCB = NULL;
03097             }
03098         }
03099     }
03100     #else /* portSTACK_GROWTH */
03101     {
03102     StackType_t *pxStack;
03103 
03104         /* Allocate space for the stack used by the task being created. */
03105         pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
03106 
03107         if( pxStack != NULL )
03108         {
03109             /* Allocate space for the TCB.  Where the memory comes from depends
03110             on the implementation of the port malloc function. */
03111             pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
03112 
03113             if( pxNewTCB != NULL )
03114             {
03115                 /* Store the stack location in the TCB. */
03116                 pxNewTCB->pxStack = pxStack;
03117             }
03118             else
03119             {
03120                 /* The stack cannot be used as the TCB was not created.  Free it
03121                 again. */
03122                 vPortFree( pxStack );
03123             }
03124         }
03125         else
03126         {
03127             pxNewTCB = NULL;
03128         }
03129     }
03130     #endif /* portSTACK_GROWTH */
03131 
03132     if( pxNewTCB != NULL )
03133     {
03134         /* Avoid dependency on memset() if it is not required. */
03135         #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
03136         {
03137             /* Just to help debugging. */
03138             ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( StackType_t ) );
03139         }
03140         #endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */
03141     }
03142 
03143     return pxNewTCB;
03144 }
03145 /*-----------------------------------------------------------*/
03146 
03147 #if ( configUSE_TRACE_FACILITY == 1 )
03148 
03149     static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )
03150     {
03151     volatile TCB_t *pxNextTCB, *pxFirstTCB;
03152     UBaseType_t uxTask = 0;
03153 
03154         if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
03155         {
03156             listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
03157 
03158             /* Populate an TaskStatus_t structure within the
03159             pxTaskStatusArray array for each task that is referenced from
03160             pxList.  See the definition of TaskStatus_t in task.h for the
03161             meaning of each TaskStatus_t structure member. */
03162             do
03163             {
03164                 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
03165 
03166                 pxTaskStatusArray[ uxTask ].xHandle = ( TaskHandle_t ) pxNextTCB;
03167                 pxTaskStatusArray[ uxTask ].pcTaskName = ( const char * ) &( pxNextTCB->pcTaskName [ 0 ] );
03168                 pxTaskStatusArray[ uxTask ].xTaskNumber = pxNextTCB->uxTCBNumber;
03169                 pxTaskStatusArray[ uxTask ].eCurrentState = eState;
03170                 pxTaskStatusArray[ uxTask ].uxCurrentPriority = pxNextTCB->uxPriority;
03171 
03172                 #if ( INCLUDE_vTaskSuspend == 1 )
03173                 {
03174                     /* If the task is in the suspended list then there is a chance
03175                     it is actually just blocked indefinitely - so really it should
03176                     be reported as being in the Blocked state. */
03177                     if( eState == eSuspended )
03178                     {
03179                         if( listLIST_ITEM_CONTAINER( &( pxNextTCB->xEventListItem ) ) != NULL )
03180                         {
03181                             pxTaskStatusArray[ uxTask ].eCurrentState = eBlocked;
03182                         }
03183                     }
03184                 }
03185                 #endif /* INCLUDE_vTaskSuspend */
03186 
03187                 #if ( configUSE_MUTEXES == 1 )
03188                 {
03189                     pxTaskStatusArray[ uxTask ].uxBasePriority = pxNextTCB->uxBasePriority;
03190                 }
03191                 #else
03192                 {
03193                     pxTaskStatusArray[ uxTask ].uxBasePriority = 0;
03194                 }
03195                 #endif
03196 
03197                 #if ( configGENERATE_RUN_TIME_STATS == 1 )
03198                 {
03199                     pxTaskStatusArray[ uxTask ].ulRunTimeCounter = pxNextTCB->ulRunTimeCounter;
03200                 }
03201                 #else
03202                 {
03203                     pxTaskStatusArray[ uxTask ].ulRunTimeCounter = 0;
03204                 }
03205                 #endif
03206 
03207                 #if ( portSTACK_GROWTH > 0 )
03208                 {
03209                     pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxEndOfStack );
03210                 }
03211                 #else
03212                 {
03213                     pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxStack );
03214                 }
03215                 #endif
03216 
03217                 uxTask++;
03218 
03219             } while( pxNextTCB != pxFirstTCB );
03220         }
03221         else
03222         {
03223             mtCOVERAGE_TEST_MARKER();
03224         }
03225 
03226         return uxTask;
03227     }
03228 
03229 #endif /* configUSE_TRACE_FACILITY */
03230 /*-----------------------------------------------------------*/
03231 
03232 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
03233 
03234     static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
03235     {
03236     uint32_t ulCount = 0U;
03237 
03238         while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE )
03239         {
03240             pucStackByte -= portSTACK_GROWTH;
03241             ulCount++;
03242         }
03243 
03244         ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */
03245 
03246         return ( uint16_t ) ulCount;
03247     }
03248 
03249 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */
03250 /*-----------------------------------------------------------*/
03251 
03252 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
03253 
03254     UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
03255     {
03256     TCB_t *pxTCB;
03257     uint8_t *pucEndOfStack;
03258     UBaseType_t uxReturn;
03259 
03260         pxTCB = prvGetTCBFromHandle( xTask );
03261 
03262         #if portSTACK_GROWTH < 0
03263         {
03264             pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
03265         }
03266         #else
03267         {
03268             pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
03269         }
03270         #endif
03271 
03272         uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );
03273 
03274         return uxReturn;
03275     }
03276 
03277 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
03278 /*-----------------------------------------------------------*/
03279 
03280 #if ( INCLUDE_vTaskDelete == 1 )
03281 
03282     static void prvDeleteTCB( TCB_t *pxTCB )
03283     {
03284         /* This call is required specifically for the TriCore port.  It must be
03285         above the vPortFree() calls.  The call is also used by ports/demos that
03286         want to allocate and clean RAM statically. */
03287         portCLEAN_UP_TCB( pxTCB );
03288 
03289         /* Free up the memory allocated by the scheduler for the task.  It is up
03290         to the task to free any memory allocated at the application level. */
03291         #if ( configUSE_NEWLIB_REENTRANT == 1 )
03292         {
03293             _reclaim_reent( &( pxTCB->xNewLib_reent ) );
03294         }
03295         #endif /* configUSE_NEWLIB_REENTRANT */
03296 
03297         #if( portUSING_MPU_WRAPPERS == 1 )
03298         {
03299             /* Only free the stack if it was allocated dynamically in the first
03300             place. */
03301             if( pxTCB->xUsingStaticallyAllocatedStack == pdFALSE )
03302             {
03303                 vPortFreeAligned( pxTCB->pxStack );
03304             }
03305         }
03306         #else
03307         {
03308             vPortFreeAligned( pxTCB->pxStack );
03309         }
03310         #endif
03311 
03312         vPortFree( pxTCB );
03313     }
03314 
03315 #endif /* INCLUDE_vTaskDelete */
03316 /*-----------------------------------------------------------*/
03317 
03318 static void prvResetNextTaskUnblockTime( void )
03319 {
03320 TCB_t *pxTCB;
03321 
03322     if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
03323     {
03324         /* The new current delayed list is empty.  Set xNextTaskUnblockTime to
03325         the maximum possible value so it is extremely unlikely that the
03326         if( xTickCount >= xNextTaskUnblockTime ) test will pass until
03327         there is an item in the delayed list. */
03328         xNextTaskUnblockTime = portMAX_DELAY;
03329     }
03330     else
03331     {
03332         /* The new current delayed list is not empty, get the value of
03333         the item at the head of the delayed list.  This is the time at
03334         which the task at the head of the delayed list should be removed
03335         from the Blocked state. */
03336         ( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
03337         xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xGenericListItem ) );
03338     }
03339 }
03340 /*-----------------------------------------------------------*/
03341 
03342 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
03343 
03344     TaskHandle_t xTaskGetCurrentTaskHandle( void )
03345     {
03346     TaskHandle_t xReturn;
03347 
03348         /* A critical section is not required as this is not called from
03349         an interrupt and the current TCB will always be the same for any
03350         individual execution thread. */
03351         xReturn = pxCurrentTCB;
03352 
03353         return xReturn;
03354     }
03355 
03356 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
03357 /*-----------------------------------------------------------*/
03358 
03359 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
03360 
03361     BaseType_t xTaskGetSchedulerState( void )
03362     {
03363     BaseType_t xReturn;
03364 
03365         if( xSchedulerRunning == pdFALSE )
03366         {
03367             xReturn = taskSCHEDULER_NOT_STARTED;
03368         }
03369         else
03370         {
03371             if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
03372             {
03373                 xReturn = taskSCHEDULER_RUNNING;
03374             }
03375             else
03376             {
03377                 xReturn = taskSCHEDULER_SUSPENDED;
03378             }
03379         }
03380 
03381         return xReturn;
03382     }
03383 
03384 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
03385 /*-----------------------------------------------------------*/
03386 
03387 #if ( configUSE_MUTEXES == 1 )
03388 
03389     void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
03390     {
03391     TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
03392 
03393         /* If the mutex was given back by an interrupt while the queue was
03394         locked then the mutex holder might now be NULL. */
03395         if( pxMutexHolder != NULL )
03396         {
03397             /* If the holder of the mutex has a priority below the priority of
03398             the task attempting to obtain the mutex then it will temporarily
03399             inherit the priority of the task attempting to obtain the mutex. */
03400             if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
03401             {
03402                 /* Adjust the mutex holder state to account for its new
03403                 priority.  Only reset the event list item value if the value is
03404                 not being used for anything else. */
03405                 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
03406                 {
03407                     listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
03408                 }
03409                 else
03410                 {
03411                     mtCOVERAGE_TEST_MARKER();
03412                 }
03413 
03414                 /* If the task being modified is in the ready state it will need
03415                 to be moved into a new list. */
03416                 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
03417                 {
03418                     if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
03419                     {
03420                         taskRESET_READY_PRIORITY( pxTCB->uxPriority );
03421                     }
03422                     else
03423                     {
03424                         mtCOVERAGE_TEST_MARKER();
03425                     }
03426 
03427                     /* Inherit the priority before being moved into the new list. */
03428                     pxTCB->uxPriority = pxCurrentTCB->uxPriority;
03429                     prvAddTaskToReadyList( pxTCB );
03430                 }
03431                 else
03432                 {
03433                     /* Just inherit the priority. */
03434                     pxTCB->uxPriority = pxCurrentTCB->uxPriority;
03435                 }
03436 
03437                 traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );
03438             }
03439             else
03440             {
03441                 mtCOVERAGE_TEST_MARKER();
03442             }
03443         }
03444         else
03445         {
03446             mtCOVERAGE_TEST_MARKER();
03447         }
03448     }
03449 
03450 #endif /* configUSE_MUTEXES */
03451 /*-----------------------------------------------------------*/
03452 
03453 #if ( configUSE_MUTEXES == 1 )
03454 
03455     BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )
03456     {
03457     TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
03458     BaseType_t xReturn = pdFALSE;
03459 
03460         if( pxMutexHolder != NULL )
03461         {
03462             /* A task can only have an inherited priority if it holds the mutex.
03463             If the mutex is held by a task then it cannot be given from an
03464             interrupt, and if a mutex is given by the holding task then it must
03465             be the running state task. */
03466             configASSERT( pxTCB == pxCurrentTCB );
03467 
03468             configASSERT( pxTCB->uxMutexesHeld );
03469             ( pxTCB->uxMutexesHeld )--;
03470 
03471             /* Has the holder of the mutex inherited the priority of another
03472             task? */
03473             if( pxTCB->uxPriority != pxTCB->uxBasePriority )
03474             {
03475                 /* Only disinherit if no other mutexes are held. */
03476                 if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
03477                 {
03478                     /* A task can only have an inherited priority if it holds
03479                     the mutex.  If the mutex is held by a task then it cannot be
03480                     given from an interrupt, and if a mutex is given by the
03481                     holding task then it must be the running state task.  Remove
03482                     the holding task from the ready list. */
03483                     if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
03484                     {
03485                         taskRESET_READY_PRIORITY( pxTCB->uxPriority );
03486                     }
03487                     else
03488                     {
03489                         mtCOVERAGE_TEST_MARKER();
03490                     }
03491 
03492                     /* Disinherit the priority before adding the task into the
03493                     new ready list. */
03494                     traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
03495                     pxTCB->uxPriority = pxTCB->uxBasePriority;
03496 
03497                     /* Reset the event list item value.  It cannot be in use for
03498                     any other purpose if this task is running, and it must be
03499                     running to give back the mutex. */
03500                     listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
03501                     prvAddTaskToReadyList( pxTCB );
03502 
03503                     /* Return true to indicate that a context switch is required.
03504                     This is only actually required in the corner case whereby
03505                     multiple mutexes were held and the mutexes were given back
03506                     in an order different to that in which they were taken.
03507                     If a context switch did not occur when the first mutex was
03508                     returned, even if a task was waiting on it, then a context
03509                     switch should occur when the last mutex is returned whether
03510                     a task is waiting on it or not. */
03511                     xReturn = pdTRUE;
03512                 }
03513                 else
03514                 {
03515                     mtCOVERAGE_TEST_MARKER();
03516                 }
03517             }
03518             else
03519             {
03520                 mtCOVERAGE_TEST_MARKER();
03521             }
03522         }
03523         else
03524         {
03525             mtCOVERAGE_TEST_MARKER();
03526         }
03527 
03528         return xReturn;
03529     }
03530 
03531 #endif /* configUSE_MUTEXES */
03532 /*-----------------------------------------------------------*/
03533 
03534 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
03535 
03536     void vTaskEnterCritical( void )
03537     {
03538         portDISABLE_INTERRUPTS();
03539 
03540         if( xSchedulerRunning != pdFALSE )
03541         {
03542             ( pxCurrentTCB->uxCriticalNesting )++;
03543 
03544             /* This is not the interrupt safe version of the enter critical
03545             function so assert() if it is being called from an interrupt
03546             context.  Only API functions that end in "FromISR" can be used in an
03547             interrupt.  Only assert if the critical nesting count is 1 to
03548             protect against recursive calls if the assert function also uses a
03549             critical section. */
03550             if( pxCurrentTCB->uxCriticalNesting == 1 )
03551             {
03552                 portASSERT_IF_IN_ISR();
03553             }
03554 
03555         }
03556         else
03557         {
03558             mtCOVERAGE_TEST_MARKER();
03559         }
03560     }
03561 
03562 #endif /* portCRITICAL_NESTING_IN_TCB */
03563 /*-----------------------------------------------------------*/
03564 
03565 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
03566 
03567     void vTaskExitCritical( void )
03568     {
03569         if( xSchedulerRunning != pdFALSE )
03570         {
03571             if( pxCurrentTCB->uxCriticalNesting > 0U )
03572             {
03573                 ( pxCurrentTCB->uxCriticalNesting )--;
03574 
03575                 if( pxCurrentTCB->uxCriticalNesting == 0U )
03576                 {
03577                     portENABLE_INTERRUPTS();
03578                 }
03579                 else
03580                 {
03581                     mtCOVERAGE_TEST_MARKER();
03582                 }
03583             }
03584             else
03585             {
03586                 mtCOVERAGE_TEST_MARKER();
03587             }
03588         }
03589         else
03590         {
03591             mtCOVERAGE_TEST_MARKER();
03592         }
03593     }
03594 
03595 #endif /* portCRITICAL_NESTING_IN_TCB */
03596 /*-----------------------------------------------------------*/
03597 
03598 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
03599 
03600     static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName )
03601     {
03602     BaseType_t x;
03603 
03604         /* Start by copying the entire string. */
03605         strcpy( pcBuffer, pcTaskName );
03606 
03607         /* Pad the end of the string with spaces to ensure columns line up when
03608         printed out. */
03609         for( x = strlen( pcBuffer ); x < ( configMAX_TASK_NAME_LEN - 1 ); x++ )
03610         {
03611             pcBuffer[ x ] = ' ';
03612         }
03613 
03614         /* Terminate. */
03615         pcBuffer[ x ] = 0x00;
03616 
03617         /* Return the new end of string. */
03618         return &( pcBuffer[ x ] );
03619     }
03620 
03621 #endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
03622 /*-----------------------------------------------------------*/
03623 
03624 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
03625 
03626     void vTaskList( char * pcWriteBuffer )
03627     {
03628     TaskStatus_t *pxTaskStatusArray;
03629     volatile UBaseType_t uxArraySize, x;
03630     char cStatus;
03631 
03632         /*
03633          * PLEASE NOTE:
03634          *
03635          * This function is provided for convenience only, and is used by many
03636          * of the demo applications.  Do not consider it to be part of the
03637          * scheduler.
03638          *
03639          * vTaskList() calls uxTaskGetSystemState(), then formats part of the
03640          * uxTaskGetSystemState() output into a human readable table that
03641          * displays task names, states and stack usage.
03642          *
03643          * vTaskList() has a dependency on the sprintf() C library function that
03644          * might bloat the code size, use a lot of stack, and provide different
03645          * results on different platforms.  An alternative, tiny, third party,
03646          * and limited functionality implementation of sprintf() is provided in
03647          * many of the FreeRTOS/Demo sub-directories in a file called
03648          * printf-stdarg.c (note printf-stdarg.c does not provide a full
03649          * snprintf() implementation!).
03650          *
03651          * It is recommended that production systems call uxTaskGetSystemState()
03652          * directly to get access to raw stats data, rather than indirectly
03653          * through a call to vTaskList().
03654          */
03655 
03656 
03657         /* Make sure the write buffer does not contain a string. */
03658         *pcWriteBuffer = 0x00;
03659 
03660         /* Take a snapshot of the number of tasks in case it changes while this
03661         function is executing. */
03662         uxArraySize = uxCurrentNumberOfTasks;
03663 
03664         /* Allocate an array index for each task. */
03665         pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
03666 
03667         if( pxTaskStatusArray != NULL )
03668         {
03669             /* Generate the (binary) data. */
03670             uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
03671 
03672             /* Create a human readable table from the binary data. */
03673             for( x = 0; x < uxArraySize; x++ )
03674             {
03675                 switch( pxTaskStatusArray[ x ].eCurrentState )
03676                 {
03677                     case eReady:        cStatus = tskREADY_CHAR;
03678                                         break;
03679 
03680                     case eBlocked:      cStatus = tskBLOCKED_CHAR;
03681                                         break;
03682 
03683                     case eSuspended:    cStatus = tskSUSPENDED_CHAR;
03684                                         break;
03685 
03686                     case eDeleted:      cStatus = tskDELETED_CHAR;
03687                                         break;
03688 
03689                     default:            /* Should not get here, but it is included
03690                                         to prevent static checking errors. */
03691                                         cStatus = 0x00;
03692                                         break;
03693                 }
03694 
03695                 /* Write the task name to the string, padding with spaces so it
03696                 can be printed in tabular form more easily. */
03697                 pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
03698 
03699                 /* Write the rest of the string. */
03700                 sprintf( pcWriteBuffer, "\t%c\t%u\t%u\t%u\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber );
03701                 pcWriteBuffer += strlen( pcWriteBuffer );
03702             }
03703 
03704             /* Free the array again. */
03705             vPortFree( pxTaskStatusArray );
03706         }
03707         else
03708         {
03709             mtCOVERAGE_TEST_MARKER();
03710         }
03711     }
03712 
03713 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
03714 /*----------------------------------------------------------*/
03715 
03716 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
03717 
03718     void vTaskGetRunTimeStats( char *pcWriteBuffer )
03719     {
03720     TaskStatus_t *pxTaskStatusArray;
03721     volatile UBaseType_t uxArraySize, x;
03722     uint32_t ulTotalTime, ulStatsAsPercentage;
03723 
03724         #if( configUSE_TRACE_FACILITY != 1 )
03725         {
03726             #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats().
03727         }
03728         #endif
03729 
03730         /*
03731          * PLEASE NOTE:
03732          *
03733          * This function is provided for convenience only, and is used by many
03734          * of the demo applications.  Do not consider it to be part of the
03735          * scheduler.
03736          *
03737          * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part
03738          * of the uxTaskGetSystemState() output into a human readable table that
03739          * displays the amount of time each task has spent in the Running state
03740          * in both absolute and percentage terms.
03741          *
03742          * vTaskGetRunTimeStats() has a dependency on the sprintf() C library
03743          * function that might bloat the code size, use a lot of stack, and
03744          * provide different results on different platforms.  An alternative,
03745          * tiny, third party, and limited functionality implementation of
03746          * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in
03747          * a file called printf-stdarg.c (note printf-stdarg.c does not provide
03748          * a full snprintf() implementation!).
03749          *
03750          * It is recommended that production systems call uxTaskGetSystemState()
03751          * directly to get access to raw stats data, rather than indirectly
03752          * through a call to vTaskGetRunTimeStats().
03753          */
03754 
03755         /* Make sure the write buffer does not contain a string. */
03756         *pcWriteBuffer = 0x00;
03757 
03758         /* Take a snapshot of the number of tasks in case it changes while this
03759         function is executing. */
03760         uxArraySize = uxCurrentNumberOfTasks;
03761 
03762         /* Allocate an array index for each task. */
03763         pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
03764 
03765         if( pxTaskStatusArray != NULL )
03766         {
03767             /* Generate the (binary) data. */
03768             uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
03769 
03770             /* For percentage calculations. */
03771             ulTotalTime /= 100UL;
03772 
03773             /* Avoid divide by zero errors. */
03774             if( ulTotalTime > 0 )
03775             {
03776                 /* Create a human readable table from the binary data. */
03777                 for( x = 0; x < uxArraySize; x++ )
03778                 {
03779                     /* What percentage of the total run time has the task used?
03780                     This will always be rounded down to the nearest integer.
03781                     ulTotalRunTimeDiv100 has already been divided by 100. */
03782                     ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
03783 
03784                     /* Write the task name to the string, padding with
03785                     spaces so it can be printed in tabular form more
03786                     easily. */
03787                     pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
03788 
03789                     if( ulStatsAsPercentage > 0UL )
03790                     {
03791                         #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
03792                         {
03793                             sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
03794                         }
03795                         #else
03796                         {
03797                             /* sizeof( int ) == sizeof( long ) so a smaller
03798                             printf() library can be used. */
03799                             sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );
03800                         }
03801                         #endif
03802                     }
03803                     else
03804                     {
03805                         /* If the percentage is zero here then the task has
03806                         consumed less than 1% of the total run time. */
03807                         #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
03808                         {
03809                             sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter );
03810                         }
03811                         #else
03812                         {
03813                             /* sizeof( int ) == sizeof( long ) so a smaller
03814                             printf() library can be used. */
03815                             sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter );
03816                         }
03817                         #endif
03818                     }
03819 
03820                     pcWriteBuffer += strlen( pcWriteBuffer );
03821                 }
03822             }
03823             else
03824             {
03825                 mtCOVERAGE_TEST_MARKER();
03826             }
03827 
03828             /* Free the array again. */
03829             vPortFree( pxTaskStatusArray );
03830         }
03831         else
03832         {
03833             mtCOVERAGE_TEST_MARKER();
03834         }
03835     }
03836 
03837 #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
03838 /*-----------------------------------------------------------*/
03839 
03840 TickType_t uxTaskResetEventItemValue( void )
03841 {
03842 TickType_t uxReturn;
03843 
03844     uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );
03845 
03846     /* Reset the event list item to its normal value - so it can be used with
03847     queues and semaphores. */
03848     listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
03849 
03850     return uxReturn;
03851 }
03852 /*-----------------------------------------------------------*/
03853 
03854 #if ( configUSE_MUTEXES == 1 )
03855 
03856     void *pvTaskIncrementMutexHeldCount( void )
03857     {
03858         /* If xSemaphoreCreateMutex() is called before any tasks have been created
03859         then pxCurrentTCB will be NULL. */
03860         if( pxCurrentTCB != NULL )
03861         {
03862             ( pxCurrentTCB->uxMutexesHeld )++;
03863         }
03864 
03865         return pxCurrentTCB;
03866     }
03867 
03868 #endif /* configUSE_MUTEXES */
03869 /*-----------------------------------------------------------*/
03870 
03871 #if( configUSE_TASK_NOTIFICATIONS == 1 )
03872 
03873     uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )
03874     {
03875     TickType_t xTimeToWake;
03876     uint32_t ulReturn;
03877 
03878         taskENTER_CRITICAL();
03879         {
03880             /* Only block if the notification count is not already non-zero. */
03881             if( pxCurrentTCB->ulNotifiedValue == 0UL )
03882             {
03883                 /* Mark this task as waiting for a notification. */
03884                 pxCurrentTCB->eNotifyState = eWaitingNotification;
03885 
03886                 if( xTicksToWait > ( TickType_t ) 0 )
03887                 {
03888                     /* The task is going to block.  First it must be removed
03889                     from the ready list. */
03890                     if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
03891                     {
03892                         /* The current task must be in a ready list, so there is
03893                         no need to check, and the port reset macro can be called
03894                         directly. */
03895                         portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
03896                     }
03897                     else
03898                     {
03899                         mtCOVERAGE_TEST_MARKER();
03900                     }
03901 
03902                     #if ( INCLUDE_vTaskSuspend == 1 )
03903                     {
03904                         if( xTicksToWait == portMAX_DELAY )
03905                         {
03906                             /* Add the task to the suspended task list instead
03907                             of a delayed task list to ensure the task is not
03908                             woken by a timing event.  It will block
03909                             indefinitely. */
03910                             vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
03911                         }
03912                         else
03913                         {
03914                             /* Calculate the time at which the task should be
03915                             woken if no notification events occur.  This may
03916                             overflow but this doesn't matter, the scheduler will
03917                             handle it. */
03918                             xTimeToWake = xTickCount + xTicksToWait;
03919                             prvAddCurrentTaskToDelayedList( xTimeToWake );
03920                         }
03921                     }
03922                     #else /* INCLUDE_vTaskSuspend */
03923                     {
03924                             /* Calculate the time at which the task should be
03925                             woken if the event does not occur.  This may
03926                             overflow but this doesn't matter, the scheduler will
03927                             handle it. */
03928                             xTimeToWake = xTickCount + xTicksToWait;
03929                             prvAddCurrentTaskToDelayedList( xTimeToWake );
03930                     }
03931                     #endif /* INCLUDE_vTaskSuspend */
03932 
03933                     /* All ports are written to allow a yield in a critical
03934                     section (some will yield immediately, others wait until the
03935                     critical section exits) - but it is not something that
03936                     application code should ever do. */
03937                     portYIELD_WITHIN_API();
03938                 }
03939                 else
03940                 {
03941                     mtCOVERAGE_TEST_MARKER();
03942                 }
03943             }
03944             else
03945             {
03946                 mtCOVERAGE_TEST_MARKER();
03947             }
03948         }
03949         taskEXIT_CRITICAL();
03950 
03951         taskENTER_CRITICAL();
03952         {
03953             ulReturn = pxCurrentTCB->ulNotifiedValue;
03954 
03955             if( ulReturn != 0UL )
03956             {
03957                 if( xClearCountOnExit != pdFALSE )
03958                 {
03959                     pxCurrentTCB->ulNotifiedValue = 0UL;
03960                 }
03961                 else
03962                 {
03963                     ( pxCurrentTCB->ulNotifiedValue )--;
03964                 }
03965             }
03966             else
03967             {
03968                 mtCOVERAGE_TEST_MARKER();
03969             }
03970 
03971             pxCurrentTCB->eNotifyState = eNotWaitingNotification;
03972         }
03973         taskEXIT_CRITICAL();
03974 
03975         return ulReturn;
03976     }
03977 
03978 #endif /* configUSE_TASK_NOTIFICATIONS */
03979 /*-----------------------------------------------------------*/
03980 
03981 #if( configUSE_TASK_NOTIFICATIONS == 1 )
03982 
03983     BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait )
03984     {
03985     TickType_t xTimeToWake;
03986     BaseType_t xReturn;
03987 
03988         taskENTER_CRITICAL();
03989         {
03990             /* Only block if a notification is not already pending. */
03991             if( pxCurrentTCB->eNotifyState != eNotified )
03992             {
03993                 /* Clear bits in the task's notification value as bits may get
03994                 set by the notifying task or interrupt.  This can be used to
03995                 clear the value to zero. */
03996                 pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry;
03997 
03998                 /* Mark this task as waiting for a notification. */
03999                 pxCurrentTCB->eNotifyState = eWaitingNotification;
04000 
04001                 if( xTicksToWait > ( TickType_t ) 0 )
04002                 {
04003                     /* The task is going to block.  First it must be removed
04004                     from the    ready list. */
04005                     if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
04006                     {
04007                         /* The current task must be in a ready list, so there is
04008                         no need to check, and the port reset macro can be called
04009                         directly. */
04010                         portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
04011                     }
04012                     else
04013                     {
04014                         mtCOVERAGE_TEST_MARKER();
04015                     }
04016 
04017                     #if ( INCLUDE_vTaskSuspend == 1 )
04018                     {
04019                         if( xTicksToWait == portMAX_DELAY )
04020                         {
04021                             /* Add the task to the suspended task list instead
04022                             of a delayed task list to ensure the task is not
04023                             woken by a timing event.  It will block
04024                             indefinitely. */
04025                             vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
04026                         }
04027                         else
04028                         {
04029                             /* Calculate the time at which the task should be
04030                             woken if no notification events occur.  This may
04031                             overflow but this doesn't matter, the scheduler will
04032                             handle it. */
04033                             xTimeToWake = xTickCount + xTicksToWait;
04034                             prvAddCurrentTaskToDelayedList( xTimeToWake );
04035                         }
04036                     }
04037                     #else /* INCLUDE_vTaskSuspend */
04038                     {
04039                             /* Calculate the time at which the task should be
04040                             woken if the event does not occur.  This may
04041                             overflow but this doesn't matter, the scheduler will
04042                             handle it. */
04043                             xTimeToWake = xTickCount + xTicksToWait;
04044                             prvAddCurrentTaskToDelayedList( xTimeToWake );
04045                     }
04046                     #endif /* INCLUDE_vTaskSuspend */
04047 
04048                     /* All ports are written to allow a yield in a critical
04049                     section (some will yield immediately, others wait until the
04050                     critical section exits) - but it is not something that
04051                     application code should ever do. */
04052                     portYIELD_WITHIN_API();
04053                 }
04054                 else
04055                 {
04056                     mtCOVERAGE_TEST_MARKER();
04057                 }
04058             }
04059             else
04060             {
04061                 mtCOVERAGE_TEST_MARKER();
04062             }
04063         }
04064         taskEXIT_CRITICAL();
04065 
04066         taskENTER_CRITICAL();
04067         {
04068             if( pulNotificationValue != NULL )
04069             {
04070                 /* Output the current notification value, which may or may not
04071                 have changed. */
04072                 *pulNotificationValue = pxCurrentTCB->ulNotifiedValue;
04073             }
04074 
04075             /* If eNotifyValue is set then either the task never entered the
04076             blocked state (because a notification was already pending) or the
04077             task unblocked because of a notification.  Otherwise the task
04078             unblocked because of a timeout. */
04079             if( pxCurrentTCB->eNotifyState == eWaitingNotification )
04080             {
04081                 /* A notification was not received. */
04082                 xReturn = pdFALSE;
04083             }
04084             else
04085             {
04086                 /* A notification was already pending or a notification was
04087                 received while the task was waiting. */
04088                 pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnExit;
04089                 xReturn = pdTRUE;
04090             }
04091 
04092             pxCurrentTCB->eNotifyState = eNotWaitingNotification;
04093         }
04094         taskEXIT_CRITICAL();
04095 
04096         return xReturn;
04097     }
04098 
04099 #endif /* configUSE_TASK_NOTIFICATIONS */
04100 /*-----------------------------------------------------------*/
04101 
04102 #if( configUSE_TASK_NOTIFICATIONS == 1 )
04103 
04104     BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue )
04105     {
04106     TCB_t * pxTCB;
04107     eNotifyValue eOriginalNotifyState;
04108     BaseType_t xReturn = pdPASS;
04109 
04110         configASSERT( xTaskToNotify );
04111         pxTCB = ( TCB_t * ) xTaskToNotify;
04112 
04113         taskENTER_CRITICAL();
04114         {
04115             if( pulPreviousNotificationValue != NULL )
04116             {
04117                 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
04118             }
04119 
04120             eOriginalNotifyState = pxTCB->eNotifyState;
04121 
04122             pxTCB->eNotifyState = eNotified;
04123 
04124             switch( eAction )
04125             {
04126                 case eSetBits   :
04127                     pxTCB->ulNotifiedValue |= ulValue;
04128                     break;
04129 
04130                 case eIncrement :
04131                     ( pxTCB->ulNotifiedValue )++;
04132                     break;
04133 
04134                 case eSetValueWithOverwrite :
04135                     pxTCB->ulNotifiedValue = ulValue;
04136                     break;
04137 
04138                 case eSetValueWithoutOverwrite :
04139                     if( eOriginalNotifyState != eNotified )
04140                     {
04141                         pxTCB->ulNotifiedValue = ulValue;
04142                     }
04143                     else
04144                     {
04145                         /* The value could not be written to the task. */
04146                         xReturn = pdFAIL;
04147                     }
04148                     break;
04149 
04150                 case eNoAction:
04151                     /* The task is being notified without its notify value being
04152                     updated. */
04153                     break;
04154             }
04155 
04156 
04157             /* If the task is in the blocked state specifically to wait for a
04158             notification then unblock it now. */
04159             if( eOriginalNotifyState == eWaitingNotification )
04160             {
04161                 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
04162                 prvAddTaskToReadyList( pxTCB );
04163 
04164                 /* The task should not have been on an event list. */
04165                 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
04166 
04167                 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
04168                 {
04169                     /* The notified task has a priority above the currently
04170                     executing task so a yield is required. */
04171                     taskYIELD_IF_USING_PREEMPTION();
04172                 }
04173                 else
04174                 {
04175                     mtCOVERAGE_TEST_MARKER();
04176                 }
04177             }
04178             else
04179             {
04180                 mtCOVERAGE_TEST_MARKER();
04181             }
04182         }
04183         taskEXIT_CRITICAL();
04184 
04185         return xReturn;
04186     }
04187 
04188 #endif /* configUSE_TASK_NOTIFICATIONS */
04189 /*-----------------------------------------------------------*/
04190 
04191 #if( configUSE_TASK_NOTIFICATIONS == 1 )
04192 
04193     BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken )
04194     {
04195     TCB_t * pxTCB;
04196     eNotifyValue eOriginalNotifyState;
04197     BaseType_t xReturn = pdPASS;
04198     UBaseType_t uxSavedInterruptStatus;
04199 
04200         configASSERT( xTaskToNotify );
04201 
04202         /* RTOS ports that support interrupt nesting have the concept of a
04203         maximum system call (or maximum API call) interrupt priority.
04204         Interrupts that are above the maximum system call priority are keep
04205         permanently enabled, even when the RTOS kernel is in a critical section,
04206         but cannot make any calls to FreeRTOS API functions.  If configASSERT()
04207         is defined in FreeRTOSConfig.h then
04208         portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
04209         failure if a FreeRTOS API function is called from an interrupt that has
04210         been assigned a priority above the configured maximum system call
04211         priority.  Only FreeRTOS functions that end in FromISR can be called
04212         from interrupts that have been assigned a priority at or (logically)
04213         below the maximum system call interrupt priority.  FreeRTOS maintains a
04214         separate interrupt safe API to ensure interrupt entry is as fast and as
04215         simple as possible.  More information (albeit Cortex-M specific) is
04216         provided on the following link:
04217         http://www.freertos.org/RTOS-Cortex-M3-M4.html */
04218         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
04219 
04220         pxTCB = ( TCB_t * ) xTaskToNotify;
04221 
04222         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
04223         {
04224             eOriginalNotifyState = pxTCB->eNotifyState;
04225 
04226             pxTCB->eNotifyState = eNotified;
04227 
04228             switch( eAction )
04229             {
04230                 case eSetBits   :
04231                     pxTCB->ulNotifiedValue |= ulValue;
04232                     break;
04233 
04234                 case eIncrement :
04235                     ( pxTCB->ulNotifiedValue )++;
04236                     break;
04237 
04238                 case eSetValueWithOverwrite :
04239                     pxTCB->ulNotifiedValue = ulValue;
04240                     break;
04241 
04242                 case eSetValueWithoutOverwrite :
04243                     if( eOriginalNotifyState != eNotified )
04244                     {
04245                         pxTCB->ulNotifiedValue = ulValue;
04246                     }
04247                     else
04248                     {
04249                         /* The value could not be written to the task. */
04250                         xReturn = pdFAIL;
04251                     }
04252                     break;
04253 
04254                 case eNoAction :
04255                     /* The task is being notified without its notify value being
04256                     updated. */
04257                     break;
04258             }
04259 
04260 
04261             /* If the task is in the blocked state specifically to wait for a
04262             notification then unblock it now. */
04263             if( eOriginalNotifyState == eWaitingNotification )
04264             {
04265                 /* The task should not have been on an event list. */
04266                 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
04267 
04268                 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
04269                 {
04270                     ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
04271                     prvAddTaskToReadyList( pxTCB );
04272                 }
04273                 else
04274                 {
04275                     /* The delayed and ready lists cannot be accessed, so hold
04276                     this task pending until the scheduler is resumed. */
04277                     vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
04278                 }
04279 
04280                 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
04281                 {
04282                     /* The notified task has a priority above the currently
04283                     executing task so a yield is required. */
04284                     if( pxHigherPriorityTaskWoken != NULL )
04285                     {
04286                         *pxHigherPriorityTaskWoken = pdTRUE;
04287                     }
04288                 }
04289                 else
04290                 {
04291                     mtCOVERAGE_TEST_MARKER();
04292                 }
04293             }
04294         }
04295         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
04296 
04297         return xReturn;
04298     }
04299 
04300 #endif /* configUSE_TASK_NOTIFICATIONS */
04301 /*-----------------------------------------------------------*/
04302 
04303 #if( configUSE_TASK_NOTIFICATIONS == 1 )
04304 
04305     void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken )
04306     {
04307     TCB_t * pxTCB;
04308     eNotifyValue eOriginalNotifyState;
04309     UBaseType_t uxSavedInterruptStatus;
04310 
04311         configASSERT( xTaskToNotify );
04312 
04313         /* RTOS ports that support interrupt nesting have the concept of a
04314         maximum system call (or maximum API call) interrupt priority.
04315         Interrupts that are above the maximum system call priority are keep
04316         permanently enabled, even when the RTOS kernel is in a critical section,
04317         but cannot make any calls to FreeRTOS API functions.  If configASSERT()
04318         is defined in FreeRTOSConfig.h then
04319         portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
04320         failure if a FreeRTOS API function is called from an interrupt that has
04321         been assigned a priority above the configured maximum system call
04322         priority.  Only FreeRTOS functions that end in FromISR can be called
04323         from interrupts that have been assigned a priority at or (logically)
04324         below the maximum system call interrupt priority.  FreeRTOS maintains a
04325         separate interrupt safe API to ensure interrupt entry is as fast and as
04326         simple as possible.  More information (albeit Cortex-M specific) is
04327         provided on the following link:
04328         http://www.freertos.org/RTOS-Cortex-M3-M4.html */
04329         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
04330 
04331         pxTCB = ( TCB_t * ) xTaskToNotify;
04332 
04333         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
04334         {
04335             eOriginalNotifyState = pxTCB->eNotifyState;
04336             pxTCB->eNotifyState = eNotified;
04337 
04338             /* 'Giving' is equivalent to incrementing a count in a counting
04339             semaphore. */
04340             ( pxTCB->ulNotifiedValue )++;
04341 
04342             /* If the task is in the blocked state specifically to wait for a
04343             notification then unblock it now. */
04344             if( eOriginalNotifyState == eWaitingNotification )
04345             {
04346                 /* The task should not have been on an event list. */
04347                 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
04348 
04349                 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
04350                 {
04351                     ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
04352                     prvAddTaskToReadyList( pxTCB );
04353                 }
04354                 else
04355                 {
04356                     /* The delayed and ready lists cannot be accessed, so hold
04357                     this task pending until the scheduler is resumed. */
04358                     vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
04359                 }
04360 
04361                 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
04362                 {
04363                     /* The notified task has a priority above the currently
04364                     executing task so a yield is required. */
04365                     if( pxHigherPriorityTaskWoken != NULL )
04366                     {
04367                         *pxHigherPriorityTaskWoken = pdTRUE;
04368                     }
04369                 }
04370                 else
04371                 {
04372                     mtCOVERAGE_TEST_MARKER();
04373                 }
04374             }
04375         }
04376         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
04377     }
04378 
04379 #endif /* configUSE_TASK_NOTIFICATIONS */
04380 
04381 /*-----------------------------------------------------------*/
04382 
04383 
04384 #ifdef FREERTOS_MODULE_TEST
04385     #include "tasks_test_access_functions.h"
04386 #endif
04387 
04388