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