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