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