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