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