]> begriffs open source - freertos/blob - tasks.c
Use the extended movx instruction instead of mov (#676)
[freertos] / tasks.c
1 /*
2  * FreeRTOS Kernel <DEVELOPMENT BRANCH>
3  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * https://www.FreeRTOS.org
25  * https://github.com/FreeRTOS
26  *
27  */
28
29 /* Standard includes. */
30 #include <stdlib.h>
31 #include <string.h>
32
33 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
34  * all the API functions to use the MPU wrappers.  That should only be done when
35  * task.h is included from an application file. */
36 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
37
38 /* FreeRTOS includes. */
39 #include "FreeRTOS.h"
40 #include "task.h"
41 #include "timers.h"
42 #include "stack_macros.h"
43
44 /* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified
45  * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
46  * for the header files above, but not in this file, in order to generate the
47  * correct privileged Vs unprivileged linkage and placement. */
48 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */
49
50 /* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting
51  * functions but without including stdio.h here. */
52 #if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 )
53
54 /* At the bottom of this file are two optional functions that can be used
55  * to generate human readable text from the raw data generated by the
56  * uxTaskGetSystemState() function.  Note the formatting functions are provided
57  * for convenience only, and are NOT considered part of the kernel. */
58     #include <stdio.h>
59 #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
60
61 #if ( configUSE_PREEMPTION == 0 )
62
63 /* If the cooperative scheduler is being used then a yield should not be
64  * performed just because a higher priority task has been woken. */
65     #define taskYIELD_IF_USING_PREEMPTION()
66 #else
67     #define taskYIELD_IF_USING_PREEMPTION()    portYIELD_WITHIN_API()
68 #endif
69
70 /* Values that can be assigned to the ucNotifyState member of the TCB. */
71 #define taskNOT_WAITING_NOTIFICATION              ( ( uint8_t ) 0 ) /* Must be zero as it is the initialised value. */
72 #define taskWAITING_NOTIFICATION                  ( ( uint8_t ) 1 )
73 #define taskNOTIFICATION_RECEIVED                 ( ( uint8_t ) 2 )
74
75 /*
76  * The value used to fill the stack of a task when the task is created.  This
77  * is used purely for checking the high water mark for tasks.
78  */
79 #define tskSTACK_FILL_BYTE                        ( 0xa5U )
80
81 /* Bits used to record how a task's stack and TCB were allocated. */
82 #define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB    ( ( uint8_t ) 0 )
83 #define tskSTATICALLY_ALLOCATED_STACK_ONLY        ( ( uint8_t ) 1 )
84 #define tskSTATICALLY_ALLOCATED_STACK_AND_TCB     ( ( uint8_t ) 2 )
85
86 /* If any of the following are set then task stacks are filled with a known
87  * value so the high water mark can be determined.  If none of the following are
88  * set then don't fill the stack so there is no unnecessary dependency on memset. */
89 #if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
90     #define tskSET_NEW_STACKS_TO_KNOWN_VALUE    1
91 #else
92     #define tskSET_NEW_STACKS_TO_KNOWN_VALUE    0
93 #endif
94
95 /*
96  * Macros used by vListTask to indicate which state a task is in.
97  */
98 #define tskRUNNING_CHAR      ( 'X' )
99 #define tskBLOCKED_CHAR      ( 'B' )
100 #define tskREADY_CHAR        ( 'R' )
101 #define tskDELETED_CHAR      ( 'D' )
102 #define tskSUSPENDED_CHAR    ( 'S' )
103
104 /*
105  * Some kernel aware debuggers require the data the debugger needs access to to
106  * be global, rather than file scope.
107  */
108 #ifdef portREMOVE_STATIC_QUALIFIER
109     #define static
110 #endif
111
112 /* The name allocated to the Idle task.  This can be overridden by defining
113  * configIDLE_TASK_NAME in FreeRTOSConfig.h. */
114 #ifndef configIDLE_TASK_NAME
115     #define configIDLE_TASK_NAME    "IDLE"
116 #endif
117
118 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
119
120 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
121  * performed in a generic way that is not optimised to any particular
122  * microcontroller architecture. */
123
124 /* uxTopReadyPriority holds the priority of the highest priority ready
125  * state task. */
126     #define taskRECORD_READY_PRIORITY( uxPriority ) \
127     {                                               \
128         if( ( uxPriority ) > uxTopReadyPriority )   \
129         {                                           \
130             uxTopReadyPriority = ( uxPriority );    \
131         }                                           \
132     } /* taskRECORD_READY_PRIORITY */
133
134 /*-----------------------------------------------------------*/
135
136     #define taskSELECT_HIGHEST_PRIORITY_TASK()                                \
137     do {                                                                      \
138         UBaseType_t uxTopPriority = uxTopReadyPriority;                       \
139                                                                               \
140         /* Find the highest priority queue that contains ready tasks. */      \
141         while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \
142         {                                                                     \
143             configASSERT( uxTopPriority );                                    \
144             --uxTopPriority;                                                  \
145         }                                                                     \
146                                                                               \
147         /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
148          * the  same priority get an equal share of the processor time. */                    \
149         listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
150         uxTopReadyPriority = uxTopPriority;                                                   \
151     } while( 0 ) /* taskSELECT_HIGHEST_PRIORITY_TASK */
152
153 /*-----------------------------------------------------------*/
154
155 /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
156  * they are only required when a port optimised method of task selection is
157  * being used. */
158     #define taskRESET_READY_PRIORITY( uxPriority )
159     #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
160
161 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
162
163 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
164  * performed in a way that is tailored to the particular microcontroller
165  * architecture being used. */
166
167 /* A port optimised version is provided.  Call the port defined macros. */
168     #define taskRECORD_READY_PRIORITY( uxPriority )    portRECORD_READY_PRIORITY( ( uxPriority ), uxTopReadyPriority )
169
170 /*-----------------------------------------------------------*/
171
172     #define taskSELECT_HIGHEST_PRIORITY_TASK()                                                  \
173     do {                                                                                        \
174         UBaseType_t uxTopPriority;                                                              \
175                                                                                                 \
176         /* Find the highest priority list that contains ready tasks. */                         \
177         portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );                          \
178         configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
179         listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );   \
180     } while( 0 )
181
182 /*-----------------------------------------------------------*/
183
184 /* A port optimised version is provided, call it only if the TCB being reset
185  * is being referenced from a ready list.  If it is referenced from a delayed
186  * or suspended list then it won't be in a ready list. */
187     #define taskRESET_READY_PRIORITY( uxPriority )                                                     \
188     do {                                                                                               \
189         if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \
190         {                                                                                              \
191             portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) );                        \
192         }                                                                                              \
193     } while( 0 )
194
195 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
196
197 /*-----------------------------------------------------------*/
198
199 /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
200  * count overflows. */
201 #define taskSWITCH_DELAYED_LISTS()                                                \
202     do {                                                                          \
203         List_t * pxTemp;                                                          \
204                                                                                   \
205         /* The delayed tasks list should be empty when the lists are switched. */ \
206         configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) );               \
207                                                                                   \
208         pxTemp = pxDelayedTaskList;                                               \
209         pxDelayedTaskList = pxOverflowDelayedTaskList;                            \
210         pxOverflowDelayedTaskList = pxTemp;                                       \
211         xNumOfOverflows++;                                                        \
212         prvResetNextTaskUnblockTime();                                            \
213     } while( 0 )
214
215 /*-----------------------------------------------------------*/
216
217 /*
218  * Place the task represented by pxTCB into the appropriate ready list for
219  * the task.  It is inserted at the end of the list.
220  */
221 #define prvAddTaskToReadyList( pxTCB )                                                                     \
222     do {                                                                                                   \
223         traceMOVED_TASK_TO_READY_STATE( pxTCB );                                                           \
224         taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority );                                                \
225         listINSERT_END( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
226         tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB );                                                      \
227     } while( 0 )
228 /*-----------------------------------------------------------*/
229
230 /*
231  * Several functions take a TaskHandle_t parameter that can optionally be NULL,
232  * where NULL is used to indicate that the handle of the currently executing
233  * task should be used in place of the parameter.  This macro simply checks to
234  * see if the parameter is NULL and returns a pointer to the appropriate TCB.
235  */
236 #define prvGetTCBFromHandle( pxHandle )    ( ( ( pxHandle ) == NULL ) ? pxCurrentTCB : ( pxHandle ) )
237
238 /* The item value of the event list item is normally used to hold the priority
239  * of the task to which it belongs (coded to allow it to be held in reverse
240  * priority order).  However, it is occasionally borrowed for other purposes.  It
241  * is important its value is not updated due to a task priority change while it is
242  * being used for another purpose.  The following bit definition is used to inform
243  * the scheduler that the value should not be changed - in which case it is the
244  * responsibility of whichever module is using the value to ensure it gets set back
245  * to its original value when it is released. */
246 #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
247     #define taskEVENT_LIST_ITEM_VALUE_IN_USE    0x8000U
248 #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
249     #define taskEVENT_LIST_ITEM_VALUE_IN_USE    0x80000000UL
250 #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_64_BITS )
251     #define taskEVENT_LIST_ITEM_VALUE_IN_USE    0x8000000000000000ULL
252 #endif
253
254 /*
255  * Task control block.  A task control block (TCB) is allocated for each task,
256  * and stores task state information, including a pointer to the task's context
257  * (the task's run time environment, including register values)
258  */
259 typedef struct tskTaskControlBlock       /* The old naming convention is used to prevent breaking kernel aware debuggers. */
260 {
261     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. */
262
263     #if ( portUSING_MPU_WRAPPERS == 1 )
264         xMPU_SETTINGS xMPUSettings; /**< The MPU settings are defined as part of the port layer.  THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
265     #endif
266
267     ListItem_t xStateListItem;                  /**< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
268     ListItem_t xEventListItem;                  /**< Used to reference a task from an event list. */
269     UBaseType_t uxPriority;                     /**< The priority of the task.  0 is the lowest priority. */
270     StackType_t * pxStack;                      /**< Points to the start of the stack. */
271     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. */
272
273     #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
274         StackType_t * pxEndOfStack; /**< Points to the highest valid address for the stack. */
275     #endif
276
277     #if ( portCRITICAL_NESTING_IN_TCB == 1 )
278         UBaseType_t uxCriticalNesting; /**< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
279     #endif
280
281     #if ( configUSE_TRACE_FACILITY == 1 )
282         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. */
283         UBaseType_t uxTaskNumber; /**< Stores a number specifically for use by third party trace code. */
284     #endif
285
286     #if ( configUSE_MUTEXES == 1 )
287         UBaseType_t uxBasePriority; /**< The priority last assigned to the task - used by the priority inheritance mechanism. */
288         UBaseType_t uxMutexesHeld;
289     #endif
290
291     #if ( configUSE_APPLICATION_TASK_TAG == 1 )
292         TaskHookFunction_t pxTaskTag;
293     #endif
294
295     #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
296         void * pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
297     #endif
298
299     #if ( configGENERATE_RUN_TIME_STATS == 1 )
300         configRUN_TIME_COUNTER_TYPE ulRunTimeCounter; /**< Stores the amount of time the task has spent in the Running state. */
301     #endif
302
303     #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
304         configTLS_BLOCK_TYPE xTLSBlock; /**< Memory block used as Thread Local Storage (TLS) Block for the task. */
305     #endif
306
307     #if ( configUSE_TASK_NOTIFICATIONS == 1 )
308         volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
309         volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
310     #endif
311
312     /* See the comments in FreeRTOS.h with the definition of
313      * tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
314     #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
315         uint8_t ucStaticallyAllocated;                     /**< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
316     #endif
317
318     #if ( INCLUDE_xTaskAbortDelay == 1 )
319         uint8_t ucDelayAborted;
320     #endif
321
322     #if ( configUSE_POSIX_ERRNO == 1 )
323         int iTaskErrno;
324     #endif
325 } tskTCB;
326
327 /* The old tskTCB name is maintained above then typedefed to the new TCB_t name
328  * below to enable the use of older kernel aware debuggers. */
329 typedef tskTCB TCB_t;
330
331 /*lint -save -e956 A manual analysis and inspection has been used to determine
332  * which static variables must be declared volatile. */
333 portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
334
335 /* Lists for ready and blocked tasks. --------------------
336  * xDelayedTaskList1 and xDelayedTaskList2 could be moved to function scope but
337  * doing so breaks some kernel aware debuggers and debuggers that rely on removing
338  * the static qualifier. */
339 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; /**< Prioritised ready tasks. */
340 PRIVILEGED_DATA static List_t xDelayedTaskList1;                         /**< Delayed tasks. */
341 PRIVILEGED_DATA static List_t xDelayedTaskList2;                         /**< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
342 PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList;              /**< Points to the delayed task list currently being used. */
343 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. */
344 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. */
345
346 #if ( INCLUDE_vTaskDelete == 1 )
347
348     PRIVILEGED_DATA static List_t xTasksWaitingTermination; /**< Tasks that have been deleted - but their memory not yet freed. */
349     PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;
350
351 #endif
352
353 #if ( INCLUDE_vTaskSuspend == 1 )
354
355     PRIVILEGED_DATA static List_t xSuspendedTaskList; /**< Tasks that are currently suspended. */
356
357 #endif
358
359 /* Global POSIX errno. Its value is changed upon context switching to match
360  * the errno of the currently running task. */
361 #if ( configUSE_POSIX_ERRNO == 1 )
362     int FreeRTOS_errno = 0;
363 #endif
364
365 /* Other file private variables. --------------------------------*/
366 PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
367 PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
368 PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
369 PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
370 PRIVILEGED_DATA static volatile TickType_t xPendedTicks = ( TickType_t ) 0U;
371 PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE;
372 PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
373 PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
374 PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */
375 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. */
376
377 /* Improve support for OpenOCD. The kernel tracks Ready tasks via priority lists.
378  * For tracking the state of remote threads, OpenOCD uses uxTopUsedPriority
379  * to determine the number of priority lists to read back from the remote target. */
380 const volatile UBaseType_t uxTopUsedPriority = configMAX_PRIORITIES - 1U;
381
382 /* Context switches are held pending while the scheduler is suspended.  Also,
383  * interrupts must not manipulate the xStateListItem of a TCB, or any of the
384  * lists the xStateListItem can be referenced from, if the scheduler is suspended.
385  * If an interrupt needs to unblock a task while the scheduler is suspended then it
386  * moves the task's event list item into the xPendingReadyList, ready for the
387  * kernel to move the task from the pending ready list into the real ready list
388  * when the scheduler is unsuspended.  The pending ready list itself can only be
389  * accessed from a critical section. */
390 PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) 0U;
391
392 #if ( configGENERATE_RUN_TIME_STATS == 1 )
393
394 /* Do not move these variables to function scope as doing so prevents the
395  * code working with debuggers that need to remove the static qualifier. */
396     PRIVILEGED_DATA static configRUN_TIME_COUNTER_TYPE ulTaskSwitchedInTime = 0UL;    /**< Holds the value of a timer/counter the last time a task was switched in. */
397     PRIVILEGED_DATA static volatile configRUN_TIME_COUNTER_TYPE ulTotalRunTime = 0UL; /**< Holds the total amount of execution time as defined by the run time counter clock. */
398
399 #endif
400
401 /*lint -restore */
402
403 /*-----------------------------------------------------------*/
404
405 /* File private functions. --------------------------------*/
406
407 /**
408  * Utility task that simply returns pdTRUE if the task referenced by xTask is
409  * currently in the Suspended state, or pdFALSE if the task referenced by xTask
410  * is in any other state.
411  */
412 #if ( INCLUDE_vTaskSuspend == 1 )
413
414     static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
415
416 #endif /* INCLUDE_vTaskSuspend */
417
418 /*
419  * Utility to ready all the lists used by the scheduler.  This is called
420  * automatically upon the creation of the first task.
421  */
422 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
423
424 /*
425  * The idle task, which as all tasks is implemented as a never ending loop.
426  * The idle task is automatically created and added to the ready lists upon
427  * creation of the first user task.
428  *
429  * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
430  * language extensions.  The equivalent prototype for this function is:
431  *
432  * void prvIdleTask( void *pvParameters );
433  *
434  */
435 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters ) portNORETURN PRIVILEGED_FUNCTION;
436
437 /*
438  * Utility to free all memory allocated by the scheduler to hold a TCB,
439  * including the stack pointed to by the TCB.
440  *
441  * This does not free memory allocated by the task itself (i.e. memory
442  * allocated by calls to pvPortMalloc from within the tasks application code).
443  */
444 #if ( INCLUDE_vTaskDelete == 1 )
445
446     static void prvDeleteTCB( TCB_t * pxTCB ) PRIVILEGED_FUNCTION;
447
448 #endif
449
450 /*
451  * Used only by the idle task.  This checks to see if anything has been placed
452  * in the list of tasks waiting to be deleted.  If so the task is cleaned up
453  * and its TCB deleted.
454  */
455 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
456
457 /*
458  * The currently executing task is entering the Blocked state.  Add the task to
459  * either the current or the overflow delayed task list.
460  */
461 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
462                                             const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION;
463
464 /*
465  * Fills an TaskStatus_t structure with information on each task that is
466  * referenced from the pxList list (which may be a ready list, a delayed list,
467  * a suspended list, etc.).
468  *
469  * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
470  * NORMAL APPLICATION CODE.
471  */
472 #if ( configUSE_TRACE_FACILITY == 1 )
473
474     static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray,
475                                                      List_t * pxList,
476                                                      eTaskState eState ) PRIVILEGED_FUNCTION;
477
478 #endif
479
480 /*
481  * Searches pxList for a task with name pcNameToQuery - returning a handle to
482  * the task if it is found, or NULL if the task is not found.
483  */
484 #if ( INCLUDE_xTaskGetHandle == 1 )
485
486     static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList,
487                                                      const char pcNameToQuery[] ) PRIVILEGED_FUNCTION;
488
489 #endif
490
491 /*
492  * When a task is created, the stack of the task is filled with a known value.
493  * This function determines the 'high water mark' of the task stack by
494  * determining how much of the stack remains at the original preset value.
495  */
496 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
497
498     static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
499
500 #endif
501
502 /*
503  * Return the amount of time, in ticks, that will pass before the kernel will
504  * next move a task from the Blocked state to the Running state.
505  *
506  * This conditional compilation should use inequality to 0, not equality to 1.
507  * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
508  * defined low power mode implementations require configUSE_TICKLESS_IDLE to be
509  * set to a value other than 1.
510  */
511 #if ( configUSE_TICKLESS_IDLE != 0 )
512
513     static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
514
515 #endif
516
517 /*
518  * Set xNextTaskUnblockTime to the time at which the next Blocked state task
519  * will exit the Blocked state.
520  */
521 static void prvResetNextTaskUnblockTime( void ) PRIVILEGED_FUNCTION;
522
523 #if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 )
524
525 /*
526  * Helper function used to pad task names with spaces when printing out
527  * human readable tables of task information.
528  */
529     static char * prvWriteNameToBuffer( char * pcBuffer,
530                                         const char * pcTaskName ) PRIVILEGED_FUNCTION;
531
532 #endif
533
534 /*
535  * Called after a Task_t structure has been allocated either statically or
536  * dynamically to fill in the structure's members.
537  */
538 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
539                                   const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
540                                   const uint32_t ulStackDepth,
541                                   void * const pvParameters,
542                                   UBaseType_t uxPriority,
543                                   TaskHandle_t * const pxCreatedTask,
544                                   TCB_t * pxNewTCB,
545                                   const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION;
546
547 /*
548  * Called after a new task has been created and initialised to place the task
549  * under the control of the scheduler.
550  */
551 static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
552
553 /*
554  * freertos_tasks_c_additions_init() should only be called if the user definable
555  * macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is the only macro
556  * called by the function.
557  */
558 #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
559
560     static void freertos_tasks_c_additions_init( void ) PRIVILEGED_FUNCTION;
561
562 #endif
563
564 /*-----------------------------------------------------------*/
565
566 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
567
568     TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
569                                     const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
570                                     const uint32_t ulStackDepth,
571                                     void * const pvParameters,
572                                     UBaseType_t uxPriority,
573                                     StackType_t * const puxStackBuffer,
574                                     StaticTask_t * const pxTaskBuffer )
575     {
576         TCB_t * pxNewTCB;
577         TaskHandle_t xReturn;
578
579         configASSERT( puxStackBuffer != NULL );
580         configASSERT( pxTaskBuffer != NULL );
581
582         #if ( configASSERT_DEFINED == 1 )
583         {
584             /* Sanity check that the size of the structure used to declare a
585              * variable of type StaticTask_t equals the size of the real task
586              * structure. */
587             volatile size_t xSize = sizeof( StaticTask_t );
588             configASSERT( xSize == sizeof( TCB_t ) );
589             ( void ) xSize; /* Prevent lint warning when configASSERT() is not used. */
590         }
591         #endif /* configASSERT_DEFINED */
592
593         if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
594         {
595             /* The memory used for the task's TCB and stack are passed into this
596              * function - use them. */
597             pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
598             memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
599             pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;
600
601             #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
602             {
603                 /* Tasks can be created statically or dynamically, so note this
604                  * task was created statically in case the task is later deleted. */
605                 pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
606             }
607             #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
608
609             prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL );
610             prvAddNewTaskToReadyList( pxNewTCB );
611         }
612         else
613         {
614             xReturn = NULL;
615         }
616
617         return xReturn;
618     }
619
620 #endif /* SUPPORT_STATIC_ALLOCATION */
621 /*-----------------------------------------------------------*/
622
623 #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
624
625     BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition,
626                                             TaskHandle_t * pxCreatedTask )
627     {
628         TCB_t * pxNewTCB;
629         BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
630
631         configASSERT( pxTaskDefinition->puxStackBuffer != NULL );
632         configASSERT( pxTaskDefinition->pxTaskBuffer != NULL );
633
634         if( ( pxTaskDefinition->puxStackBuffer != NULL ) && ( pxTaskDefinition->pxTaskBuffer != NULL ) )
635         {
636             /* Allocate space for the TCB.  Where the memory comes from depends
637              * on the implementation of the port malloc function and whether or
638              * not static allocation is being used. */
639             pxNewTCB = ( TCB_t * ) pxTaskDefinition->pxTaskBuffer;
640             memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
641
642             /* Store the stack location in the TCB. */
643             pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
644
645             #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
646             {
647                 /* Tasks can be created statically or dynamically, so note this
648                  * task was created statically in case the task is later deleted. */
649                 pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
650             }
651             #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
652
653             prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
654                                   pxTaskDefinition->pcName,
655                                   ( uint32_t ) pxTaskDefinition->usStackDepth,
656                                   pxTaskDefinition->pvParameters,
657                                   pxTaskDefinition->uxPriority,
658                                   pxCreatedTask, pxNewTCB,
659                                   pxTaskDefinition->xRegions );
660
661             prvAddNewTaskToReadyList( pxNewTCB );
662             xReturn = pdPASS;
663         }
664
665         return xReturn;
666     }
667
668 #endif /* ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
669 /*-----------------------------------------------------------*/
670
671 #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
672
673     BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition,
674                                       TaskHandle_t * pxCreatedTask )
675     {
676         TCB_t * pxNewTCB;
677         BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
678
679         configASSERT( pxTaskDefinition->puxStackBuffer );
680
681         if( pxTaskDefinition->puxStackBuffer != NULL )
682         {
683             /* Allocate space for the TCB.  Where the memory comes from depends
684              * on the implementation of the port malloc function and whether or
685              * not static allocation is being used. */
686             pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
687
688             if( pxNewTCB != NULL )
689             {
690                 memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
691
692                 /* Store the stack location in the TCB. */
693                 pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
694
695                 #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
696                 {
697                     /* Tasks can be created statically or dynamically, so note
698                      * this task had a statically allocated stack in case it is
699                      * later deleted.  The TCB was allocated dynamically. */
700                     pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY;
701                 }
702                 #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
703
704                 prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
705                                       pxTaskDefinition->pcName,
706                                       ( uint32_t ) pxTaskDefinition->usStackDepth,
707                                       pxTaskDefinition->pvParameters,
708                                       pxTaskDefinition->uxPriority,
709                                       pxCreatedTask, pxNewTCB,
710                                       pxTaskDefinition->xRegions );
711
712                 prvAddNewTaskToReadyList( pxNewTCB );
713                 xReturn = pdPASS;
714             }
715         }
716
717         return xReturn;
718     }
719
720 #endif /* portUSING_MPU_WRAPPERS */
721 /*-----------------------------------------------------------*/
722
723 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
724
725     BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
726                             const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
727                             const configSTACK_DEPTH_TYPE usStackDepth,
728                             void * const pvParameters,
729                             UBaseType_t uxPriority,
730                             TaskHandle_t * const pxCreatedTask )
731     {
732         TCB_t * pxNewTCB;
733         BaseType_t xReturn;
734
735         /* If the stack grows down then allocate the stack then the TCB so the stack
736          * does not grow into the TCB.  Likewise if the stack grows up then allocate
737          * the TCB then the stack. */
738         #if ( portSTACK_GROWTH > 0 )
739         {
740             /* Allocate space for the TCB.  Where the memory comes from depends on
741              * the implementation of the port malloc function and whether or not static
742              * allocation is being used. */
743             pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
744
745             if( pxNewTCB != NULL )
746             {
747                 memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
748
749                 /* Allocate space for the stack used by the task being created.
750                  * The base of the stack memory stored in the TCB so the task can
751                  * be deleted later if required. */
752                 pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
753
754                 if( pxNewTCB->pxStack == NULL )
755                 {
756                     /* Could not allocate the stack.  Delete the allocated TCB. */
757                     vPortFree( pxNewTCB );
758                     pxNewTCB = NULL;
759                 }
760             }
761         }
762         #else /* portSTACK_GROWTH */
763         {
764             StackType_t * pxStack;
765
766             /* Allocate space for the stack used by the task being created. */
767             pxStack = pvPortMallocStack( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */
768
769             if( pxStack != NULL )
770             {
771                 /* Allocate space for the TCB. */
772                 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */
773
774                 if( pxNewTCB != NULL )
775                 {
776                     memset( ( void * ) pxNewTCB, 0x00, sizeof( TCB_t ) );
777
778                     /* Store the stack location in the TCB. */
779                     pxNewTCB->pxStack = pxStack;
780                 }
781                 else
782                 {
783                     /* The stack cannot be used as the TCB was not created.  Free
784                      * it again. */
785                     vPortFreeStack( pxStack );
786                 }
787             }
788             else
789             {
790                 pxNewTCB = NULL;
791             }
792         }
793         #endif /* portSTACK_GROWTH */
794
795         if( pxNewTCB != NULL )
796         {
797             #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e9029 !e731 Macro has been consolidated for readability reasons. */
798             {
799                 /* Tasks can be created statically or dynamically, so note this
800                  * task was created dynamically in case it is later deleted. */
801                 pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
802             }
803             #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
804
805             prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
806             prvAddNewTaskToReadyList( pxNewTCB );
807             xReturn = pdPASS;
808         }
809         else
810         {
811             xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
812         }
813
814         return xReturn;
815     }
816
817 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
818 /*-----------------------------------------------------------*/
819
820 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
821                                   const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
822                                   const uint32_t ulStackDepth,
823                                   void * const pvParameters,
824                                   UBaseType_t uxPriority,
825                                   TaskHandle_t * const pxCreatedTask,
826                                   TCB_t * pxNewTCB,
827                                   const MemoryRegion_t * const xRegions )
828 {
829     StackType_t * pxTopOfStack;
830     UBaseType_t x;
831
832     #if ( portUSING_MPU_WRAPPERS == 1 )
833         /* Should the task be created in privileged mode? */
834         BaseType_t xRunPrivileged;
835
836         if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
837         {
838             xRunPrivileged = pdTRUE;
839         }
840         else
841         {
842             xRunPrivileged = pdFALSE;
843         }
844         uxPriority &= ~portPRIVILEGE_BIT;
845     #endif /* portUSING_MPU_WRAPPERS == 1 */
846
847     /* Avoid dependency on memset() if it is not required. */
848     #if ( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 )
849     {
850         /* Fill the stack with a known value to assist debugging. */
851         ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );
852     }
853     #endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */
854
855     /* Calculate the top of stack address.  This depends on whether the stack
856      * grows from high memory to low (as per the 80x86) or vice versa.
857      * portSTACK_GROWTH is used to make the result positive or negative as required
858      * by the port. */
859     #if ( portSTACK_GROWTH < 0 )
860     {
861         pxTopOfStack = &( pxNewTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] );
862         pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 !e9033 !e9078 MISRA exception.  Avoiding casts between pointers and integers is not practical.  Size differences accounted for using portPOINTER_SIZE_TYPE type.  Checked by assert(). */
863
864         /* Check the alignment of the calculated top of stack is correct. */
865         configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
866
867         #if ( configRECORD_STACK_HIGH_ADDRESS == 1 )
868         {
869             /* Also record the stack's high address, which may assist
870              * debugging. */
871             pxNewTCB->pxEndOfStack = pxTopOfStack;
872         }
873         #endif /* configRECORD_STACK_HIGH_ADDRESS */
874     }
875     #else /* portSTACK_GROWTH */
876     {
877         pxTopOfStack = pxNewTCB->pxStack;
878
879         /* Check the alignment of the stack buffer is correct. */
880         configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
881
882         /* The other extreme of the stack space is required if stack checking is
883          * performed. */
884         pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
885     }
886     #endif /* portSTACK_GROWTH */
887
888     /* Store the task name in the TCB. */
889     if( pcName != NULL )
890     {
891         for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
892         {
893             pxNewTCB->pcTaskName[ x ] = pcName[ x ];
894
895             /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
896              * configMAX_TASK_NAME_LEN characters just in case the memory after the
897              * string is not accessible (extremely unlikely). */
898             if( pcName[ x ] == ( char ) 0x00 )
899             {
900                 break;
901             }
902             else
903             {
904                 mtCOVERAGE_TEST_MARKER();
905             }
906         }
907
908         /* Ensure the name string is terminated in the case that the string length
909          * was greater or equal to configMAX_TASK_NAME_LEN. */
910         pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
911     }
912     else
913     {
914         mtCOVERAGE_TEST_MARKER();
915     }
916
917     /* This is used as an array index so must ensure it's not too large. */
918     configASSERT( uxPriority < configMAX_PRIORITIES );
919
920     if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
921     {
922         uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
923     }
924     else
925     {
926         mtCOVERAGE_TEST_MARKER();
927     }
928
929     pxNewTCB->uxPriority = uxPriority;
930     #if ( configUSE_MUTEXES == 1 )
931     {
932         pxNewTCB->uxBasePriority = uxPriority;
933     }
934     #endif /* configUSE_MUTEXES */
935
936     vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
937     vListInitialiseItem( &( pxNewTCB->xEventListItem ) );
938
939     /* Set the pxNewTCB as a link back from the ListItem_t.  This is so we can get
940      * back to  the containing TCB from a generic item in a list. */
941     listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );
942
943     /* Event lists are always in priority order. */
944     listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
945     listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );
946
947     #if ( portUSING_MPU_WRAPPERS == 1 )
948     {
949         vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth );
950     }
951     #else
952     {
953         /* Avoid compiler warning about unreferenced parameter. */
954         ( void ) xRegions;
955     }
956     #endif
957
958     #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
959     {
960         /* Allocate and initialize memory for the task's TLS Block. */
961         configINIT_TLS_BLOCK( pxNewTCB->xTLSBlock, pxTopOfStack );
962     }
963     #endif
964
965     /* Initialize the TCB stack to look as if the task was already running,
966      * but had been interrupted by the scheduler.  The return address is set
967      * to the start of the task function. Once the stack has been initialised
968      * the top of stack variable is updated. */
969     #if ( portUSING_MPU_WRAPPERS == 1 )
970     {
971         /* If the port has capability to detect stack overflow,
972          * pass the stack end address to the stack initialization
973          * function as well. */
974         #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
975         {
976             #if ( portSTACK_GROWTH < 0 )
977             {
978                 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters, xRunPrivileged );
979             }
980             #else /* portSTACK_GROWTH */
981             {
982                 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters, xRunPrivileged );
983             }
984             #endif /* portSTACK_GROWTH */
985         }
986         #else /* portHAS_STACK_OVERFLOW_CHECKING */
987         {
988             pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
989         }
990         #endif /* portHAS_STACK_OVERFLOW_CHECKING */
991     }
992     #else /* portUSING_MPU_WRAPPERS */
993     {
994         /* If the port has capability to detect stack overflow,
995          * pass the stack end address to the stack initialization
996          * function as well. */
997         #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 )
998         {
999             #if ( portSTACK_GROWTH < 0 )
1000             {
1001                 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxStack, pxTaskCode, pvParameters );
1002             }
1003             #else /* portSTACK_GROWTH */
1004             {
1005                 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxNewTCB->pxEndOfStack, pxTaskCode, pvParameters );
1006             }
1007             #endif /* portSTACK_GROWTH */
1008         }
1009         #else /* portHAS_STACK_OVERFLOW_CHECKING */
1010         {
1011             pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
1012         }
1013         #endif /* portHAS_STACK_OVERFLOW_CHECKING */
1014     }
1015     #endif /* portUSING_MPU_WRAPPERS */
1016
1017     if( pxCreatedTask != NULL )
1018     {
1019         /* Pass the handle out in an anonymous way.  The handle can be used to
1020          * change the created task's priority, delete the created task, etc.*/
1021         *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
1022     }
1023     else
1024     {
1025         mtCOVERAGE_TEST_MARKER();
1026     }
1027 }
1028 /*-----------------------------------------------------------*/
1029
1030 static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
1031 {
1032     /* Ensure interrupts don't access the task lists while the lists are being
1033      * updated. */
1034     taskENTER_CRITICAL();
1035     {
1036         uxCurrentNumberOfTasks++;
1037
1038         if( pxCurrentTCB == NULL )
1039         {
1040             /* There are no other tasks, or all the other tasks are in
1041              * the suspended state - make this the current task. */
1042             pxCurrentTCB = pxNewTCB;
1043
1044             if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
1045             {
1046                 /* This is the first task to be created so do the preliminary
1047                  * initialisation required.  We will not recover if this call
1048                  * fails, but we will report the failure. */
1049                 prvInitialiseTaskLists();
1050             }
1051             else
1052             {
1053                 mtCOVERAGE_TEST_MARKER();
1054             }
1055         }
1056         else
1057         {
1058             /* If the scheduler is not already running, make this task the
1059              * current task if it is the highest priority task to be created
1060              * so far. */
1061             if( xSchedulerRunning == pdFALSE )
1062             {
1063                 if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )
1064                 {
1065                     pxCurrentTCB = pxNewTCB;
1066                 }
1067                 else
1068                 {
1069                     mtCOVERAGE_TEST_MARKER();
1070                 }
1071             }
1072             else
1073             {
1074                 mtCOVERAGE_TEST_MARKER();
1075             }
1076         }
1077
1078         uxTaskNumber++;
1079
1080         #if ( configUSE_TRACE_FACILITY == 1 )
1081         {
1082             /* Add a counter into the TCB for tracing only. */
1083             pxNewTCB->uxTCBNumber = uxTaskNumber;
1084         }
1085         #endif /* configUSE_TRACE_FACILITY */
1086         traceTASK_CREATE( pxNewTCB );
1087
1088         prvAddTaskToReadyList( pxNewTCB );
1089
1090         portSETUP_TCB( pxNewTCB );
1091     }
1092     taskEXIT_CRITICAL();
1093
1094     if( xSchedulerRunning != pdFALSE )
1095     {
1096         /* If the created task is of a higher priority than the current task
1097          * then it should run now. */
1098         if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority )
1099         {
1100             taskYIELD_IF_USING_PREEMPTION();
1101         }
1102         else
1103         {
1104             mtCOVERAGE_TEST_MARKER();
1105         }
1106     }
1107     else
1108     {
1109         mtCOVERAGE_TEST_MARKER();
1110     }
1111 }
1112 /*-----------------------------------------------------------*/
1113
1114 #if ( INCLUDE_vTaskDelete == 1 )
1115
1116     void vTaskDelete( TaskHandle_t xTaskToDelete )
1117     {
1118         TCB_t * pxTCB;
1119
1120         taskENTER_CRITICAL();
1121         {
1122             /* If null is passed in here then it is the calling task that is
1123              * being deleted. */
1124             pxTCB = prvGetTCBFromHandle( xTaskToDelete );
1125
1126             /* Remove task from the ready/delayed list. */
1127             if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
1128             {
1129                 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
1130             }
1131             else
1132             {
1133                 mtCOVERAGE_TEST_MARKER();
1134             }
1135
1136             /* Is the task waiting on an event also? */
1137             if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
1138             {
1139                 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
1140             }
1141             else
1142             {
1143                 mtCOVERAGE_TEST_MARKER();
1144             }
1145
1146             /* Increment the uxTaskNumber also so kernel aware debuggers can
1147              * detect that the task lists need re-generating.  This is done before
1148              * portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will
1149              * not return. */
1150             uxTaskNumber++;
1151
1152             if( pxTCB == pxCurrentTCB )
1153             {
1154                 /* A task is deleting itself.  This cannot complete within the
1155                  * task itself, as a context switch to another task is required.
1156                  * Place the task in the termination list.  The idle task will
1157                  * check the termination list and free up any memory allocated by
1158                  * the scheduler for the TCB and stack of the deleted task. */
1159                 vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );
1160
1161                 /* Increment the ucTasksDeleted variable so the idle task knows
1162                  * there is a task that has been deleted and that it should therefore
1163                  * check the xTasksWaitingTermination list. */
1164                 ++uxDeletedTasksWaitingCleanUp;
1165
1166                 /* Call the delete hook before portPRE_TASK_DELETE_HOOK() as
1167                  * portPRE_TASK_DELETE_HOOK() does not return in the Win32 port. */
1168                 traceTASK_DELETE( pxTCB );
1169
1170                 /* The pre-delete hook is primarily for the Windows simulator,
1171                  * in which Windows specific clean up operations are performed,
1172                  * after which it is not possible to yield away from this task -
1173                  * hence xYieldPending is used to latch that a context switch is
1174                  * required. */
1175                 portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
1176             }
1177             else
1178             {
1179                 --uxCurrentNumberOfTasks;
1180                 traceTASK_DELETE( pxTCB );
1181
1182                 /* Reset the next expected unblock time in case it referred to
1183                  * the task that has just been deleted. */
1184                 prvResetNextTaskUnblockTime();
1185             }
1186         }
1187         taskEXIT_CRITICAL();
1188
1189         /* If the task is not deleting itself, call prvDeleteTCB from outside of
1190          * critical section. If a task deletes itself, prvDeleteTCB is called
1191          * from prvCheckTasksWaitingTermination which is called from Idle task. */
1192         if( pxTCB != pxCurrentTCB )
1193         {
1194             prvDeleteTCB( pxTCB );
1195         }
1196
1197         /* Force a reschedule if it is the currently running task that has just
1198          * been deleted. */
1199         if( xSchedulerRunning != pdFALSE )
1200         {
1201             if( pxTCB == pxCurrentTCB )
1202             {
1203                 configASSERT( uxSchedulerSuspended == ( UBaseType_t ) 0U );
1204                 portYIELD_WITHIN_API();
1205             }
1206             else
1207             {
1208                 mtCOVERAGE_TEST_MARKER();
1209             }
1210         }
1211     }
1212
1213 #endif /* INCLUDE_vTaskDelete */
1214 /*-----------------------------------------------------------*/
1215
1216 #if ( INCLUDE_xTaskDelayUntil == 1 )
1217
1218     BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
1219                                 const TickType_t xTimeIncrement )
1220     {
1221         TickType_t xTimeToWake;
1222         BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
1223
1224         configASSERT( pxPreviousWakeTime );
1225         configASSERT( ( xTimeIncrement > 0U ) );
1226         configASSERT( uxSchedulerSuspended == ( UBaseType_t ) 0U );
1227
1228         vTaskSuspendAll();
1229         {
1230             /* Minor optimisation.  The tick count cannot change in this
1231              * block. */
1232             const TickType_t xConstTickCount = xTickCount;
1233
1234             /* Generate the tick time at which the task wants to wake. */
1235             xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
1236
1237             if( xConstTickCount < *pxPreviousWakeTime )
1238             {
1239                 /* The tick count has overflowed since this function was
1240                  * lasted called.  In this case the only time we should ever
1241                  * actually delay is if the wake time has also  overflowed,
1242                  * and the wake time is greater than the tick time.  When this
1243                  * is the case it is as if neither time had overflowed. */
1244                 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
1245                 {
1246                     xShouldDelay = pdTRUE;
1247                 }
1248                 else
1249                 {
1250                     mtCOVERAGE_TEST_MARKER();
1251                 }
1252             }
1253             else
1254             {
1255                 /* The tick time has not overflowed.  In this case we will
1256                  * delay if either the wake time has overflowed, and/or the
1257                  * tick time is less than the wake time. */
1258                 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
1259                 {
1260                     xShouldDelay = pdTRUE;
1261                 }
1262                 else
1263                 {
1264                     mtCOVERAGE_TEST_MARKER();
1265                 }
1266             }
1267
1268             /* Update the wake time ready for the next call. */
1269             *pxPreviousWakeTime = xTimeToWake;
1270
1271             if( xShouldDelay != pdFALSE )
1272             {
1273                 traceTASK_DELAY_UNTIL( xTimeToWake );
1274
1275                 /* prvAddCurrentTaskToDelayedList() needs the block time, not
1276                  * the time to wake, so subtract the current tick count. */
1277                 prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE );
1278             }
1279             else
1280             {
1281                 mtCOVERAGE_TEST_MARKER();
1282             }
1283         }
1284         xAlreadyYielded = xTaskResumeAll();
1285
1286         /* Force a reschedule if xTaskResumeAll has not already done so, we may
1287          * have put ourselves to sleep. */
1288         if( xAlreadyYielded == pdFALSE )
1289         {
1290             portYIELD_WITHIN_API();
1291         }
1292         else
1293         {
1294             mtCOVERAGE_TEST_MARKER();
1295         }
1296
1297         return xShouldDelay;
1298     }
1299
1300 #endif /* INCLUDE_xTaskDelayUntil */
1301 /*-----------------------------------------------------------*/
1302
1303 #if ( INCLUDE_vTaskDelay == 1 )
1304
1305     void vTaskDelay( const TickType_t xTicksToDelay )
1306     {
1307         BaseType_t xAlreadyYielded = pdFALSE;
1308
1309         /* A delay time of zero just forces a reschedule. */
1310         if( xTicksToDelay > ( TickType_t ) 0U )
1311         {
1312             configASSERT( uxSchedulerSuspended == ( UBaseType_t ) 0U );
1313             vTaskSuspendAll();
1314             {
1315                 traceTASK_DELAY();
1316
1317                 /* A task that is removed from the event list while the
1318                  * scheduler is suspended will not get placed in the ready
1319                  * list or removed from the blocked list until the scheduler
1320                  * is resumed.
1321                  *
1322                  * This task cannot be in an event list as it is the currently
1323                  * executing task. */
1324                 prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
1325             }
1326             xAlreadyYielded = xTaskResumeAll();
1327         }
1328         else
1329         {
1330             mtCOVERAGE_TEST_MARKER();
1331         }
1332
1333         /* Force a reschedule if xTaskResumeAll has not already done so, we may
1334          * have put ourselves to sleep. */
1335         if( xAlreadyYielded == pdFALSE )
1336         {
1337             portYIELD_WITHIN_API();
1338         }
1339         else
1340         {
1341             mtCOVERAGE_TEST_MARKER();
1342         }
1343     }
1344
1345 #endif /* INCLUDE_vTaskDelay */
1346 /*-----------------------------------------------------------*/
1347
1348 #if ( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_xTaskAbortDelay == 1 ) )
1349
1350     eTaskState eTaskGetState( TaskHandle_t xTask )
1351     {
1352         eTaskState eReturn;
1353         List_t const * pxStateList;
1354         List_t const * pxDelayedList;
1355         List_t const * pxOverflowedDelayedList;
1356         const TCB_t * const pxTCB = xTask;
1357
1358         configASSERT( pxTCB );
1359
1360         if( pxTCB == pxCurrentTCB )
1361         {
1362             /* The task calling this function is querying its own state. */
1363             eReturn = eRunning;
1364         }
1365         else
1366         {
1367             taskENTER_CRITICAL();
1368             {
1369                 pxStateList = listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) );
1370                 pxDelayedList = pxDelayedTaskList;
1371                 pxOverflowedDelayedList = pxOverflowDelayedTaskList;
1372             }
1373             taskEXIT_CRITICAL();
1374
1375             if( ( pxStateList == pxDelayedList ) || ( pxStateList == pxOverflowedDelayedList ) )
1376             {
1377                 /* The task being queried is referenced from one of the Blocked
1378                  * lists. */
1379                 eReturn = eBlocked;
1380             }
1381
1382             #if ( INCLUDE_vTaskSuspend == 1 )
1383                 else if( pxStateList == &xSuspendedTaskList )
1384                 {
1385                     /* The task being queried is referenced from the suspended
1386                      * list.  Is it genuinely suspended or is it blocked
1387                      * indefinitely? */
1388                     if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
1389                     {
1390                         #if ( configUSE_TASK_NOTIFICATIONS == 1 )
1391                         {
1392                             BaseType_t x;
1393
1394                             /* The task does not appear on the event list item of
1395                              * and of the RTOS objects, but could still be in the
1396                              * blocked state if it is waiting on its notification
1397                              * rather than waiting on an object.  If not, is
1398                              * suspended. */
1399                             eReturn = eSuspended;
1400
1401                             for( x = 0; x < configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )
1402                             {
1403                                 if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION )
1404                                 {
1405                                     eReturn = eBlocked;
1406                                     break;
1407                                 }
1408                             }
1409                         }
1410                         #else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
1411                         {
1412                             eReturn = eSuspended;
1413                         }
1414                         #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
1415                     }
1416                     else
1417                     {
1418                         eReturn = eBlocked;
1419                     }
1420                 }
1421             #endif /* if ( INCLUDE_vTaskSuspend == 1 ) */
1422
1423             #if ( INCLUDE_vTaskDelete == 1 )
1424                 else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) )
1425                 {
1426                     /* The task being queried is referenced from the deleted
1427                      * tasks list, or it is not referenced from any lists at
1428                      * all. */
1429                     eReturn = eDeleted;
1430                 }
1431             #endif
1432
1433             else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */
1434             {
1435                 /* If the task is not in any other state, it must be in the
1436                  * Ready (including pending ready) state. */
1437                 eReturn = eReady;
1438             }
1439         }
1440
1441         return eReturn;
1442     } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
1443
1444 #endif /* INCLUDE_eTaskGetState */
1445 /*-----------------------------------------------------------*/
1446
1447 #if ( INCLUDE_uxTaskPriorityGet == 1 )
1448
1449     UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask )
1450     {
1451         TCB_t const * pxTCB;
1452         UBaseType_t uxReturn;
1453
1454         taskENTER_CRITICAL();
1455         {
1456             /* If null is passed in here then it is the priority of the task
1457              * that called uxTaskPriorityGet() that is being queried. */
1458             pxTCB = prvGetTCBFromHandle( xTask );
1459             uxReturn = pxTCB->uxPriority;
1460         }
1461         taskEXIT_CRITICAL();
1462
1463         return uxReturn;
1464     }
1465
1466 #endif /* INCLUDE_uxTaskPriorityGet */
1467 /*-----------------------------------------------------------*/
1468
1469 #if ( INCLUDE_uxTaskPriorityGet == 1 )
1470
1471     UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask )
1472     {
1473         TCB_t const * pxTCB;
1474         UBaseType_t uxReturn;
1475         portBASE_TYPE xSavedInterruptState;
1476
1477         /* RTOS ports that support interrupt nesting have the concept of a
1478          * maximum  system call (or maximum API call) interrupt priority.
1479          * Interrupts that are  above the maximum system call priority are keep
1480          * permanently enabled, even when the RTOS kernel is in a critical section,
1481          * but cannot make any calls to FreeRTOS API functions.  If configASSERT()
1482          * is defined in FreeRTOSConfig.h then
1483          * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
1484          * failure if a FreeRTOS API function is called from an interrupt that has
1485          * been assigned a priority above the configured maximum system call
1486          * priority.  Only FreeRTOS functions that end in FromISR can be called
1487          * from interrupts  that have been assigned a priority at or (logically)
1488          * below the maximum system call interrupt priority.  FreeRTOS maintains a
1489          * separate interrupt safe API to ensure interrupt entry is as fast and as
1490          * simple as possible.  More information (albeit Cortex-M specific) is
1491          * provided on the following link:
1492          * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
1493         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
1494
1495         xSavedInterruptState = portSET_INTERRUPT_MASK_FROM_ISR();
1496         {
1497             /* If null is passed in here then it is the priority of the calling
1498              * task that is being queried. */
1499             pxTCB = prvGetTCBFromHandle( xTask );
1500             uxReturn = pxTCB->uxPriority;
1501         }
1502         portCLEAR_INTERRUPT_MASK_FROM_ISR( xSavedInterruptState );
1503
1504         return uxReturn;
1505     }
1506
1507 #endif /* INCLUDE_uxTaskPriorityGet */
1508 /*-----------------------------------------------------------*/
1509
1510 #if ( INCLUDE_vTaskPrioritySet == 1 )
1511
1512     void vTaskPrioritySet( TaskHandle_t xTask,
1513                            UBaseType_t uxNewPriority )
1514     {
1515         TCB_t * pxTCB;
1516         UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;
1517         BaseType_t xYieldRequired = pdFALSE;
1518
1519         configASSERT( uxNewPriority < configMAX_PRIORITIES );
1520
1521         /* Ensure the new priority is valid. */
1522         if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
1523         {
1524             uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
1525         }
1526         else
1527         {
1528             mtCOVERAGE_TEST_MARKER();
1529         }
1530
1531         taskENTER_CRITICAL();
1532         {
1533             /* If null is passed in here then it is the priority of the calling
1534              * task that is being changed. */
1535             pxTCB = prvGetTCBFromHandle( xTask );
1536
1537             traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
1538
1539             #if ( configUSE_MUTEXES == 1 )
1540             {
1541                 uxCurrentBasePriority = pxTCB->uxBasePriority;
1542             }
1543             #else
1544             {
1545                 uxCurrentBasePriority = pxTCB->uxPriority;
1546             }
1547             #endif
1548
1549             if( uxCurrentBasePriority != uxNewPriority )
1550             {
1551                 /* The priority change may have readied a task of higher
1552                  * priority than the calling task. */
1553                 if( uxNewPriority > uxCurrentBasePriority )
1554                 {
1555                     if( pxTCB != pxCurrentTCB )
1556                     {
1557                         /* The priority of a task other than the currently
1558                          * running task is being raised.  Is the priority being
1559                          * raised above that of the running task? */
1560                         if( uxNewPriority > pxCurrentTCB->uxPriority )
1561                         {
1562                             xYieldRequired = pdTRUE;
1563                         }
1564                         else
1565                         {
1566                             mtCOVERAGE_TEST_MARKER();
1567                         }
1568                     }
1569                     else
1570                     {
1571                         /* The priority of the running task is being raised,
1572                          * but the running task must already be the highest
1573                          * priority task able to run so no yield is required. */
1574                     }
1575                 }
1576                 else if( pxTCB == pxCurrentTCB )
1577                 {
1578                     /* Setting the priority of the running task down means
1579                      * there may now be another task of higher priority that
1580                      * is ready to execute. */
1581                     xYieldRequired = pdTRUE;
1582                 }
1583                 else
1584                 {
1585                     /* Setting the priority of any other task down does not
1586                      * require a yield as the running task must be above the
1587                      * new priority of the task being modified. */
1588                 }
1589
1590                 /* Remember the ready list the task might be referenced from
1591                  * before its uxPriority member is changed so the
1592                  * taskRESET_READY_PRIORITY() macro can function correctly. */
1593                 uxPriorityUsedOnEntry = pxTCB->uxPriority;
1594
1595                 #if ( configUSE_MUTEXES == 1 )
1596                 {
1597                     /* Only change the priority being used if the task is not
1598                      * currently using an inherited priority. */
1599                     if( pxTCB->uxBasePriority == pxTCB->uxPriority )
1600                     {
1601                         pxTCB->uxPriority = uxNewPriority;
1602                     }
1603                     else
1604                     {
1605                         mtCOVERAGE_TEST_MARKER();
1606                     }
1607
1608                     /* The base priority gets set whatever. */
1609                     pxTCB->uxBasePriority = uxNewPriority;
1610                 }
1611                 #else /* if ( configUSE_MUTEXES == 1 ) */
1612                 {
1613                     pxTCB->uxPriority = uxNewPriority;
1614                 }
1615                 #endif /* if ( configUSE_MUTEXES == 1 ) */
1616
1617                 /* Only reset the event list item value if the value is not
1618                  * being used for anything else. */
1619                 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
1620                 {
1621                     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. */
1622                 }
1623                 else
1624                 {
1625                     mtCOVERAGE_TEST_MARKER();
1626                 }
1627
1628                 /* If the task is in the blocked or suspended list we need do
1629                  * nothing more than change its priority variable. However, if
1630                  * the task is in a ready list it needs to be removed and placed
1631                  * in the list appropriate to its new priority. */
1632                 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
1633                 {
1634                     /* The task is currently in its ready list - remove before
1635                      * adding it to its new ready list.  As we are in a critical
1636                      * section we can do this even if the scheduler is suspended. */
1637                     if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
1638                     {
1639                         /* It is known that the task is in its ready list so
1640                          * there is no need to check again and the port level
1641                          * reset macro can be called directly. */
1642                         portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
1643                     }
1644                     else
1645                     {
1646                         mtCOVERAGE_TEST_MARKER();
1647                     }
1648
1649                     prvAddTaskToReadyList( pxTCB );
1650                 }
1651                 else
1652                 {
1653                     mtCOVERAGE_TEST_MARKER();
1654                 }
1655
1656                 if( xYieldRequired != pdFALSE )
1657                 {
1658                     taskYIELD_IF_USING_PREEMPTION();
1659                 }
1660                 else
1661                 {
1662                     mtCOVERAGE_TEST_MARKER();
1663                 }
1664
1665                 /* Remove compiler warning about unused variables when the port
1666                  * optimised task selection is not being used. */
1667                 ( void ) uxPriorityUsedOnEntry;
1668             }
1669         }
1670         taskEXIT_CRITICAL();
1671     }
1672
1673 #endif /* INCLUDE_vTaskPrioritySet */
1674 /*-----------------------------------------------------------*/
1675
1676 #if ( INCLUDE_vTaskSuspend == 1 )
1677
1678     void vTaskSuspend( TaskHandle_t xTaskToSuspend )
1679     {
1680         TCB_t * pxTCB;
1681
1682         taskENTER_CRITICAL();
1683         {
1684             /* If null is passed in here then it is the running task that is
1685              * being suspended. */
1686             pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
1687
1688             traceTASK_SUSPEND( pxTCB );
1689
1690             /* Remove task from the ready/delayed list and place in the
1691              * suspended list. */
1692             if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
1693             {
1694                 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
1695             }
1696             else
1697             {
1698                 mtCOVERAGE_TEST_MARKER();
1699             }
1700
1701             /* Is the task waiting on an event also? */
1702             if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
1703             {
1704                 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
1705             }
1706             else
1707             {
1708                 mtCOVERAGE_TEST_MARKER();
1709             }
1710
1711             vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
1712
1713             #if ( configUSE_TASK_NOTIFICATIONS == 1 )
1714             {
1715                 BaseType_t x;
1716
1717                 for( x = 0; x < configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )
1718                 {
1719                     if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION )
1720                     {
1721                         /* The task was blocked to wait for a notification, but is
1722                          * now suspended, so no notification was received. */
1723                         pxTCB->ucNotifyState[ x ] = taskNOT_WAITING_NOTIFICATION;
1724                     }
1725                 }
1726             }
1727             #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
1728         }
1729         taskEXIT_CRITICAL();
1730
1731         if( xSchedulerRunning != pdFALSE )
1732         {
1733             /* Reset the next expected unblock time in case it referred to the
1734              * task that is now in the Suspended state. */
1735             taskENTER_CRITICAL();
1736             {
1737                 prvResetNextTaskUnblockTime();
1738             }
1739             taskEXIT_CRITICAL();
1740         }
1741         else
1742         {
1743             mtCOVERAGE_TEST_MARKER();
1744         }
1745
1746         if( pxTCB == pxCurrentTCB )
1747         {
1748             if( xSchedulerRunning != pdFALSE )
1749             {
1750                 /* The current task has just been suspended. */
1751                 configASSERT( uxSchedulerSuspended == ( UBaseType_t ) 0U );
1752                 portYIELD_WITHIN_API();
1753             }
1754             else
1755             {
1756                 /* The scheduler is not running, but the task that was pointed
1757                  * to by pxCurrentTCB has just been suspended and pxCurrentTCB
1758                  * must be adjusted to point to a different task. */
1759                 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) /*lint !e931 Right has no side effect, just volatile. */
1760                 {
1761                     /* No other tasks are ready, so set pxCurrentTCB back to
1762                      * NULL so when the next task is created pxCurrentTCB will
1763                      * be set to point to it no matter what its relative priority
1764                      * is. */
1765                     pxCurrentTCB = NULL;
1766                 }
1767                 else
1768                 {
1769                     vTaskSwitchContext();
1770                 }
1771             }
1772         }
1773         else
1774         {
1775             mtCOVERAGE_TEST_MARKER();
1776         }
1777     }
1778
1779 #endif /* INCLUDE_vTaskSuspend */
1780 /*-----------------------------------------------------------*/
1781
1782 #if ( INCLUDE_vTaskSuspend == 1 )
1783
1784     static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
1785     {
1786         BaseType_t xReturn = pdFALSE;
1787         const TCB_t * const pxTCB = xTask;
1788
1789         /* Accesses xPendingReadyList so must be called from a critical
1790          * section. */
1791
1792         /* It does not make sense to check if the calling task is suspended. */
1793         configASSERT( xTask );
1794
1795         /* Is the task being resumed actually in the suspended list? */
1796         if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE )
1797         {
1798             /* Has the task already been resumed from within an ISR? */
1799             if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
1800             {
1801                 /* Is it in the suspended list because it is in the Suspended
1802                  * state, or because is is blocked with no timeout? */
1803                 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) /*lint !e961.  The cast is only redundant when NULL is used. */
1804                 {
1805                     xReturn = pdTRUE;
1806                 }
1807                 else
1808                 {
1809                     mtCOVERAGE_TEST_MARKER();
1810                 }
1811             }
1812             else
1813             {
1814                 mtCOVERAGE_TEST_MARKER();
1815             }
1816         }
1817         else
1818         {
1819             mtCOVERAGE_TEST_MARKER();
1820         }
1821
1822         return xReturn;
1823     } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
1824
1825 #endif /* INCLUDE_vTaskSuspend */
1826 /*-----------------------------------------------------------*/
1827
1828 #if ( INCLUDE_vTaskSuspend == 1 )
1829
1830     void vTaskResume( TaskHandle_t xTaskToResume )
1831     {
1832         TCB_t * const pxTCB = xTaskToResume;
1833
1834         /* It does not make sense to resume the calling task. */
1835         configASSERT( xTaskToResume );
1836
1837         /* The parameter cannot be NULL as it is impossible to resume the
1838          * currently executing task. */
1839         if( ( pxTCB != pxCurrentTCB ) && ( pxTCB != NULL ) )
1840         {
1841             taskENTER_CRITICAL();
1842             {
1843                 if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
1844                 {
1845                     traceTASK_RESUME( pxTCB );
1846
1847                     /* The ready list can be accessed even if the scheduler is
1848                      * suspended because this is inside a critical section. */
1849                     ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
1850                     prvAddTaskToReadyList( pxTCB );
1851
1852                     /* A higher priority task may have just been resumed. */
1853                     if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
1854                     {
1855                         /* This yield may not cause the task just resumed to run,
1856                          * but will leave the lists in the correct state for the
1857                          * next yield. */
1858                         taskYIELD_IF_USING_PREEMPTION();
1859                     }
1860                     else
1861                     {
1862                         mtCOVERAGE_TEST_MARKER();
1863                     }
1864                 }
1865                 else
1866                 {
1867                     mtCOVERAGE_TEST_MARKER();
1868                 }
1869             }
1870             taskEXIT_CRITICAL();
1871         }
1872         else
1873         {
1874             mtCOVERAGE_TEST_MARKER();
1875         }
1876     }
1877
1878 #endif /* INCLUDE_vTaskSuspend */
1879
1880 /*-----------------------------------------------------------*/
1881
1882 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
1883
1884     BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
1885     {
1886         BaseType_t xYieldRequired = pdFALSE;
1887         TCB_t * const pxTCB = xTaskToResume;
1888         portBASE_TYPE xSavedInterruptStatus;
1889
1890         configASSERT( xTaskToResume );
1891
1892         /* RTOS ports that support interrupt nesting have the concept of a
1893          * maximum  system call (or maximum API call) interrupt priority.
1894          * Interrupts that are  above the maximum system call priority are keep
1895          * permanently enabled, even when the RTOS kernel is in a critical section,
1896          * but cannot make any calls to FreeRTOS API functions.  If configASSERT()
1897          * is defined in FreeRTOSConfig.h then
1898          * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
1899          * failure if a FreeRTOS API function is called from an interrupt that has
1900          * been assigned a priority above the configured maximum system call
1901          * priority.  Only FreeRTOS functions that end in FromISR can be called
1902          * from interrupts  that have been assigned a priority at or (logically)
1903          * below the maximum system call interrupt priority.  FreeRTOS maintains a
1904          * separate interrupt safe API to ensure interrupt entry is as fast and as
1905          * simple as possible.  More information (albeit Cortex-M specific) is
1906          * provided on the following link:
1907          * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
1908         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
1909
1910         xSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
1911         {
1912             if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
1913             {
1914                 traceTASK_RESUME_FROM_ISR( pxTCB );
1915
1916                 /* Check the ready lists can be accessed. */
1917                 if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
1918                 {
1919                     /* Ready lists can be accessed so move the task from the
1920                      * suspended list to the ready list directly. */
1921                     if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
1922                     {
1923                         xYieldRequired = pdTRUE;
1924
1925                         /* Mark that a yield is pending in case the user is not
1926                          * using the return value to initiate a context switch
1927                          * from the ISR using portYIELD_FROM_ISR. */
1928                         xYieldPending = pdTRUE;
1929                     }
1930                     else
1931                     {
1932                         mtCOVERAGE_TEST_MARKER();
1933                     }
1934
1935                     ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
1936                     prvAddTaskToReadyList( pxTCB );
1937                 }
1938                 else
1939                 {
1940                     /* The delayed or ready lists cannot be accessed so the task
1941                      * is held in the pending ready list until the scheduler is
1942                      * unsuspended. */
1943                     vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
1944                 }
1945             }
1946             else
1947             {
1948                 mtCOVERAGE_TEST_MARKER();
1949             }
1950         }
1951         portCLEAR_INTERRUPT_MASK_FROM_ISR( xSavedInterruptStatus );
1952
1953         return xYieldRequired;
1954     }
1955
1956 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
1957 /*-----------------------------------------------------------*/
1958
1959 void vTaskStartScheduler( void )
1960 {
1961     BaseType_t xReturn;
1962
1963     /* Add the idle task at the lowest priority. */
1964     #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
1965     {
1966         StaticTask_t * pxIdleTaskTCBBuffer = NULL;
1967         StackType_t * pxIdleTaskStackBuffer = NULL;
1968         uint32_t ulIdleTaskStackSize;
1969
1970         /* The Idle task is created using user provided RAM - obtain the
1971          * address of the RAM then create the idle task. */
1972         vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );
1973         xIdleTaskHandle = xTaskCreateStatic( prvIdleTask,
1974                                              configIDLE_TASK_NAME,
1975                                              ulIdleTaskStackSize,
1976                                              ( void * ) NULL,       /*lint !e961.  The cast is not redundant for all compilers. */
1977                                              portPRIVILEGE_BIT,     /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
1978                                              pxIdleTaskStackBuffer,
1979                                              pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
1980
1981         if( xIdleTaskHandle != NULL )
1982         {
1983             xReturn = pdPASS;
1984         }
1985         else
1986         {
1987             xReturn = pdFAIL;
1988         }
1989     }
1990     #else /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
1991     {
1992         /* The Idle task is being created using dynamically allocated RAM. */
1993         xReturn = xTaskCreate( prvIdleTask,
1994                                configIDLE_TASK_NAME,
1995                                configMINIMAL_STACK_SIZE,
1996                                ( void * ) NULL,
1997                                portPRIVILEGE_BIT,  /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
1998                                &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
1999     }
2000     #endif /* configSUPPORT_STATIC_ALLOCATION */
2001
2002     #if ( configUSE_TIMERS == 1 )
2003     {
2004         if( xReturn == pdPASS )
2005         {
2006             xReturn = xTimerCreateTimerTask();
2007         }
2008         else
2009         {
2010             mtCOVERAGE_TEST_MARKER();
2011         }
2012     }
2013     #endif /* configUSE_TIMERS */
2014
2015     if( xReturn == pdPASS )
2016     {
2017         /* freertos_tasks_c_additions_init() should only be called if the user
2018          * definable macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is
2019          * the only macro called by the function. */
2020         #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
2021         {
2022             freertos_tasks_c_additions_init();
2023         }
2024         #endif
2025
2026         /* Interrupts are turned off here, to ensure a tick does not occur
2027          * before or during the call to xPortStartScheduler().  The stacks of
2028          * the created tasks contain a status word with interrupts switched on
2029          * so interrupts will automatically get re-enabled when the first task
2030          * starts to run. */
2031         portDISABLE_INTERRUPTS();
2032
2033         #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
2034         {
2035             /* Switch C-Runtime's TLS Block to point to the TLS
2036              * block specific to the task that will run first. */
2037             configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
2038         }
2039         #endif
2040
2041         xNextTaskUnblockTime = portMAX_DELAY;
2042         xSchedulerRunning = pdTRUE;
2043         xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
2044
2045         /* If configGENERATE_RUN_TIME_STATS is defined then the following
2046          * macro must be defined to configure the timer/counter used to generate
2047          * the run time counter time base.   NOTE:  If configGENERATE_RUN_TIME_STATS
2048          * is set to 0 and the following line fails to build then ensure you do not
2049          * have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your
2050          * FreeRTOSConfig.h file. */
2051         portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
2052
2053         traceTASK_SWITCHED_IN();
2054
2055         /* Setting up the timer tick is hardware specific and thus in the
2056          * portable interface. */
2057         xPortStartScheduler();
2058
2059         /* In most cases, xPortStartScheduler() will not return. If it
2060          * returns pdTRUE then there was not enough heap memory available
2061          * to create either the Idle or the Timer task. If it returned
2062          * pdFALSE, then the application called xTaskEndScheduler().
2063          * Most ports don't implement xTaskEndScheduler() as there is
2064          * nothing to return to. */
2065     }
2066     else
2067     {
2068         /* This line will only be reached if the kernel could not be started,
2069          * because there was not enough FreeRTOS heap to create the idle task
2070          * or the timer task. */
2071         configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );
2072     }
2073
2074     /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,
2075      * meaning xIdleTaskHandle is not used anywhere else. */
2076     ( void ) xIdleTaskHandle;
2077
2078     /* OpenOCD makes use of uxTopUsedPriority for thread debugging. Prevent uxTopUsedPriority
2079      * from getting optimized out as it is no longer used by the kernel. */
2080     ( void ) uxTopUsedPriority;
2081 }
2082 /*-----------------------------------------------------------*/
2083
2084 void vTaskEndScheduler( void )
2085 {
2086     /* Stop the scheduler interrupts and call the portable scheduler end
2087      * routine so the original ISRs can be restored if necessary.  The port
2088      * layer must ensure interrupts enable  bit is left in the correct state. */
2089     portDISABLE_INTERRUPTS();
2090     xSchedulerRunning = pdFALSE;
2091     vPortEndScheduler();
2092 }
2093 /*----------------------------------------------------------*/
2094
2095 void vTaskSuspendAll( void )
2096 {
2097     /* A critical section is not required as the variable is of type
2098      * BaseType_t.  Please read Richard Barry's reply in the following link to a
2099      * post in the FreeRTOS support forum before reporting this as a bug! -
2100      * https://goo.gl/wu4acr */
2101
2102     /* portSOFTWARE_BARRIER() is only implemented for emulated/simulated ports that
2103      * do not otherwise exhibit real time behaviour. */
2104     portSOFTWARE_BARRIER();
2105
2106     /* The scheduler is suspended if uxSchedulerSuspended is non-zero.  An increment
2107      * is used to allow calls to vTaskSuspendAll() to nest. */
2108     ++uxSchedulerSuspended;
2109
2110     /* Enforces ordering for ports and optimised compilers that may otherwise place
2111      * the above increment elsewhere. */
2112     portMEMORY_BARRIER();
2113 }
2114 /*----------------------------------------------------------*/
2115
2116 #if ( configUSE_TICKLESS_IDLE != 0 )
2117
2118     static TickType_t prvGetExpectedIdleTime( void )
2119     {
2120         TickType_t xReturn;
2121         UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;
2122
2123         /* uxHigherPriorityReadyTasks takes care of the case where
2124          * configUSE_PREEMPTION is 0, so there may be tasks above the idle priority
2125          * task that are in the Ready state, even though the idle task is
2126          * running. */
2127         #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
2128         {
2129             if( uxTopReadyPriority > tskIDLE_PRIORITY )
2130             {
2131                 uxHigherPriorityReadyTasks = pdTRUE;
2132             }
2133         }
2134         #else
2135         {
2136             const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;
2137
2138             /* When port optimised task selection is used the uxTopReadyPriority
2139              * variable is used as a bit map.  If bits other than the least
2140              * significant bit are set then there are tasks that have a priority
2141              * above the idle priority that are in the Ready state.  This takes
2142              * care of the case where the co-operative scheduler is in use. */
2143             if( uxTopReadyPriority > uxLeastSignificantBit )
2144             {
2145                 uxHigherPriorityReadyTasks = pdTRUE;
2146             }
2147         }
2148         #endif /* if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 ) */
2149
2150         if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
2151         {
2152             xReturn = 0;
2153         }
2154         else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
2155         {
2156             /* There are other idle priority tasks in the ready state.  If
2157              * time slicing is used then the very next tick interrupt must be
2158              * processed. */
2159             xReturn = 0;
2160         }
2161         else if( uxHigherPriorityReadyTasks != pdFALSE )
2162         {
2163             /* There are tasks in the Ready state that have a priority above the
2164              * idle priority.  This path can only be reached if
2165              * configUSE_PREEMPTION is 0. */
2166             xReturn = 0;
2167         }
2168         else
2169         {
2170             xReturn = xNextTaskUnblockTime - xTickCount;
2171         }
2172
2173         return xReturn;
2174     }
2175
2176 #endif /* configUSE_TICKLESS_IDLE */
2177 /*----------------------------------------------------------*/
2178
2179 BaseType_t xTaskResumeAll( void )
2180 {
2181     TCB_t * pxTCB = NULL;
2182     BaseType_t xAlreadyYielded = pdFALSE;
2183
2184     /* If uxSchedulerSuspended is zero then this function does not match a
2185      * previous call to vTaskSuspendAll(). */
2186     configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U );
2187
2188     /* It is possible that an ISR caused a task to be removed from an event
2189      * list while the scheduler was suspended.  If this was the case then the
2190      * removed task will have been added to the xPendingReadyList.  Once the
2191      * scheduler has been resumed it is safe to move all the pending ready
2192      * tasks from this list into their appropriate ready list. */
2193     taskENTER_CRITICAL();
2194     {
2195         --uxSchedulerSuspended;
2196
2197         if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
2198         {
2199             if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )
2200             {
2201                 /* Move any readied tasks from the pending list into the
2202                  * appropriate ready list. */
2203                 while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
2204                 {
2205                     pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
2206                     listREMOVE_ITEM( &( pxTCB->xEventListItem ) );
2207                     portMEMORY_BARRIER();
2208                     listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
2209                     prvAddTaskToReadyList( pxTCB );
2210
2211                     /* If the moved task has a priority higher than the current
2212                      * task then a yield must be performed. */
2213                     if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
2214                     {
2215                         xYieldPending = pdTRUE;
2216                     }
2217                     else
2218                     {
2219                         mtCOVERAGE_TEST_MARKER();
2220                     }
2221                 }
2222
2223                 if( pxTCB != NULL )
2224                 {
2225                     /* A task was unblocked while the scheduler was suspended,
2226                      * which may have prevented the next unblock time from being
2227                      * re-calculated, in which case re-calculate it now.  Mainly
2228                      * important for low power tickless implementations, where
2229                      * this can prevent an unnecessary exit from low power
2230                      * state. */
2231                     prvResetNextTaskUnblockTime();
2232                 }
2233
2234                 /* If any ticks occurred while the scheduler was suspended then
2235                  * they should be processed now.  This ensures the tick count does
2236                  * not  slip, and that any delayed tasks are resumed at the correct
2237                  * time. */
2238                 {
2239                     TickType_t xPendedCounts = xPendedTicks; /* Non-volatile copy. */
2240
2241                     if( xPendedCounts > ( TickType_t ) 0U )
2242                     {
2243                         do
2244                         {
2245                             if( xTaskIncrementTick() != pdFALSE )
2246                             {
2247                                 xYieldPending = pdTRUE;
2248                             }
2249                             else
2250                             {
2251                                 mtCOVERAGE_TEST_MARKER();
2252                             }
2253
2254                             --xPendedCounts;
2255                         } while( xPendedCounts > ( TickType_t ) 0U );
2256
2257                         xPendedTicks = 0;
2258                     }
2259                     else
2260                     {
2261                         mtCOVERAGE_TEST_MARKER();
2262                     }
2263                 }
2264
2265                 if( xYieldPending != pdFALSE )
2266                 {
2267                     #if ( configUSE_PREEMPTION != 0 )
2268                     {
2269                         xAlreadyYielded = pdTRUE;
2270                     }
2271                     #endif
2272                     taskYIELD_IF_USING_PREEMPTION();
2273                 }
2274                 else
2275                 {
2276                     mtCOVERAGE_TEST_MARKER();
2277                 }
2278             }
2279         }
2280         else
2281         {
2282             mtCOVERAGE_TEST_MARKER();
2283         }
2284     }
2285     taskEXIT_CRITICAL();
2286
2287     return xAlreadyYielded;
2288 }
2289 /*-----------------------------------------------------------*/
2290
2291 TickType_t xTaskGetTickCount( void )
2292 {
2293     TickType_t xTicks;
2294
2295     /* Critical section required if running on a 16 bit processor. */
2296     portTICK_TYPE_ENTER_CRITICAL();
2297     {
2298         xTicks = xTickCount;
2299     }
2300     portTICK_TYPE_EXIT_CRITICAL();
2301
2302     return xTicks;
2303 }
2304 /*-----------------------------------------------------------*/
2305
2306 TickType_t xTaskGetTickCountFromISR( void )
2307 {
2308     TickType_t xReturn;
2309     portBASE_TYPE xSavedInterruptStatus;
2310
2311     /* RTOS ports that support interrupt nesting have the concept of a maximum
2312      * system call (or maximum API call) interrupt priority.  Interrupts that are
2313      * above the maximum system call priority are kept permanently enabled, even
2314      * when the RTOS kernel is in a critical section, but cannot make any calls to
2315      * FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h
2316      * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
2317      * failure if a FreeRTOS API function is called from an interrupt that has been
2318      * assigned a priority above the configured maximum system call priority.
2319      * Only FreeRTOS functions that end in FromISR can be called from interrupts
2320      * that have been assigned a priority at or (logically) below the maximum
2321      * system call  interrupt priority.  FreeRTOS maintains a separate interrupt
2322      * safe API to ensure interrupt entry is as fast and as simple as possible.
2323      * More information (albeit Cortex-M specific) is provided on the following
2324      * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
2325     portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
2326
2327     xSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR();
2328     {
2329         xReturn = xTickCount;
2330     }
2331     portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( xSavedInterruptStatus );
2332
2333     return xReturn;
2334 }
2335 /*-----------------------------------------------------------*/
2336
2337 UBaseType_t uxTaskGetNumberOfTasks( void )
2338 {
2339     /* A critical section is not required because the variables are of type
2340      * BaseType_t. */
2341     return uxCurrentNumberOfTasks;
2342 }
2343 /*-----------------------------------------------------------*/
2344
2345 char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
2346 {
2347     TCB_t * pxTCB;
2348
2349     /* If null is passed in here then the name of the calling task is being
2350      * queried. */
2351     pxTCB = prvGetTCBFromHandle( xTaskToQuery );
2352     configASSERT( pxTCB );
2353     return &( pxTCB->pcTaskName[ 0 ] );
2354 }
2355 /*-----------------------------------------------------------*/
2356
2357 #if ( INCLUDE_xTaskGetHandle == 1 )
2358
2359     static TCB_t * prvSearchForNameWithinSingleList( List_t * pxList,
2360                                                      const char pcNameToQuery[] )
2361     {
2362         TCB_t * pxNextTCB;
2363         TCB_t * pxFirstTCB;
2364         TCB_t * pxReturn = NULL;
2365         UBaseType_t x;
2366         char cNextChar;
2367         BaseType_t xBreakLoop;
2368
2369         /* This function is called with the scheduler suspended. */
2370
2371         if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
2372         {
2373             listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
2374
2375             do
2376             {
2377                 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
2378
2379                 /* Check each character in the name looking for a match or
2380                  * mismatch. */
2381                 xBreakLoop = pdFALSE;
2382
2383                 for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
2384                 {
2385                     cNextChar = pxNextTCB->pcTaskName[ x ];
2386
2387                     if( cNextChar != pcNameToQuery[ x ] )
2388                     {
2389                         /* Characters didn't match. */
2390                         xBreakLoop = pdTRUE;
2391                     }
2392                     else if( cNextChar == ( char ) 0x00 )
2393                     {
2394                         /* Both strings terminated, a match must have been
2395                          * found. */
2396                         pxReturn = pxNextTCB;
2397                         xBreakLoop = pdTRUE;
2398                     }
2399                     else
2400                     {
2401                         mtCOVERAGE_TEST_MARKER();
2402                     }
2403
2404                     if( xBreakLoop != pdFALSE )
2405                     {
2406                         break;
2407                     }
2408                 }
2409
2410                 if( pxReturn != NULL )
2411                 {
2412                     /* The handle has been found. */
2413                     break;
2414                 }
2415             } while( pxNextTCB != pxFirstTCB );
2416         }
2417         else
2418         {
2419             mtCOVERAGE_TEST_MARKER();
2420         }
2421
2422         return pxReturn;
2423     }
2424
2425 #endif /* INCLUDE_xTaskGetHandle */
2426 /*-----------------------------------------------------------*/
2427
2428 #if ( INCLUDE_xTaskGetHandle == 1 )
2429
2430     TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
2431     {
2432         UBaseType_t uxQueue = configMAX_PRIORITIES;
2433         TCB_t * pxTCB;
2434
2435         /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */
2436         configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN );
2437
2438         vTaskSuspendAll();
2439         {
2440             /* Search the ready lists. */
2441             do
2442             {
2443                 uxQueue--;
2444                 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery );
2445
2446                 if( pxTCB != NULL )
2447                 {
2448                     /* Found the handle. */
2449                     break;
2450                 }
2451             } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
2452
2453             /* Search the delayed lists. */
2454             if( pxTCB == NULL )
2455             {
2456                 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery );
2457             }
2458
2459             if( pxTCB == NULL )
2460             {
2461                 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery );
2462             }
2463
2464             #if ( INCLUDE_vTaskSuspend == 1 )
2465             {
2466                 if( pxTCB == NULL )
2467                 {
2468                     /* Search the suspended list. */
2469                     pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery );
2470                 }
2471             }
2472             #endif
2473
2474             #if ( INCLUDE_vTaskDelete == 1 )
2475             {
2476                 if( pxTCB == NULL )
2477                 {
2478                     /* Search the deleted list. */
2479                     pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery );
2480                 }
2481             }
2482             #endif
2483         }
2484         ( void ) xTaskResumeAll();
2485
2486         return pxTCB;
2487     }
2488
2489 #endif /* INCLUDE_xTaskGetHandle */
2490 /*-----------------------------------------------------------*/
2491
2492 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
2493
2494     BaseType_t xTaskGetStaticBuffers( TaskHandle_t xTask,
2495                                       StackType_t ** ppuxStackBuffer,
2496                                       StaticTask_t ** ppxTaskBuffer )
2497     {
2498         BaseType_t xReturn;
2499         TCB_t * pxTCB;
2500
2501         configASSERT( ppuxStackBuffer != NULL );
2502         configASSERT( ppxTaskBuffer != NULL );
2503
2504         pxTCB = prvGetTCBFromHandle( xTask );
2505
2506         #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 )
2507         {
2508             if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB )
2509             {
2510                 *ppuxStackBuffer = pxTCB->pxStack;
2511                 *ppxTaskBuffer = ( StaticTask_t * ) pxTCB;
2512                 xReturn = pdTRUE;
2513             }
2514             else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY )
2515             {
2516                 *ppuxStackBuffer = pxTCB->pxStack;
2517                 *ppxTaskBuffer = NULL;
2518                 xReturn = pdTRUE;
2519             }
2520             else
2521             {
2522                 xReturn = pdFALSE;
2523             }
2524         }
2525         #else /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 */
2526         {
2527             *ppuxStackBuffer = pxTCB->pxStack;
2528             *ppxTaskBuffer = ( StaticTask_t * ) pxTCB;
2529             xReturn = pdTRUE;
2530         }
2531         #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 */
2532
2533         return xReturn;
2534     }
2535
2536 #endif /* configSUPPORT_STATIC_ALLOCATION */
2537 /*-----------------------------------------------------------*/
2538
2539 #if ( configUSE_TRACE_FACILITY == 1 )
2540
2541     UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
2542                                       const UBaseType_t uxArraySize,
2543                                       configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime )
2544     {
2545         UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
2546
2547         vTaskSuspendAll();
2548         {
2549             /* Is there a space in the array for each task in the system? */
2550             if( uxArraySize >= uxCurrentNumberOfTasks )
2551             {
2552                 /* Fill in an TaskStatus_t structure with information on each
2553                  * task in the Ready state. */
2554                 do
2555                 {
2556                     uxQueue--;
2557                     uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
2558                 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
2559
2560                 /* Fill in an TaskStatus_t structure with information on each
2561                  * task in the Blocked state. */
2562                 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );
2563                 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );
2564
2565                 #if ( INCLUDE_vTaskDelete == 1 )
2566                 {
2567                     /* Fill in an TaskStatus_t structure with information on
2568                      * each task that has been deleted but not yet cleaned up. */
2569                     uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
2570                 }
2571                 #endif
2572
2573                 #if ( INCLUDE_vTaskSuspend == 1 )
2574                 {
2575                     /* Fill in an TaskStatus_t structure with information on
2576                      * each task in the Suspended state. */
2577                     uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
2578                 }
2579                 #endif
2580
2581                 #if ( configGENERATE_RUN_TIME_STATS == 1 )
2582                 {
2583                     if( pulTotalRunTime != NULL )
2584                     {
2585                         #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
2586                             portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
2587                         #else
2588                             *pulTotalRunTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE();
2589                         #endif
2590                     }
2591                 }
2592                 #else /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
2593                 {
2594                     if( pulTotalRunTime != NULL )
2595                     {
2596                         *pulTotalRunTime = 0;
2597                     }
2598                 }
2599                 #endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
2600             }
2601             else
2602             {
2603                 mtCOVERAGE_TEST_MARKER();
2604             }
2605         }
2606         ( void ) xTaskResumeAll();
2607
2608         return uxTask;
2609     }
2610
2611 #endif /* configUSE_TRACE_FACILITY */
2612 /*----------------------------------------------------------*/
2613
2614 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
2615
2616     TaskHandle_t xTaskGetIdleTaskHandle( void )
2617     {
2618         /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
2619          * started, then xIdleTaskHandle will be NULL. */
2620         configASSERT( ( xIdleTaskHandle != NULL ) );
2621         return xIdleTaskHandle;
2622     }
2623
2624 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
2625 /*----------------------------------------------------------*/
2626
2627 /* This conditional compilation should use inequality to 0, not equality to 1.
2628  * This is to ensure vTaskStepTick() is available when user defined low power mode
2629  * implementations require configUSE_TICKLESS_IDLE to be set to a value other than
2630  * 1. */
2631 #if ( configUSE_TICKLESS_IDLE != 0 )
2632
2633     void vTaskStepTick( TickType_t xTicksToJump )
2634     {
2635         /* Correct the tick count value after a period during which the tick
2636          * was suppressed.  Note this does *not* call the tick hook function for
2637          * each stepped tick. */
2638         configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
2639
2640         if( ( xTickCount + xTicksToJump ) == xNextTaskUnblockTime )
2641         {
2642             /* Arrange for xTickCount to reach xNextTaskUnblockTime in
2643              * xTaskIncrementTick() when the scheduler resumes.  This ensures
2644              * that any delayed tasks are resumed at the correct time. */
2645             configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U );
2646             configASSERT( xTicksToJump != ( TickType_t ) 0 );
2647
2648             /* Prevent the tick interrupt modifying xPendedTicks simultaneously. */
2649             taskENTER_CRITICAL();
2650             {
2651                 xPendedTicks++;
2652             }
2653             taskEXIT_CRITICAL();
2654             xTicksToJump--;
2655         }
2656         else
2657         {
2658             mtCOVERAGE_TEST_MARKER();
2659         }
2660
2661         xTickCount += xTicksToJump;
2662         traceINCREASE_TICK_COUNT( xTicksToJump );
2663     }
2664
2665 #endif /* configUSE_TICKLESS_IDLE */
2666 /*----------------------------------------------------------*/
2667
2668 BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp )
2669 {
2670     BaseType_t xYieldOccurred;
2671
2672     /* Must not be called with the scheduler suspended as the implementation
2673      * relies on xPendedTicks being wound down to 0 in xTaskResumeAll(). */
2674     configASSERT( uxSchedulerSuspended == ( UBaseType_t ) 0U );
2675
2676     /* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occurring when
2677      * the scheduler is suspended so the ticks are executed in xTaskResumeAll(). */
2678     vTaskSuspendAll();
2679
2680     /* Prevent the tick interrupt modifying xPendedTicks simultaneously. */
2681     taskENTER_CRITICAL();
2682     {
2683         xPendedTicks += xTicksToCatchUp;
2684     }
2685     taskEXIT_CRITICAL();
2686     xYieldOccurred = xTaskResumeAll();
2687
2688     return xYieldOccurred;
2689 }
2690 /*----------------------------------------------------------*/
2691
2692 #if ( INCLUDE_xTaskAbortDelay == 1 )
2693
2694     BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
2695     {
2696         TCB_t * pxTCB = xTask;
2697         BaseType_t xReturn;
2698
2699         configASSERT( pxTCB );
2700
2701         vTaskSuspendAll();
2702         {
2703             /* A task can only be prematurely removed from the Blocked state if
2704              * it is actually in the Blocked state. */
2705             if( eTaskGetState( xTask ) == eBlocked )
2706             {
2707                 xReturn = pdPASS;
2708
2709                 /* Remove the reference to the task from the blocked list.  An
2710                  * interrupt won't touch the xStateListItem because the
2711                  * scheduler is suspended. */
2712                 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
2713
2714                 /* Is the task waiting on an event also?  If so remove it from
2715                  * the event list too.  Interrupts can touch the event list item,
2716                  * even though the scheduler is suspended, so a critical section
2717                  * is used. */
2718                 taskENTER_CRITICAL();
2719                 {
2720                     if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
2721                     {
2722                         ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
2723
2724                         /* This lets the task know it was forcibly removed from the
2725                          * blocked state so it should not re-evaluate its block time and
2726                          * then block again. */
2727                         pxTCB->ucDelayAborted = pdTRUE;
2728                     }
2729                     else
2730                     {
2731                         mtCOVERAGE_TEST_MARKER();
2732                     }
2733                 }
2734                 taskEXIT_CRITICAL();
2735
2736                 /* Place the unblocked task into the appropriate ready list. */
2737                 prvAddTaskToReadyList( pxTCB );
2738
2739                 /* A task being unblocked cannot cause an immediate context
2740                  * switch if preemption is turned off. */
2741                 #if ( configUSE_PREEMPTION == 1 )
2742                 {
2743                     /* Preemption is on, but a context switch should only be
2744                      * performed if the unblocked task has a priority that is
2745                      * higher than the currently executing task. */
2746                     if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
2747                     {
2748                         /* Pend the yield to be performed when the scheduler
2749                          * is unsuspended. */
2750                         xYieldPending = pdTRUE;
2751                     }
2752                     else
2753                     {
2754                         mtCOVERAGE_TEST_MARKER();
2755                     }
2756                 }
2757                 #endif /* configUSE_PREEMPTION */
2758             }
2759             else
2760             {
2761                 xReturn = pdFAIL;
2762             }
2763         }
2764         ( void ) xTaskResumeAll();
2765
2766         return xReturn;
2767     }
2768
2769 #endif /* INCLUDE_xTaskAbortDelay */
2770 /*----------------------------------------------------------*/
2771
2772 BaseType_t xTaskIncrementTick( void )
2773 {
2774     TCB_t * pxTCB;
2775     TickType_t xItemValue;
2776     BaseType_t xSwitchRequired = pdFALSE;
2777
2778     /* Called by the portable layer each time a tick interrupt occurs.
2779      * Increments the tick then checks to see if the new tick value will cause any
2780      * tasks to be unblocked. */
2781     traceTASK_INCREMENT_TICK( xTickCount );
2782
2783     if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
2784     {
2785         /* Minor optimisation.  The tick count cannot change in this
2786          * block. */
2787         const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
2788
2789         /* Increment the RTOS tick, switching the delayed and overflowed
2790          * delayed lists if it wraps to 0. */
2791         xTickCount = xConstTickCount;
2792
2793         if( xConstTickCount == ( TickType_t ) 0U ) /*lint !e774 'if' does not always evaluate to false as it is looking for an overflow. */
2794         {
2795             taskSWITCH_DELAYED_LISTS();
2796         }
2797         else
2798         {
2799             mtCOVERAGE_TEST_MARKER();
2800         }
2801
2802         /* See if this tick has made a timeout expire.  Tasks are stored in
2803          * the  queue in the order of their wake time - meaning once one task
2804          * has been found whose block time has not expired there is no need to
2805          * look any further down the list. */
2806         if( xConstTickCount >= xNextTaskUnblockTime )
2807         {
2808             for( ; ; )
2809             {
2810                 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
2811                 {
2812                     /* The delayed list is empty.  Set xNextTaskUnblockTime
2813                      * to the maximum possible value so it is extremely
2814                      * unlikely that the
2815                      * if( xTickCount >= xNextTaskUnblockTime ) test will pass
2816                      * next time through. */
2817                     xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
2818                     break;
2819                 }
2820                 else
2821                 {
2822                     /* The delayed list is not empty, get the value of the
2823                      * item at the head of the delayed list.  This is the time
2824                      * at which the task at the head of the delayed list must
2825                      * be removed from the Blocked state. */
2826                     pxTCB = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
2827                     xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );
2828
2829                     if( xConstTickCount < xItemValue )
2830                     {
2831                         /* It is not time to unblock this item yet, but the
2832                          * item value is the time at which the task at the head
2833                          * of the blocked list must be removed from the Blocked
2834                          * state -  so record the item value in
2835                          * xNextTaskUnblockTime. */
2836                         xNextTaskUnblockTime = xItemValue;
2837                         break; /*lint !e9011 Code structure here is deemed easier to understand with multiple breaks. */
2838                     }
2839                     else
2840                     {
2841                         mtCOVERAGE_TEST_MARKER();
2842                     }
2843
2844                     /* It is time to remove the item from the Blocked state. */
2845                     listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
2846
2847                     /* Is the task waiting on an event also?  If so remove
2848                      * it from the event list. */
2849                     if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
2850                     {
2851                         listREMOVE_ITEM( &( pxTCB->xEventListItem ) );
2852                     }
2853                     else
2854                     {
2855                         mtCOVERAGE_TEST_MARKER();
2856                     }
2857
2858                     /* Place the unblocked task into the appropriate ready
2859                      * list. */
2860                     prvAddTaskToReadyList( pxTCB );
2861
2862                     /* A task being unblocked cannot cause an immediate
2863                      * context switch if preemption is turned off. */
2864                     #if ( configUSE_PREEMPTION == 1 )
2865                     {
2866                         /* Preemption is on, but a context switch should
2867                          * only be performed if the unblocked task's
2868                          * priority is higher than the currently executing
2869                          * task.
2870                          * The case of equal priority tasks sharing
2871                          * processing time (which happens when both
2872                          * preemption and time slicing are on) is
2873                          * handled below.*/
2874                         if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
2875                         {
2876                             xSwitchRequired = pdTRUE;
2877                         }
2878                         else
2879                         {
2880                             mtCOVERAGE_TEST_MARKER();
2881                         }
2882                     }
2883                     #endif /* configUSE_PREEMPTION */
2884                 }
2885             }
2886         }
2887
2888         /* Tasks of equal priority to the currently running task will share
2889          * processing time (time slice) if preemption is on, and the application
2890          * writer has not explicitly turned time slicing off. */
2891         #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
2892         {
2893             if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )
2894             {
2895                 xSwitchRequired = pdTRUE;
2896             }
2897             else
2898             {
2899                 mtCOVERAGE_TEST_MARKER();
2900             }
2901         }
2902         #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
2903
2904         #if ( configUSE_TICK_HOOK == 1 )
2905         {
2906             /* Guard against the tick hook being called when the pended tick
2907              * count is being unwound (when the scheduler is being unlocked). */
2908             if( xPendedTicks == ( TickType_t ) 0 )
2909             {
2910                 vApplicationTickHook();
2911             }
2912             else
2913             {
2914                 mtCOVERAGE_TEST_MARKER();
2915             }
2916         }
2917         #endif /* configUSE_TICK_HOOK */
2918
2919         #if ( configUSE_PREEMPTION == 1 )
2920         {
2921             if( xYieldPending != pdFALSE )
2922             {
2923                 xSwitchRequired = pdTRUE;
2924             }
2925             else
2926             {
2927                 mtCOVERAGE_TEST_MARKER();
2928             }
2929         }
2930         #endif /* configUSE_PREEMPTION */
2931     }
2932     else
2933     {
2934         ++xPendedTicks;
2935
2936         /* The tick hook gets called at regular intervals, even if the
2937          * scheduler is locked. */
2938         #if ( configUSE_TICK_HOOK == 1 )
2939         {
2940             vApplicationTickHook();
2941         }
2942         #endif
2943     }
2944
2945     return xSwitchRequired;
2946 }
2947 /*-----------------------------------------------------------*/
2948
2949 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
2950
2951     void vTaskSetApplicationTaskTag( TaskHandle_t xTask,
2952                                      TaskHookFunction_t pxHookFunction )
2953     {
2954         TCB_t * xTCB;
2955
2956         /* If xTask is NULL then it is the task hook of the calling task that is
2957          * getting set. */
2958         if( xTask == NULL )
2959         {
2960             xTCB = ( TCB_t * ) pxCurrentTCB;
2961         }
2962         else
2963         {
2964             xTCB = xTask;
2965         }
2966
2967         /* Save the hook function in the TCB.  A critical section is required as
2968          * the value can be accessed from an interrupt. */
2969         taskENTER_CRITICAL();
2970         {
2971             xTCB->pxTaskTag = pxHookFunction;
2972         }
2973         taskEXIT_CRITICAL();
2974     }
2975
2976 #endif /* configUSE_APPLICATION_TASK_TAG */
2977 /*-----------------------------------------------------------*/
2978
2979 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
2980
2981     TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
2982     {
2983         TCB_t * pxTCB;
2984         TaskHookFunction_t xReturn;
2985
2986         /* If xTask is NULL then set the calling task's hook. */
2987         pxTCB = prvGetTCBFromHandle( xTask );
2988
2989         /* Save the hook function in the TCB.  A critical section is required as
2990          * the value can be accessed from an interrupt. */
2991         taskENTER_CRITICAL();
2992         {
2993             xReturn = pxTCB->pxTaskTag;
2994         }
2995         taskEXIT_CRITICAL();
2996
2997         return xReturn;
2998     }
2999
3000 #endif /* configUSE_APPLICATION_TASK_TAG */
3001 /*-----------------------------------------------------------*/
3002
3003 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
3004
3005     TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask )
3006     {
3007         TCB_t * pxTCB;
3008         TaskHookFunction_t xReturn;
3009         portBASE_TYPE xSavedInterruptStatus;
3010
3011         /* If xTask is NULL then set the calling task's hook. */
3012         pxTCB = prvGetTCBFromHandle( xTask );
3013
3014         /* Save the hook function in the TCB.  A critical section is required as
3015          * the value can be accessed from an interrupt. */
3016         xSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
3017         {
3018             xReturn = pxTCB->pxTaskTag;
3019         }
3020         portCLEAR_INTERRUPT_MASK_FROM_ISR( xSavedInterruptStatus );
3021
3022         return xReturn;
3023     }
3024
3025 #endif /* configUSE_APPLICATION_TASK_TAG */
3026 /*-----------------------------------------------------------*/
3027
3028 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
3029
3030     BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask,
3031                                              void * pvParameter )
3032     {
3033         TCB_t * xTCB;
3034         BaseType_t xReturn;
3035
3036         /* If xTask is NULL then we are calling our own task hook. */
3037         if( xTask == NULL )
3038         {
3039             xTCB = pxCurrentTCB;
3040         }
3041         else
3042         {
3043             xTCB = xTask;
3044         }
3045
3046         if( xTCB->pxTaskTag != NULL )
3047         {
3048             xReturn = xTCB->pxTaskTag( pvParameter );
3049         }
3050         else
3051         {
3052             xReturn = pdFAIL;
3053         }
3054
3055         return xReturn;
3056     }
3057
3058 #endif /* configUSE_APPLICATION_TASK_TAG */
3059 /*-----------------------------------------------------------*/
3060
3061 void vTaskSwitchContext( void )
3062 {
3063     if( uxSchedulerSuspended != ( UBaseType_t ) 0U )
3064     {
3065         /* The scheduler is currently suspended - do not allow a context
3066          * switch. */
3067         xYieldPending = pdTRUE;
3068     }
3069     else
3070     {
3071         xYieldPending = pdFALSE;
3072         traceTASK_SWITCHED_OUT();
3073
3074         #if ( configGENERATE_RUN_TIME_STATS == 1 )
3075         {
3076             #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
3077                 portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
3078             #else
3079                 ulTotalRunTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE();
3080             #endif
3081
3082             /* Add the amount of time the task has been running to the
3083              * accumulated time so far.  The time the task started running was
3084              * stored in ulTaskSwitchedInTime.  Note that there is no overflow
3085              * protection here so count values are only valid until the timer
3086              * overflows.  The guard against negative values is to protect
3087              * against suspect run time stat counter implementations - which
3088              * are provided by the application, not the kernel. */
3089             if( ulTotalRunTime > ulTaskSwitchedInTime )
3090             {
3091                 pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
3092             }
3093             else
3094             {
3095                 mtCOVERAGE_TEST_MARKER();
3096             }
3097
3098             ulTaskSwitchedInTime = ulTotalRunTime;
3099         }
3100         #endif /* configGENERATE_RUN_TIME_STATS */
3101
3102         /* Check for stack overflow, if configured. */
3103         taskCHECK_FOR_STACK_OVERFLOW();
3104
3105         /* Before the currently running task is switched out, save its errno. */
3106         #if ( configUSE_POSIX_ERRNO == 1 )
3107         {
3108             pxCurrentTCB->iTaskErrno = FreeRTOS_errno;
3109         }
3110         #endif
3111
3112         /* Select a new task to run using either the generic C or port
3113          * optimised asm code. */
3114         taskSELECT_HIGHEST_PRIORITY_TASK(); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
3115         traceTASK_SWITCHED_IN();
3116
3117         /* After the new task is switched in, update the global errno. */
3118         #if ( configUSE_POSIX_ERRNO == 1 )
3119         {
3120             FreeRTOS_errno = pxCurrentTCB->iTaskErrno;
3121         }
3122         #endif
3123
3124         #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
3125         {
3126             /* Switch C-Runtime's TLS Block to point to the TLS
3127              * Block specific to this task. */
3128             configSET_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
3129         }
3130         #endif
3131     }
3132 }
3133 /*-----------------------------------------------------------*/
3134
3135 void vTaskPlaceOnEventList( List_t * const pxEventList,
3136                             const TickType_t xTicksToWait )
3137 {
3138     configASSERT( pxEventList );
3139
3140     /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
3141      * SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
3142
3143     /* Place the event list item of the TCB in the appropriate event list.
3144      * This is placed in the list in priority order so the highest priority task
3145      * is the first to be woken by the event.
3146      *
3147      * Note: Lists are sorted in ascending order by ListItem_t.xItemValue.
3148      * Normally, the xItemValue of a TCB's ListItem_t members is:
3149      *      xItemValue = ( configMAX_PRIORITIES - uxPriority )
3150      * Therefore, the event list is sorted in descending priority order.
3151      *
3152      * The queue that contains the event list is locked, preventing
3153      * simultaneous access from interrupts. */
3154     vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
3155
3156     prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
3157 }
3158 /*-----------------------------------------------------------*/
3159
3160 void vTaskPlaceOnUnorderedEventList( List_t * pxEventList,
3161                                      const TickType_t xItemValue,
3162                                      const TickType_t xTicksToWait )
3163 {
3164     configASSERT( pxEventList );
3165
3166     /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by
3167      * the event groups implementation. */
3168     configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U );
3169
3170     /* Store the item value in the event list item.  It is safe to access the
3171      * event list item here as interrupts won't access the event list item of a
3172      * task that is not in the Blocked state. */
3173     listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
3174
3175     /* Place the event list item of the TCB at the end of the appropriate event
3176      * list.  It is safe to access the event list here because it is part of an
3177      * event group implementation - and interrupts don't access event groups
3178      * directly (instead they access them indirectly by pending function calls to
3179      * the task level). */
3180     listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) );
3181
3182     prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
3183 }
3184 /*-----------------------------------------------------------*/
3185
3186 #if ( configUSE_TIMERS == 1 )
3187
3188     void vTaskPlaceOnEventListRestricted( List_t * const pxEventList,
3189                                           TickType_t xTicksToWait,
3190                                           const BaseType_t xWaitIndefinitely )
3191     {
3192         configASSERT( pxEventList );
3193
3194         /* This function should not be called by application code hence the
3195          * 'Restricted' in its name.  It is not part of the public API.  It is
3196          * designed for use by kernel code, and has special calling requirements -
3197          * it should be called with the scheduler suspended. */
3198
3199
3200         /* Place the event list item of the TCB in the appropriate event list.
3201          * In this case it is assume that this is the only task that is going to
3202          * be waiting on this event list, so the faster vListInsertEnd() function
3203          * can be used in place of vListInsert. */
3204         listINSERT_END( pxEventList, &( pxCurrentTCB->xEventListItem ) );
3205
3206         /* If the task should block indefinitely then set the block time to a
3207          * value that will be recognised as an indefinite delay inside the
3208          * prvAddCurrentTaskToDelayedList() function. */
3209         if( xWaitIndefinitely != pdFALSE )
3210         {
3211             xTicksToWait = portMAX_DELAY;
3212         }
3213
3214         traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) );
3215         prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely );
3216     }
3217
3218 #endif /* configUSE_TIMERS */
3219 /*-----------------------------------------------------------*/
3220
3221 BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
3222 {
3223     TCB_t * pxUnblockedTCB;
3224     BaseType_t xReturn;
3225
3226     /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION.  It can also be
3227      * called from a critical section within an ISR. */
3228
3229     /* The event list is sorted in priority order, so the first in the list can
3230      * be removed as it is known to be the highest priority.  Remove the TCB from
3231      * the delayed list, and add it to the ready list.
3232      *
3233      * If an event is for a queue that is locked then this function will never
3234      * get called - the lock count on the queue will get modified instead.  This
3235      * means exclusive access to the event list is guaranteed here.
3236      *
3237      * This function assumes that a check has already been made to ensure that
3238      * pxEventList is not empty. */
3239     pxUnblockedTCB = listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
3240     configASSERT( pxUnblockedTCB );
3241     listREMOVE_ITEM( &( pxUnblockedTCB->xEventListItem ) );
3242
3243     if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
3244     {
3245         listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) );
3246         prvAddTaskToReadyList( pxUnblockedTCB );
3247
3248         #if ( configUSE_TICKLESS_IDLE != 0 )
3249         {
3250             /* If a task is blocked on a kernel object then xNextTaskUnblockTime
3251              * might be set to the blocked task's time out time.  If the task is
3252              * unblocked for a reason other than a timeout xNextTaskUnblockTime is
3253              * normally left unchanged, because it is automatically reset to a new
3254              * value when the tick count equals xNextTaskUnblockTime.  However if
3255              * tickless idling is used it might be more important to enter sleep mode
3256              * at the earliest possible time - so reset xNextTaskUnblockTime here to
3257              * ensure it is updated at the earliest possible time. */
3258             prvResetNextTaskUnblockTime();
3259         }
3260         #endif
3261     }
3262     else
3263     {
3264         /* The delayed and ready lists cannot be accessed, so hold this task
3265          * pending until the scheduler is resumed. */
3266         listINSERT_END( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
3267     }
3268
3269     if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
3270     {
3271         /* Return true if the task removed from the event list has a higher
3272          * priority than the calling task.  This allows the calling task to know if
3273          * it should force a context switch now. */
3274         xReturn = pdTRUE;
3275
3276         /* Mark that a yield is pending in case the user is not using the
3277          * "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
3278         xYieldPending = pdTRUE;
3279     }
3280     else
3281     {
3282         xReturn = pdFALSE;
3283     }
3284
3285     return xReturn;
3286 }
3287 /*-----------------------------------------------------------*/
3288
3289 void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
3290                                         const TickType_t xItemValue )
3291 {
3292     TCB_t * pxUnblockedTCB;
3293
3294     /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by
3295      * the event flags implementation. */
3296     configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U );
3297
3298     /* Store the new item value in the event list. */
3299     listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
3300
3301     /* Remove the event list form the event flag.  Interrupts do not access
3302      * event flags. */
3303     pxUnblockedTCB = listGET_LIST_ITEM_OWNER( pxEventListItem ); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
3304     configASSERT( pxUnblockedTCB );
3305     listREMOVE_ITEM( pxEventListItem );
3306
3307     #if ( configUSE_TICKLESS_IDLE != 0 )
3308     {
3309         /* If a task is blocked on a kernel object then xNextTaskUnblockTime
3310          * might be set to the blocked task's time out time.  If the task is
3311          * unblocked for a reason other than a timeout xNextTaskUnblockTime is
3312          * normally left unchanged, because it is automatically reset to a new
3313          * value when the tick count equals xNextTaskUnblockTime.  However if
3314          * tickless idling is used it might be more important to enter sleep mode
3315          * at the earliest possible time - so reset xNextTaskUnblockTime here to
3316          * ensure it is updated at the earliest possible time. */
3317         prvResetNextTaskUnblockTime();
3318     }
3319     #endif
3320
3321     /* Remove the task from the delayed list and add it to the ready list.  The
3322      * scheduler is suspended so interrupts will not be accessing the ready
3323      * lists. */
3324     listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) );
3325     prvAddTaskToReadyList( pxUnblockedTCB );
3326
3327     if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
3328     {
3329         /* The unblocked task has a priority above that of the calling task, so
3330          * a context switch is required.  This function is called with the
3331          * scheduler suspended so xYieldPending is set so the context switch
3332          * occurs immediately that the scheduler is resumed (unsuspended). */
3333         xYieldPending = pdTRUE;
3334     }
3335 }
3336 /*-----------------------------------------------------------*/
3337
3338 void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
3339 {
3340     configASSERT( pxTimeOut );
3341     taskENTER_CRITICAL();
3342     {
3343         pxTimeOut->xOverflowCount = xNumOfOverflows;
3344         pxTimeOut->xTimeOnEntering = xTickCount;
3345     }
3346     taskEXIT_CRITICAL();
3347 }
3348 /*-----------------------------------------------------------*/
3349
3350 void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut )
3351 {
3352     /* For internal use only as it does not use a critical section. */
3353     pxTimeOut->xOverflowCount = xNumOfOverflows;
3354     pxTimeOut->xTimeOnEntering = xTickCount;
3355 }
3356 /*-----------------------------------------------------------*/
3357
3358 BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
3359                                  TickType_t * const pxTicksToWait )
3360 {
3361     BaseType_t xReturn;
3362
3363     configASSERT( pxTimeOut );
3364     configASSERT( pxTicksToWait );
3365
3366     taskENTER_CRITICAL();
3367     {
3368         /* Minor optimisation.  The tick count cannot change in this block. */
3369         const TickType_t xConstTickCount = xTickCount;
3370         const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering;
3371
3372         #if ( INCLUDE_xTaskAbortDelay == 1 )
3373             if( pxCurrentTCB->ucDelayAborted != ( uint8_t ) pdFALSE )
3374             {
3375                 /* The delay was aborted, which is not the same as a time out,
3376                  * but has the same result. */
3377                 pxCurrentTCB->ucDelayAborted = pdFALSE;
3378                 xReturn = pdTRUE;
3379             }
3380             else
3381         #endif
3382
3383         #if ( INCLUDE_vTaskSuspend == 1 )
3384             if( *pxTicksToWait == portMAX_DELAY )
3385             {
3386                 /* If INCLUDE_vTaskSuspend is set to 1 and the block time
3387                  * specified is the maximum block time then the task should block
3388                  * indefinitely, and therefore never time out. */
3389                 xReturn = pdFALSE;
3390             }
3391             else
3392         #endif
3393
3394         if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
3395         {
3396             /* The tick count is greater than the time at which
3397              * vTaskSetTimeout() was called, but has also overflowed since
3398              * vTaskSetTimeOut() was called.  It must have wrapped all the way
3399              * around and gone past again. This passed since vTaskSetTimeout()
3400              * was called. */
3401             xReturn = pdTRUE;
3402             *pxTicksToWait = ( TickType_t ) 0;
3403         }
3404         else if( xElapsedTime < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */
3405         {
3406             /* Not a genuine timeout. Adjust parameters for time remaining. */
3407             *pxTicksToWait -= xElapsedTime;
3408             vTaskInternalSetTimeOutState( pxTimeOut );
3409             xReturn = pdFALSE;
3410         }
3411         else
3412         {
3413             *pxTicksToWait = ( TickType_t ) 0;
3414             xReturn = pdTRUE;
3415         }
3416     }
3417     taskEXIT_CRITICAL();
3418
3419     return xReturn;
3420 }
3421 /*-----------------------------------------------------------*/
3422
3423 void vTaskMissedYield( void )
3424 {
3425     xYieldPending = pdTRUE;
3426 }
3427 /*-----------------------------------------------------------*/
3428
3429 #if ( configUSE_TRACE_FACILITY == 1 )
3430
3431     UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )
3432     {
3433         UBaseType_t uxReturn;
3434         TCB_t const * pxTCB;
3435
3436         if( xTask != NULL )
3437         {
3438             pxTCB = xTask;
3439             uxReturn = pxTCB->uxTaskNumber;
3440         }
3441         else
3442         {
3443             uxReturn = 0U;
3444         }
3445
3446         return uxReturn;
3447     }
3448
3449 #endif /* configUSE_TRACE_FACILITY */
3450 /*-----------------------------------------------------------*/
3451
3452 #if ( configUSE_TRACE_FACILITY == 1 )
3453
3454     void vTaskSetTaskNumber( TaskHandle_t xTask,
3455                              const UBaseType_t uxHandle )
3456     {
3457         TCB_t * pxTCB;
3458
3459         if( xTask != NULL )
3460         {
3461             pxTCB = xTask;
3462             pxTCB->uxTaskNumber = uxHandle;
3463         }
3464     }
3465
3466 #endif /* configUSE_TRACE_FACILITY */
3467
3468 /*
3469  * -----------------------------------------------------------
3470  * The Idle task.
3471  * ----------------------------------------------------------
3472  *
3473  * The portTASK_FUNCTION() macro is used to allow port/compiler specific
3474  * language extensions.  The equivalent prototype for this function is:
3475  *
3476  * void prvIdleTask( void *pvParameters );
3477  *
3478  */
3479
3480 portTASK_FUNCTION( prvIdleTask, pvParameters )
3481 {
3482     /* Stop warnings. */
3483     ( void ) pvParameters;
3484
3485     /** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
3486      * SCHEDULER IS STARTED. **/
3487
3488     /* In case a task that has a secure context deletes itself, in which case
3489      * the idle task is responsible for deleting the task's secure context, if
3490      * any. */
3491     portALLOCATE_SECURE_CONTEXT( configMINIMAL_SECURE_STACK_SIZE );
3492
3493     for( ; ; )
3494     {
3495         /* See if any tasks have deleted themselves - if so then the idle task
3496          * is responsible for freeing the deleted task's TCB and stack. */
3497         prvCheckTasksWaitingTermination();
3498
3499         #if ( configUSE_PREEMPTION == 0 )
3500         {
3501             /* If we are not using preemption we keep forcing a task switch to
3502              * see if any other task has become available.  If we are using
3503              * preemption we don't need to do this as any task becoming available
3504              * will automatically get the processor anyway. */
3505             taskYIELD();
3506         }
3507         #endif /* configUSE_PREEMPTION */
3508
3509         #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
3510         {
3511             /* When using preemption tasks of equal priority will be
3512              * timesliced.  If a task that is sharing the idle priority is ready
3513              * to run then the idle task should yield before the end of the
3514              * timeslice.
3515              *
3516              * A critical region is not required here as we are just reading from
3517              * the list, and an occasional incorrect value will not matter.  If
3518              * the ready list at the idle priority contains more than one task
3519              * then a task other than the idle task is ready to execute. */
3520             if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )
3521             {
3522                 taskYIELD();
3523             }
3524             else
3525             {
3526                 mtCOVERAGE_TEST_MARKER();
3527             }
3528         }
3529         #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
3530
3531         #if ( configUSE_IDLE_HOOK == 1 )
3532         {
3533             /* Call the user defined function from within the idle task. */
3534             vApplicationIdleHook();
3535         }
3536         #endif /* configUSE_IDLE_HOOK */
3537
3538         /* This conditional compilation should use inequality to 0, not equality
3539          * to 1.  This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
3540          * user defined low power mode  implementations require
3541          * configUSE_TICKLESS_IDLE to be set to a value other than 1. */
3542         #if ( configUSE_TICKLESS_IDLE != 0 )
3543         {
3544             TickType_t xExpectedIdleTime;
3545
3546             /* It is not desirable to suspend then resume the scheduler on
3547              * each iteration of the idle task.  Therefore, a preliminary
3548              * test of the expected idle time is performed without the
3549              * scheduler suspended.  The result here is not necessarily
3550              * valid. */
3551             xExpectedIdleTime = prvGetExpectedIdleTime();
3552
3553             if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
3554             {
3555                 vTaskSuspendAll();
3556                 {
3557                     /* Now the scheduler is suspended, the expected idle
3558                      * time can be sampled again, and this time its value can
3559                      * be used. */
3560                     configASSERT( xNextTaskUnblockTime >= xTickCount );
3561                     xExpectedIdleTime = prvGetExpectedIdleTime();
3562
3563                     /* Define the following macro to set xExpectedIdleTime to 0
3564                      * if the application does not want
3565                      * portSUPPRESS_TICKS_AND_SLEEP() to be called. */
3566                     configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime );
3567
3568                     if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
3569                     {
3570                         traceLOW_POWER_IDLE_BEGIN();
3571                         portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
3572                         traceLOW_POWER_IDLE_END();
3573                     }
3574                     else
3575                     {
3576                         mtCOVERAGE_TEST_MARKER();
3577                     }
3578                 }
3579                 ( void ) xTaskResumeAll();
3580             }
3581             else
3582             {
3583                 mtCOVERAGE_TEST_MARKER();
3584             }
3585         }
3586         #endif /* configUSE_TICKLESS_IDLE */
3587     }
3588 }
3589 /*-----------------------------------------------------------*/
3590
3591 #if ( configUSE_TICKLESS_IDLE != 0 )
3592
3593     eSleepModeStatus eTaskConfirmSleepModeStatus( void )
3594     {
3595         #if ( INCLUDE_vTaskSuspend == 1 )
3596             /* The idle task exists in addition to the application tasks. */
3597             const UBaseType_t uxNonApplicationTasks = 1;
3598         #endif /* INCLUDE_vTaskSuspend */
3599
3600         eSleepModeStatus eReturn = eStandardSleep;
3601
3602         /* This function must be called from a critical section. */
3603
3604         if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
3605         {
3606             /* A task was made ready while the scheduler was suspended. */
3607             eReturn = eAbortSleep;
3608         }
3609         else if( xYieldPending != pdFALSE )
3610         {
3611             /* A yield was pended while the scheduler was suspended. */
3612             eReturn = eAbortSleep;
3613         }
3614         else if( xPendedTicks != 0 )
3615         {
3616             /* A tick interrupt has already occurred but was held pending
3617              * because the scheduler is suspended. */
3618             eReturn = eAbortSleep;
3619         }
3620
3621         #if ( INCLUDE_vTaskSuspend == 1 )
3622             else if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
3623             {
3624                 /* If all the tasks are in the suspended list (which might mean they
3625                  * have an infinite block time rather than actually being suspended)
3626                  * then it is safe to turn all clocks off and just wait for external
3627                  * interrupts. */
3628                 eReturn = eNoTasksWaitingTimeout;
3629             }
3630         #endif /* INCLUDE_vTaskSuspend */
3631         else
3632         {
3633             mtCOVERAGE_TEST_MARKER();
3634         }
3635
3636         return eReturn;
3637     }
3638
3639 #endif /* configUSE_TICKLESS_IDLE */
3640 /*-----------------------------------------------------------*/
3641
3642 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
3643
3644     void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet,
3645                                             BaseType_t xIndex,
3646                                             void * pvValue )
3647     {
3648         TCB_t * pxTCB;
3649
3650         if( ( xIndex >= 0 ) &&
3651             ( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) )
3652         {
3653             pxTCB = prvGetTCBFromHandle( xTaskToSet );
3654             configASSERT( pxTCB != NULL );
3655             pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue;
3656         }
3657     }
3658
3659 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
3660 /*-----------------------------------------------------------*/
3661
3662 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
3663
3664     void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery,
3665                                                BaseType_t xIndex )
3666     {
3667         void * pvReturn = NULL;
3668         TCB_t * pxTCB;
3669
3670         if( ( xIndex >= 0 ) &&
3671             ( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS ) )
3672         {
3673             pxTCB = prvGetTCBFromHandle( xTaskToQuery );
3674             pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ];
3675         }
3676         else
3677         {
3678             pvReturn = NULL;
3679         }
3680
3681         return pvReturn;
3682     }
3683
3684 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
3685 /*-----------------------------------------------------------*/
3686
3687 #if ( portUSING_MPU_WRAPPERS == 1 )
3688
3689     void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify,
3690                                   const MemoryRegion_t * const xRegions )
3691     {
3692         TCB_t * pxTCB;
3693
3694         /* If null is passed in here then we are modifying the MPU settings of
3695          * the calling task. */
3696         pxTCB = prvGetTCBFromHandle( xTaskToModify );
3697
3698         vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
3699     }
3700
3701 #endif /* portUSING_MPU_WRAPPERS */
3702 /*-----------------------------------------------------------*/
3703
3704 static void prvInitialiseTaskLists( void )
3705 {
3706     UBaseType_t uxPriority;
3707
3708     for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
3709     {
3710         vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
3711     }
3712
3713     vListInitialise( &xDelayedTaskList1 );
3714     vListInitialise( &xDelayedTaskList2 );
3715     vListInitialise( &xPendingReadyList );
3716
3717     #if ( INCLUDE_vTaskDelete == 1 )
3718     {
3719         vListInitialise( &xTasksWaitingTermination );
3720     }
3721     #endif /* INCLUDE_vTaskDelete */
3722
3723     #if ( INCLUDE_vTaskSuspend == 1 )
3724     {
3725         vListInitialise( &xSuspendedTaskList );
3726     }
3727     #endif /* INCLUDE_vTaskSuspend */
3728
3729     /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
3730      * using list2. */
3731     pxDelayedTaskList = &xDelayedTaskList1;
3732     pxOverflowDelayedTaskList = &xDelayedTaskList2;
3733 }
3734 /*-----------------------------------------------------------*/
3735
3736 static void prvCheckTasksWaitingTermination( void )
3737 {
3738     /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/
3739
3740     #if ( INCLUDE_vTaskDelete == 1 )
3741     {
3742         TCB_t * pxTCB;
3743
3744         /* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL()
3745          * being called too often in the idle task. */
3746         while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
3747         {
3748             taskENTER_CRITICAL();
3749             {
3750                 pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
3751                 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
3752                 --uxCurrentNumberOfTasks;
3753                 --uxDeletedTasksWaitingCleanUp;
3754             }
3755             taskEXIT_CRITICAL();
3756
3757             prvDeleteTCB( pxTCB );
3758         }
3759     }
3760     #endif /* INCLUDE_vTaskDelete */
3761 }
3762 /*-----------------------------------------------------------*/
3763
3764 #if ( configUSE_TRACE_FACILITY == 1 )
3765
3766     void vTaskGetInfo( TaskHandle_t xTask,
3767                        TaskStatus_t * pxTaskStatus,
3768                        BaseType_t xGetFreeStackSpace,
3769                        eTaskState eState )
3770     {
3771         TCB_t * pxTCB;
3772
3773         /* xTask is NULL then get the state of the calling task. */
3774         pxTCB = prvGetTCBFromHandle( xTask );
3775
3776         pxTaskStatus->xHandle = ( TaskHandle_t ) pxTCB;
3777         pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName[ 0 ] );
3778         pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority;
3779         pxTaskStatus->pxStackBase = pxTCB->pxStack;
3780         #if ( ( portSTACK_GROWTH > 0 ) && ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
3781             pxTaskStatus->pxTopOfStack = pxTCB->pxTopOfStack;
3782             pxTaskStatus->pxEndOfStack = pxTCB->pxEndOfStack;
3783         #endif
3784         pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber;
3785
3786         #if ( configUSE_MUTEXES == 1 )
3787         {
3788             pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;
3789         }
3790         #else
3791         {
3792             pxTaskStatus->uxBasePriority = 0;
3793         }
3794         #endif
3795
3796         #if ( configGENERATE_RUN_TIME_STATS == 1 )
3797         {
3798             pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter;
3799         }
3800         #else
3801         {
3802             pxTaskStatus->ulRunTimeCounter = ( configRUN_TIME_COUNTER_TYPE ) 0;
3803         }
3804         #endif
3805
3806         /* Obtaining the task state is a little fiddly, so is only done if the
3807          * value of eState passed into this function is eInvalid - otherwise the
3808          * state is just set to whatever is passed in. */
3809         if( eState != eInvalid )
3810         {
3811             if( pxTCB == pxCurrentTCB )
3812             {
3813                 pxTaskStatus->eCurrentState = eRunning;
3814             }
3815             else
3816             {
3817                 pxTaskStatus->eCurrentState = eState;
3818
3819                 #if ( INCLUDE_vTaskSuspend == 1 )
3820                 {
3821                     /* If the task is in the suspended list then there is a
3822                      *  chance it is actually just blocked indefinitely - so really
3823                      *  it should be reported as being in the Blocked state. */
3824                     if( eState == eSuspended )
3825                     {
3826                         vTaskSuspendAll();
3827                         {
3828                             if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
3829                             {
3830                                 pxTaskStatus->eCurrentState = eBlocked;
3831                             }
3832                         }
3833                         ( void ) xTaskResumeAll();
3834                     }
3835                 }
3836                 #endif /* INCLUDE_vTaskSuspend */
3837             }
3838         }
3839         else
3840         {
3841             pxTaskStatus->eCurrentState = eTaskGetState( pxTCB );
3842         }
3843
3844         /* Obtaining the stack space takes some time, so the xGetFreeStackSpace
3845          * parameter is provided to allow it to be skipped. */
3846         if( xGetFreeStackSpace != pdFALSE )
3847         {
3848             #if ( portSTACK_GROWTH > 0 )
3849             {
3850                 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack );
3851             }
3852             #else
3853             {
3854                 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack );
3855             }
3856             #endif
3857         }
3858         else
3859         {
3860             pxTaskStatus->usStackHighWaterMark = 0;
3861         }
3862     }
3863
3864 #endif /* configUSE_TRACE_FACILITY */
3865 /*-----------------------------------------------------------*/
3866
3867 #if ( configUSE_TRACE_FACILITY == 1 )
3868
3869     static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray,
3870                                                      List_t * pxList,
3871                                                      eTaskState eState )
3872     {
3873         configLIST_VOLATILE TCB_t * pxNextTCB;
3874         configLIST_VOLATILE TCB_t * pxFirstTCB;
3875         UBaseType_t uxTask = 0;
3876
3877         if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
3878         {
3879             listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
3880
3881             /* Populate an TaskStatus_t structure within the
3882              * pxTaskStatusArray array for each task that is referenced from
3883              * pxList.  See the definition of TaskStatus_t in task.h for the
3884              * meaning of each TaskStatus_t structure member. */
3885             do
3886             {
3887                 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers too.  Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
3888                 vTaskGetInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState );
3889                 uxTask++;
3890             } while( pxNextTCB != pxFirstTCB );
3891         }
3892         else
3893         {
3894             mtCOVERAGE_TEST_MARKER();
3895         }
3896
3897         return uxTask;
3898     }
3899
3900 #endif /* configUSE_TRACE_FACILITY */
3901 /*-----------------------------------------------------------*/
3902
3903 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) )
3904
3905     static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
3906     {
3907         uint32_t ulCount = 0U;
3908
3909         while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE )
3910         {
3911             pucStackByte -= portSTACK_GROWTH;
3912             ulCount++;
3913         }
3914
3915         ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */
3916
3917         return ( configSTACK_DEPTH_TYPE ) ulCount;
3918     }
3919
3920 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) ) */
3921 /*-----------------------------------------------------------*/
3922
3923 #if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 )
3924
3925 /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the
3926  * same except for their return type.  Using configSTACK_DEPTH_TYPE allows the
3927  * user to determine the return type.  It gets around the problem of the value
3928  * overflowing on 8-bit types without breaking backward compatibility for
3929  * applications that expect an 8-bit return type. */
3930     configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask )
3931     {
3932         TCB_t * pxTCB;
3933         uint8_t * pucEndOfStack;
3934         configSTACK_DEPTH_TYPE uxReturn;
3935
3936         /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are
3937          * the same except for their return type.  Using configSTACK_DEPTH_TYPE
3938          * allows the user to determine the return type.  It gets around the
3939          * problem of the value overflowing on 8-bit types without breaking
3940          * backward compatibility for applications that expect an 8-bit return
3941          * type. */
3942
3943         pxTCB = prvGetTCBFromHandle( xTask );
3944
3945         #if portSTACK_GROWTH < 0
3946         {
3947             pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
3948         }
3949         #else
3950         {
3951             pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
3952         }
3953         #endif
3954
3955         uxReturn = prvTaskCheckFreeStackSpace( pucEndOfStack );
3956
3957         return uxReturn;
3958     }
3959
3960 #endif /* INCLUDE_uxTaskGetStackHighWaterMark2 */
3961 /*-----------------------------------------------------------*/
3962
3963 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
3964
3965     UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
3966     {
3967         TCB_t * pxTCB;
3968         uint8_t * pucEndOfStack;
3969         UBaseType_t uxReturn;
3970
3971         pxTCB = prvGetTCBFromHandle( xTask );
3972
3973         #if portSTACK_GROWTH < 0
3974         {
3975             pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
3976         }
3977         #else
3978         {
3979             pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
3980         }
3981         #endif
3982
3983         uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );
3984
3985         return uxReturn;
3986     }
3987
3988 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
3989 /*-----------------------------------------------------------*/
3990
3991 #if ( INCLUDE_vTaskDelete == 1 )
3992
3993     static void prvDeleteTCB( TCB_t * pxTCB )
3994     {
3995         /* This call is required specifically for the TriCore port.  It must be
3996          * above the vPortFree() calls.  The call is also used by ports/demos that
3997          * want to allocate and clean RAM statically. */
3998         portCLEAN_UP_TCB( pxTCB );
3999
4000         #if ( configUSE_C_RUNTIME_TLS_SUPPORT == 1 )
4001         {
4002             /* Free up the memory allocated for the task's TLS Block. */
4003             configDEINIT_TLS_BLOCK( pxCurrentTCB->xTLSBlock );
4004         }
4005         #endif
4006
4007         #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
4008         {
4009             /* The task can only have been allocated dynamically - free both
4010              * the stack and TCB. */
4011             vPortFreeStack( pxTCB->pxStack );
4012             vPortFree( pxTCB );
4013         }
4014         #elif ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
4015         {
4016             /* The task could have been allocated statically or dynamically, so
4017              * check what was statically allocated before trying to free the
4018              * memory. */
4019             if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB )
4020             {
4021                 /* Both the stack and TCB were allocated dynamically, so both
4022                  * must be freed. */
4023                 vPortFreeStack( pxTCB->pxStack );
4024                 vPortFree( pxTCB );
4025             }
4026             else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY )
4027             {
4028                 /* Only the stack was statically allocated, so the TCB is the
4029                  * only memory that must be freed. */
4030                 vPortFree( pxTCB );
4031             }
4032             else
4033             {
4034                 /* Neither the stack nor the TCB were allocated dynamically, so
4035                  * nothing needs to be freed. */
4036                 configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB );
4037                 mtCOVERAGE_TEST_MARKER();
4038             }
4039         }
4040         #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
4041     }
4042
4043 #endif /* INCLUDE_vTaskDelete */
4044 /*-----------------------------------------------------------*/
4045
4046 static void prvResetNextTaskUnblockTime( void )
4047 {
4048     if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
4049     {
4050         /* The new current delayed list is empty.  Set xNextTaskUnblockTime to
4051          * the maximum possible value so it is  extremely unlikely that the
4052          * if( xTickCount >= xNextTaskUnblockTime ) test will pass until
4053          * there is an item in the delayed list. */
4054         xNextTaskUnblockTime = portMAX_DELAY;
4055     }
4056     else
4057     {
4058         /* The new current delayed list is not empty, get the value of
4059          * the item at the head of the delayed list.  This is the time at
4060          * which the task at the head of the delayed list should be removed
4061          * from the Blocked state. */
4062         xNextTaskUnblockTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxDelayedTaskList );
4063     }
4064 }
4065 /*-----------------------------------------------------------*/
4066
4067 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
4068
4069     TaskHandle_t xTaskGetCurrentTaskHandle( void )
4070     {
4071         TaskHandle_t xReturn;
4072
4073         /* A critical section is not required as this is not called from
4074          * an interrupt and the current TCB will always be the same for any
4075          * individual execution thread. */
4076         xReturn = pxCurrentTCB;
4077
4078         return xReturn;
4079     }
4080
4081 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
4082 /*-----------------------------------------------------------*/
4083
4084 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
4085
4086     BaseType_t xTaskGetSchedulerState( void )
4087     {
4088         BaseType_t xReturn;
4089
4090         if( xSchedulerRunning == pdFALSE )
4091         {
4092             xReturn = taskSCHEDULER_NOT_STARTED;
4093         }
4094         else
4095         {
4096             if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
4097             {
4098                 xReturn = taskSCHEDULER_RUNNING;
4099             }
4100             else
4101             {
4102                 xReturn = taskSCHEDULER_SUSPENDED;
4103             }
4104         }
4105
4106         return xReturn;
4107     }
4108
4109 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
4110 /*-----------------------------------------------------------*/
4111
4112 #if ( configUSE_MUTEXES == 1 )
4113
4114     BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
4115     {
4116         TCB_t * const pxMutexHolderTCB = pxMutexHolder;
4117         BaseType_t xReturn = pdFALSE;
4118
4119         /* If the mutex was given back by an interrupt while the queue was
4120          * locked then the mutex holder might now be NULL.  _RB_ Is this still
4121          * needed as interrupts can no longer use mutexes? */
4122         if( pxMutexHolder != NULL )
4123         {
4124             /* If the holder of the mutex has a priority below the priority of
4125              * the task attempting to obtain the mutex then it will temporarily
4126              * inherit the priority of the task attempting to obtain the mutex. */
4127             if( pxMutexHolderTCB->uxPriority < pxCurrentTCB->uxPriority )
4128             {
4129                 /* Adjust the mutex holder state to account for its new
4130                  * priority.  Only reset the event list item value if the value is
4131                  * not being used for anything else. */
4132                 if( ( listGET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
4133                 {
4134                     listSET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
4135                 }
4136                 else
4137                 {
4138                     mtCOVERAGE_TEST_MARKER();
4139                 }
4140
4141                 /* If the task being modified is in the ready state it will need
4142                  * to be moved into a new list. */
4143                 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxMutexHolderTCB->uxPriority ] ), &( pxMutexHolderTCB->xStateListItem ) ) != pdFALSE )
4144                 {
4145                     if( uxListRemove( &( pxMutexHolderTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
4146                     {
4147                         /* It is known that the task is in its ready list so
4148                          * there is no need to check again and the port level
4149                          * reset macro can be called directly. */
4150                         portRESET_READY_PRIORITY( pxMutexHolderTCB->uxPriority, uxTopReadyPriority );
4151                     }
4152                     else
4153                     {
4154                         mtCOVERAGE_TEST_MARKER();
4155                     }
4156
4157                     /* Inherit the priority before being moved into the new list. */
4158                     pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
4159                     prvAddTaskToReadyList( pxMutexHolderTCB );
4160                 }
4161                 else
4162                 {
4163                     /* Just inherit the priority. */
4164                     pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
4165                 }
4166
4167                 traceTASK_PRIORITY_INHERIT( pxMutexHolderTCB, pxCurrentTCB->uxPriority );
4168
4169                 /* Inheritance occurred. */
4170                 xReturn = pdTRUE;
4171             }
4172             else
4173             {
4174                 if( pxMutexHolderTCB->uxBasePriority < pxCurrentTCB->uxPriority )
4175                 {
4176                     /* The base priority of the mutex holder is lower than the
4177                      * priority of the task attempting to take the mutex, but the
4178                      * current priority of the mutex holder is not lower than the
4179                      * priority of the task attempting to take the mutex.
4180                      * Therefore the mutex holder must have already inherited a
4181                      * priority, but inheritance would have occurred if that had
4182                      * not been the case. */
4183                     xReturn = pdTRUE;
4184                 }
4185                 else
4186                 {
4187                     mtCOVERAGE_TEST_MARKER();
4188                 }
4189             }
4190         }
4191         else
4192         {
4193             mtCOVERAGE_TEST_MARKER();
4194         }
4195
4196         return xReturn;
4197     }
4198
4199 #endif /* configUSE_MUTEXES */
4200 /*-----------------------------------------------------------*/
4201
4202 #if ( configUSE_MUTEXES == 1 )
4203
4204     BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )
4205     {
4206         TCB_t * const pxTCB = pxMutexHolder;
4207         BaseType_t xReturn = pdFALSE;
4208
4209         if( pxMutexHolder != NULL )
4210         {
4211             /* A task can only have an inherited priority if it holds the mutex.
4212              * If the mutex is held by a task then it cannot be given from an
4213              * interrupt, and if a mutex is given by the holding task then it must
4214              * be the running state task. */
4215             configASSERT( pxTCB == pxCurrentTCB );
4216             configASSERT( pxTCB->uxMutexesHeld );
4217             ( pxTCB->uxMutexesHeld )--;
4218
4219             /* Has the holder of the mutex inherited the priority of another
4220              * task? */
4221             if( pxTCB->uxPriority != pxTCB->uxBasePriority )
4222             {
4223                 /* Only disinherit if no other mutexes are held. */
4224                 if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
4225                 {
4226                     /* A task can only have an inherited priority if it holds
4227                      * the mutex.  If the mutex is held by a task then it cannot be
4228                      * given from an interrupt, and if a mutex is given by the
4229                      * holding task then it must be the running state task.  Remove
4230                      * the holding task from the ready list. */
4231                     if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
4232                     {
4233                         portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );
4234                     }
4235                     else
4236                     {
4237                         mtCOVERAGE_TEST_MARKER();
4238                     }
4239
4240                     /* Disinherit the priority before adding the task into the
4241                      * new  ready list. */
4242                     traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
4243                     pxTCB->uxPriority = pxTCB->uxBasePriority;
4244
4245                     /* Reset the event list item value.  It cannot be in use for
4246                      * any other purpose if this task is running, and it must be
4247                      * running to give back the mutex. */
4248                     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. */
4249                     prvAddTaskToReadyList( pxTCB );
4250
4251                     /* Return true to indicate that a context switch is required.
4252                      * This is only actually required in the corner case whereby
4253                      * multiple mutexes were held and the mutexes were given back
4254                      * in an order different to that in which they were taken.
4255                      * If a context switch did not occur when the first mutex was
4256                      * returned, even if a task was waiting on it, then a context
4257                      * switch should occur when the last mutex is returned whether
4258                      * a task is waiting on it or not. */
4259                     xReturn = pdTRUE;
4260                 }
4261                 else
4262                 {
4263                     mtCOVERAGE_TEST_MARKER();
4264                 }
4265             }
4266             else
4267             {
4268                 mtCOVERAGE_TEST_MARKER();
4269             }
4270         }
4271         else
4272         {
4273             mtCOVERAGE_TEST_MARKER();
4274         }
4275
4276         return xReturn;
4277     }
4278
4279 #endif /* configUSE_MUTEXES */
4280 /*-----------------------------------------------------------*/
4281
4282 #if ( configUSE_MUTEXES == 1 )
4283
4284     void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder,
4285                                               UBaseType_t uxHighestPriorityWaitingTask )
4286     {
4287         TCB_t * const pxTCB = pxMutexHolder;
4288         UBaseType_t uxPriorityUsedOnEntry, uxPriorityToUse;
4289         const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1;
4290
4291         if( pxMutexHolder != NULL )
4292         {
4293             /* If pxMutexHolder is not NULL then the holder must hold at least
4294              * one mutex. */
4295             configASSERT( pxTCB->uxMutexesHeld );
4296
4297             /* Determine the priority to which the priority of the task that
4298              * holds the mutex should be set.  This will be the greater of the
4299              * holding task's base priority and the priority of the highest
4300              * priority task that is waiting to obtain the mutex. */
4301             if( pxTCB->uxBasePriority < uxHighestPriorityWaitingTask )
4302             {
4303                 uxPriorityToUse = uxHighestPriorityWaitingTask;
4304             }
4305             else
4306             {
4307                 uxPriorityToUse = pxTCB->uxBasePriority;
4308             }
4309
4310             /* Does the priority need to change? */
4311             if( pxTCB->uxPriority != uxPriorityToUse )
4312             {
4313                 /* Only disinherit if no other mutexes are held.  This is a
4314                  * simplification in the priority inheritance implementation.  If
4315                  * the task that holds the mutex is also holding other mutexes then
4316                  * the other mutexes may have caused the priority inheritance. */
4317                 if( pxTCB->uxMutexesHeld == uxOnlyOneMutexHeld )
4318                 {
4319                     /* If a task has timed out because it already holds the
4320                      * mutex it was trying to obtain then it cannot of inherited
4321                      * its own priority. */
4322                     configASSERT( pxTCB != pxCurrentTCB );
4323
4324                     /* Disinherit the priority, remembering the previous
4325                      * priority to facilitate determining the subject task's
4326                      * state. */
4327                     traceTASK_PRIORITY_DISINHERIT( pxTCB, uxPriorityToUse );
4328                     uxPriorityUsedOnEntry = pxTCB->uxPriority;
4329                     pxTCB->uxPriority = uxPriorityToUse;
4330
4331                     /* Only reset the event list item value if the value is not
4332                      * being used for anything else. */
4333                     if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
4334                     {
4335                         listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriorityToUse ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
4336                     }
4337                     else
4338                     {
4339                         mtCOVERAGE_TEST_MARKER();
4340                     }
4341
4342                     /* If the running task is not the task that holds the mutex
4343                      * then the task that holds the mutex could be in either the
4344                      * Ready, Blocked or Suspended states.  Only remove the task
4345                      * from its current state list if it is in the Ready state as
4346                      * the task's priority is going to change and there is one
4347                      * Ready list per priority. */
4348                     if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
4349                     {
4350                         if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
4351                         {
4352                             /* It is known that the task is in its ready list so
4353                              * there is no need to check again and the port level
4354                              * reset macro can be called directly. */
4355                             portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );
4356                         }
4357                         else
4358                         {
4359                             mtCOVERAGE_TEST_MARKER();
4360                         }
4361
4362                         prvAddTaskToReadyList( pxTCB );
4363                     }
4364                     else
4365                     {
4366                         mtCOVERAGE_TEST_MARKER();
4367                     }
4368                 }
4369                 else
4370                 {
4371                     mtCOVERAGE_TEST_MARKER();
4372                 }
4373             }
4374             else
4375             {
4376                 mtCOVERAGE_TEST_MARKER();
4377             }
4378         }
4379         else
4380         {
4381             mtCOVERAGE_TEST_MARKER();
4382         }
4383     }
4384
4385 #endif /* configUSE_MUTEXES */
4386 /*-----------------------------------------------------------*/
4387
4388 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
4389
4390     void vTaskEnterCritical( void )
4391     {
4392         portDISABLE_INTERRUPTS();
4393
4394         if( xSchedulerRunning != pdFALSE )
4395         {
4396             ( pxCurrentTCB->uxCriticalNesting )++;
4397
4398             /* This is not the interrupt safe version of the enter critical
4399              * function so  assert() if it is being called from an interrupt
4400              * context.  Only API functions that end in "FromISR" can be used in an
4401              * interrupt.  Only assert if the critical nesting count is 1 to
4402              * protect against recursive calls if the assert function also uses a
4403              * critical section. */
4404             if( pxCurrentTCB->uxCriticalNesting == 1 )
4405             {
4406                 portASSERT_IF_IN_ISR();
4407             }
4408         }
4409         else
4410         {
4411             mtCOVERAGE_TEST_MARKER();
4412         }
4413     }
4414
4415 #endif /* portCRITICAL_NESTING_IN_TCB */
4416 /*-----------------------------------------------------------*/
4417
4418 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
4419
4420     void vTaskExitCritical( void )
4421     {
4422         if( xSchedulerRunning != pdFALSE )
4423         {
4424             if( pxCurrentTCB->uxCriticalNesting > 0U )
4425             {
4426                 ( pxCurrentTCB->uxCriticalNesting )--;
4427
4428                 if( pxCurrentTCB->uxCriticalNesting == 0U )
4429                 {
4430                     portENABLE_INTERRUPTS();
4431                 }
4432                 else
4433                 {
4434                     mtCOVERAGE_TEST_MARKER();
4435                 }
4436             }
4437             else
4438             {
4439                 mtCOVERAGE_TEST_MARKER();
4440             }
4441         }
4442         else
4443         {
4444             mtCOVERAGE_TEST_MARKER();
4445         }
4446     }
4447
4448 #endif /* portCRITICAL_NESTING_IN_TCB */
4449 /*-----------------------------------------------------------*/
4450
4451 #if ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 )
4452
4453     static char * prvWriteNameToBuffer( char * pcBuffer,
4454                                         const char * pcTaskName )
4455     {
4456         size_t x;
4457
4458         /* Start by copying the entire string. */
4459         strcpy( pcBuffer, pcTaskName );
4460
4461         /* Pad the end of the string with spaces to ensure columns line up when
4462          * printed out. */
4463         for( x = strlen( pcBuffer ); x < ( size_t ) ( configMAX_TASK_NAME_LEN - 1 ); x++ )
4464         {
4465             pcBuffer[ x ] = ' ';
4466         }
4467
4468         /* Terminate. */
4469         pcBuffer[ x ] = ( char ) 0x00;
4470
4471         /* Return the new end of string. */
4472         return &( pcBuffer[ x ] );
4473     }
4474
4475 #endif /* ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
4476 /*-----------------------------------------------------------*/
4477
4478 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
4479
4480     void vTaskList( char * pcWriteBuffer )
4481     {
4482         TaskStatus_t * pxTaskStatusArray;
4483         UBaseType_t uxArraySize, x;
4484         char cStatus;
4485
4486         /*
4487          * PLEASE NOTE:
4488          *
4489          * This function is provided for convenience only, and is used by many
4490          * of the demo applications.  Do not consider it to be part of the
4491          * scheduler.
4492          *
4493          * vTaskList() calls uxTaskGetSystemState(), then formats part of the
4494          * uxTaskGetSystemState() output into a human readable table that
4495          * displays task: names, states, priority, stack usage and task number.
4496          * Stack usage specified as the number of unused StackType_t words stack can hold
4497          * on top of stack - not the number of bytes.
4498          *
4499          * vTaskList() has a dependency on the sprintf() C library function that
4500          * might bloat the code size, use a lot of stack, and provide different
4501          * results on different platforms.  An alternative, tiny, third party,
4502          * and limited functionality implementation of sprintf() is provided in
4503          * many of the FreeRTOS/Demo sub-directories in a file called
4504          * printf-stdarg.c (note printf-stdarg.c does not provide a full
4505          * snprintf() implementation!).
4506          *
4507          * It is recommended that production systems call uxTaskGetSystemState()
4508          * directly to get access to raw stats data, rather than indirectly
4509          * through a call to vTaskList().
4510          */
4511
4512
4513         /* Make sure the write buffer does not contain a string. */
4514         *pcWriteBuffer = ( char ) 0x00;
4515
4516         /* Take a snapshot of the number of tasks in case it changes while this
4517          * function is executing. */
4518         uxArraySize = uxCurrentNumberOfTasks;
4519
4520         /* Allocate an array index for each task.  NOTE!  if
4521          * configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
4522          * equate to NULL. */
4523         pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation allocates a struct that has the alignment requirements of a pointer. */
4524
4525         if( pxTaskStatusArray != NULL )
4526         {
4527             /* Generate the (binary) data. */
4528             uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
4529
4530             /* Create a human readable table from the binary data. */
4531             for( x = 0; x < uxArraySize; x++ )
4532             {
4533                 switch( pxTaskStatusArray[ x ].eCurrentState )
4534                 {
4535                     case eRunning:
4536                         cStatus = tskRUNNING_CHAR;
4537                         break;
4538
4539                     case eReady:
4540                         cStatus = tskREADY_CHAR;
4541                         break;
4542
4543                     case eBlocked:
4544                         cStatus = tskBLOCKED_CHAR;
4545                         break;
4546
4547                     case eSuspended:
4548                         cStatus = tskSUSPENDED_CHAR;
4549                         break;
4550
4551                     case eDeleted:
4552                         cStatus = tskDELETED_CHAR;
4553                         break;
4554
4555                     case eInvalid: /* Fall through. */
4556                     default:       /* Should not get here, but it is included
4557                                     * to prevent static checking errors. */
4558                         cStatus = ( char ) 0x00;
4559                         break;
4560                 }
4561
4562                 /* Write the task name to the string, padding with spaces so it
4563                  * can be printed in tabular form more easily. */
4564                 pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
4565
4566                 /* Write the rest of the string. */
4567                 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 ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */
4568                 pcWriteBuffer += strlen( pcWriteBuffer );                                                                                                                                                                                                /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */
4569             }
4570
4571             /* Free the array again.  NOTE!  If configSUPPORT_DYNAMIC_ALLOCATION
4572              * is 0 then vPortFree() will be #defined to nothing. */
4573             vPortFree( pxTaskStatusArray );
4574         }
4575         else
4576         {
4577             mtCOVERAGE_TEST_MARKER();
4578         }
4579     }
4580
4581 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
4582 /*----------------------------------------------------------*/
4583
4584 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configUSE_TRACE_FACILITY == 1 ) )
4585
4586     void vTaskGetRunTimeStats( char * pcWriteBuffer )
4587     {
4588         TaskStatus_t * pxTaskStatusArray;
4589         UBaseType_t uxArraySize, x;
4590         configRUN_TIME_COUNTER_TYPE ulTotalTime, ulStatsAsPercentage;
4591
4592         /*
4593          * PLEASE NOTE:
4594          *
4595          * This function is provided for convenience only, and is used by many
4596          * of the demo applications.  Do not consider it to be part of the
4597          * scheduler.
4598          *
4599          * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part
4600          * of the uxTaskGetSystemState() output into a human readable table that
4601          * displays the amount of time each task has spent in the Running state
4602          * in both absolute and percentage terms.
4603          *
4604          * vTaskGetRunTimeStats() has a dependency on the sprintf() C library
4605          * function that might bloat the code size, use a lot of stack, and
4606          * provide different results on different platforms.  An alternative,
4607          * tiny, third party, and limited functionality implementation of
4608          * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in
4609          * a file called printf-stdarg.c (note printf-stdarg.c does not provide
4610          * a full snprintf() implementation!).
4611          *
4612          * It is recommended that production systems call uxTaskGetSystemState()
4613          * directly to get access to raw stats data, rather than indirectly
4614          * through a call to vTaskGetRunTimeStats().
4615          */
4616
4617         /* Make sure the write buffer does not contain a string. */
4618         *pcWriteBuffer = ( char ) 0x00;
4619
4620         /* Take a snapshot of the number of tasks in case it changes while this
4621          * function is executing. */
4622         uxArraySize = uxCurrentNumberOfTasks;
4623
4624         /* Allocate an array index for each task.  NOTE!  If
4625          * configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
4626          * equate to NULL. */
4627         pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation allocates a struct that has the alignment requirements of a pointer. */
4628
4629         if( pxTaskStatusArray != NULL )
4630         {
4631             /* Generate the (binary) data. */
4632             uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
4633
4634             /* For percentage calculations. */
4635             ulTotalTime /= 100UL;
4636
4637             /* Avoid divide by zero errors. */
4638             if( ulTotalTime > 0UL )
4639             {
4640                 /* Create a human readable table from the binary data. */
4641                 for( x = 0; x < uxArraySize; x++ )
4642                 {
4643                     /* What percentage of the total run time has the task used?
4644                      * This will always be rounded down to the nearest integer.
4645                      * ulTotalRunTime has already been divided by 100. */
4646                     ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
4647
4648                     /* Write the task name to the string, padding with
4649                      * spaces so it can be printed in tabular form more
4650                      * easily. */
4651                     pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
4652
4653                     if( ulStatsAsPercentage > 0UL )
4654                     {
4655                         #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
4656                         {
4657                             sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
4658                         }
4659                         #else
4660                         {
4661                             /* sizeof( int ) == sizeof( long ) so a smaller
4662                              * printf() library can be used. */
4663                             sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */
4664                         }
4665                         #endif
4666                     }
4667                     else
4668                     {
4669                         /* If the percentage is zero here then the task has
4670                          * consumed less than 1% of the total run time. */
4671                         #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
4672                         {
4673                             sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter );
4674                         }
4675                         #else
4676                         {
4677                             /* sizeof( int ) == sizeof( long ) so a smaller
4678                              * printf() library can be used. */
4679                             sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */
4680                         }
4681                         #endif
4682                     }
4683
4684                     pcWriteBuffer += strlen( pcWriteBuffer ); /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */
4685                 }
4686             }
4687             else
4688             {
4689                 mtCOVERAGE_TEST_MARKER();
4690             }
4691
4692             /* Free the array again.  NOTE!  If configSUPPORT_DYNAMIC_ALLOCATION
4693              * is 0 then vPortFree() will be #defined to nothing. */
4694             vPortFree( pxTaskStatusArray );
4695         }
4696         else
4697         {
4698             mtCOVERAGE_TEST_MARKER();
4699         }
4700     }
4701
4702 #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
4703 /*-----------------------------------------------------------*/
4704
4705 TickType_t uxTaskResetEventItemValue( void )
4706 {
4707     TickType_t uxReturn;
4708
4709     uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );
4710
4711     /* Reset the event list item to its normal value - so it can be used with
4712      * queues and semaphores. */
4713     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. */
4714
4715     return uxReturn;
4716 }
4717 /*-----------------------------------------------------------*/
4718
4719 #if ( configUSE_MUTEXES == 1 )
4720
4721     TaskHandle_t pvTaskIncrementMutexHeldCount( void )
4722     {
4723         /* If xSemaphoreCreateMutex() is called before any tasks have been created
4724          * then pxCurrentTCB will be NULL. */
4725         if( pxCurrentTCB != NULL )
4726         {
4727             ( pxCurrentTCB->uxMutexesHeld )++;
4728         }
4729
4730         return pxCurrentTCB;
4731     }
4732
4733 #endif /* configUSE_MUTEXES */
4734 /*-----------------------------------------------------------*/
4735
4736 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
4737
4738     uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWait,
4739                                       BaseType_t xClearCountOnExit,
4740                                       TickType_t xTicksToWait )
4741     {
4742         uint32_t ulReturn;
4743
4744         configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
4745
4746         taskENTER_CRITICAL();
4747         {
4748             /* Only block if the notification count is not already non-zero. */
4749             if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] == 0UL )
4750             {
4751                 /* Mark this task as waiting for a notification. */
4752                 pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
4753
4754                 if( xTicksToWait > ( TickType_t ) 0 )
4755                 {
4756                     prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
4757                     traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWait );
4758
4759                     /* All ports are written to allow a yield in a critical
4760                      * section (some will yield immediately, others wait until the
4761                      * critical section exits) - but it is not something that
4762                      * application code should ever do. */
4763                     portYIELD_WITHIN_API();
4764                 }
4765                 else
4766                 {
4767                     mtCOVERAGE_TEST_MARKER();
4768                 }
4769             }
4770             else
4771             {
4772                 mtCOVERAGE_TEST_MARKER();
4773             }
4774         }
4775         taskEXIT_CRITICAL();
4776
4777         taskENTER_CRITICAL();
4778         {
4779             traceTASK_NOTIFY_TAKE( uxIndexToWait );
4780             ulReturn = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ];
4781
4782             if( ulReturn != 0UL )
4783             {
4784                 if( xClearCountOnExit != pdFALSE )
4785                 {
4786                     pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = 0UL;
4787                 }
4788                 else
4789                 {
4790                     pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = ulReturn - ( uint32_t ) 1;
4791                 }
4792             }
4793             else
4794             {
4795                 mtCOVERAGE_TEST_MARKER();
4796             }
4797
4798             pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION;
4799         }
4800         taskEXIT_CRITICAL();
4801
4802         return ulReturn;
4803     }
4804
4805 #endif /* configUSE_TASK_NOTIFICATIONS */
4806 /*-----------------------------------------------------------*/
4807
4808 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
4809
4810     BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWait,
4811                                        uint32_t ulBitsToClearOnEntry,
4812                                        uint32_t ulBitsToClearOnExit,
4813                                        uint32_t * pulNotificationValue,
4814                                        TickType_t xTicksToWait )
4815     {
4816         BaseType_t xReturn;
4817
4818         configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
4819
4820         taskENTER_CRITICAL();
4821         {
4822             /* Only block if a notification is not already pending. */
4823             if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
4824             {
4825                 /* Clear bits in the task's notification value as bits may get
4826                  * set  by the notifying task or interrupt.  This can be used to
4827                  * clear the value to zero. */
4828                 pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnEntry;
4829
4830                 /* Mark this task as waiting for a notification. */
4831                 pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
4832
4833                 if( xTicksToWait > ( TickType_t ) 0 )
4834                 {
4835                     prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
4836                     traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWait );
4837
4838                     /* All ports are written to allow a yield in a critical
4839                      * section (some will yield immediately, others wait until the
4840                      * critical section exits) - but it is not something that
4841                      * application code should ever do. */
4842                     portYIELD_WITHIN_API();
4843                 }
4844                 else
4845                 {
4846                     mtCOVERAGE_TEST_MARKER();
4847                 }
4848             }
4849             else
4850             {
4851                 mtCOVERAGE_TEST_MARKER();
4852             }
4853         }
4854         taskEXIT_CRITICAL();
4855
4856         taskENTER_CRITICAL();
4857         {
4858             traceTASK_NOTIFY_WAIT( uxIndexToWait );
4859
4860             if( pulNotificationValue != NULL )
4861             {
4862                 /* Output the current notification value, which may or may not
4863                  * have changed. */
4864                 *pulNotificationValue = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ];
4865             }
4866
4867             /* If ucNotifyValue is set then either the task never entered the
4868              * blocked state (because a notification was already pending) or the
4869              * task unblocked because of a notification.  Otherwise the task
4870              * unblocked because of a timeout. */
4871             if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
4872             {
4873                 /* A notification was not received. */
4874                 xReturn = pdFALSE;
4875             }
4876             else
4877             {
4878                 /* A notification was already pending or a notification was
4879                  * received while the task was waiting. */
4880                 pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnExit;
4881                 xReturn = pdTRUE;
4882             }
4883
4884             pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION;
4885         }
4886         taskEXIT_CRITICAL();
4887
4888         return xReturn;
4889     }
4890
4891 #endif /* configUSE_TASK_NOTIFICATIONS */
4892 /*-----------------------------------------------------------*/
4893
4894 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
4895
4896     BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify,
4897                                    UBaseType_t uxIndexToNotify,
4898                                    uint32_t ulValue,
4899                                    eNotifyAction eAction,
4900                                    uint32_t * pulPreviousNotificationValue )
4901     {
4902         TCB_t * pxTCB;
4903         BaseType_t xReturn = pdPASS;
4904         uint8_t ucOriginalNotifyState;
4905
4906         configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
4907         configASSERT( xTaskToNotify );
4908         pxTCB = xTaskToNotify;
4909
4910         taskENTER_CRITICAL();
4911         {
4912             if( pulPreviousNotificationValue != NULL )
4913             {
4914                 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
4915             }
4916
4917             ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
4918
4919             pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
4920
4921             switch( eAction )
4922             {
4923                 case eSetBits:
4924                     pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
4925                     break;
4926
4927                 case eIncrement:
4928                     ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
4929                     break;
4930
4931                 case eSetValueWithOverwrite:
4932                     pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
4933                     break;
4934
4935                 case eSetValueWithoutOverwrite:
4936
4937                     if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
4938                     {
4939                         pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
4940                     }
4941                     else
4942                     {
4943                         /* The value could not be written to the task. */
4944                         xReturn = pdFAIL;
4945                     }
4946
4947                     break;
4948
4949                 case eNoAction:
4950
4951                     /* The task is being notified without its notify value being
4952                      * updated. */
4953                     break;
4954
4955                 default:
4956
4957                     /* Should not get here if all enums are handled.
4958                      * Artificially force an assert by testing a value the
4959                      * compiler can't assume is const. */
4960                     configASSERT( xTickCount == ( TickType_t ) 0 );
4961
4962                     break;
4963             }
4964
4965             traceTASK_NOTIFY( uxIndexToNotify );
4966
4967             /* If the task is in the blocked state specifically to wait for a
4968              * notification then unblock it now. */
4969             if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
4970             {
4971                 listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
4972                 prvAddTaskToReadyList( pxTCB );
4973
4974                 /* The task should not have been on an event list. */
4975                 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
4976
4977                 #if ( configUSE_TICKLESS_IDLE != 0 )
4978                 {
4979                     /* If a task is blocked waiting for a notification then
4980                      * xNextTaskUnblockTime might be set to the blocked task's time
4981                      * out time.  If the task is unblocked for a reason other than
4982                      * a timeout xNextTaskUnblockTime is normally left unchanged,
4983                      * because it will automatically get reset to a new value when
4984                      * the tick count equals xNextTaskUnblockTime.  However if
4985                      * tickless idling is used it might be more important to enter
4986                      * sleep mode at the earliest possible time - so reset
4987                      * xNextTaskUnblockTime here to ensure it is updated at the
4988                      * earliest possible time. */
4989                     prvResetNextTaskUnblockTime();
4990                 }
4991                 #endif
4992
4993                 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
4994                 {
4995                     /* The notified task has a priority above the currently
4996                      * executing task so a yield is required. */
4997                     taskYIELD_IF_USING_PREEMPTION();
4998                 }
4999                 else
5000                 {
5001                     mtCOVERAGE_TEST_MARKER();
5002                 }
5003             }
5004             else
5005             {
5006                 mtCOVERAGE_TEST_MARKER();
5007             }
5008         }
5009         taskEXIT_CRITICAL();
5010
5011         return xReturn;
5012     }
5013
5014 #endif /* configUSE_TASK_NOTIFICATIONS */
5015 /*-----------------------------------------------------------*/
5016
5017 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
5018
5019     BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify,
5020                                           UBaseType_t uxIndexToNotify,
5021                                           uint32_t ulValue,
5022                                           eNotifyAction eAction,
5023                                           uint32_t * pulPreviousNotificationValue,
5024                                           BaseType_t * pxHigherPriorityTaskWoken )
5025     {
5026         TCB_t * pxTCB;
5027         uint8_t ucOriginalNotifyState;
5028         BaseType_t xReturn = pdPASS;
5029         portBASE_TYPE xSavedInterruptStatus;
5030
5031         configASSERT( xTaskToNotify );
5032         configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
5033
5034         /* RTOS ports that support interrupt nesting have the concept of a
5035          * maximum  system call (or maximum API call) interrupt priority.
5036          * Interrupts that are  above the maximum system call priority are keep
5037          * permanently enabled, even when the RTOS kernel is in a critical section,
5038          * but cannot make any calls to FreeRTOS API functions.  If configASSERT()
5039          * is defined in FreeRTOSConfig.h then
5040          * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
5041          * failure if a FreeRTOS API function is called from an interrupt that has
5042          * been assigned a priority above the configured maximum system call
5043          * priority.  Only FreeRTOS functions that end in FromISR can be called
5044          * from interrupts  that have been assigned a priority at or (logically)
5045          * below the maximum system call interrupt priority.  FreeRTOS maintains a
5046          * separate interrupt safe API to ensure interrupt entry is as fast and as
5047          * simple as possible.  More information (albeit Cortex-M specific) is
5048          * provided on the following link:
5049          * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
5050         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
5051
5052         pxTCB = xTaskToNotify;
5053
5054         xSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
5055         {
5056             if( pulPreviousNotificationValue != NULL )
5057             {
5058                 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
5059             }
5060
5061             ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
5062             pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
5063
5064             switch( eAction )
5065             {
5066                 case eSetBits:
5067                     pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
5068                     break;
5069
5070                 case eIncrement:
5071                     ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
5072                     break;
5073
5074                 case eSetValueWithOverwrite:
5075                     pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
5076                     break;
5077
5078                 case eSetValueWithoutOverwrite:
5079
5080                     if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
5081                     {
5082                         pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
5083                     }
5084                     else
5085                     {
5086                         /* The value could not be written to the task. */
5087                         xReturn = pdFAIL;
5088                     }
5089
5090                     break;
5091
5092                 case eNoAction:
5093
5094                     /* The task is being notified without its notify value being
5095                      * updated. */
5096                     break;
5097
5098                 default:
5099
5100                     /* Should not get here if all enums are handled.
5101                      * Artificially force an assert by testing a value the
5102                      * compiler can't assume is const. */
5103                     configASSERT( xTickCount == ( TickType_t ) 0 );
5104                     break;
5105             }
5106
5107             traceTASK_NOTIFY_FROM_ISR( uxIndexToNotify );
5108
5109             /* If the task is in the blocked state specifically to wait for a
5110              * notification then unblock it now. */
5111             if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
5112             {
5113                 /* The task should not have been on an event list. */
5114                 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
5115
5116                 if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
5117                 {
5118                     listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
5119                     prvAddTaskToReadyList( pxTCB );
5120                 }
5121                 else
5122                 {
5123                     /* The delayed and ready lists cannot be accessed, so hold
5124                      * this task pending until the scheduler is resumed. */
5125                     listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
5126                 }
5127
5128                 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
5129                 {
5130                     /* The notified task has a priority above the currently
5131                      * executing task so a yield is required. */
5132                     if( pxHigherPriorityTaskWoken != NULL )
5133                     {
5134                         *pxHigherPriorityTaskWoken = pdTRUE;
5135                     }
5136
5137                     /* Mark that a yield is pending in case the user is not
5138                      * using the "xHigherPriorityTaskWoken" parameter to an ISR
5139                      * safe FreeRTOS function. */
5140                     xYieldPending = pdTRUE;
5141                 }
5142                 else
5143                 {
5144                     mtCOVERAGE_TEST_MARKER();
5145                 }
5146             }
5147         }
5148         portCLEAR_INTERRUPT_MASK_FROM_ISR( xSavedInterruptStatus );
5149
5150         return xReturn;
5151     }
5152
5153 #endif /* configUSE_TASK_NOTIFICATIONS */
5154 /*-----------------------------------------------------------*/
5155
5156 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
5157
5158     void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
5159                                         UBaseType_t uxIndexToNotify,
5160                                         BaseType_t * pxHigherPriorityTaskWoken )
5161     {
5162         TCB_t * pxTCB;
5163         uint8_t ucOriginalNotifyState;
5164         portBASE_TYPE xSavedInterruptStatus;
5165
5166         configASSERT( xTaskToNotify );
5167         configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
5168
5169         /* RTOS ports that support interrupt nesting have the concept of a
5170          * maximum  system call (or maximum API call) interrupt priority.
5171          * Interrupts that are  above the maximum system call priority are keep
5172          * permanently enabled, even when the RTOS kernel is in a critical section,
5173          * but cannot make any calls to FreeRTOS API functions.  If configASSERT()
5174          * is defined in FreeRTOSConfig.h then
5175          * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
5176          * failure if a FreeRTOS API function is called from an interrupt that has
5177          * been assigned a priority above the configured maximum system call
5178          * priority.  Only FreeRTOS functions that end in FromISR can be called
5179          * from interrupts  that have been assigned a priority at or (logically)
5180          * below the maximum system call interrupt priority.  FreeRTOS maintains a
5181          * separate interrupt safe API to ensure interrupt entry is as fast and as
5182          * simple as possible.  More information (albeit Cortex-M specific) is
5183          * provided on the following link:
5184          * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
5185         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
5186
5187         pxTCB = xTaskToNotify;
5188
5189         xSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
5190         {
5191             ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
5192             pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
5193
5194             /* 'Giving' is equivalent to incrementing a count in a counting
5195              * semaphore. */
5196             ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
5197
5198             traceTASK_NOTIFY_GIVE_FROM_ISR( uxIndexToNotify );
5199
5200             /* If the task is in the blocked state specifically to wait for a
5201              * notification then unblock it now. */
5202             if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
5203             {
5204                 /* The task should not have been on an event list. */
5205                 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
5206
5207                 if( uxSchedulerSuspended == ( UBaseType_t ) 0U )
5208                 {
5209                     listREMOVE_ITEM( &( pxTCB->xStateListItem ) );
5210                     prvAddTaskToReadyList( pxTCB );
5211                 }
5212                 else
5213                 {
5214                     /* The delayed and ready lists cannot be accessed, so hold
5215                      * this task pending until the scheduler is resumed. */
5216                     listINSERT_END( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
5217                 }
5218
5219                 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
5220                 {
5221                     /* The notified task has a priority above the currently
5222                      * executing task so a yield is required. */
5223                     if( pxHigherPriorityTaskWoken != NULL )
5224                     {
5225                         *pxHigherPriorityTaskWoken = pdTRUE;
5226                     }
5227
5228                     /* Mark that a yield is pending in case the user is not
5229                      * using the "xHigherPriorityTaskWoken" parameter in an ISR
5230                      * safe FreeRTOS function. */
5231                     xYieldPending = pdTRUE;
5232                 }
5233                 else
5234                 {
5235                     mtCOVERAGE_TEST_MARKER();
5236                 }
5237             }
5238         }
5239         portCLEAR_INTERRUPT_MASK_FROM_ISR( xSavedInterruptStatus );
5240     }
5241
5242 #endif /* configUSE_TASK_NOTIFICATIONS */
5243 /*-----------------------------------------------------------*/
5244
5245 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
5246
5247     BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask,
5248                                              UBaseType_t uxIndexToClear )
5249     {
5250         TCB_t * pxTCB;
5251         BaseType_t xReturn;
5252
5253         configASSERT( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES );
5254
5255         /* If null is passed in here then it is the calling task that is having
5256          * its notification state cleared. */
5257         pxTCB = prvGetTCBFromHandle( xTask );
5258
5259         taskENTER_CRITICAL();
5260         {
5261             if( pxTCB->ucNotifyState[ uxIndexToClear ] == taskNOTIFICATION_RECEIVED )
5262             {
5263                 pxTCB->ucNotifyState[ uxIndexToClear ] = taskNOT_WAITING_NOTIFICATION;
5264                 xReturn = pdPASS;
5265             }
5266             else
5267             {
5268                 xReturn = pdFAIL;
5269             }
5270         }
5271         taskEXIT_CRITICAL();
5272
5273         return xReturn;
5274     }
5275
5276 #endif /* configUSE_TASK_NOTIFICATIONS */
5277 /*-----------------------------------------------------------*/
5278
5279 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
5280
5281     uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask,
5282                                             UBaseType_t uxIndexToClear,
5283                                             uint32_t ulBitsToClear )
5284     {
5285         TCB_t * pxTCB;
5286         uint32_t ulReturn;
5287
5288         /* If null is passed in here then it is the calling task that is having
5289          * its notification state cleared. */
5290         pxTCB = prvGetTCBFromHandle( xTask );
5291
5292         taskENTER_CRITICAL();
5293         {
5294             /* Return the notification as it was before the bits were cleared,
5295              * then clear the bit mask. */
5296             ulReturn = pxTCB->ulNotifiedValue[ uxIndexToClear ];
5297             pxTCB->ulNotifiedValue[ uxIndexToClear ] &= ~ulBitsToClear;
5298         }
5299         taskEXIT_CRITICAL();
5300
5301         return ulReturn;
5302     }
5303
5304 #endif /* configUSE_TASK_NOTIFICATIONS */
5305 /*-----------------------------------------------------------*/
5306
5307 #if ( configGENERATE_RUN_TIME_STATS == 1 )
5308
5309     configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimeCounter( const TaskHandle_t xTask )
5310     {
5311         return xTask->ulRunTimeCounter;
5312     }
5313
5314 #endif
5315 /*-----------------------------------------------------------*/
5316
5317 #if ( configGENERATE_RUN_TIME_STATS == 1 )
5318
5319     configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent( const TaskHandle_t xTask )
5320     {
5321         configRUN_TIME_COUNTER_TYPE ulTotalTime, ulReturn;
5322
5323         ulTotalTime = ( configRUN_TIME_COUNTER_TYPE ) portGET_RUN_TIME_COUNTER_VALUE();
5324
5325         /* For percentage calculations. */
5326         ulTotalTime /= ( configRUN_TIME_COUNTER_TYPE ) 100;
5327
5328         /* Avoid divide by zero errors. */
5329         if( ulTotalTime > ( configRUN_TIME_COUNTER_TYPE ) 0 )
5330         {
5331             ulReturn = xTask->ulRunTimeCounter / ulTotalTime;
5332         }
5333         else
5334         {
5335             ulReturn = 0;
5336         }
5337
5338         return ulReturn;
5339     }
5340
5341 #endif /* if ( configGENERATE_RUN_TIME_STATS == 1 ) */
5342 /*-----------------------------------------------------------*/
5343
5344 #if ( configGENERATE_RUN_TIME_STATS == 1 )
5345
5346     configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void )
5347     {
5348         return ulTaskGetRunTimeCounter( xIdleTaskHandle );
5349     }
5350
5351 #endif
5352 /*-----------------------------------------------------------*/
5353
5354 #if ( configGENERATE_RUN_TIME_STATS == 1 )
5355
5356     configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void )
5357     {
5358         return ulTaskGetRunTimePercent( xIdleTaskHandle );
5359     }
5360
5361 #endif
5362 /*-----------------------------------------------------------*/
5363
5364 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
5365                                             const BaseType_t xCanBlockIndefinitely )
5366 {
5367     TickType_t xTimeToWake;
5368     const TickType_t xConstTickCount = xTickCount;
5369
5370     #if ( INCLUDE_xTaskAbortDelay == 1 )
5371     {
5372         /* About to enter a delayed list, so ensure the ucDelayAborted flag is
5373          * reset to pdFALSE so it can be detected as having been set to pdTRUE
5374          * when the task leaves the Blocked state. */
5375         pxCurrentTCB->ucDelayAborted = pdFALSE;
5376     }
5377     #endif
5378
5379     /* Remove the task from the ready list before adding it to the blocked list
5380      * as the same list item is used for both lists. */
5381     if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
5382     {
5383         /* The current task must be in a ready list, so there is no need to
5384          * check, and the port reset macro can be called directly. */
5385         portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); /*lint !e931 pxCurrentTCB cannot change as it is the calling task.  pxCurrentTCB->uxPriority and uxTopReadyPriority cannot change as called with scheduler suspended or in a critical section. */
5386     }
5387     else
5388     {
5389         mtCOVERAGE_TEST_MARKER();
5390     }
5391
5392     #if ( INCLUDE_vTaskSuspend == 1 )
5393     {
5394         if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )
5395         {
5396             /* Add the task to the suspended task list instead of a delayed task
5397              * list to ensure it is not woken by a timing event.  It will block
5398              * indefinitely. */
5399             listINSERT_END( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
5400         }
5401         else
5402         {
5403             /* Calculate the time at which the task should be woken if the event
5404              * does not occur.  This may overflow but this doesn't matter, the
5405              * kernel will manage it correctly. */
5406             xTimeToWake = xConstTickCount + xTicksToWait;
5407
5408             /* The list item will be inserted in wake time order. */
5409             listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
5410
5411             if( xTimeToWake < xConstTickCount )
5412             {
5413                 /* Wake time has overflowed.  Place this item in the overflow
5414                  * list. */
5415                 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
5416             }
5417             else
5418             {
5419                 /* The wake time has not overflowed, so the current block list
5420                  * is used. */
5421                 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
5422
5423                 /* If the task entering the blocked state was placed at the
5424                  * head of the list of blocked tasks then xNextTaskUnblockTime
5425                  * needs to be updated too. */
5426                 if( xTimeToWake < xNextTaskUnblockTime )
5427                 {
5428                     xNextTaskUnblockTime = xTimeToWake;
5429                 }
5430                 else
5431                 {
5432                     mtCOVERAGE_TEST_MARKER();
5433                 }
5434             }
5435         }
5436     }
5437     #else /* INCLUDE_vTaskSuspend */
5438     {
5439         /* Calculate the time at which the task should be woken if the event
5440          * does not occur.  This may overflow but this doesn't matter, the kernel
5441          * will manage it correctly. */
5442         xTimeToWake = xConstTickCount + xTicksToWait;
5443
5444         /* The list item will be inserted in wake time order. */
5445         listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
5446
5447         if( xTimeToWake < xConstTickCount )
5448         {
5449             /* Wake time has overflowed.  Place this item in the overflow list. */
5450             vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
5451         }
5452         else
5453         {
5454             /* The wake time has not overflowed, so the current block list is used. */
5455             vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
5456
5457             /* If the task entering the blocked state was placed at the head of the
5458              * list of blocked tasks then xNextTaskUnblockTime needs to be updated
5459              * too. */
5460             if( xTimeToWake < xNextTaskUnblockTime )
5461             {
5462                 xNextTaskUnblockTime = xTimeToWake;
5463             }
5464             else
5465             {
5466                 mtCOVERAGE_TEST_MARKER();
5467             }
5468         }
5469
5470         /* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */
5471         ( void ) xCanBlockIndefinitely;
5472     }
5473     #endif /* INCLUDE_vTaskSuspend */
5474 }
5475
5476 /* Code below here allows additional code to be inserted into this source file,
5477  * especially where access to file scope functions and data is needed (for example
5478  * when performing module tests). */
5479
5480 #ifdef FREERTOS_MODULE_TEST
5481     #include "tasks_test_access_functions.h"
5482 #endif
5483
5484
5485 #if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 )
5486
5487     #include "freertos_tasks_c_additions.h"
5488
5489     #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
5490         static void freertos_tasks_c_additions_init( void )
5491         {
5492             FREERTOS_TASKS_C_ADDITIONS_INIT();
5493         }
5494     #endif
5495
5496 #endif /* if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 ) */