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