]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/tasks.c
Update version number ready for release.
[freertos] / FreeRTOS / Source / tasks.c
1 /*\r
2     FreeRTOS V8.0.1 - Copyright (C) 2014 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     ***************************************************************************\r
8      *                                                                       *\r
9      *    FreeRTOS provides completely free yet professionally developed,    *\r
10      *    robust, strictly quality controlled, supported, and cross          *\r
11      *    platform software that has become a de facto standard.             *\r
12      *                                                                       *\r
13      *    Help yourself get started quickly and support the FreeRTOS         *\r
14      *    project by purchasing a FreeRTOS tutorial book, reference          *\r
15      *    manual, or both from: http://www.FreeRTOS.org/Documentation        *\r
16      *                                                                       *\r
17      *    Thank you!                                                         *\r
18      *                                                                       *\r
19     ***************************************************************************\r
20 \r
21     This file is part of the FreeRTOS distribution.\r
22 \r
23     FreeRTOS is free software; you can redistribute it and/or modify it under\r
24     the terms of the GNU General Public License (version 2) as published by the\r
25     Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
26 \r
27     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
28     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
29     >>!   obliged to provide the source code for proprietary components     !<<\r
30     >>!   outside of the FreeRTOS kernel.                                   !<<\r
31 \r
32     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
33     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
34     FOR A PARTICULAR PURPOSE.  Full license text is available from the following\r
35     link: http://www.freertos.org/a00114.html\r
36 \r
37     1 tab == 4 spaces!\r
38 \r
39     ***************************************************************************\r
40      *                                                                       *\r
41      *    Having a problem?  Start by reading the FAQ "My application does   *\r
42      *    not run, what could be wrong?"                                     *\r
43      *                                                                       *\r
44      *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
45      *                                                                       *\r
46     ***************************************************************************\r
47 \r
48     http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
49     license and Real Time Engineers Ltd. contact details.\r
50 \r
51     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
52     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
53     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
54 \r
55     http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
56     Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
57     licenses offer ticketed support, indemnification and middleware.\r
58 \r
59     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
60     engineered and independently SIL3 certified version for use in safety and\r
61     mission critical applications that require provable dependability.\r
62 \r
63     1 tab == 4 spaces!\r
64 */\r
65 \r
66 /* Standard includes. */\r
67 #include <stdlib.h>\r
68 #include <string.h>\r
69 \r
70 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining\r
71 all the API functions to use the MPU wrappers.  That should only be done when\r
72 task.h is included from an application file. */\r
73 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
74 \r
75 /* FreeRTOS includes. */\r
76 #include "FreeRTOS.h"\r
77 #include "task.h"\r
78 #include "timers.h"\r
79 #include "StackMacros.h"\r
80 \r
81 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the\r
82 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the\r
83 header files above, but not in this file, in order to generate the correct\r
84 privileged Vs unprivileged linkage and placement. */\r
85 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */\r
86 \r
87 #if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 )\r
88         /* At the bottom of this file are two optional functions that can be used\r
89         to generate human readable text from the raw data generated by the\r
90         uxTaskGetSystemState() function.  Note the formatting functions are provided\r
91         for convenience only, and are NOT considered part of the kernel. */\r
92         #include <stdio.h>\r
93 #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */\r
94 \r
95 /* Sanity check the configuration. */\r
96 #if configUSE_TICKLESS_IDLE != 0\r
97         #if INCLUDE_vTaskSuspend != 1\r
98                 #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0\r
99         #endif /* INCLUDE_vTaskSuspend */\r
100 #endif /* configUSE_TICKLESS_IDLE */\r
101 \r
102 /*\r
103  * Defines the size, in words, of the stack allocated to the idle task.\r
104  */\r
105 #define tskIDLE_STACK_SIZE      configMINIMAL_STACK_SIZE\r
106 \r
107 #if( configUSE_PREEMPTION == 0 )\r
108         /* If the cooperative scheduler is being used then a yield should not be\r
109         performed just because a higher priority task has been woken. */\r
110         #define taskYIELD_IF_USING_PREEMPTION()\r
111 #else\r
112         #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()\r
113 #endif\r
114 \r
115 /*\r
116  * Task control block.  A task control block (TCB) is allocated for each task,\r
117  * and stores task state information, including a pointer to the task's context\r
118  * (the task's run time environment, including register values)\r
119  */\r
120 typedef struct tskTaskControlBlock\r
121 {\r
122         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
123 \r
124         #if ( portUSING_MPU_WRAPPERS == 1 )\r
125                 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
126         #endif\r
127 \r
128         ListItem_t                      xGenericListItem;       /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */\r
129         ListItem_t                      xEventListItem;         /*< Used to reference a task from an event list. */\r
130         UBaseType_t                     uxPriority;                     /*< The priority of the task.  0 is the lowest priority. */\r
131         StackType_t                     *pxStack;                       /*< Points to the start of the stack. */\r
132         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
133 \r
134         #if ( portSTACK_GROWTH > 0 )\r
135                 StackType_t             *pxEndOfStack;          /*< Points to the end of the stack on architectures where the stack grows up from low memory. */\r
136         #endif\r
137 \r
138         #if ( portCRITICAL_NESTING_IN_TCB == 1 )\r
139                 UBaseType_t     uxCriticalNesting;      /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */\r
140         #endif\r
141 \r
142         #if ( configUSE_TRACE_FACILITY == 1 )\r
143                 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
144                 UBaseType_t     uxTaskNumber;           /*< Stores a number specifically for use by third party trace code. */\r
145         #endif\r
146 \r
147         #if ( configUSE_MUTEXES == 1 )\r
148                 UBaseType_t     uxBasePriority;         /*< The priority last assigned to the task - used by the priority inheritance mechanism. */\r
149         #endif\r
150 \r
151         #if ( configUSE_APPLICATION_TASK_TAG == 1 )\r
152                 TaskHookFunction_t pxTaskTag;\r
153         #endif\r
154 \r
155         #if ( configGENERATE_RUN_TIME_STATS == 1 )\r
156                 uint32_t                ulRunTimeCounter;       /*< Stores the amount of time the task has spent in the Running state. */\r
157         #endif\r
158 \r
159         #if ( configUSE_NEWLIB_REENTRANT == 1 )\r
160                 /* Allocate a Newlib reent structure that is specific to this task.\r
161                 Note Newlib support has been included by popular demand, but is not\r
162                 used by the FreeRTOS maintainers themselves.  FreeRTOS is not\r
163                 responsible for resulting newlib operation.  User must be familiar with\r
164                 newlib and must provide system-wide implementations of the necessary\r
165                 stubs. Be warned that (at the time of writing) the current newlib design\r
166                 implements a system-wide malloc() that must be provided with locks. */\r
167                 struct  _reent xNewLib_reent;\r
168         #endif\r
169 \r
170 } tskTCB;\r
171 \r
172 /* The old tskTCB name is maintained above then typedefed to the new TCB_t name\r
173 below to enable the use of older kernel aware debuggers. */\r
174 typedef tskTCB TCB_t;\r
175 \r
176 /*\r
177  * Some kernel aware debuggers require the data the debugger needs access to to\r
178  * be global, rather than file scope.\r
179  */\r
180 #ifdef portREMOVE_STATIC_QUALIFIER\r
181         #define static\r
182 #endif\r
183 \r
184 /*lint -e956 A manual analysis and inspection has been used to determine which\r
185 static variables must be declared volatile. */\r
186 \r
187 PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;\r
188 \r
189 /* Lists for ready and blocked tasks. --------------------*/\r
190 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */\r
191 PRIVILEGED_DATA static List_t xDelayedTaskList1;                                                /*< Delayed tasks. */\r
192 PRIVILEGED_DATA static List_t xDelayedTaskList2;                                                /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */\r
193 PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList;                             /*< Points to the delayed task list currently being used. */\r
194 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
195 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
196 \r
197 #if ( INCLUDE_vTaskDelete == 1 )\r
198 \r
199         PRIVILEGED_DATA static List_t xTasksWaitingTermination;                         /*< Tasks that have been deleted - but their memory not yet freed. */\r
200         PRIVILEGED_DATA static volatile UBaseType_t uxTasksDeleted = ( UBaseType_t ) 0U;\r
201 \r
202 #endif\r
203 \r
204 #if ( INCLUDE_vTaskSuspend == 1 )\r
205 \r
206         PRIVILEGED_DATA static List_t xSuspendedTaskList;                                       /*< Tasks that are currently suspended. */\r
207 \r
208 #endif\r
209 \r
210 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )\r
211 \r
212         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
213 \r
214 #endif\r
215 \r
216 /* Other file private variables. --------------------------------*/\r
217 PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks      = ( UBaseType_t ) 0U;\r
218 PRIVILEGED_DATA static volatile TickType_t xTickCount                           = ( TickType_t ) 0U;\r
219 PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority          = tskIDLE_PRIORITY;\r
220 PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning            = pdFALSE;\r
221 PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks                       = ( UBaseType_t ) 0U;\r
222 PRIVILEGED_DATA static volatile BaseType_t xYieldPending                        = pdFALSE;\r
223 PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows                      = ( BaseType_t ) 0;\r
224 PRIVILEGED_DATA static UBaseType_t uxTaskNumber                                         = ( UBaseType_t ) 0U;\r
225 PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime         = portMAX_DELAY;\r
226 \r
227 /* Context switches are held pending while the scheduler is suspended.  Also,\r
228 interrupts must not manipulate the xStateListItem of a TCB, or any of the\r
229 lists the xStateListItem can be referenced from, if the scheduler is suspended.\r
230 If an interrupt needs to unblock a task while the scheduler is suspended then it\r
231 moves the task's event list item into the xPendingReadyList, ready for the\r
232 kernel to move the task from the pending ready list into the real ready list\r
233 when the scheduler is unsuspended.  The pending ready list itself can only be\r
234 accessed from a critical section. */\r
235 PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended        = ( UBaseType_t ) pdFALSE;\r
236 \r
237 #if ( configGENERATE_RUN_TIME_STATS == 1 )\r
238 \r
239         PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL;     /*< Holds the value of a timer/counter the last time a task was switched in. */\r
240         PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL;           /*< Holds the total amount of execution time as defined by the run time counter clock. */\r
241 \r
242 #endif\r
243 \r
244 /*lint +e956 */\r
245 \r
246 /* Debugging and trace facilities private variables and macros. ------------*/\r
247 \r
248 /*\r
249  * The value used to fill the stack of a task when the task is created.  This\r
250  * is used purely for checking the high water mark for tasks.\r
251  */\r
252 #define tskSTACK_FILL_BYTE      ( 0xa5U )\r
253 \r
254 /*\r
255  * Macros used by vListTask to indicate which state a task is in.\r
256  */\r
257 #define tskBLOCKED_CHAR         ( 'B' )\r
258 #define tskREADY_CHAR           ( 'R' )\r
259 #define tskDELETED_CHAR         ( 'D' )\r
260 #define tskSUSPENDED_CHAR       ( 'S' )\r
261 \r
262 /*-----------------------------------------------------------*/\r
263 \r
264 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )\r
265 \r
266         /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is\r
267         performed in a generic way that is not optimised to any particular\r
268         microcontroller architecture. */\r
269 \r
270         /* uxTopReadyPriority holds the priority of the highest priority ready\r
271         state task. */\r
272         #define taskRECORD_READY_PRIORITY( uxPriority )                                                                                                         \\r
273         {                                                                                                                                                                                                       \\r
274                 if( ( uxPriority ) > uxTopReadyPriority )                                                                                                               \\r
275                 {                                                                                                                                                                                               \\r
276                         uxTopReadyPriority = ( uxPriority );                                                                                                            \\r
277                 }                                                                                                                                                                                               \\r
278         } /* taskRECORD_READY_PRIORITY */\r
279 \r
280         /*-----------------------------------------------------------*/\r
281 \r
282         #define taskSELECT_HIGHEST_PRIORITY_TASK()                                                                                                                      \\r
283         {                                                                                                                                                                                                       \\r
284                 /* Find the highest priority queue that contains ready tasks. */                                                                \\r
285                 while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) )                                              \\r
286                 {                                                                                                                                                                                               \\r
287                         configASSERT( uxTopReadyPriority );                                                                                                                     \\r
288                         --uxTopReadyPriority;                                                                                                                                           \\r
289                 }                                                                                                                                                                                               \\r
290                                                                                                                                                                                                                 \\r
291                 /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of                                                \\r
292                 the     same priority get an equal share of the processor time. */                                                                      \\r
293                 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) );              \\r
294         } /* taskSELECT_HIGHEST_PRIORITY_TASK */\r
295 \r
296         /*-----------------------------------------------------------*/\r
297 \r
298         /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as\r
299         they are only required when a port optimised method of task selection is\r
300         being used. */\r
301         #define taskRESET_READY_PRIORITY( uxPriority )\r
302         #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )\r
303 \r
304 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */\r
305 \r
306         /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is\r
307         performed in a way that is tailored to the particular microcontroller\r
308         architecture being used. */\r
309 \r
310         /* A port optimised version is provided.  Call the port defined macros. */\r
311         #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )\r
312 \r
313         /*-----------------------------------------------------------*/\r
314 \r
315         #define taskSELECT_HIGHEST_PRIORITY_TASK()                                                                                                              \\r
316         {                                                                                                                                                                                               \\r
317         UBaseType_t uxTopPriority;                                                                                                                                              \\r
318                                                                                                                                                                                                         \\r
319                 /* Find the highest priority queue that contains ready tasks. */                                                        \\r
320                 portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );                                                          \\r
321                 configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 );         \\r
322                 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );           \\r
323         } /* taskSELECT_HIGHEST_PRIORITY_TASK() */\r
324 \r
325         /*-----------------------------------------------------------*/\r
326 \r
327         /* A port optimised version is provided, call it only if the TCB being reset\r
328         is being referenced from a ready list.  If it is referenced from a delayed\r
329         or suspended list then it won't be in a ready list. */\r
330         #define taskRESET_READY_PRIORITY( uxPriority )                                                                                                  \\r
331         {                                                                                                                                                                                               \\r
332                 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == 0 )                          \\r
333                 {                                                                                                                                                                                       \\r
334                         portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) );                                             \\r
335                 }                                                                                                                                                                                       \\r
336         }\r
337 \r
338 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */\r
339 \r
340 /*-----------------------------------------------------------*/\r
341 \r
342 /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick\r
343 count overflows. */\r
344 #define taskSWITCH_DELAYED_LISTS()                                                                                                                                      \\r
345 {                                                                                                                                                                                                       \\r
346         List_t *pxTemp;                                                                                                                                                                 \\r
347                                                                                                                                                                                                         \\r
348         /* The delayed tasks list should be empty when the lists are switched. */                                               \\r
349         configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) );                                                                             \\r
350                                                                                                                                                                                                         \\r
351         pxTemp = pxDelayedTaskList;                                                                                                                                             \\r
352         pxDelayedTaskList = pxOverflowDelayedTaskList;                                                                                                  \\r
353         pxOverflowDelayedTaskList = pxTemp;                                                                                                                             \\r
354         xNumOfOverflows++;                                                                                                                                                              \\r
355         prvResetNextTaskUnblockTime();                                                                                                                                  \\r
356 }\r
357 \r
358 /*-----------------------------------------------------------*/\r
359 \r
360 /*\r
361  * Place the task represented by pxTCB into the appropriate ready list for\r
362  * the task.  It is inserted at the end of the list.\r
363  */\r
364 #define prvAddTaskToReadyList( pxTCB )                                                                                                                          \\r
365         traceMOVED_TASK_TO_READY_STATE( pxTCB )                                                                                                                 \\r
366         taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority );                                                                                             \\r
367         vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) )\r
368 /*-----------------------------------------------------------*/\r
369 \r
370 /*\r
371  * Several functions take an TaskHandle_t parameter that can optionally be NULL,\r
372  * where NULL is used to indicate that the handle of the currently executing\r
373  * task should be used in place of the parameter.  This macro simply checks to\r
374  * see if the parameter is NULL and returns a pointer to the appropriate TCB.\r
375  */\r
376 #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TCB_t * ) pxCurrentTCB : ( TCB_t * ) ( pxHandle ) )\r
377 \r
378 /* The item value of the event list item is normally used to hold the priority\r
379 of the task to which it belongs (coded to allow it to be held in reverse\r
380 priority order).  However, it is occasionally borrowed for other purposes.  It\r
381 is important its value is not updated due to a task priority change while it is\r
382 being used for another purpose.  The following bit definition is used to inform\r
383 the scheduler that the value should not be changed - in which case it is the\r
384 responsibility of whichever module is using the value to ensure it gets set back\r
385 to its original value when it is released. */\r
386 #if configUSE_16_BIT_TICKS == 1\r
387         #define taskEVENT_LIST_ITEM_VALUE_IN_USE        0x8000U\r
388 #else\r
389         #define taskEVENT_LIST_ITEM_VALUE_IN_USE        0x80000000UL\r
390 #endif\r
391 \r
392 /* Callback function prototypes. --------------------------*/\r
393 #if configCHECK_FOR_STACK_OVERFLOW > 0\r
394         extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName );\r
395 #endif\r
396 \r
397 #if configUSE_TICK_HOOK > 0\r
398         extern void vApplicationTickHook( void );\r
399 #endif\r
400 \r
401 /* File private functions. --------------------------------*/\r
402 \r
403 /*\r
404  * Utility to ready a TCB for a given task.  Mainly just copies the parameters\r
405  * into the TCB structure.\r
406  */\r
407 static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
408 \r
409 /**\r
410  * Utility task that simply returns pdTRUE if the task referenced by xTask is\r
411  * currently in the Suspended state, or pdFALSE if the task referenced by xTask\r
412  * is in any other state.\r
413  */\r
414 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;\r
415 \r
416 /*\r
417  * Utility to ready all the lists used by the scheduler.  This is called\r
418  * automatically upon the creation of the first task.\r
419  */\r
420 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;\r
421 \r
422 /*\r
423  * The idle task, which as all tasks is implemented as a never ending loop.\r
424  * The idle task is automatically created and added to the ready lists upon\r
425  * creation of the first user task.\r
426  *\r
427  * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific\r
428  * language extensions.  The equivalent prototype for this function is:\r
429  *\r
430  * void prvIdleTask( void *pvParameters );\r
431  *\r
432  */\r
433 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );\r
434 \r
435 /*\r
436  * Utility to free all memory allocated by the scheduler to hold a TCB,\r
437  * including the stack pointed to by the TCB.\r
438  *\r
439  * This does not free memory allocated by the task itself (i.e. memory\r
440  * allocated by calls to pvPortMalloc from within the tasks application code).\r
441  */\r
442 #if ( INCLUDE_vTaskDelete == 1 )\r
443 \r
444         static void prvDeleteTCB( TCB_t *pxTCB ) PRIVILEGED_FUNCTION;\r
445 \r
446 #endif\r
447 \r
448 /*\r
449  * Used only by the idle task.  This checks to see if anything has been placed\r
450  * in the list of tasks waiting to be deleted.  If so the task is cleaned up\r
451  * and its TCB deleted.\r
452  */\r
453 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;\r
454 \r
455 /*\r
456  * The currently executing task is entering the Blocked state.  Add the task to\r
457  * either the current or the overflow delayed task list.\r
458  */\r
459 static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake ) PRIVILEGED_FUNCTION;\r
460 \r
461 /*\r
462  * Allocates memory from the heap for a TCB and associated stack.  Checks the\r
463  * allocation was successful.\r
464  */\r
465 static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer ) PRIVILEGED_FUNCTION;\r
466 \r
467 /*\r
468  * Fills an TaskStatus_t structure with information on each task that is\r
469  * referenced from the pxList list (which may be a ready list, a delayed list,\r
470  * a suspended list, etc.).\r
471  *\r
472  * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM\r
473  * NORMAL APPLICATION CODE.\r
474  */\r
475 #if ( configUSE_TRACE_FACILITY == 1 )\r
476 \r
477         static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;\r
478 \r
479 #endif\r
480 \r
481 /*\r
482  * When a task is created, the stack of the task is filled with a known value.\r
483  * This function determines the 'high water mark' of the task stack by\r
484  * determining how much of the stack remains at the original preset value.\r
485  */\r
486 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )\r
487 \r
488         static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;\r
489 \r
490 #endif\r
491 \r
492 /*\r
493  * Return the amount of time, in ticks, that will pass before the kernel will\r
494  * next move a task from the Blocked state to the Running state.\r
495  *\r
496  * This conditional compilation should use inequality to 0, not equality to 1.\r
497  * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user\r
498  * defined low power mode implementations require configUSE_TICKLESS_IDLE to be\r
499  * set to a value other than 1.\r
500  */\r
501 #if ( configUSE_TICKLESS_IDLE != 0 )\r
502 \r
503         static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;\r
504 \r
505 #endif\r
506 \r
507 /*\r
508  * Set xNextTaskUnblockTime to the time at which the next Blocked state task\r
509  * will exit the Blocked state.\r
510  */\r
511 static void prvResetNextTaskUnblockTime( void );\r
512 \r
513 /*-----------------------------------------------------------*/\r
514 \r
515 BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
516 {\r
517 BaseType_t xReturn;\r
518 TCB_t * pxNewTCB;\r
519 \r
520         configASSERT( pxTaskCode );\r
521         configASSERT( ( ( uxPriority & ( ~portPRIVILEGE_BIT ) ) < configMAX_PRIORITIES ) );\r
522 \r
523         /* Allocate the memory required by the TCB and stack for the new task,\r
524         checking that the allocation was successful. */\r
525         pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer );\r
526 \r
527         if( pxNewTCB != NULL )\r
528         {\r
529                 StackType_t *pxTopOfStack;\r
530 \r
531                 #if( portUSING_MPU_WRAPPERS == 1 )\r
532                         /* Should the task be created in privileged mode? */\r
533                         BaseType_t xRunPrivileged;\r
534                         if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )\r
535                         {\r
536                                 xRunPrivileged = pdTRUE;\r
537                         }\r
538                         else\r
539                         {\r
540                                 xRunPrivileged = pdFALSE;\r
541                         }\r
542                         uxPriority &= ~portPRIVILEGE_BIT;\r
543                 #endif /* portUSING_MPU_WRAPPERS == 1 */\r
544 \r
545                 /* Calculate the top of stack address.  This depends on whether the\r
546                 stack grows from high memory to low (as per the 80x86) or vice versa.\r
547                 portSTACK_GROWTH is used to make the result positive or negative as\r
548                 required by the port. */\r
549                 #if( portSTACK_GROWTH < 0 )\r
550                 {\r
551                         pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( uint16_t ) 1 );\r
552                         pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK  ) ); /*lint !e923 MISRA exception.  Avoiding casts between pointers and integers is not practical.  Size differences accounted for using portPOINTER_SIZE_TYPE type. */\r
553 \r
554                         /* Check the alignment of the calculated top of stack is correct. */\r
555                         configASSERT( ( ( ( uint32_t ) pxTopOfStack & ( uint32_t ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );\r
556                 }\r
557                 #else /* portSTACK_GROWTH */\r
558                 {\r
559                         pxTopOfStack = pxNewTCB->pxStack;\r
560 \r
561                         /* Check the alignment of the stack buffer is correct. */\r
562                         configASSERT( ( ( ( uint32_t ) pxNewTCB->pxStack & ( uint32_t ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );\r
563 \r
564                         /* If we want to use stack checking on architectures that use\r
565                         a positive stack growth direction then we also need to store the\r
566                         other extreme of the stack space. */\r
567                         pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );\r
568                 }\r
569                 #endif /* portSTACK_GROWTH */\r
570 \r
571                 /* Setup the newly allocated TCB with the initial state of the task. */\r
572                 prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth );\r
573 \r
574                 /* Initialize the TCB stack to look as if the task was already running,\r
575                 but had been interrupted by the scheduler.  The return address is set\r
576                 to the start of the task function. Once the stack has been initialised\r
577                 the     top of stack variable is updated. */\r
578                 #if( portUSING_MPU_WRAPPERS == 1 )\r
579                 {\r
580                         pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );\r
581                 }\r
582                 #else /* portUSING_MPU_WRAPPERS */\r
583                 {\r
584                         pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );\r
585                 }\r
586                 #endif /* portUSING_MPU_WRAPPERS */\r
587 \r
588                 if( ( void * ) pxCreatedTask != NULL )\r
589                 {\r
590                         /* Pass the TCB out - in an anonymous way.  The calling function/\r
591                         task can use this as a handle to delete the task later if\r
592                         required.*/\r
593                         *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;\r
594                 }\r
595                 else\r
596                 {\r
597                         mtCOVERAGE_TEST_MARKER();\r
598                 }\r
599 \r
600                 /* Ensure interrupts don't access the task lists while they are being\r
601                 updated. */\r
602                 taskENTER_CRITICAL();\r
603                 {\r
604                         uxCurrentNumberOfTasks++;\r
605                         if( pxCurrentTCB == NULL )\r
606                         {\r
607                                 /* There are no other tasks, or all the other tasks are in\r
608                                 the suspended state - make this the current task. */\r
609                                 pxCurrentTCB =  pxNewTCB;\r
610 \r
611                                 if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )\r
612                                 {\r
613                                         /* This is the first task to be created so do the preliminary\r
614                                         initialisation required.  We will not recover if this call\r
615                                         fails, but we will report the failure. */\r
616                                         prvInitialiseTaskLists();\r
617                                 }\r
618                                 else\r
619                                 {\r
620                                         mtCOVERAGE_TEST_MARKER();\r
621                                 }\r
622                         }\r
623                         else\r
624                         {\r
625                                 /* If the scheduler is not already running, make this task the\r
626                                 current task if it is the highest priority task to be created\r
627                                 so far. */\r
628                                 if( xSchedulerRunning == pdFALSE )\r
629                                 {\r
630                                         if( pxCurrentTCB->uxPriority <= uxPriority )\r
631                                         {\r
632                                                 pxCurrentTCB = pxNewTCB;\r
633                                         }\r
634                                         else\r
635                                         {\r
636                                                 mtCOVERAGE_TEST_MARKER();\r
637                                         }\r
638                                 }\r
639                                 else\r
640                                 {\r
641                                         mtCOVERAGE_TEST_MARKER();\r
642                                 }\r
643                         }\r
644 \r
645                         uxTaskNumber++;\r
646 \r
647                         #if ( configUSE_TRACE_FACILITY == 1 )\r
648                         {\r
649                                 /* Add a counter into the TCB for tracing only. */\r
650                                 pxNewTCB->uxTCBNumber = uxTaskNumber;\r
651                         }\r
652                         #endif /* configUSE_TRACE_FACILITY */\r
653                         traceTASK_CREATE( pxNewTCB );\r
654 \r
655                         prvAddTaskToReadyList( pxNewTCB );\r
656 \r
657                         xReturn = pdPASS;\r
658                         portSETUP_TCB( pxNewTCB );\r
659                 }\r
660                 taskEXIT_CRITICAL();\r
661         }\r
662         else\r
663         {\r
664                 xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;\r
665                 traceTASK_CREATE_FAILED();\r
666         }\r
667 \r
668         if( xReturn == pdPASS )\r
669         {\r
670                 if( xSchedulerRunning != pdFALSE )\r
671                 {\r
672                         /* If the created task is of a higher priority than the current task\r
673                         then it should run now. */\r
674                         if( pxCurrentTCB->uxPriority < uxPriority )\r
675                         {\r
676                                 taskYIELD_IF_USING_PREEMPTION();\r
677                         }\r
678                         else\r
679                         {\r
680                                 mtCOVERAGE_TEST_MARKER();\r
681                         }\r
682                 }\r
683                 else\r
684                 {\r
685                         mtCOVERAGE_TEST_MARKER();\r
686                 }\r
687         }\r
688 \r
689         return xReturn;\r
690 }\r
691 /*-----------------------------------------------------------*/\r
692 \r
693 #if ( INCLUDE_vTaskDelete == 1 )\r
694 \r
695         void vTaskDelete( TaskHandle_t xTaskToDelete )\r
696         {\r
697         TCB_t *pxTCB;\r
698 \r
699                 taskENTER_CRITICAL();\r
700                 {\r
701                         /* If null is passed in here then it is the calling task that is\r
702                         being deleted. */\r
703                         pxTCB = prvGetTCBFromHandle( xTaskToDelete );\r
704 \r
705                         /* Remove task from the ready list and place in the     termination list.\r
706                         This will stop the task from be scheduled.  The idle task will check\r
707                         the termination list and free up any memory allocated by the\r
708                         scheduler for the TCB and stack. */\r
709                         if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )\r
710                         {\r
711                                 taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
712                         }\r
713                         else\r
714                         {\r
715                                 mtCOVERAGE_TEST_MARKER();\r
716                         }\r
717 \r
718                         /* Is the task waiting on an event also? */\r
719                         if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )\r
720                         {\r
721                                 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );\r
722                         }\r
723                         else\r
724                         {\r
725                                 mtCOVERAGE_TEST_MARKER();\r
726                         }\r
727 \r
728                         vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );\r
729 \r
730                         /* Increment the ucTasksDeleted variable so the idle task knows\r
731                         there is a task that has been deleted and that it should therefore\r
732                         check the xTasksWaitingTermination list. */\r
733                         ++uxTasksDeleted;\r
734 \r
735                         /* Increment the uxTaskNumberVariable also so kernel aware debuggers\r
736                         can detect that the task lists need re-generating. */\r
737                         uxTaskNumber++;\r
738 \r
739                         traceTASK_DELETE( pxTCB );\r
740                 }\r
741                 taskEXIT_CRITICAL();\r
742 \r
743                 /* Force a reschedule if it is the currently running task that has just\r
744                 been deleted. */\r
745                 if( xSchedulerRunning != pdFALSE )\r
746                 {\r
747                         if( pxTCB == pxCurrentTCB )\r
748                         {\r
749                                 configASSERT( uxSchedulerSuspended == 0 );\r
750 \r
751                                 /* The pre-delete hook is primarily for the Windows simulator,\r
752                                 in which Windows specific clean up operations are performed,\r
753                                 after which it is not possible to yield away from this task -\r
754                                 hence xYieldPending is used to latch that a context switch is\r
755                                 required. */\r
756                                 portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );\r
757                                 portYIELD_WITHIN_API();\r
758                         }\r
759                         else\r
760                         {\r
761                                 /* Reset the next expected unblock time in case it referred to\r
762                                 the task that has just been deleted. */\r
763                                 taskENTER_CRITICAL();\r
764                                 {\r
765                                         prvResetNextTaskUnblockTime();\r
766                                 }\r
767                                 taskEXIT_CRITICAL();\r
768                         }\r
769                 }\r
770         }\r
771 \r
772 #endif /* INCLUDE_vTaskDelete */\r
773 /*-----------------------------------------------------------*/\r
774 \r
775 #if ( INCLUDE_vTaskDelayUntil == 1 )\r
776 \r
777         void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )\r
778         {\r
779         TickType_t xTimeToWake;\r
780         BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;\r
781 \r
782                 configASSERT( pxPreviousWakeTime );\r
783                 configASSERT( ( xTimeIncrement > 0U ) );\r
784                 configASSERT( uxSchedulerSuspended == 0 );\r
785 \r
786                 vTaskSuspendAll();\r
787                 {\r
788                         /* Minor optimisation.  The tick count cannot change in this\r
789                         block. */\r
790                         const TickType_t xConstTickCount = xTickCount;\r
791 \r
792                         /* Generate the tick time at which the task wants to wake. */\r
793                         xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;\r
794 \r
795                         if( xConstTickCount < *pxPreviousWakeTime )\r
796                         {\r
797                                 /* The tick count has overflowed since this function was\r
798                                 lasted called.  In this case the only time we should ever\r
799                                 actually delay is if the wake time has also     overflowed,\r
800                                 and the wake time is greater than the tick time.  When this\r
801                                 is the case it is as if neither time had overflowed. */\r
802                                 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )\r
803                                 {\r
804                                         xShouldDelay = pdTRUE;\r
805                                 }\r
806                                 else\r
807                                 {\r
808                                         mtCOVERAGE_TEST_MARKER();\r
809                                 }\r
810                         }\r
811                         else\r
812                         {\r
813                                 /* The tick time has not overflowed.  In this case we will\r
814                                 delay if either the wake time has overflowed, and/or the\r
815                                 tick time is less than the wake time. */\r
816                                 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )\r
817                                 {\r
818                                         xShouldDelay = pdTRUE;\r
819                                 }\r
820                                 else\r
821                                 {\r
822                                         mtCOVERAGE_TEST_MARKER();\r
823                                 }\r
824                         }\r
825 \r
826                         /* Update the wake time ready for the next call. */\r
827                         *pxPreviousWakeTime = xTimeToWake;\r
828 \r
829                         if( xShouldDelay != pdFALSE )\r
830                         {\r
831                                 traceTASK_DELAY_UNTIL();\r
832 \r
833                                 /* Remove the task from the ready list before adding it to the\r
834                                 blocked list as the same list item is used for both lists. */\r
835                                 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )\r
836                                 {\r
837                                         /* The current task must be in a ready list, so there is\r
838                                         no need to check, and the port reset macro can be called\r
839                                         directly. */\r
840                                         portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );\r
841                                 }\r
842                                 else\r
843                                 {\r
844                                         mtCOVERAGE_TEST_MARKER();\r
845                                 }\r
846 \r
847                                 prvAddCurrentTaskToDelayedList( xTimeToWake );\r
848                         }\r
849                         else\r
850                         {\r
851                                 mtCOVERAGE_TEST_MARKER();\r
852                         }\r
853                 }\r
854                 xAlreadyYielded = xTaskResumeAll();\r
855 \r
856                 /* Force a reschedule if xTaskResumeAll has not already done so, we may\r
857                 have put ourselves to sleep. */\r
858                 if( xAlreadyYielded == pdFALSE )\r
859                 {\r
860                         portYIELD_WITHIN_API();\r
861                 }\r
862                 else\r
863                 {\r
864                         mtCOVERAGE_TEST_MARKER();\r
865                 }\r
866         }\r
867 \r
868 #endif /* INCLUDE_vTaskDelayUntil */\r
869 /*-----------------------------------------------------------*/\r
870 \r
871 #if ( INCLUDE_vTaskDelay == 1 )\r
872 \r
873         void vTaskDelay( const TickType_t xTicksToDelay )\r
874         {\r
875         TickType_t xTimeToWake;\r
876         BaseType_t xAlreadyYielded = pdFALSE;\r
877 \r
878 \r
879                 /* A delay time of zero just forces a reschedule. */\r
880                 if( xTicksToDelay > ( TickType_t ) 0U )\r
881                 {\r
882                         configASSERT( uxSchedulerSuspended == 0 );\r
883                         vTaskSuspendAll();\r
884                         {\r
885                                 traceTASK_DELAY();\r
886 \r
887                                 /* A task that is removed from the event list while the\r
888                                 scheduler is suspended will not get placed in the ready\r
889                                 list or removed from the blocked list until the scheduler\r
890                                 is resumed.\r
891 \r
892                                 This task cannot be in an event list as it is the currently\r
893                                 executing task. */\r
894 \r
895                                 /* Calculate the time to wake - this may overflow but this is\r
896                                 not a problem. */\r
897                                 xTimeToWake = xTickCount + xTicksToDelay;\r
898 \r
899                                 /* We must remove ourselves from the ready list before adding\r
900                                 ourselves to the blocked list as the same list item is used for\r
901                                 both lists. */\r
902                                 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )\r
903                                 {\r
904                                         /* The current task must be in a ready list, so there is\r
905                                         no need to check, and the port reset macro can be called\r
906                                         directly. */\r
907                                         portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );\r
908                                 }\r
909                                 else\r
910                                 {\r
911                                         mtCOVERAGE_TEST_MARKER();\r
912                                 }\r
913                                 prvAddCurrentTaskToDelayedList( xTimeToWake );\r
914                         }\r
915                         xAlreadyYielded = xTaskResumeAll();\r
916                 }\r
917                 else\r
918                 {\r
919                         mtCOVERAGE_TEST_MARKER();\r
920                 }\r
921 \r
922                 /* Force a reschedule if xTaskResumeAll has not already done so, we may\r
923                 have put ourselves to sleep. */\r
924                 if( xAlreadyYielded == pdFALSE )\r
925                 {\r
926                         portYIELD_WITHIN_API();\r
927                 }\r
928                 else\r
929                 {\r
930                         mtCOVERAGE_TEST_MARKER();\r
931                 }\r
932         }\r
933 \r
934 #endif /* INCLUDE_vTaskDelay */\r
935 /*-----------------------------------------------------------*/\r
936 \r
937 #if ( INCLUDE_eTaskGetState == 1 )\r
938 \r
939         eTaskState eTaskGetState( TaskHandle_t xTask )\r
940         {\r
941         eTaskState eReturn;\r
942         List_t *pxStateList;\r
943         const TCB_t * const pxTCB = ( TCB_t * ) xTask;\r
944 \r
945                 configASSERT( pxTCB );\r
946 \r
947                 if( pxTCB == pxCurrentTCB )\r
948                 {\r
949                         /* The task calling this function is querying its own state. */\r
950                         eReturn = eRunning;\r
951                 }\r
952                 else\r
953                 {\r
954                         taskENTER_CRITICAL();\r
955                         {\r
956                                 pxStateList = ( List_t * ) listLIST_ITEM_CONTAINER( &( pxTCB->xGenericListItem ) );\r
957                         }\r
958                         taskEXIT_CRITICAL();\r
959 \r
960                         if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) )\r
961                         {\r
962                                 /* The task being queried is referenced from one of the Blocked\r
963                                 lists. */\r
964                                 eReturn = eBlocked;\r
965                         }\r
966 \r
967                         #if ( INCLUDE_vTaskSuspend == 1 )\r
968                                 else if( pxStateList == &xSuspendedTaskList )\r
969                                 {\r
970                                         /* The task being queried is referenced from the suspended\r
971                                         list.  Is it genuinely suspended or is it block\r
972                                         indefinitely? */\r
973                                         if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )\r
974                                         {\r
975                                                 eReturn = eSuspended;\r
976                                         }\r
977                                         else\r
978                                         {\r
979                                                 eReturn = eBlocked;\r
980                                         }\r
981                                 }\r
982                         #endif\r
983 \r
984                         #if ( INCLUDE_vTaskDelete == 1 )\r
985                                 else if( pxStateList == &xTasksWaitingTermination )\r
986                                 {\r
987                                         /* The task being queried is referenced from the deleted\r
988                                         tasks list. */\r
989                                         eReturn = eDeleted;\r
990                                 }\r
991                         #endif\r
992 \r
993                         else\r
994                         {\r
995                                 /* If the task is not in any other state, it must be in the\r
996                                 Ready (including pending ready) state. */\r
997                                 eReturn = eReady;\r
998                         }\r
999                 }\r
1000 \r
1001                 return eReturn;\r
1002         }\r
1003 \r
1004 #endif /* INCLUDE_eTaskGetState */\r
1005 /*-----------------------------------------------------------*/\r
1006 \r
1007 #if ( INCLUDE_uxTaskPriorityGet == 1 )\r
1008 \r
1009         UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask )\r
1010         {\r
1011         TCB_t *pxTCB;\r
1012         UBaseType_t uxReturn;\r
1013 \r
1014                 taskENTER_CRITICAL();\r
1015                 {\r
1016                         /* If null is passed in here then we are changing the\r
1017                         priority of the calling function. */\r
1018                         pxTCB = prvGetTCBFromHandle( xTask );\r
1019                         uxReturn = pxTCB->uxPriority;\r
1020                 }\r
1021                 taskEXIT_CRITICAL();\r
1022 \r
1023                 return uxReturn;\r
1024         }\r
1025 \r
1026 #endif /* INCLUDE_uxTaskPriorityGet */\r
1027 /*-----------------------------------------------------------*/\r
1028 \r
1029 #if ( INCLUDE_vTaskPrioritySet == 1 )\r
1030 \r
1031         void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )\r
1032         {\r
1033         TCB_t *pxTCB;\r
1034         UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;\r
1035         BaseType_t xYieldRequired = pdFALSE;\r
1036 \r
1037                 configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );\r
1038 \r
1039                 /* Ensure the new priority is valid. */\r
1040                 if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )\r
1041                 {\r
1042                         uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;\r
1043                 }\r
1044                 else\r
1045                 {\r
1046                         mtCOVERAGE_TEST_MARKER();\r
1047                 }\r
1048 \r
1049                 taskENTER_CRITICAL();\r
1050                 {\r
1051                         /* If null is passed in here then it is the priority of the calling\r
1052                         task that is being changed. */\r
1053                         pxTCB = prvGetTCBFromHandle( xTask );\r
1054 \r
1055                         traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );\r
1056 \r
1057                         #if ( configUSE_MUTEXES == 1 )\r
1058                         {\r
1059                                 uxCurrentBasePriority = pxTCB->uxBasePriority;\r
1060                         }\r
1061                         #else\r
1062                         {\r
1063                                 uxCurrentBasePriority = pxTCB->uxPriority;\r
1064                         }\r
1065                         #endif\r
1066 \r
1067                         if( uxCurrentBasePriority != uxNewPriority )\r
1068                         {\r
1069                                 /* The priority change may have readied a task of higher\r
1070                                 priority than the calling task. */\r
1071                                 if( uxNewPriority > uxCurrentBasePriority )\r
1072                                 {\r
1073                                         if( pxTCB != pxCurrentTCB )\r
1074                                         {\r
1075                                                 /* The priority of a task other than the currently\r
1076                                                 running task is being raised.  Is the priority being\r
1077                                                 raised above that of the running task? */\r
1078                                                 if( uxNewPriority >= pxCurrentTCB->uxPriority )\r
1079                                                 {\r
1080                                                         xYieldRequired = pdTRUE;\r
1081                                                 }\r
1082                                                 else\r
1083                                                 {\r
1084                                                         mtCOVERAGE_TEST_MARKER();\r
1085                                                 }\r
1086                                         }\r
1087                                         else\r
1088                                         {\r
1089                                                 /* The priority of the running task is being raised,\r
1090                                                 but the running task must already be the highest\r
1091                                                 priority task able to run so no yield is required. */\r
1092                                         }\r
1093                                 }\r
1094                                 else if( pxTCB == pxCurrentTCB )\r
1095                                 {\r
1096                                         /* Setting the priority of the running task down means\r
1097                                         there may now be another task of higher priority that\r
1098                                         is ready to execute. */\r
1099                                         xYieldRequired = pdTRUE;\r
1100                                 }\r
1101                                 else\r
1102                                 {\r
1103                                         /* Setting the priority of any other task down does not\r
1104                                         require a yield as the running task must be above the\r
1105                                         new priority of the task being modified. */\r
1106                                 }\r
1107 \r
1108                                 /* Remember the ready list the task might be referenced from\r
1109                                 before its uxPriority member is changed so the\r
1110                                 taskRESET_READY_PRIORITY() macro can function correctly. */\r
1111                                 uxPriorityUsedOnEntry = pxTCB->uxPriority;\r
1112 \r
1113                                 #if ( configUSE_MUTEXES == 1 )\r
1114                                 {\r
1115                                         /* Only change the priority being used if the task is not\r
1116                                         currently using an inherited priority. */\r
1117                                         if( pxTCB->uxBasePriority == pxTCB->uxPriority )\r
1118                                         {\r
1119                                                 pxTCB->uxPriority = uxNewPriority;\r
1120                                         }\r
1121                                         else\r
1122                                         {\r
1123                                                 mtCOVERAGE_TEST_MARKER();\r
1124                                         }\r
1125 \r
1126                                         /* The base priority gets set whatever. */\r
1127                                         pxTCB->uxBasePriority = uxNewPriority;\r
1128                                 }\r
1129                                 #else\r
1130                                 {\r
1131                                         pxTCB->uxPriority = uxNewPriority;\r
1132                                 }\r
1133                                 #endif\r
1134 \r
1135                                 /* Only reset the event list item value if the value is not\r
1136                                 being used for anything else. */\r
1137                                 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )\r
1138                                 {\r
1139                                         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
1140                                 }\r
1141                                 else\r
1142                                 {\r
1143                                         mtCOVERAGE_TEST_MARKER();\r
1144                                 }\r
1145 \r
1146                                 /* If the task is in the blocked or suspended list we need do\r
1147                                 nothing more than change it's priority variable. However, if\r
1148                                 the task is in a ready list it needs to be removed and placed\r
1149                                 in the list appropriate to its new priority. */\r
1150                                 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )\r
1151                                 {\r
1152                                         /* The task is currently in its ready list - remove before adding\r
1153                                         it to it's new ready list.  As we are in a critical section we\r
1154                                         can do this even if the scheduler is suspended. */\r
1155                                         if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )\r
1156                                         {\r
1157                                                 /* It is known that the task is in its ready list so\r
1158                                                 there is no need to check again and the port level\r
1159                                                 reset macro can be called directly. */\r
1160                                                 portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );\r
1161                                         }\r
1162                                         else\r
1163                                         {\r
1164                                                 mtCOVERAGE_TEST_MARKER();\r
1165                                         }\r
1166                                         prvAddTaskToReadyList( pxTCB );\r
1167                                 }\r
1168                                 else\r
1169                                 {\r
1170                                         mtCOVERAGE_TEST_MARKER();\r
1171                                 }\r
1172 \r
1173                                 if( xYieldRequired == pdTRUE )\r
1174                                 {\r
1175                                         taskYIELD_IF_USING_PREEMPTION();\r
1176                                 }\r
1177                                 else\r
1178                                 {\r
1179                                         mtCOVERAGE_TEST_MARKER();\r
1180                                 }\r
1181 \r
1182                                 /* Remove compiler warning about unused variables when the port\r
1183                                 optimised task selection is not being used. */\r
1184                                 ( void ) uxPriorityUsedOnEntry;\r
1185                         }\r
1186                 }\r
1187                 taskEXIT_CRITICAL();\r
1188         }\r
1189 \r
1190 #endif /* INCLUDE_vTaskPrioritySet */\r
1191 /*-----------------------------------------------------------*/\r
1192 \r
1193 #if ( INCLUDE_vTaskSuspend == 1 )\r
1194 \r
1195         void vTaskSuspend( TaskHandle_t xTaskToSuspend )\r
1196         {\r
1197         TCB_t *pxTCB;\r
1198 \r
1199                 taskENTER_CRITICAL();\r
1200                 {\r
1201                         /* If null is passed in here then it is the running task that is\r
1202                         being suspended. */\r
1203                         pxTCB = prvGetTCBFromHandle( xTaskToSuspend );\r
1204 \r
1205                         traceTASK_SUSPEND( pxTCB );\r
1206 \r
1207                         /* Remove task from the ready/delayed list and place in the\r
1208                         suspended list. */\r
1209                         if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )\r
1210                         {\r
1211                                 taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
1212                         }\r
1213                         else\r
1214                         {\r
1215                                 mtCOVERAGE_TEST_MARKER();\r
1216                         }\r
1217 \r
1218                         /* Is the task waiting on an event also? */\r
1219                         if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )\r
1220                         {\r
1221                                 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );\r
1222                         }\r
1223                         else\r
1224                         {\r
1225                                 mtCOVERAGE_TEST_MARKER();\r
1226                         }\r
1227 \r
1228                         vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) );\r
1229                 }\r
1230                 taskEXIT_CRITICAL();\r
1231 \r
1232                 if( pxTCB == pxCurrentTCB )\r
1233                 {\r
1234                         if( xSchedulerRunning != pdFALSE )\r
1235                         {\r
1236                                 /* The current task has just been suspended. */\r
1237                                 configASSERT( uxSchedulerSuspended == 0 );\r
1238                                 portYIELD_WITHIN_API();\r
1239                         }\r
1240                         else\r
1241                         {\r
1242                                 /* The scheduler is not running, but the task that was pointed\r
1243                                 to by pxCurrentTCB has just been suspended and pxCurrentTCB\r
1244                                 must be adjusted to point to a different task. */\r
1245                                 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )\r
1246                                 {\r
1247                                         /* No other tasks are ready, so set pxCurrentTCB back to\r
1248                                         NULL so when the next task is created pxCurrentTCB will\r
1249                                         be set to point to it no matter what its relative priority\r
1250                                         is. */\r
1251                                         pxCurrentTCB = NULL;\r
1252                                 }\r
1253                                 else\r
1254                                 {\r
1255                                         vTaskSwitchContext();\r
1256                                 }\r
1257                         }\r
1258                 }\r
1259                 else\r
1260                 {\r
1261                         if( xSchedulerRunning != pdFALSE )\r
1262                         {\r
1263                                 /* A task other than the currently running task was suspended,\r
1264                                 reset the next expected unblock time in case it referred to the\r
1265                                 task that is now in the Suspended state. */\r
1266                                 taskENTER_CRITICAL();\r
1267                                 {\r
1268                                         prvResetNextTaskUnblockTime();\r
1269                                 }\r
1270                                 taskEXIT_CRITICAL();\r
1271                         }\r
1272                         else\r
1273                         {\r
1274                                 mtCOVERAGE_TEST_MARKER();\r
1275                         }\r
1276                 }\r
1277         }\r
1278 \r
1279 #endif /* INCLUDE_vTaskSuspend */\r
1280 /*-----------------------------------------------------------*/\r
1281 \r
1282 #if ( INCLUDE_vTaskSuspend == 1 )\r
1283 \r
1284         static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )\r
1285         {\r
1286         BaseType_t xReturn = pdFALSE;\r
1287         const TCB_t * const pxTCB = ( TCB_t * ) xTask;\r
1288 \r
1289                 /* Accesses xPendingReadyList so must be called from a critical\r
1290                 section. */\r
1291 \r
1292                 /* It does not make sense to check if the calling task is suspended. */\r
1293                 configASSERT( xTask );\r
1294 \r
1295                 /* Is the task being resumed actually in the suspended list? */\r
1296                 if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )\r
1297                 {\r
1298                         /* Has the task already been resumed from within an ISR? */\r
1299                         if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )\r
1300                         {\r
1301                                 /* Is it in the suspended list because it is in the     Suspended\r
1302                                 state, or because is is blocked with no timeout? */\r
1303                                 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )\r
1304                                 {\r
1305                                         xReturn = pdTRUE;\r
1306                                 }\r
1307                                 else\r
1308                                 {\r
1309                                         mtCOVERAGE_TEST_MARKER();\r
1310                                 }\r
1311                         }\r
1312                         else\r
1313                         {\r
1314                                 mtCOVERAGE_TEST_MARKER();\r
1315                         }\r
1316                 }\r
1317                 else\r
1318                 {\r
1319                         mtCOVERAGE_TEST_MARKER();\r
1320                 }\r
1321 \r
1322                 return xReturn;\r
1323         } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */\r
1324 \r
1325 #endif /* INCLUDE_vTaskSuspend */\r
1326 /*-----------------------------------------------------------*/\r
1327 \r
1328 #if ( INCLUDE_vTaskSuspend == 1 )\r
1329 \r
1330         void vTaskResume( TaskHandle_t xTaskToResume )\r
1331         {\r
1332         TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;\r
1333 \r
1334                 /* It does not make sense to resume the calling task. */\r
1335                 configASSERT( xTaskToResume );\r
1336 \r
1337                 /* The parameter cannot be NULL as it is impossible to resume the\r
1338                 currently executing task. */\r
1339                 if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )\r
1340                 {\r
1341                         taskENTER_CRITICAL();\r
1342                         {\r
1343                                 if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE )\r
1344                                 {\r
1345                                         traceTASK_RESUME( pxTCB );\r
1346 \r
1347                                         /* As we are in a critical section we can access the ready\r
1348                                         lists even if the scheduler is suspended. */\r
1349                                         ( void ) uxListRemove(  &( pxTCB->xGenericListItem ) );\r
1350                                         prvAddTaskToReadyList( pxTCB );\r
1351 \r
1352                                         /* We may have just resumed a higher priority task. */\r
1353                                         if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )\r
1354                                         {\r
1355                                                 /* This yield may not cause the task just resumed to run,\r
1356                                                 but will leave the lists in the correct state for the\r
1357                                                 next yield. */\r
1358                                                 taskYIELD_IF_USING_PREEMPTION();\r
1359                                         }\r
1360                                         else\r
1361                                         {\r
1362                                                 mtCOVERAGE_TEST_MARKER();\r
1363                                         }\r
1364                                 }\r
1365                                 else\r
1366                                 {\r
1367                                         mtCOVERAGE_TEST_MARKER();\r
1368                                 }\r
1369                         }\r
1370                         taskEXIT_CRITICAL();\r
1371                 }\r
1372                 else\r
1373                 {\r
1374                         mtCOVERAGE_TEST_MARKER();\r
1375                 }\r
1376         }\r
1377 \r
1378 #endif /* INCLUDE_vTaskSuspend */\r
1379 \r
1380 /*-----------------------------------------------------------*/\r
1381 \r
1382 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )\r
1383 \r
1384         BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )\r
1385         {\r
1386         BaseType_t xYieldRequired = pdFALSE;\r
1387         TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;\r
1388         UBaseType_t uxSavedInterruptStatus;\r
1389 \r
1390                 configASSERT( xTaskToResume );\r
1391 \r
1392                 /* RTOS ports that support interrupt nesting have the concept of a\r
1393                 maximum system call (or maximum API call) interrupt priority.\r
1394                 Interrupts that are     above the maximum system call priority are keep\r
1395                 permanently enabled, even when the RTOS kernel is in a critical section,\r
1396                 but cannot make any calls to FreeRTOS API functions.  If configASSERT()\r
1397                 is defined in FreeRTOSConfig.h then\r
1398                 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
1399                 failure if a FreeRTOS API function is called from an interrupt that has\r
1400                 been assigned a priority above the configured maximum system call\r
1401                 priority.  Only FreeRTOS functions that end in FromISR can be called\r
1402                 from interrupts that have been assigned a priority at or (logically)\r
1403                 below the maximum system call interrupt priority.  FreeRTOS maintains a\r
1404                 separate interrupt safe API to ensure interrupt entry is as fast and as\r
1405                 simple as possible.  More information (albeit Cortex-M specific) is\r
1406                 provided on the following link:\r
1407                 http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
1408                 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
1409 \r
1410                 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
1411                 {\r
1412                         if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE )\r
1413                         {\r
1414                                 traceTASK_RESUME_FROM_ISR( pxTCB );\r
1415 \r
1416                                 /* Check the ready lists can be accessed. */\r
1417                                 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )\r
1418                                 {\r
1419                                         /* Ready lists can be accessed so move the task from the\r
1420                                         suspended list to the ready list directly. */\r
1421                                         if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )\r
1422                                         {\r
1423                                                 xYieldRequired = pdTRUE;\r
1424                                         }\r
1425                                         else\r
1426                                         {\r
1427                                                 mtCOVERAGE_TEST_MARKER();\r
1428                                         }\r
1429 \r
1430                                         ( void ) uxListRemove(  &( pxTCB->xGenericListItem ) );\r
1431                                         prvAddTaskToReadyList( pxTCB );\r
1432                                 }\r
1433                                 else\r
1434                                 {\r
1435                                         /* The delayed or ready lists cannot be accessed so the task\r
1436                                         is held in the pending ready list until the scheduler is\r
1437                                         unsuspended. */\r
1438                                         vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );\r
1439                                 }\r
1440                         }\r
1441                         else\r
1442                         {\r
1443                                 mtCOVERAGE_TEST_MARKER();\r
1444                         }\r
1445                 }\r
1446                 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
1447 \r
1448                 return xYieldRequired;\r
1449         }\r
1450 \r
1451 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */\r
1452 /*-----------------------------------------------------------*/\r
1453 \r
1454 void vTaskStartScheduler( void )\r
1455 {\r
1456 BaseType_t xReturn;\r
1457 \r
1458         /* Add the idle task at the lowest priority. */\r
1459         #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )\r
1460         {\r
1461                 /* Create the idle task, storing its handle in xIdleTaskHandle so it can\r
1462                 be returned by the xTaskGetIdleTaskHandle() function. */\r
1463                 xReturn = xTaskCreate( prvIdleTask, "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */\r
1464         }\r
1465         #else\r
1466         {\r
1467                 /* Create the idle task without storing its handle. */\r
1468                 xReturn = xTaskCreate( prvIdleTask, "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), NULL );  /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */\r
1469         }\r
1470         #endif /* INCLUDE_xTaskGetIdleTaskHandle */\r
1471 \r
1472         #if ( configUSE_TIMERS == 1 )\r
1473         {\r
1474                 if( xReturn == pdPASS )\r
1475                 {\r
1476                         xReturn = xTimerCreateTimerTask();\r
1477                 }\r
1478                 else\r
1479                 {\r
1480                         mtCOVERAGE_TEST_MARKER();\r
1481                 }\r
1482         }\r
1483         #endif /* configUSE_TIMERS */\r
1484 \r
1485         if( xReturn == pdPASS )\r
1486         {\r
1487                 /* Interrupts are turned off here, to ensure a tick does not occur\r
1488                 before or during the call to xPortStartScheduler().  The stacks of\r
1489                 the created tasks contain a status word with interrupts switched on\r
1490                 so interrupts will automatically get re-enabled when the first task\r
1491                 starts to run. */\r
1492                 portDISABLE_INTERRUPTS();\r
1493 \r
1494                 #if ( configUSE_NEWLIB_REENTRANT == 1 )\r
1495                 {\r
1496                         /* Switch Newlib's _impure_ptr variable to point to the _reent\r
1497                         structure specific to the task that will run first. */\r
1498                         _impure_ptr = &( pxCurrentTCB->xNewLib_reent );\r
1499                 }\r
1500                 #endif /* configUSE_NEWLIB_REENTRANT */\r
1501 \r
1502                 xSchedulerRunning = pdTRUE;\r
1503                 xTickCount = ( TickType_t ) 0U;\r
1504 \r
1505                 /* If configGENERATE_RUN_TIME_STATS is defined then the following\r
1506                 macro must be defined to configure the timer/counter used to generate\r
1507                 the run time counter time base. */\r
1508                 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();\r
1509 \r
1510                 /* Setting up the timer tick is hardware specific and thus in the\r
1511                 portable interface. */\r
1512                 if( xPortStartScheduler() != pdFALSE )\r
1513                 {\r
1514                         /* Should not reach here as if the scheduler is running the\r
1515                         function will not return. */\r
1516                 }\r
1517                 else\r
1518                 {\r
1519                         /* Should only reach here if a task calls xTaskEndScheduler(). */\r
1520                 }\r
1521         }\r
1522         else\r
1523         {\r
1524                 /* This line will only be reached if the kernel could not be started,\r
1525                 because there was not enough FreeRTOS heap to create the idle task\r
1526                 or the timer task. */\r
1527                 configASSERT( xReturn );\r
1528         }\r
1529 }\r
1530 /*-----------------------------------------------------------*/\r
1531 \r
1532 void vTaskEndScheduler( void )\r
1533 {\r
1534         /* Stop the scheduler interrupts and call the portable scheduler end\r
1535         routine so the original ISRs can be restored if necessary.  The port\r
1536         layer must ensure interrupts enable     bit is left in the correct state. */\r
1537         portDISABLE_INTERRUPTS();\r
1538         xSchedulerRunning = pdFALSE;\r
1539         vPortEndScheduler();\r
1540 }\r
1541 /*----------------------------------------------------------*/\r
1542 \r
1543 void vTaskSuspendAll( void )\r
1544 {\r
1545         /* A critical section is not required as the variable is of type\r
1546         BaseType_t.  Please read Richard Barry's reply in the following link to a\r
1547         post in the FreeRTOS support forum before reporting this as a bug! -\r
1548         http://goo.gl/wu4acr */\r
1549         ++uxSchedulerSuspended;\r
1550 }\r
1551 /*----------------------------------------------------------*/\r
1552 \r
1553 #if ( configUSE_TICKLESS_IDLE != 0 )\r
1554 \r
1555         static TickType_t prvGetExpectedIdleTime( void )\r
1556         {\r
1557         TickType_t xReturn;\r
1558 \r
1559                 if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )\r
1560                 {\r
1561                         xReturn = 0;\r
1562                 }\r
1563                 else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )\r
1564                 {\r
1565                         /* There are other idle priority tasks in the ready state.  If\r
1566                         time slicing is used then the very next tick interrupt must be\r
1567                         processed. */\r
1568                         xReturn = 0;\r
1569                 }\r
1570                 else\r
1571                 {\r
1572                         xReturn = xNextTaskUnblockTime - xTickCount;\r
1573                 }\r
1574 \r
1575                 return xReturn;\r
1576         }\r
1577 \r
1578 #endif /* configUSE_TICKLESS_IDLE */\r
1579 /*----------------------------------------------------------*/\r
1580 \r
1581 BaseType_t xTaskResumeAll( void )\r
1582 {\r
1583 TCB_t *pxTCB;\r
1584 BaseType_t xAlreadyYielded = pdFALSE;\r
1585 \r
1586         /* If uxSchedulerSuspended is zero then this function does not match a\r
1587         previous call to vTaskSuspendAll(). */\r
1588         configASSERT( uxSchedulerSuspended );\r
1589 \r
1590         /* It is possible that an ISR caused a task to be removed from an event\r
1591         list while the scheduler was suspended.  If this was the case then the\r
1592         removed task will have been added to the xPendingReadyList.  Once the\r
1593         scheduler has been resumed it is safe to move all the pending ready\r
1594         tasks from this list into their appropriate ready list. */\r
1595         taskENTER_CRITICAL();\r
1596         {\r
1597                 --uxSchedulerSuspended;\r
1598 \r
1599                 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )\r
1600                 {\r
1601                         if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )\r
1602                         {\r
1603                                 /* Move any readied tasks from the pending list into the\r
1604                                 appropriate ready list. */\r
1605                                 while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )\r
1606                                 {\r
1607                                         pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );\r
1608                                         ( void ) uxListRemove( &( pxTCB->xEventListItem ) );\r
1609                                         ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );\r
1610                                         prvAddTaskToReadyList( pxTCB );\r
1611 \r
1612                                         /* If we have moved a task that has a priority higher than\r
1613                                         the current task then we should yield. */\r
1614                                         if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )\r
1615                                         {\r
1616                                                 xYieldPending = pdTRUE;\r
1617                                         }\r
1618                                         else\r
1619                                         {\r
1620                                                 mtCOVERAGE_TEST_MARKER();\r
1621                                         }\r
1622                                 }\r
1623 \r
1624                                 /* If any ticks occurred while the scheduler was suspended then\r
1625                                 they should be processed now.  This ensures the tick count does\r
1626                                 not     slip, and that any delayed tasks are resumed at the correct\r
1627                                 time. */\r
1628                                 if( uxPendedTicks > ( UBaseType_t ) 0U )\r
1629                                 {\r
1630                                         while( uxPendedTicks > ( UBaseType_t ) 0U )\r
1631                                         {\r
1632                                                 if( xTaskIncrementTick() != pdFALSE )\r
1633                                                 {\r
1634                                                         xYieldPending = pdTRUE;\r
1635                                                 }\r
1636                                                 else\r
1637                                                 {\r
1638                                                         mtCOVERAGE_TEST_MARKER();\r
1639                                                 }\r
1640                                                 --uxPendedTicks;\r
1641                                         }\r
1642                                 }\r
1643                                 else\r
1644                                 {\r
1645                                         mtCOVERAGE_TEST_MARKER();\r
1646                                 }\r
1647 \r
1648                                 if( xYieldPending == pdTRUE )\r
1649                                 {\r
1650                                         #if( configUSE_PREEMPTION != 0 )\r
1651                                         {\r
1652                                                 xAlreadyYielded = pdTRUE;\r
1653                                         }\r
1654                                         #endif\r
1655                                         taskYIELD_IF_USING_PREEMPTION();\r
1656                                 }\r
1657                                 else\r
1658                                 {\r
1659                                         mtCOVERAGE_TEST_MARKER();\r
1660                                 }\r
1661                         }\r
1662                 }\r
1663                 else\r
1664                 {\r
1665                         mtCOVERAGE_TEST_MARKER();\r
1666                 }\r
1667         }\r
1668         taskEXIT_CRITICAL();\r
1669 \r
1670         return xAlreadyYielded;\r
1671 }\r
1672 /*-----------------------------------------------------------*/\r
1673 \r
1674 TickType_t xTaskGetTickCount( void )\r
1675 {\r
1676 TickType_t xTicks;\r
1677 \r
1678         /* Critical section required if running on a 16 bit processor. */\r
1679         taskENTER_CRITICAL();\r
1680         {\r
1681                 xTicks = xTickCount;\r
1682         }\r
1683         taskEXIT_CRITICAL();\r
1684 \r
1685         return xTicks;\r
1686 }\r
1687 /*-----------------------------------------------------------*/\r
1688 \r
1689 TickType_t xTaskGetTickCountFromISR( void )\r
1690 {\r
1691 TickType_t xReturn;\r
1692 UBaseType_t uxSavedInterruptStatus;\r
1693 \r
1694         /* RTOS ports that support interrupt nesting have the concept of a maximum\r
1695         system call (or maximum API call) interrupt priority.  Interrupts that are\r
1696         above the maximum system call priority are kept permanently enabled, even\r
1697         when the RTOS kernel is in a critical section, but cannot make any calls to\r
1698         FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h\r
1699         then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
1700         failure if a FreeRTOS API function is called from an interrupt that has been\r
1701         assigned a priority above the configured maximum system call priority.\r
1702         Only FreeRTOS functions that end in FromISR can be called from interrupts\r
1703         that have been assigned a priority at or (logically) below the maximum\r
1704         system call     interrupt priority.  FreeRTOS maintains a separate interrupt\r
1705         safe API to ensure interrupt entry is as fast and as simple as possible.\r
1706         More information (albeit Cortex-M specific) is provided on the following\r
1707         link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
1708         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
1709 \r
1710         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
1711         {\r
1712                 xReturn = xTickCount;\r
1713         }\r
1714         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
1715 \r
1716         return xReturn;\r
1717 }\r
1718 /*-----------------------------------------------------------*/\r
1719 \r
1720 UBaseType_t uxTaskGetNumberOfTasks( void )\r
1721 {\r
1722         /* A critical section is not required because the variables are of type\r
1723         BaseType_t. */\r
1724         return uxCurrentNumberOfTasks;\r
1725 }\r
1726 /*-----------------------------------------------------------*/\r
1727 \r
1728 #if ( INCLUDE_pcTaskGetTaskName == 1 )\r
1729 \r
1730         char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery )\r
1731         {\r
1732         TCB_t *pxTCB;\r
1733 \r
1734                 /* If null is passed in here then the name of the calling task is being queried. */\r
1735                 pxTCB = prvGetTCBFromHandle( xTaskToQuery );\r
1736                 configASSERT( pxTCB );\r
1737                 return &( pxTCB->pcTaskName[ 0 ] );\r
1738         }\r
1739 \r
1740 #endif /* INCLUDE_pcTaskGetTaskName */\r
1741 /*-----------------------------------------------------------*/\r
1742 \r
1743 #if ( configUSE_TRACE_FACILITY == 1 )\r
1744 \r
1745         UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime )\r
1746         {\r
1747         UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;\r
1748 \r
1749                 vTaskSuspendAll();\r
1750                 {\r
1751                         /* Is there a space in the array for each task in the system? */\r
1752                         if( uxArraySize >= uxCurrentNumberOfTasks )\r
1753                         {\r
1754                                 /* Fill in an TaskStatus_t structure with information on each\r
1755                                 task in the Ready state. */\r
1756                                 do\r
1757                                 {\r
1758                                         uxQueue--;\r
1759                                         uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );\r
1760 \r
1761                                 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
1762 \r
1763                                 /* Fill in an TaskStatus_t structure with information on each\r
1764                                 task in the Blocked state. */\r
1765                                 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );\r
1766                                 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );\r
1767 \r
1768                                 #if( INCLUDE_vTaskDelete == 1 )\r
1769                                 {\r
1770                                         /* Fill in an TaskStatus_t structure with information on\r
1771                                         each task that has been deleted but not yet cleaned up. */\r
1772                                         uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );\r
1773                                 }\r
1774                                 #endif\r
1775 \r
1776                                 #if ( INCLUDE_vTaskSuspend == 1 )\r
1777                                 {\r
1778                                         /* Fill in an TaskStatus_t structure with information on\r
1779                                         each task in the Suspended state. */\r
1780                                         uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );\r
1781                                 }\r
1782                                 #endif\r
1783 \r
1784                                 #if ( configGENERATE_RUN_TIME_STATS == 1)\r
1785                                 {\r
1786                                         if( pulTotalRunTime != NULL )\r
1787                                         {\r
1788                                                 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE\r
1789                                                         portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );\r
1790                                                 #else\r
1791                                                         *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();\r
1792                                                 #endif\r
1793                                         }\r
1794                                 }\r
1795                                 #else\r
1796                                 {\r
1797                                         if( pulTotalRunTime != NULL )\r
1798                                         {\r
1799                                                 *pulTotalRunTime = 0;\r
1800                                         }\r
1801                                 }\r
1802                                 #endif\r
1803                         }\r
1804                         else\r
1805                         {\r
1806                                 mtCOVERAGE_TEST_MARKER();\r
1807                         }\r
1808                 }\r
1809                 ( void ) xTaskResumeAll();\r
1810 \r
1811                 return uxTask;\r
1812         }\r
1813 \r
1814 #endif /* configUSE_TRACE_FACILITY */\r
1815 /*----------------------------------------------------------*/\r
1816 \r
1817 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )\r
1818 \r
1819         TaskHandle_t xTaskGetIdleTaskHandle( void )\r
1820         {\r
1821                 /* If xTaskGetIdleTaskHandle() is called before the scheduler has been\r
1822                 started, then xIdleTaskHandle will be NULL. */\r
1823                 configASSERT( ( xIdleTaskHandle != NULL ) );\r
1824                 return xIdleTaskHandle;\r
1825         }\r
1826 \r
1827 #endif /* INCLUDE_xTaskGetIdleTaskHandle */\r
1828 /*----------------------------------------------------------*/\r
1829 \r
1830 /* This conditional compilation should use inequality to 0, not equality to 1.\r
1831 This is to ensure vTaskStepTick() is available when user defined low power mode\r
1832 implementations require configUSE_TICKLESS_IDLE to be set to a value other than\r
1833 1. */\r
1834 #if ( configUSE_TICKLESS_IDLE != 0 )\r
1835 \r
1836         void vTaskStepTick( const TickType_t xTicksToJump )\r
1837         {\r
1838                 /* Correct the tick count value after a period during which the tick\r
1839                 was suppressed.  Note this does *not* call the tick hook function for\r
1840                 each stepped tick. */\r
1841                 configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );\r
1842                 xTickCount += xTicksToJump;\r
1843                 traceINCREASE_TICK_COUNT( xTicksToJump );\r
1844         }\r
1845 \r
1846 #endif /* configUSE_TICKLESS_IDLE */\r
1847 /*----------------------------------------------------------*/\r
1848 \r
1849 BaseType_t xTaskIncrementTick( void )\r
1850 {\r
1851 TCB_t * pxTCB;\r
1852 TickType_t xItemValue;\r
1853 BaseType_t xSwitchRequired = pdFALSE;\r
1854 \r
1855         /* Called by the portable layer each time a tick interrupt occurs.\r
1856         Increments the tick then checks to see if the new tick value will cause any\r
1857         tasks to be unblocked. */\r
1858         traceTASK_INCREMENT_TICK( xTickCount );\r
1859         if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )\r
1860         {\r
1861                 /* Increment the RTOS tick, switching the delayed and overflowed\r
1862                 delayed lists if it wraps to 0. */\r
1863                 ++xTickCount;\r
1864 \r
1865                 {\r
1866                         /* Minor optimisation.  The tick count cannot change in this\r
1867                         block. */\r
1868                         const TickType_t xConstTickCount = xTickCount;\r
1869 \r
1870                         if( xConstTickCount == ( TickType_t ) 0U )\r
1871                         {\r
1872                                 taskSWITCH_DELAYED_LISTS();\r
1873                         }\r
1874                         else\r
1875                         {\r
1876                                 mtCOVERAGE_TEST_MARKER();\r
1877                         }\r
1878 \r
1879                         /* See if this tick has made a timeout expire.  Tasks are stored in\r
1880                         the     queue in the order of their wake time - meaning once one task\r
1881                         has been found whose block time has not expired there is no need to\r
1882                         look any further        down the list. */\r
1883                         if( xConstTickCount >= xNextTaskUnblockTime )\r
1884                         {\r
1885                                 for( ;; )\r
1886                                 {\r
1887                                         if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )\r
1888                                         {\r
1889                                                 /* The delayed list is empty.  Set xNextTaskUnblockTime\r
1890                                                 to the maximum possible value so it is extremely\r
1891                                                 unlikely that the\r
1892                                                 if( xTickCount >= xNextTaskUnblockTime ) test will pass\r
1893                                                 next time through. */\r
1894                                                 xNextTaskUnblockTime = portMAX_DELAY;\r
1895                                                 break;\r
1896                                         }\r
1897                                         else\r
1898                                         {\r
1899                                                 /* The delayed list is not empty, get the value of the\r
1900                                                 item at the head of the delayed list.  This is the time\r
1901                                                 at which the task at the head of the delayed list must\r
1902                                                 be removed from the Blocked state. */\r
1903                                                 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );\r
1904                                                 xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );\r
1905 \r
1906                                                 if( xConstTickCount < xItemValue )\r
1907                                                 {\r
1908                                                         /* It is not time to unblock this item yet, but the\r
1909                                                         item value is the time at which the task at the head\r
1910                                                         of the blocked list must be removed from the Blocked\r
1911                                                         state - so record the item value in\r
1912                                                         xNextTaskUnblockTime. */\r
1913                                                         xNextTaskUnblockTime = xItemValue;\r
1914                                                         break;\r
1915                                                 }\r
1916                                                 else\r
1917                                                 {\r
1918                                                         mtCOVERAGE_TEST_MARKER();\r
1919                                                 }\r
1920 \r
1921                                                 /* It is time to remove the item from the Blocked state. */\r
1922                                                 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );\r
1923 \r
1924                                                 /* Is the task waiting on an event also?  If so remove\r
1925                                                 it from the event list. */\r
1926                                                 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )\r
1927                                                 {\r
1928                                                         ( void ) uxListRemove( &( pxTCB->xEventListItem ) );\r
1929                                                 }\r
1930                                                 else\r
1931                                                 {\r
1932                                                         mtCOVERAGE_TEST_MARKER();\r
1933                                                 }\r
1934 \r
1935                                                 /* Place the unblocked task into the appropriate ready\r
1936                                                 list. */\r
1937                                                 prvAddTaskToReadyList( pxTCB );\r
1938 \r
1939                                                 /* A task being unblocked cannot cause an immediate\r
1940                                                 context switch if preemption is turned off. */\r
1941                                                 #if (  configUSE_PREEMPTION == 1 )\r
1942                                                 {\r
1943                                                         /* Preemption is on, but a context switch should\r
1944                                                         only be performed if the unblocked task has a\r
1945                                                         priority that is equal to or higher than the\r
1946                                                         currently executing task. */\r
1947                                                         if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )\r
1948                                                         {\r
1949                                                                 xSwitchRequired = pdTRUE;\r
1950                                                         }\r
1951                                                         else\r
1952                                                         {\r
1953                                                                 mtCOVERAGE_TEST_MARKER();\r
1954                                                         }\r
1955                                                 }\r
1956                                                 #endif /* configUSE_PREEMPTION */\r
1957                                         }\r
1958                                 }\r
1959                         }\r
1960                 }\r
1961 \r
1962                 /* Tasks of equal priority to the currently running task will share\r
1963                 processing time (time slice) if preemption is on, and the application\r
1964                 writer has not explicitly turned time slicing off. */\r
1965                 #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )\r
1966                 {\r
1967                         if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )\r
1968                         {\r
1969                                 xSwitchRequired = pdTRUE;\r
1970                         }\r
1971                         else\r
1972                         {\r
1973                                 mtCOVERAGE_TEST_MARKER();\r
1974                         }\r
1975                 }\r
1976                 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */\r
1977 \r
1978                 #if ( configUSE_TICK_HOOK == 1 )\r
1979                 {\r
1980                         /* Guard against the tick hook being called when the pended tick\r
1981                         count is being unwound (when the scheduler is being unlocked). */\r
1982                         if( uxPendedTicks == ( UBaseType_t ) 0U )\r
1983                         {\r
1984                                 vApplicationTickHook();\r
1985                         }\r
1986                         else\r
1987                         {\r
1988                                 mtCOVERAGE_TEST_MARKER();\r
1989                         }\r
1990                 }\r
1991                 #endif /* configUSE_TICK_HOOK */\r
1992         }\r
1993         else\r
1994         {\r
1995                 ++uxPendedTicks;\r
1996 \r
1997                 /* The tick hook gets called at regular intervals, even if the\r
1998                 scheduler is locked. */\r
1999                 #if ( configUSE_TICK_HOOK == 1 )\r
2000                 {\r
2001                         vApplicationTickHook();\r
2002                 }\r
2003                 #endif\r
2004         }\r
2005 \r
2006         #if ( configUSE_PREEMPTION == 1 )\r
2007         {\r
2008                 if( xYieldPending != pdFALSE )\r
2009                 {\r
2010                         xSwitchRequired = pdTRUE;\r
2011                 }\r
2012                 else\r
2013                 {\r
2014                         mtCOVERAGE_TEST_MARKER();\r
2015                 }\r
2016         }\r
2017         #endif /* configUSE_PREEMPTION */\r
2018 \r
2019         return xSwitchRequired;\r
2020 }\r
2021 /*-----------------------------------------------------------*/\r
2022 \r
2023 #if ( configUSE_APPLICATION_TASK_TAG == 1 )\r
2024 \r
2025         void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction )\r
2026         {\r
2027         TCB_t *xTCB;\r
2028 \r
2029                 /* If xTask is NULL then it is the task hook of the calling task that is\r
2030                 getting set. */\r
2031                 if( xTask == NULL )\r
2032                 {\r
2033                         xTCB = ( TCB_t * ) pxCurrentTCB;\r
2034                 }\r
2035                 else\r
2036                 {\r
2037                         xTCB = ( TCB_t * ) xTask;\r
2038                 }\r
2039 \r
2040                 /* Save the hook function in the TCB.  A critical section is required as\r
2041                 the value can be accessed from an interrupt. */\r
2042                 taskENTER_CRITICAL();\r
2043                         xTCB->pxTaskTag = pxHookFunction;\r
2044                 taskEXIT_CRITICAL();\r
2045         }\r
2046 \r
2047 #endif /* configUSE_APPLICATION_TASK_TAG */\r
2048 /*-----------------------------------------------------------*/\r
2049 \r
2050 #if ( configUSE_APPLICATION_TASK_TAG == 1 )\r
2051 \r
2052         TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )\r
2053         {\r
2054         TCB_t *xTCB;\r
2055         TaskHookFunction_t xReturn;\r
2056 \r
2057                 /* If xTask is NULL then we are setting our own task hook. */\r
2058                 if( xTask == NULL )\r
2059                 {\r
2060                         xTCB = ( TCB_t * ) pxCurrentTCB;\r
2061                 }\r
2062                 else\r
2063                 {\r
2064                         xTCB = ( TCB_t * ) xTask;\r
2065                 }\r
2066 \r
2067                 /* Save the hook function in the TCB.  A critical section is required as\r
2068                 the value can be accessed from an interrupt. */\r
2069                 taskENTER_CRITICAL();\r
2070                 {\r
2071                         xReturn = xTCB->pxTaskTag;\r
2072                 }\r
2073                 taskEXIT_CRITICAL();\r
2074 \r
2075                 return xReturn;\r
2076         }\r
2077 \r
2078 #endif /* configUSE_APPLICATION_TASK_TAG */\r
2079 /*-----------------------------------------------------------*/\r
2080 \r
2081 #if ( configUSE_APPLICATION_TASK_TAG == 1 )\r
2082 \r
2083         BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter )\r
2084         {\r
2085         TCB_t *xTCB;\r
2086         BaseType_t xReturn;\r
2087 \r
2088                 /* If xTask is NULL then we are calling our own task hook. */\r
2089                 if( xTask == NULL )\r
2090                 {\r
2091                         xTCB = ( TCB_t * ) pxCurrentTCB;\r
2092                 }\r
2093                 else\r
2094                 {\r
2095                         xTCB = ( TCB_t * ) xTask;\r
2096                 }\r
2097 \r
2098                 if( xTCB->pxTaskTag != NULL )\r
2099                 {\r
2100                         xReturn = xTCB->pxTaskTag( pvParameter );\r
2101                 }\r
2102                 else\r
2103                 {\r
2104                         xReturn = pdFAIL;\r
2105                 }\r
2106 \r
2107                 return xReturn;\r
2108         }\r
2109 \r
2110 #endif /* configUSE_APPLICATION_TASK_TAG */\r
2111 /*-----------------------------------------------------------*/\r
2112 \r
2113 void vTaskSwitchContext( void )\r
2114 {\r
2115         if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )\r
2116         {\r
2117                 /* The scheduler is currently suspended - do not allow a context\r
2118                 switch. */\r
2119                 xYieldPending = pdTRUE;\r
2120         }\r
2121         else\r
2122         {\r
2123                 xYieldPending = pdFALSE;\r
2124                 traceTASK_SWITCHED_OUT();\r
2125 \r
2126                 #if ( configGENERATE_RUN_TIME_STATS == 1 )\r
2127                 {\r
2128                                 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE\r
2129                                         portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );\r
2130                                 #else\r
2131                                         ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();\r
2132                                 #endif\r
2133 \r
2134                                 /* Add the amount of time the task has been running to the\r
2135                                 accumulated     time so far.  The time the task started running was\r
2136                                 stored in ulTaskSwitchedInTime.  Note that there is no overflow\r
2137                                 protection here so count values are only valid until the timer\r
2138                                 overflows.  The guard against negative values is to protect\r
2139                                 against suspect run time stat counter implementations - which\r
2140                                 are provided by the application, not the kernel. */\r
2141                                 if( ulTotalRunTime > ulTaskSwitchedInTime )\r
2142                                 {\r
2143                                         pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );\r
2144                                 }\r
2145                                 else\r
2146                                 {\r
2147                                         mtCOVERAGE_TEST_MARKER();\r
2148                                 }\r
2149                                 ulTaskSwitchedInTime = ulTotalRunTime;\r
2150                 }\r
2151                 #endif /* configGENERATE_RUN_TIME_STATS */\r
2152 \r
2153                 taskFIRST_CHECK_FOR_STACK_OVERFLOW();\r
2154                 taskSECOND_CHECK_FOR_STACK_OVERFLOW();\r
2155 \r
2156                 taskSELECT_HIGHEST_PRIORITY_TASK();\r
2157 \r
2158                 traceTASK_SWITCHED_IN();\r
2159 \r
2160                 #if ( configUSE_NEWLIB_REENTRANT == 1 )\r
2161                 {\r
2162                         /* Switch Newlib's _impure_ptr variable to point to the _reent\r
2163                         structure specific to this task. */\r
2164                         _impure_ptr = &( pxCurrentTCB->xNewLib_reent );\r
2165                 }\r
2166                 #endif /* configUSE_NEWLIB_REENTRANT */\r
2167         }\r
2168 }\r
2169 /*-----------------------------------------------------------*/\r
2170 \r
2171 void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )\r
2172 {\r
2173 TickType_t xTimeToWake;\r
2174 \r
2175         configASSERT( pxEventList );\r
2176 \r
2177         /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE\r
2178         SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */\r
2179 \r
2180         /* Place the event list item of the TCB in the appropriate event list.\r
2181         This is placed in the list in priority order so the highest priority task\r
2182         is the first to be woken by the event.  The queue that contains the event\r
2183         list is locked, preventing simultaneous access from interrupts. */\r
2184         vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );\r
2185 \r
2186         /* The task must be removed from from the ready list before it is added to\r
2187         the blocked list as the same list item is used for both lists.  Exclusive\r
2188         access to the ready lists guaranteed because the scheduler is locked. */\r
2189         if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )\r
2190         {\r
2191                 /* The current task must be in a ready list, so there is no need to\r
2192                 check, and the port reset macro can be called directly. */\r
2193                 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );\r
2194         }\r
2195         else\r
2196         {\r
2197                 mtCOVERAGE_TEST_MARKER();\r
2198         }\r
2199 \r
2200         #if ( INCLUDE_vTaskSuspend == 1 )\r
2201         {\r
2202                 if( xTicksToWait == portMAX_DELAY )\r
2203                 {\r
2204                         /* Add the task to the suspended task list instead of a delayed task\r
2205                         list to ensure the task is not woken by a timing event.  It will\r
2206                         block indefinitely. */\r
2207                         vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );\r
2208                 }\r
2209                 else\r
2210                 {\r
2211                         /* Calculate the time at which the task should be woken if the event\r
2212                         does not occur.  This may overflow but this doesn't matter, the\r
2213                         scheduler will handle it. */\r
2214                         xTimeToWake = xTickCount + xTicksToWait;\r
2215                         prvAddCurrentTaskToDelayedList( xTimeToWake );\r
2216                 }\r
2217         }\r
2218         #else /* INCLUDE_vTaskSuspend */\r
2219         {\r
2220                         /* Calculate the time at which the task should be woken if the event does\r
2221                         not occur.  This may overflow but this doesn't matter, the scheduler\r
2222                         will handle it. */\r
2223                         xTimeToWake = xTickCount + xTicksToWait;\r
2224                         prvAddCurrentTaskToDelayedList( xTimeToWake );\r
2225         }\r
2226         #endif /* INCLUDE_vTaskSuspend */\r
2227 }\r
2228 /*-----------------------------------------------------------*/\r
2229 \r
2230 void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait )\r
2231 {\r
2232 TickType_t xTimeToWake;\r
2233 \r
2234         configASSERT( pxEventList );\r
2235 \r
2236         /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by\r
2237         the event groups implementation. */\r
2238         configASSERT( uxSchedulerSuspended != 0 );\r
2239 \r
2240         /* Store the item value in the event list item.  It is safe to access the\r
2241         event list item here as interrupts won't access the event list item of a\r
2242         task that is not in the Blocked state. */\r
2243         listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );\r
2244 \r
2245         /* Place the event list item of the TCB at the end of the appropriate event\r
2246         list.  It is safe to access the event list here because it is part of an\r
2247         event group implementation - and interrupts don't access event groups\r
2248         directly (instead they access them indirectly by pending function calls to\r
2249         the task level). */\r
2250         vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );\r
2251 \r
2252         /* The task must be removed from the ready list before it is added to the\r
2253         blocked list.  Exclusive access can be assured to the ready list as the\r
2254         scheduler is locked. */\r
2255         if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )\r
2256         {\r
2257                 /* The current task must be in a ready list, so there is no need to\r
2258                 check, and the port reset macro can be called directly. */\r
2259                 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );\r
2260         }\r
2261         else\r
2262         {\r
2263                 mtCOVERAGE_TEST_MARKER();\r
2264         }\r
2265 \r
2266         #if ( INCLUDE_vTaskSuspend == 1 )\r
2267         {\r
2268                 if( xTicksToWait == portMAX_DELAY )\r
2269                 {\r
2270                         /* Add the task to the suspended task list instead of a delayed task\r
2271                         list to ensure it is not woken by a timing event.  It will block\r
2272                         indefinitely. */\r
2273                         vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );\r
2274                 }\r
2275                 else\r
2276                 {\r
2277                         /* Calculate the time at which the task should be woken if the event\r
2278                         does not occur.  This may overflow but this doesn't matter, the\r
2279                         kernel will manage it correctly. */\r
2280                         xTimeToWake = xTickCount + xTicksToWait;\r
2281                         prvAddCurrentTaskToDelayedList( xTimeToWake );\r
2282                 }\r
2283         }\r
2284         #else /* INCLUDE_vTaskSuspend */\r
2285         {\r
2286                         /* Calculate the time at which the task should be woken if the event does\r
2287                         not occur.  This may overflow but this doesn't matter, the kernel\r
2288                         will manage it correctly. */\r
2289                         xTimeToWake = xTickCount + xTicksToWait;\r
2290                         prvAddCurrentTaskToDelayedList( xTimeToWake );\r
2291         }\r
2292         #endif /* INCLUDE_vTaskSuspend */\r
2293 }\r
2294 /*-----------------------------------------------------------*/\r
2295 \r
2296 #if configUSE_TIMERS == 1\r
2297 \r
2298         void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait )\r
2299         {\r
2300         TickType_t xTimeToWake;\r
2301 \r
2302                 configASSERT( pxEventList );\r
2303 \r
2304                 /* This function should not be called by application code hence the\r
2305                 'Restricted' in its name.  It is not part of the public API.  It is\r
2306                 designed for use by kernel code, and has special calling requirements -\r
2307                 it should be called from a critical section. */\r
2308 \r
2309 \r
2310                 /* Place the event list item of the TCB in the appropriate event list.\r
2311                 In this case it is assume that this is the only task that is going to\r
2312                 be waiting on this event list, so the faster vListInsertEnd() function\r
2313                 can be used in place of vListInsert. */\r
2314                 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );\r
2315 \r
2316                 /* We must remove this task from the ready list before adding it to the\r
2317                 blocked list as the same list item is used for both lists.  This\r
2318                 function is called form a critical section. */\r
2319                 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )\r
2320                 {\r
2321                         /* The current task must be in a ready list, so there is no need to\r
2322                         check, and the port reset macro can be called directly. */\r
2323                         portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );\r
2324                 }\r
2325                 else\r
2326                 {\r
2327                         mtCOVERAGE_TEST_MARKER();\r
2328                 }\r
2329 \r
2330                 /* Calculate the time at which the task should be woken if the event does\r
2331                 not occur.  This may overflow but this doesn't matter. */\r
2332                 xTimeToWake = xTickCount + xTicksToWait;\r
2333 \r
2334                 traceTASK_DELAY_UNTIL();\r
2335                 prvAddCurrentTaskToDelayedList( xTimeToWake );\r
2336         }\r
2337 \r
2338 #endif /* configUSE_TIMERS */\r
2339 /*-----------------------------------------------------------*/\r
2340 \r
2341 BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )\r
2342 {\r
2343 TCB_t *pxUnblockedTCB;\r
2344 BaseType_t xReturn;\r
2345 \r
2346         /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION.  It can also be\r
2347         called from a critical section within an ISR. */\r
2348 \r
2349         /* The event list is sorted in priority order, so the first in the list can\r
2350         be removed as it is known to be the highest priority.  Remove the TCB from\r
2351         the delayed list, and add it to the ready list.\r
2352 \r
2353         If an event is for a queue that is locked then this function will never\r
2354         get called - the lock count on the queue will get modified instead.  This\r
2355         means exclusive access to the event list is guaranteed here.\r
2356 \r
2357         This function assumes that a check has already been made to ensure that\r
2358         pxEventList is not empty. */\r
2359         pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );\r
2360         configASSERT( pxUnblockedTCB );\r
2361         ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );\r
2362 \r
2363         if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )\r
2364         {\r
2365                 ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );\r
2366                 prvAddTaskToReadyList( pxUnblockedTCB );\r
2367         }\r
2368         else\r
2369         {\r
2370                 /* The delayed and ready lists cannot be accessed, so hold this task\r
2371                 pending until the scheduler is resumed. */\r
2372                 vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );\r
2373         }\r
2374 \r
2375         if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )\r
2376         {\r
2377                 /* Return true if the task removed from the event list has a higher\r
2378                 priority than the calling task.  This allows the calling task to know if\r
2379                 it should force a context switch now. */\r
2380                 xReturn = pdTRUE;\r
2381 \r
2382                 /* Mark that a yield is pending in case the user is not using the\r
2383                 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */\r
2384                 xYieldPending = pdTRUE;\r
2385         }\r
2386         else\r
2387         {\r
2388                 xReturn = pdFALSE;\r
2389         }\r
2390 \r
2391         return xReturn;\r
2392 }\r
2393 /*-----------------------------------------------------------*/\r
2394 \r
2395 BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )\r
2396 {\r
2397 TCB_t *pxUnblockedTCB;\r
2398 BaseType_t xReturn;\r
2399 \r
2400         /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by\r
2401         the event flags implementation. */\r
2402         configASSERT( uxSchedulerSuspended != pdFALSE );\r
2403 \r
2404         /* Store the new item value in the event list. */\r
2405         listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );\r
2406 \r
2407         /* Remove the event list form the event flag.  Interrupts do not access\r
2408         event flags. */\r
2409         pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem );\r
2410         configASSERT( pxUnblockedTCB );\r
2411         ( void ) uxListRemove( pxEventListItem );\r
2412 \r
2413         /* Remove the task from the delayed list and add it to the ready list.  The\r
2414         scheduler is suspended so interrupts will not be accessing the ready\r
2415         lists. */\r
2416         ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );\r
2417         prvAddTaskToReadyList( pxUnblockedTCB );\r
2418 \r
2419         if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )\r
2420         {\r
2421                 /* Return true if the task removed from the event list has\r
2422                 a higher priority than the calling task.  This allows\r
2423                 the calling task to know if it should force a context\r
2424                 switch now. */\r
2425                 xReturn = pdTRUE;\r
2426 \r
2427                 /* Mark that a yield is pending in case the user is not using the\r
2428                 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */\r
2429                 xYieldPending = pdTRUE;\r
2430         }\r
2431         else\r
2432         {\r
2433                 xReturn = pdFALSE;\r
2434         }\r
2435 \r
2436         return xReturn;\r
2437 }\r
2438 /*-----------------------------------------------------------*/\r
2439 \r
2440 void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )\r
2441 {\r
2442         configASSERT( pxTimeOut );\r
2443         pxTimeOut->xOverflowCount = xNumOfOverflows;\r
2444         pxTimeOut->xTimeOnEntering = xTickCount;\r
2445 }\r
2446 /*-----------------------------------------------------------*/\r
2447 \r
2448 BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait )\r
2449 {\r
2450 BaseType_t xReturn;\r
2451 \r
2452         configASSERT( pxTimeOut );\r
2453         configASSERT( pxTicksToWait );\r
2454 \r
2455         taskENTER_CRITICAL();\r
2456         {\r
2457                 /* Minor optimisation.  The tick count cannot change in this block. */\r
2458                 const TickType_t xConstTickCount = xTickCount;\r
2459 \r
2460                 #if ( INCLUDE_vTaskSuspend == 1 )\r
2461                         /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is\r
2462                         the maximum block time then the task should block indefinitely, and\r
2463                         therefore never time out. */\r
2464                         if( *pxTicksToWait == portMAX_DELAY )\r
2465                         {\r
2466                                 xReturn = pdFALSE;\r
2467                         }\r
2468                         else /* We are not blocking indefinitely, perform the checks below. */\r
2469                 #endif\r
2470 \r
2471                 if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */\r
2472                 {\r
2473                         /* The tick count is greater than the time at which vTaskSetTimeout()\r
2474                         was called, but has also overflowed since vTaskSetTimeOut() was called.\r
2475                         It must have wrapped all the way around and gone past us again. This\r
2476                         passed since vTaskSetTimeout() was called. */\r
2477                         xReturn = pdTRUE;\r
2478                 }\r
2479                 else if( ( xConstTickCount - pxTimeOut->xTimeOnEntering ) < *pxTicksToWait )\r
2480                 {\r
2481                         /* Not a genuine timeout. Adjust parameters for time remaining. */\r
2482                         *pxTicksToWait -= ( xConstTickCount -  pxTimeOut->xTimeOnEntering );\r
2483                         vTaskSetTimeOutState( pxTimeOut );\r
2484                         xReturn = pdFALSE;\r
2485                 }\r
2486                 else\r
2487                 {\r
2488                         xReturn = pdTRUE;\r
2489                 }\r
2490         }\r
2491         taskEXIT_CRITICAL();\r
2492 \r
2493         return xReturn;\r
2494 }\r
2495 /*-----------------------------------------------------------*/\r
2496 \r
2497 void vTaskMissedYield( void )\r
2498 {\r
2499         xYieldPending = pdTRUE;\r
2500 }\r
2501 /*-----------------------------------------------------------*/\r
2502 \r
2503 #if ( configUSE_TRACE_FACILITY == 1 )\r
2504 \r
2505         UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )\r
2506         {\r
2507         UBaseType_t uxReturn;\r
2508         TCB_t *pxTCB;\r
2509 \r
2510                 if( xTask != NULL )\r
2511                 {\r
2512                         pxTCB = ( TCB_t * ) xTask;\r
2513                         uxReturn = pxTCB->uxTaskNumber;\r
2514                 }\r
2515                 else\r
2516                 {\r
2517                         uxReturn = 0U;\r
2518                 }\r
2519 \r
2520                 return uxReturn;\r
2521         }\r
2522 \r
2523 #endif /* configUSE_TRACE_FACILITY */\r
2524 /*-----------------------------------------------------------*/\r
2525 \r
2526 #if ( configUSE_TRACE_FACILITY == 1 )\r
2527 \r
2528         void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle )\r
2529         {\r
2530         TCB_t *pxTCB;\r
2531 \r
2532                 if( xTask != NULL )\r
2533                 {\r
2534                         pxTCB = ( TCB_t * ) xTask;\r
2535                         pxTCB->uxTaskNumber = uxHandle;\r
2536                 }\r
2537         }\r
2538 \r
2539 #endif /* configUSE_TRACE_FACILITY */\r
2540 \r
2541 /*\r
2542  * -----------------------------------------------------------\r
2543  * The Idle task.\r
2544  * ----------------------------------------------------------\r
2545  *\r
2546  * The portTASK_FUNCTION() macro is used to allow port/compiler specific\r
2547  * language extensions.  The equivalent prototype for this function is:\r
2548  *\r
2549  * void prvIdleTask( void *pvParameters );\r
2550  *\r
2551  */\r
2552 static portTASK_FUNCTION( prvIdleTask, pvParameters )\r
2553 {\r
2554         /* Stop warnings. */\r
2555         ( void ) pvParameters;\r
2556 \r
2557         for( ;; )\r
2558         {\r
2559                 /* See if any tasks have been deleted. */\r
2560                 prvCheckTasksWaitingTermination();\r
2561 \r
2562                 #if ( configUSE_PREEMPTION == 0 )\r
2563                 {\r
2564                         /* If we are not using preemption we keep forcing a task switch to\r
2565                         see if any other task has become available.  If we are using\r
2566                         preemption we don't need to do this as any task becoming available\r
2567                         will automatically get the processor anyway. */\r
2568                         taskYIELD();\r
2569                 }\r
2570                 #endif /* configUSE_PREEMPTION */\r
2571 \r
2572                 #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )\r
2573                 {\r
2574                         /* When using preemption tasks of equal priority will be\r
2575                         timesliced.  If a task that is sharing the idle priority is ready\r
2576                         to run then the idle task should yield before the end of the\r
2577                         timeslice.\r
2578 \r
2579                         A critical region is not required here as we are just reading from\r
2580                         the list, and an occasional incorrect value will not matter.  If\r
2581                         the ready list at the idle priority contains more than one task\r
2582                         then a task other than the idle task is ready to execute. */\r
2583                         if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )\r
2584                         {\r
2585                                 taskYIELD();\r
2586                         }\r
2587                         else\r
2588                         {\r
2589                                 mtCOVERAGE_TEST_MARKER();\r
2590                         }\r
2591                 }\r
2592                 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */\r
2593 \r
2594                 #if ( configUSE_IDLE_HOOK == 1 )\r
2595                 {\r
2596                         extern void vApplicationIdleHook( void );\r
2597 \r
2598                         /* Call the user defined function from within the idle task.  This\r
2599                         allows the application designer to add background functionality\r
2600                         without the overhead of a separate task.\r
2601                         NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,\r
2602                         CALL A FUNCTION THAT MIGHT BLOCK. */\r
2603                         vApplicationIdleHook();\r
2604                 }\r
2605                 #endif /* configUSE_IDLE_HOOK */\r
2606 \r
2607                 /* This conditional compilation should use inequality to 0, not equality\r
2608                 to 1.  This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when\r
2609                 user defined low power mode     implementations require\r
2610                 configUSE_TICKLESS_IDLE to be set to a value other than 1. */\r
2611                 #if ( configUSE_TICKLESS_IDLE != 0 )\r
2612                 {\r
2613                 TickType_t xExpectedIdleTime;\r
2614 \r
2615                         /* It is not desirable to suspend then resume the scheduler on\r
2616                         each iteration of the idle task.  Therefore, a preliminary\r
2617                         test of the expected idle time is performed without the\r
2618                         scheduler suspended.  The result here is not necessarily\r
2619                         valid. */\r
2620                         xExpectedIdleTime = prvGetExpectedIdleTime();\r
2621 \r
2622                         if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )\r
2623                         {\r
2624                                 vTaskSuspendAll();\r
2625                                 {\r
2626                                         /* Now the scheduler is suspended, the expected idle\r
2627                                         time can be sampled again, and this time its value can\r
2628                                         be used. */\r
2629                                         configASSERT( xNextTaskUnblockTime >= xTickCount );\r
2630                                         xExpectedIdleTime = prvGetExpectedIdleTime();\r
2631 \r
2632                                         if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )\r
2633                                         {\r
2634                                                 traceLOW_POWER_IDLE_BEGIN();\r
2635                                                 portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );\r
2636                                                 traceLOW_POWER_IDLE_END();\r
2637                                         }\r
2638                                         else\r
2639                                         {\r
2640                                                 mtCOVERAGE_TEST_MARKER();\r
2641                                         }\r
2642                                 }\r
2643                                 ( void ) xTaskResumeAll();\r
2644                         }\r
2645                         else\r
2646                         {\r
2647                                 mtCOVERAGE_TEST_MARKER();\r
2648                         }\r
2649                 }\r
2650                 #endif /* configUSE_TICKLESS_IDLE */\r
2651         }\r
2652 }\r
2653 /*-----------------------------------------------------------*/\r
2654 \r
2655 #if configUSE_TICKLESS_IDLE != 0\r
2656 \r
2657         eSleepModeStatus eTaskConfirmSleepModeStatus( void )\r
2658         {\r
2659         eSleepModeStatus eReturn = eStandardSleep;\r
2660 \r
2661                 if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )\r
2662                 {\r
2663                         /* A task was made ready while the scheduler was suspended. */\r
2664                         eReturn = eAbortSleep;\r
2665                 }\r
2666                 else if( xYieldPending != pdFALSE )\r
2667                 {\r
2668                         /* A yield was pended while the scheduler was suspended. */\r
2669                         eReturn = eAbortSleep;\r
2670                 }\r
2671                 else\r
2672                 {\r
2673                         #if configUSE_TIMERS == 0\r
2674                         {\r
2675                                 /* The idle task exists in addition to the application tasks. */\r
2676                                 const UBaseType_t uxNonApplicationTasks = 1;\r
2677 \r
2678                                 /* If timers are not being used and all the tasks are in the\r
2679                                 suspended list (which might mean they have an infinite block\r
2680                                 time rather than actually being suspended) then it is safe to\r
2681                                 turn all clocks off and just wait for external interrupts. */\r
2682                                 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )\r
2683                                 {\r
2684                                         eReturn = eNoTasksWaitingTimeout;\r
2685                                 }\r
2686                                 else\r
2687                                 {\r
2688                                         mtCOVERAGE_TEST_MARKER();\r
2689                                 }\r
2690                         }\r
2691                         #endif /* configUSE_TIMERS */\r
2692                 }\r
2693 \r
2694                 return eReturn;\r
2695         }\r
2696 #endif /* configUSE_TICKLESS_IDLE */\r
2697 /*-----------------------------------------------------------*/\r
2698 \r
2699 static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
2700 {\r
2701 UBaseType_t x;\r
2702 \r
2703         /* Store the task name in the TCB. */\r
2704         for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )\r
2705         {\r
2706                 pxTCB->pcTaskName[ x ] = pcName[ x ];\r
2707 \r
2708                 /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than\r
2709                 configMAX_TASK_NAME_LEN characters just in case the memory after the\r
2710                 string is not accessible (extremely unlikely). */\r
2711                 if( pcName[ x ] == 0x00 )\r
2712                 {\r
2713                         break;\r
2714                 }\r
2715                 else\r
2716                 {\r
2717                         mtCOVERAGE_TEST_MARKER();\r
2718                 }\r
2719         }\r
2720 \r
2721         /* Ensure the name string is terminated in the case that the string length\r
2722         was greater or equal to configMAX_TASK_NAME_LEN. */\r
2723         pxTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';\r
2724 \r
2725         /* This is used as an array index so must ensure it's not too large.  First\r
2726         remove the privilege bit if one is present. */\r
2727         if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )\r
2728         {\r
2729                 uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;\r
2730         }\r
2731         else\r
2732         {\r
2733                 mtCOVERAGE_TEST_MARKER();\r
2734         }\r
2735 \r
2736         pxTCB->uxPriority = uxPriority;\r
2737         #if ( configUSE_MUTEXES == 1 )\r
2738         {\r
2739                 pxTCB->uxBasePriority = uxPriority;\r
2740         }\r
2741         #endif /* configUSE_MUTEXES */\r
2742 \r
2743         vListInitialiseItem( &( pxTCB->xGenericListItem ) );\r
2744         vListInitialiseItem( &( pxTCB->xEventListItem ) );\r
2745 \r
2746         /* Set the pxTCB as a link back from the ListItem_t.  This is so we can get\r
2747         back to the containing TCB from a generic item in a list. */\r
2748         listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB );\r
2749 \r
2750         /* Event lists are always in priority order. */\r
2751         listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
2752         listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB );\r
2753 \r
2754         #if ( portCRITICAL_NESTING_IN_TCB == 1 )\r
2755         {\r
2756                 pxTCB->uxCriticalNesting = ( UBaseType_t ) 0U;\r
2757         }\r
2758         #endif /* portCRITICAL_NESTING_IN_TCB */\r
2759 \r
2760         #if ( configUSE_APPLICATION_TASK_TAG == 1 )\r
2761         {\r
2762                 pxTCB->pxTaskTag = NULL;\r
2763         }\r
2764         #endif /* configUSE_APPLICATION_TASK_TAG */\r
2765 \r
2766         #if ( configGENERATE_RUN_TIME_STATS == 1 )\r
2767         {\r
2768                 pxTCB->ulRunTimeCounter = 0UL;\r
2769         }\r
2770         #endif /* configGENERATE_RUN_TIME_STATS */\r
2771 \r
2772         #if ( portUSING_MPU_WRAPPERS == 1 )\r
2773         {\r
2774                 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth );\r
2775         }\r
2776         #else /* portUSING_MPU_WRAPPERS */\r
2777         {\r
2778                 ( void ) xRegions;\r
2779                 ( void ) usStackDepth;\r
2780         }\r
2781         #endif /* portUSING_MPU_WRAPPERS */\r
2782 \r
2783         #if ( configUSE_NEWLIB_REENTRANT == 1 )\r
2784         {\r
2785                 /* Initialise this task's Newlib reent structure. */\r
2786                 _REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) );\r
2787         }\r
2788         #endif /* configUSE_NEWLIB_REENTRANT */\r
2789 }\r
2790 /*-----------------------------------------------------------*/\r
2791 \r
2792 #if ( portUSING_MPU_WRAPPERS == 1 )\r
2793 \r
2794         void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions )\r
2795         {\r
2796         TCB_t *pxTCB;\r
2797 \r
2798                 /* If null is passed in here then we are deleting ourselves. */\r
2799                 pxTCB = prvGetTCBFromHandle( xTaskToModify );\r
2800 \r
2801         vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );\r
2802         }\r
2803 \r
2804 #endif /* portUSING_MPU_WRAPPERS */\r
2805 /*-----------------------------------------------------------*/\r
2806 \r
2807 static void prvInitialiseTaskLists( void )\r
2808 {\r
2809 UBaseType_t uxPriority;\r
2810 \r
2811         for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )\r
2812         {\r
2813                 vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );\r
2814         }\r
2815 \r
2816         vListInitialise( &xDelayedTaskList1 );\r
2817         vListInitialise( &xDelayedTaskList2 );\r
2818         vListInitialise( &xPendingReadyList );\r
2819 \r
2820         #if ( INCLUDE_vTaskDelete == 1 )\r
2821         {\r
2822                 vListInitialise( &xTasksWaitingTermination );\r
2823         }\r
2824         #endif /* INCLUDE_vTaskDelete */\r
2825 \r
2826         #if ( INCLUDE_vTaskSuspend == 1 )\r
2827         {\r
2828                 vListInitialise( &xSuspendedTaskList );\r
2829         }\r
2830         #endif /* INCLUDE_vTaskSuspend */\r
2831 \r
2832         /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList\r
2833         using list2. */\r
2834         pxDelayedTaskList = &xDelayedTaskList1;\r
2835         pxOverflowDelayedTaskList = &xDelayedTaskList2;\r
2836 }\r
2837 /*-----------------------------------------------------------*/\r
2838 \r
2839 static void prvCheckTasksWaitingTermination( void )\r
2840 {\r
2841         #if ( INCLUDE_vTaskDelete == 1 )\r
2842         {\r
2843                 BaseType_t xListIsEmpty;\r
2844 \r
2845                 /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called\r
2846                 too often in the idle task. */\r
2847                 while( uxTasksDeleted > ( UBaseType_t ) 0U )\r
2848                 {\r
2849                         vTaskSuspendAll();\r
2850                         {\r
2851                                 xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );\r
2852                         }\r
2853                         ( void ) xTaskResumeAll();\r
2854 \r
2855                         if( xListIsEmpty == pdFALSE )\r
2856                         {\r
2857                                 TCB_t *pxTCB;\r
2858 \r
2859                                 taskENTER_CRITICAL();\r
2860                                 {\r
2861                                         pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );\r
2862                                         ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );\r
2863                                         --uxCurrentNumberOfTasks;\r
2864                                         --uxTasksDeleted;\r
2865                                 }\r
2866                                 taskEXIT_CRITICAL();\r
2867 \r
2868                                 prvDeleteTCB( pxTCB );\r
2869                         }\r
2870                         else\r
2871                         {\r
2872                                 mtCOVERAGE_TEST_MARKER();\r
2873                         }\r
2874                 }\r
2875         }\r
2876         #endif /* vTaskDelete */\r
2877 }\r
2878 /*-----------------------------------------------------------*/\r
2879 \r
2880 static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake )\r
2881 {\r
2882         /* The list item will be inserted in wake time order. */\r
2883         listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );\r
2884 \r
2885         if( xTimeToWake < xTickCount )\r
2886         {\r
2887                 /* Wake time has overflowed.  Place this item in the overflow list. */\r
2888                 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );\r
2889         }\r
2890         else\r
2891         {\r
2892                 /* The wake time has not overflowed, so the current block list is used. */\r
2893                 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );\r
2894 \r
2895                 /* If the task entering the blocked state was placed at the head of the\r
2896                 list of blocked tasks then xNextTaskUnblockTime needs to be updated\r
2897                 too. */\r
2898                 if( xTimeToWake < xNextTaskUnblockTime )\r
2899                 {\r
2900                         xNextTaskUnblockTime = xTimeToWake;\r
2901                 }\r
2902                 else\r
2903                 {\r
2904                         mtCOVERAGE_TEST_MARKER();\r
2905                 }\r
2906         }\r
2907 }\r
2908 /*-----------------------------------------------------------*/\r
2909 \r
2910 static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer )\r
2911 {\r
2912 TCB_t *pxNewTCB;\r
2913 \r
2914         /* Allocate space for the TCB.  Where the memory comes from depends on\r
2915         the implementation of the port malloc function. */\r
2916         pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );\r
2917 \r
2918         if( pxNewTCB != NULL )\r
2919         {\r
2920                 /* Allocate space for the stack used by the task being created.\r
2921                 The base of the stack memory stored in the TCB so the task can\r
2922                 be deleted later if required. */\r
2923                 pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
2924 \r
2925                 if( pxNewTCB->pxStack == NULL )\r
2926                 {\r
2927                         /* Could not allocate the stack.  Delete the allocated TCB. */\r
2928                         vPortFree( pxNewTCB );\r
2929                         pxNewTCB = NULL;\r
2930                 }\r
2931                 else\r
2932                 {\r
2933                         /* Avoid dependency on memset() if it is not required. */\r
2934                         #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )\r
2935                         {\r
2936                                 /* Just to help debugging. */\r
2937                                 ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( StackType_t ) );\r
2938                         }\r
2939                         #endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */\r
2940                 }\r
2941         }\r
2942 \r
2943         return pxNewTCB;\r
2944 }\r
2945 /*-----------------------------------------------------------*/\r
2946 \r
2947 #if ( configUSE_TRACE_FACILITY == 1 )\r
2948 \r
2949         static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )\r
2950         {\r
2951         volatile TCB_t *pxNextTCB, *pxFirstTCB;\r
2952         UBaseType_t uxTask = 0;\r
2953 \r
2954                 if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )\r
2955                 {\r
2956                         listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );\r
2957 \r
2958                         /* Populate an TaskStatus_t structure within the\r
2959                         pxTaskStatusArray array for each task that is referenced from\r
2960                         pxList.  See the definition of TaskStatus_t in task.h for the\r
2961                         meaning of each TaskStatus_t structure member. */\r
2962                         do\r
2963                         {\r
2964                                 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );\r
2965 \r
2966                                 pxTaskStatusArray[ uxTask ].xHandle = ( TaskHandle_t ) pxNextTCB;\r
2967                                 pxTaskStatusArray[ uxTask ].pcTaskName = ( const char * ) &( pxNextTCB->pcTaskName [ 0 ] );\r
2968                                 pxTaskStatusArray[ uxTask ].xTaskNumber = pxNextTCB->uxTCBNumber;\r
2969                                 pxTaskStatusArray[ uxTask ].eCurrentState = eState;\r
2970                                 pxTaskStatusArray[ uxTask ].uxCurrentPriority = pxNextTCB->uxPriority;\r
2971 \r
2972                                 #if ( INCLUDE_vTaskSuspend == 1 )\r
2973                                 {\r
2974                                         /* If the task is in the suspended list then there is a chance\r
2975                                         it is actually just blocked indefinitely - so really it should\r
2976                                         be reported as being in the Blocked state. */\r
2977                                         if( eState == eSuspended )\r
2978                                         {\r
2979                                                 if( listLIST_ITEM_CONTAINER( &( pxNextTCB->xEventListItem ) ) != NULL )\r
2980                                                 {\r
2981                                                         pxTaskStatusArray[ uxTask ].eCurrentState = eBlocked;\r
2982                                                 }\r
2983                                         }\r
2984                                 }\r
2985                                 #endif /* INCLUDE_vTaskSuspend */\r
2986 \r
2987                                 #if ( configUSE_MUTEXES == 1 )\r
2988                                 {\r
2989                                         pxTaskStatusArray[ uxTask ].uxBasePriority = pxNextTCB->uxBasePriority;\r
2990                                 }\r
2991                                 #else\r
2992                                 {\r
2993                                         pxTaskStatusArray[ uxTask ].uxBasePriority = 0;\r
2994                                 }\r
2995                                 #endif\r
2996 \r
2997                                 #if ( configGENERATE_RUN_TIME_STATS == 1 )\r
2998                                 {\r
2999                                         pxTaskStatusArray[ uxTask ].ulRunTimeCounter = pxNextTCB->ulRunTimeCounter;\r
3000                                 }\r
3001                                 #else\r
3002                                 {\r
3003                                         pxTaskStatusArray[ uxTask ].ulRunTimeCounter = 0;\r
3004                                 }\r
3005                                 #endif\r
3006 \r
3007                                 #if ( portSTACK_GROWTH > 0 )\r
3008                                 {\r
3009                                         pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxEndOfStack );\r
3010                                 }\r
3011                                 #else\r
3012                                 {\r
3013                                         pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxStack );\r
3014                                 }\r
3015                                 #endif\r
3016 \r
3017                                 uxTask++;\r
3018 \r
3019                         } while( pxNextTCB != pxFirstTCB );\r
3020                 }\r
3021                 else\r
3022                 {\r
3023                         mtCOVERAGE_TEST_MARKER();\r
3024                 }\r
3025 \r
3026                 return uxTask;\r
3027         }\r
3028 \r
3029 #endif /* configUSE_TRACE_FACILITY */\r
3030 /*-----------------------------------------------------------*/\r
3031 \r
3032 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )\r
3033 \r
3034         static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )\r
3035         {\r
3036         uint32_t ulCount = 0U;\r
3037 \r
3038                 while( *pucStackByte == tskSTACK_FILL_BYTE )\r
3039                 {\r
3040                         pucStackByte -= portSTACK_GROWTH;\r
3041                         ulCount++;\r
3042                 }\r
3043 \r
3044                 ulCount /= ( uint32_t ) sizeof( StackType_t );\r
3045 \r
3046                 return ( uint16_t ) ulCount;\r
3047         }\r
3048 \r
3049 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */\r
3050 /*-----------------------------------------------------------*/\r
3051 \r
3052 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )\r
3053 \r
3054         UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )\r
3055         {\r
3056         TCB_t *pxTCB;\r
3057         uint8_t *pucEndOfStack;\r
3058         UBaseType_t uxReturn;\r
3059 \r
3060                 pxTCB = prvGetTCBFromHandle( xTask );\r
3061 \r
3062                 #if portSTACK_GROWTH < 0\r
3063                 {\r
3064                         pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;\r
3065                 }\r
3066                 #else\r
3067                 {\r
3068                         pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;\r
3069                 }\r
3070                 #endif\r
3071 \r
3072                 uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );\r
3073 \r
3074                 return uxReturn;\r
3075         }\r
3076 \r
3077 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */\r
3078 /*-----------------------------------------------------------*/\r
3079 \r
3080 #if ( INCLUDE_vTaskDelete == 1 )\r
3081 \r
3082         static void prvDeleteTCB( TCB_t *pxTCB )\r
3083         {\r
3084                 /* This call is required specifically for the TriCore port.  It must be\r
3085                 above the vPortFree() calls.  The call is also used by ports/demos that\r
3086                 want to allocate and clean RAM statically. */\r
3087                 portCLEAN_UP_TCB( pxTCB );\r
3088 \r
3089                 /* Free up the memory allocated by the scheduler for the task.  It is up\r
3090                 to the task to free any memory allocated at the application level. */\r
3091                 #if ( configUSE_NEWLIB_REENTRANT == 1 )\r
3092                 {\r
3093                         _reclaim_reent( &( pxTCB->xNewLib_reent ) );\r
3094                 }\r
3095                 #endif /* configUSE_NEWLIB_REENTRANT */\r
3096                 vPortFreeAligned( pxTCB->pxStack );\r
3097                 vPortFree( pxTCB );\r
3098         }\r
3099 \r
3100 #endif /* INCLUDE_vTaskDelete */\r
3101 /*-----------------------------------------------------------*/\r
3102 \r
3103 static void prvResetNextTaskUnblockTime( void )\r
3104 {\r
3105 TCB_t *pxTCB;\r
3106 \r
3107         if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )\r
3108         {\r
3109                 /* The new current delayed list is empty.  Set\r
3110                 xNextTaskUnblockTime to the maximum possible value so it is\r
3111                 extremely unlikely that the\r
3112                 if( xTickCount >= xNextTaskUnblockTime ) test will pass until\r
3113                 there is an item in the delayed list. */\r
3114                 xNextTaskUnblockTime = portMAX_DELAY;\r
3115         }\r
3116         else\r
3117         {\r
3118                 /* The new current delayed list is not empty, get the value of\r
3119                 the item at the head of the delayed list.  This is the time at\r
3120                 which the task at the head of the delayed list should be removed\r
3121                 from the Blocked state. */\r
3122                 ( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );\r
3123                 xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xGenericListItem ) );\r
3124         }\r
3125 }\r
3126 /*-----------------------------------------------------------*/\r
3127 \r
3128 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )\r
3129 \r
3130         TaskHandle_t xTaskGetCurrentTaskHandle( void )\r
3131         {\r
3132         TaskHandle_t xReturn;\r
3133 \r
3134                 /* A critical section is not required as this is not called from\r
3135                 an interrupt and the current TCB will always be the same for any\r
3136                 individual execution thread. */\r
3137                 xReturn = pxCurrentTCB;\r
3138 \r
3139                 return xReturn;\r
3140         }\r
3141 \r
3142 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */\r
3143 /*-----------------------------------------------------------*/\r
3144 \r
3145 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )\r
3146 \r
3147         BaseType_t xTaskGetSchedulerState( void )\r
3148         {\r
3149         BaseType_t xReturn;\r
3150 \r
3151                 if( xSchedulerRunning == pdFALSE )\r
3152                 {\r
3153                         xReturn = taskSCHEDULER_NOT_STARTED;\r
3154                 }\r
3155                 else\r
3156                 {\r
3157                         if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )\r
3158                         {\r
3159                                 xReturn = taskSCHEDULER_RUNNING;\r
3160                         }\r
3161                         else\r
3162                         {\r
3163                                 xReturn = taskSCHEDULER_SUSPENDED;\r
3164                         }\r
3165                 }\r
3166 \r
3167                 return xReturn;\r
3168         }\r
3169 \r
3170 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */\r
3171 /*-----------------------------------------------------------*/\r
3172 \r
3173 #if ( configUSE_MUTEXES == 1 )\r
3174 \r
3175         void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder )\r
3176         {\r
3177         TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;\r
3178 \r
3179                 /* If the mutex was given back by an interrupt while the queue was\r
3180                 locked then the mutex holder might now be NULL. */\r
3181                 if( pxMutexHolder != NULL )\r
3182                 {\r
3183                         if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )\r
3184                         {\r
3185                                 /* Adjust the mutex holder state to account for its new\r
3186                                 priority.  Only reset the event list item value if the value is\r
3187                                 not     being used for anything else. */\r
3188                                 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )\r
3189                                 {\r
3190                                         listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
3191                                 }\r
3192                                 else\r
3193                                 {\r
3194                                         mtCOVERAGE_TEST_MARKER();\r
3195                                 }\r
3196 \r
3197                                 /* If the task being modified is in the ready state it will need to\r
3198                                 be moved into a new list. */\r
3199                                 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )\r
3200                                 {\r
3201                                         if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )\r
3202                                         {\r
3203                                                 taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
3204                                         }\r
3205                                         else\r
3206                                         {\r
3207                                                 mtCOVERAGE_TEST_MARKER();\r
3208                                         }\r
3209 \r
3210                                         /* Inherit the priority before being moved into the new list. */\r
3211                                         pxTCB->uxPriority = pxCurrentTCB->uxPriority;\r
3212                                         prvAddTaskToReadyList( pxTCB );\r
3213                                 }\r
3214                                 else\r
3215                                 {\r
3216                                         /* Just inherit the priority. */\r
3217                                         pxTCB->uxPriority = pxCurrentTCB->uxPriority;\r
3218                                 }\r
3219 \r
3220                                 traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );\r
3221                         }\r
3222                         else\r
3223                         {\r
3224                                 mtCOVERAGE_TEST_MARKER();\r
3225                         }\r
3226                 }\r
3227                 else\r
3228                 {\r
3229                         mtCOVERAGE_TEST_MARKER();\r
3230                 }\r
3231         }\r
3232 \r
3233 #endif /* configUSE_MUTEXES */\r
3234 /*-----------------------------------------------------------*/\r
3235 \r
3236 #if ( configUSE_MUTEXES == 1 )\r
3237 \r
3238         void vTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )\r
3239         {\r
3240         TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;\r
3241 \r
3242                 if( pxMutexHolder != NULL )\r
3243                 {\r
3244                         if( pxTCB->uxPriority != pxTCB->uxBasePriority )\r
3245                         {\r
3246                                 /* We must be the running task to be able to give the mutex back.\r
3247                                 Remove ourselves from the ready list we currently appear in. */\r
3248                                 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )\r
3249                                 {\r
3250                                         taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
3251                                 }\r
3252                                 else\r
3253                                 {\r
3254                                         mtCOVERAGE_TEST_MARKER();\r
3255                                 }\r
3256 \r
3257                                 /* Disinherit the priority before adding the task into the new\r
3258                                 ready list. */\r
3259                                 traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );\r
3260                                 pxTCB->uxPriority = pxTCB->uxBasePriority;\r
3261 \r
3262                                 /* Only reset the event list item value if the value is not\r
3263                                 being used for anything else. */\r
3264                                 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )\r
3265                                 {\r
3266                                         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
3267                                 }\r
3268                                 else\r
3269                                 {\r
3270                                         mtCOVERAGE_TEST_MARKER();\r
3271                                 }\r
3272                                 prvAddTaskToReadyList( pxTCB );\r
3273                         }\r
3274                         else\r
3275                         {\r
3276                                 mtCOVERAGE_TEST_MARKER();\r
3277                         }\r
3278                 }\r
3279                 else\r
3280                 {\r
3281                         mtCOVERAGE_TEST_MARKER();\r
3282                 }\r
3283         }\r
3284 \r
3285 #endif /* configUSE_MUTEXES */\r
3286 /*-----------------------------------------------------------*/\r
3287 \r
3288 #if ( portCRITICAL_NESTING_IN_TCB == 1 )\r
3289 \r
3290         void vTaskEnterCritical( void )\r
3291         {\r
3292                 portDISABLE_INTERRUPTS();\r
3293 \r
3294                 if( xSchedulerRunning != pdFALSE )\r
3295                 {\r
3296                         ( pxCurrentTCB->uxCriticalNesting )++;\r
3297                 }\r
3298                 else\r
3299                 {\r
3300                         mtCOVERAGE_TEST_MARKER();\r
3301                 }\r
3302         }\r
3303 \r
3304 #endif /* portCRITICAL_NESTING_IN_TCB */\r
3305 /*-----------------------------------------------------------*/\r
3306 \r
3307 #if ( portCRITICAL_NESTING_IN_TCB == 1 )\r
3308 \r
3309         void vTaskExitCritical( void )\r
3310         {\r
3311                 if( xSchedulerRunning != pdFALSE )\r
3312                 {\r
3313                         if( pxCurrentTCB->uxCriticalNesting > 0U )\r
3314                         {\r
3315                                 ( pxCurrentTCB->uxCriticalNesting )--;\r
3316 \r
3317                                 if( pxCurrentTCB->uxCriticalNesting == 0U )\r
3318                                 {\r
3319                                         portENABLE_INTERRUPTS();\r
3320                                 }\r
3321                                 else\r
3322                                 {\r
3323                                         mtCOVERAGE_TEST_MARKER();\r
3324                                 }\r
3325                         }\r
3326                         else\r
3327                         {\r
3328                                 mtCOVERAGE_TEST_MARKER();\r
3329                         }\r
3330                 }\r
3331                 else\r
3332                 {\r
3333                         mtCOVERAGE_TEST_MARKER();\r
3334                 }\r
3335         }\r
3336 \r
3337 #endif /* portCRITICAL_NESTING_IN_TCB */\r
3338 /*-----------------------------------------------------------*/\r
3339 \r
3340 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) )\r
3341 \r
3342         void vTaskList( char * pcWriteBuffer )\r
3343         {\r
3344         TaskStatus_t *pxTaskStatusArray;\r
3345         volatile UBaseType_t uxArraySize, x;\r
3346         char cStatus;\r
3347 \r
3348                 /*\r
3349                  * PLEASE NOTE:\r
3350                  *\r
3351                  * This function is provided for convenience only, and is used by many\r
3352                  * of the demo applications.  Do not consider it to be part of the\r
3353                  * scheduler.\r
3354                  *\r
3355                  * vTaskList() calls uxTaskGetSystemState(), then formats part of the\r
3356                  * uxTaskGetSystemState() output into a human readable table that\r
3357                  * displays task names, states and stack usage.\r
3358                  *\r
3359                  * vTaskList() has a dependency on the sprintf() C library function that\r
3360                  * might bloat the code size, use a lot of stack, and provide different\r
3361                  * results on different platforms.  An alternative, tiny, third party,\r
3362                  * and limited functionality implementation of sprintf() is provided in\r
3363                  * many of the FreeRTOS/Demo sub-directories in a file called\r
3364                  * printf-stdarg.c (note printf-stdarg.c does not provide a full\r
3365                  * snprintf() implementation!).\r
3366                  *\r
3367                  * It is recommended that production systems call uxTaskGetSystemState()\r
3368                  * directly to get access to raw stats data, rather than indirectly\r
3369                  * through a call to vTaskList().\r
3370                  */\r
3371 \r
3372 \r
3373                 /* Make sure the write buffer does not contain a string. */\r
3374                 *pcWriteBuffer = 0x00;\r
3375 \r
3376                 /* Take a snapshot of the number of tasks in case it changes while this\r
3377                 function is executing. */\r
3378                 uxArraySize = uxCurrentNumberOfTasks;\r
3379 \r
3380                 /* Allocate an array index for each task. */\r
3381                 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );\r
3382 \r
3383                 if( pxTaskStatusArray != NULL )\r
3384                 {\r
3385                         /* Generate the (binary) data. */\r
3386                         uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );\r
3387 \r
3388                         /* Create a human readable table from the binary data. */\r
3389                         for( x = 0; x < uxArraySize; x++ )\r
3390                         {\r
3391                                 switch( pxTaskStatusArray[ x ].eCurrentState )\r
3392                                 {\r
3393                                 case eReady:            cStatus = tskREADY_CHAR;\r
3394                                                                         break;\r
3395 \r
3396                                 case eBlocked:          cStatus = tskBLOCKED_CHAR;\r
3397                                                                         break;\r
3398 \r
3399                                 case eSuspended:        cStatus = tskSUSPENDED_CHAR;\r
3400                                                                         break;\r
3401 \r
3402                                 case eDeleted:          cStatus = tskDELETED_CHAR;\r
3403                                                                         break;\r
3404 \r
3405                                 default:                        /* Should not get here, but it is included\r
3406                                                                         to prevent static checking errors. */\r
3407                                                                         cStatus = 0x00;\r
3408                                                                         break;\r
3409                                 }\r
3410 \r
3411                                 sprintf( pcWriteBuffer, "%s\t\t%c\t%u\t%u\t%u\r\n", pxTaskStatusArray[ x ].pcTaskName, cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber );\r
3412                                 pcWriteBuffer += strlen( pcWriteBuffer );\r
3413                         }\r
3414 \r
3415                         /* Free the array again. */\r
3416                         vPortFree( pxTaskStatusArray );\r
3417                 }\r
3418                 else\r
3419                 {\r
3420                         mtCOVERAGE_TEST_MARKER();\r
3421                 }\r
3422         }\r
3423 \r
3424 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) */\r
3425 /*----------------------------------------------------------*/\r
3426 \r
3427 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) )\r
3428 \r
3429         void vTaskGetRunTimeStats( char *pcWriteBuffer )\r
3430         {\r
3431         TaskStatus_t *pxTaskStatusArray;\r
3432         volatile UBaseType_t uxArraySize, x;\r
3433         uint32_t ulTotalTime, ulStatsAsPercentage;\r
3434 \r
3435                 #if( configUSE_TRACE_FACILITY != 1 )\r
3436                 {\r
3437                         #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats().\r
3438                 }\r
3439                 #endif\r
3440 \r
3441                 /*\r
3442                  * PLEASE NOTE:\r
3443                  *\r
3444                  * This function is provided for convenience only, and is used by many\r
3445                  * of the demo applications.  Do not consider it to be part of the\r
3446                  * scheduler.\r
3447                  *\r
3448                  * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part\r
3449                  * of the uxTaskGetSystemState() output into a human readable table that\r
3450                  * displays the amount of time each task has spent in the Running state\r
3451                  * in both absolute and percentage terms.\r
3452                  *\r
3453                  * vTaskGetRunTimeStats() has a dependency on the sprintf() C library\r
3454                  * function that might bloat the code size, use a lot of stack, and\r
3455                  * provide different results on different platforms.  An alternative,\r
3456                  * tiny, third party, and limited functionality implementation of\r
3457                  * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in\r
3458                  * a file called printf-stdarg.c (note printf-stdarg.c does not provide\r
3459                  * a full snprintf() implementation!).\r
3460                  *\r
3461                  * It is recommended that production systems call uxTaskGetSystemState()\r
3462                  * directly to get access to raw stats data, rather than indirectly\r
3463                  * through a call to vTaskGetRunTimeStats().\r
3464                  */\r
3465 \r
3466                 /* Make sure the write buffer does not contain a string. */\r
3467                 *pcWriteBuffer = 0x00;\r
3468 \r
3469                 /* Take a snapshot of the number of tasks in case it changes while this\r
3470                 function is executing. */\r
3471                 uxArraySize = uxCurrentNumberOfTasks;\r
3472 \r
3473                 /* Allocate an array index for each task. */\r
3474                 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );\r
3475 \r
3476                 if( pxTaskStatusArray != NULL )\r
3477                 {\r
3478                         /* Generate the (binary) data. */\r
3479                         uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );\r
3480 \r
3481                         /* For percentage calculations. */\r
3482                         ulTotalTime /= 100UL;\r
3483 \r
3484                         /* Avoid divide by zero errors. */\r
3485                         if( ulTotalTime > 0 )\r
3486                         {\r
3487                                 /* Create a human readable table from the binary data. */\r
3488                                 for( x = 0; x < uxArraySize; x++ )\r
3489                                 {\r
3490                                         /* What percentage of the total run time has the task used?\r
3491                                         This will always be rounded down to the nearest integer.\r
3492                                         ulTotalRunTimeDiv100 has already been divided by 100. */\r
3493                                         ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;\r
3494 \r
3495                                         if( ulStatsAsPercentage > 0UL )\r
3496                                         {\r
3497                                                 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED\r
3498                                                 {\r
3499                                                         sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );\r
3500                                                 }\r
3501                                                 #else\r
3502                                                 {\r
3503                                                         /* sizeof( int ) == sizeof( long ) so a smaller\r
3504                                                         printf() library can be used. */\r
3505                                                         sprintf( pcWriteBuffer, "%s\t\t%u\t\t%u%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );\r
3506                                                 }\r
3507                                                 #endif\r
3508                                         }\r
3509                                         else\r
3510                                         {\r
3511                                                 /* If the percentage is zero here then the task has\r
3512                                                 consumed less than 1% of the total run time. */\r
3513                                                 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED\r
3514                                                 {\r
3515                                                         sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );\r
3516                                                 }\r
3517                                                 #else\r
3518                                                 {\r
3519                                                         /* sizeof( int ) == sizeof( long ) so a smaller\r
3520                                                         printf() library can be used. */\r
3521                                                         sprintf( pcWriteBuffer, "%s\t\t%u\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter );\r
3522                                                 }\r
3523                                                 #endif\r
3524                                         }\r
3525 \r
3526                                         pcWriteBuffer += strlen( pcWriteBuffer );\r
3527                                 }\r
3528                         }\r
3529                         else\r
3530                         {\r
3531                                 mtCOVERAGE_TEST_MARKER();\r
3532                         }\r
3533 \r
3534                         /* Free the array again. */\r
3535                         vPortFree( pxTaskStatusArray );\r
3536                 }\r
3537                 else\r
3538                 {\r
3539                         mtCOVERAGE_TEST_MARKER();\r
3540                 }\r
3541         }\r
3542 \r
3543 #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) */\r
3544 /*-----------------------------------------------------------*/\r
3545 \r
3546 TickType_t uxTaskResetEventItemValue( void )\r
3547 {\r
3548 TickType_t uxReturn;\r
3549 \r
3550         uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );\r
3551 \r
3552         /* Reset the event list item to its normal value - so it can be used with\r
3553         queues and semaphores. */\r
3554         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
3555 \r
3556         return uxReturn;\r
3557 }\r
3558 /*-----------------------------------------------------------*/\r
3559 \r
3560 #ifdef FREERTOS_MODULE_TEST\r
3561         #include "tasks_test_access_functions.h"\r
3562 #endif\r
3563 \r