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