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