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