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