]> begriffs open source - freertos/blob - FreeRTOS/Source/tasks.c
Notes:
[freertos] / FreeRTOS / Source / tasks.c
1 /*\r
2     FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     This file is part of the FreeRTOS distribution.\r
8 \r
9     FreeRTOS is free software; you can redistribute it and/or modify it under\r
10     the terms of the GNU General Public License (version 2) as published by the\r
11     Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
12 \r
13     ***************************************************************************\r
14     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
15     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
16     >>!   obliged to provide the source code for proprietary components     !<<\r
17     >>!   outside of the FreeRTOS kernel.                                   !<<\r
18     ***************************************************************************\r
19 \r
20     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
21     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
22     FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
23     link: http://www.freertos.org/a00114.html\r
24 \r
25     ***************************************************************************\r
26      *                                                                       *\r
27      *    FreeRTOS provides completely free yet professionally developed,    *\r
28      *    robust, strictly quality controlled, supported, and cross          *\r
29      *    platform software that is more than just the market leader, it     *\r
30      *    is the industry's de facto standard.                               *\r
31      *                                                                       *\r
32      *    Help yourself get started quickly while simultaneously helping     *\r
33      *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
34      *    tutorial book, reference manual, or both:                          *\r
35      *    http://www.FreeRTOS.org/Documentation                              *\r
36      *                                                                       *\r
37     ***************************************************************************\r
38 \r
39     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
40     the FAQ page "My application does not run, what could be wrong?".  Have you\r
41     defined configASSERT()?\r
42 \r
43     http://www.FreeRTOS.org/support - In return for receiving this top quality\r
44     embedded software for free we request you assist our global community by\r
45     participating in the support forum.\r
46 \r
47     http://www.FreeRTOS.org/training - Investing in training allows your team to\r
48     be as productive as possible as early as possible.  Now you can receive\r
49     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
50     Ltd, and the world's leading authority on the world's leading RTOS.\r
51 \r
52     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
53     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
54     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
55 \r
56     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
57     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
58 \r
59     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
60     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
61     licenses offer ticketed support, indemnification and commercial middleware.\r
62 \r
63     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
64     engineered and independently SIL3 certified version for use in safety and\r
65     mission critical applications that require provable dependability.\r
66 \r
67     1 tab == 4 spaces!\r
68 */\r
69 \r
70 /* Standard includes. */\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 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the\r
86 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the\r
87 header files above, but not in this file, in order to generate the correct\r
88 privileged Vs unprivileged linkage and placement. */\r
89 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */\r
90 \r
91 /* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting\r
92 functions but without including stdio.h here. */\r
93 #if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 )\r
94         /* At the bottom of this file are two optional functions that can be used\r
95         to generate human readable text from the raw data generated by the\r
96         uxTaskGetSystemState() function.  Note the formatting functions are provided\r
97         for convenience only, and are NOT considered part of the kernel. */\r
98         #include <stdio.h>\r
99 #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */\r
100 \r
101 #if( configUSE_PREEMPTION == 0 )\r
102         /* If the cooperative scheduler is being used then a yield should not be\r
103         performed just because a higher priority task has been woken. */\r
104         #define taskYIELD_IF_USING_PREEMPTION()\r
105 #else\r
106         #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()\r
107 #endif\r
108 \r
109 /* Values that can be assigned to the ucNotifyState member of the TCB. */\r
110 #define taskNOT_WAITING_NOTIFICATION    ( ( uint8_t ) 0 )\r
111 #define taskWAITING_NOTIFICATION                ( ( uint8_t ) 1 )\r
112 #define taskNOTIFICATION_RECEIVED               ( ( uint8_t ) 2 )\r
113 \r
114 /*\r
115  * The value used to fill the stack of a task when the task is created.  This\r
116  * is used purely for checking the high water mark for tasks.\r
117  */\r
118 #define tskSTACK_FILL_BYTE      ( 0xa5U )\r
119 \r
120 /*\r
121  * Macros used by vListTask to indicate which state a task is in.\r
122  */\r
123 #define tskBLOCKED_CHAR         ( 'B' )\r
124 #define tskREADY_CHAR           ( 'R' )\r
125 #define tskDELETED_CHAR         ( 'D' )\r
126 #define tskSUSPENDED_CHAR       ( 'S' )\r
127 \r
128 /*\r
129  * Some kernel aware debuggers require the data the debugger needs access to be\r
130  * global, rather than file scope.\r
131  */\r
132 #ifdef portREMOVE_STATIC_QUALIFIER\r
133         #define static\r
134 #endif\r
135 \r
136 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )\r
137 \r
138         /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is\r
139         performed in a generic way that is not optimised to any particular\r
140         microcontroller architecture. */\r
141 \r
142         /* uxTopReadyPriority holds the priority of the highest priority ready\r
143         state task. */\r
144         #define taskRECORD_READY_PRIORITY( uxPriority )                                                                                                         \\r
145         {                                                                                                                                                                                                       \\r
146                 if( ( uxPriority ) > uxTopReadyPriority )                                                                                                               \\r
147                 {                                                                                                                                                                                               \\r
148                         uxTopReadyPriority = ( uxPriority );                                                                                                            \\r
149                 }                                                                                                                                                                                               \\r
150         } /* taskRECORD_READY_PRIORITY */\r
151 \r
152         /*-----------------------------------------------------------*/\r
153 \r
154         #define taskSELECT_HIGHEST_PRIORITY_TASK()                                                                                                                      \\r
155         {                                                                                                                                                                                                       \\r
156                 /* Find the highest priority queue that contains ready tasks. */                                                                \\r
157                 while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) )                                              \\r
158                 {                                                                                                                                                                                               \\r
159                         configASSERT( uxTopReadyPriority );                                                                                                                     \\r
160                         --uxTopReadyPriority;                                                                                                                                           \\r
161                 }                                                                                                                                                                                               \\r
162                                                                                                                                                                                                                 \\r
163                 /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of                                                \\r
164                 the     same priority get an equal share of the processor time. */                                                                      \\r
165                 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) );              \\r
166         } /* taskSELECT_HIGHEST_PRIORITY_TASK */\r
167 \r
168         /*-----------------------------------------------------------*/\r
169 \r
170         /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as\r
171         they are only required when a port optimised method of task selection is\r
172         being used. */\r
173         #define taskRESET_READY_PRIORITY( uxPriority )\r
174         #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )\r
175 \r
176 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */\r
177 \r
178         /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is\r
179         performed in a way that is tailored to the particular microcontroller\r
180         architecture being used. */\r
181 \r
182         /* A port optimised version is provided.  Call the port defined macros. */\r
183         #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )\r
184 \r
185         /*-----------------------------------------------------------*/\r
186 \r
187         #define taskSELECT_HIGHEST_PRIORITY_TASK()                                                                                                              \\r
188         {                                                                                                                                                                                               \\r
189         UBaseType_t uxTopPriority;                                                                                                                                              \\r
190                                                                                                                                                                                                         \\r
191                 /* Find the highest priority list that contains ready tasks. */                                                         \\r
192                 portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );                                                          \\r
193                 configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 );         \\r
194                 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );           \\r
195         } /* taskSELECT_HIGHEST_PRIORITY_TASK() */\r
196 \r
197         /*-----------------------------------------------------------*/\r
198 \r
199         /* A port optimised version is provided, call it only if the TCB being reset\r
200         is being referenced from a ready list.  If it is referenced from a delayed\r
201         or suspended list then it won't be in a ready list. */\r
202         #define taskRESET_READY_PRIORITY( uxPriority )                                                                                                          \\r
203         {                                                                                                                                                                                                       \\r
204                 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 )  \\r
205                 {                                                                                                                                                                                               \\r
206                         portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) );                                                     \\r
207                 }                                                                                                                                                                                               \\r
208         }\r
209 \r
210 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */\r
211 \r
212 /*-----------------------------------------------------------*/\r
213 \r
214 /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick\r
215 count overflows. */\r
216 #define taskSWITCH_DELAYED_LISTS()                                                                                                                                      \\r
217 {                                                                                                                                                                                                       \\r
218         List_t *pxTemp;                                                                                                                                                                 \\r
219                                                                                                                                                                                                         \\r
220         /* The delayed tasks list should be empty when the lists are switched. */                                               \\r
221         configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) );                                                                             \\r
222                                                                                                                                                                                                         \\r
223         pxTemp = pxDelayedTaskList;                                                                                                                                             \\r
224         pxDelayedTaskList = pxOverflowDelayedTaskList;                                                                                                  \\r
225         pxOverflowDelayedTaskList = pxTemp;                                                                                                                             \\r
226         xNumOfOverflows++;                                                                                                                                                              \\r
227         prvResetNextTaskUnblockTime();                                                                                                                                  \\r
228 }\r
229 \r
230 /*-----------------------------------------------------------*/\r
231 \r
232 /*\r
233  * Place the task represented by pxTCB into the appropriate ready list for\r
234  * the task.  It is inserted at the end of the list.\r
235  */\r
236 #define prvAddTaskToReadyList( pxTCB )                                                                                                                          \\r
237         traceMOVED_TASK_TO_READY_STATE( pxTCB );                                                                                                                \\r
238         taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority );                                                                                             \\r
239         vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \\r
240         tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )\r
241 /*-----------------------------------------------------------*/\r
242 \r
243 /*\r
244  * Several functions take an TaskHandle_t parameter that can optionally be NULL,\r
245  * where NULL is used to indicate that the handle of the currently executing\r
246  * task should be used in place of the parameter.  This macro simply checks to\r
247  * see if the parameter is NULL and returns a pointer to the appropriate TCB.\r
248  */\r
249 #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TCB_t * ) pxCurrentTCB : ( TCB_t * ) ( pxHandle ) )\r
250 \r
251 /* The item value of the event list item is normally used to hold the priority\r
252 of the task to which it belongs (coded to allow it to be held in reverse\r
253 priority order).  However, it is occasionally borrowed for other purposes.  It\r
254 is important its value is not updated due to a task priority change while it is\r
255 being used for another purpose.  The following bit definition is used to inform\r
256 the scheduler that the value should not be changed - in which case it is the\r
257 responsibility of whichever module is using the value to ensure it gets set back\r
258 to its original value when it is released. */\r
259 #if( configUSE_16_BIT_TICKS == 1 )\r
260         #define taskEVENT_LIST_ITEM_VALUE_IN_USE        0x8000U\r
261 #else\r
262         #define taskEVENT_LIST_ITEM_VALUE_IN_USE        0x80000000UL\r
263 #endif\r
264 \r
265 /*\r
266  * Task control block.  A task control block (TCB) is allocated for each task,\r
267  * and stores task state information, including a pointer to the task's context\r
268  * (the task's run time environment, including register values)\r
269  */\r
270 typedef struct tskTaskControlBlock\r
271 {\r
272         volatile StackType_t    *pxTopOfStack;  /*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */\r
273 \r
274         #if ( portUSING_MPU_WRAPPERS == 1 )\r
275                 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
276         #endif\r
277 \r
278         ListItem_t                      xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */\r
279         ListItem_t                      xEventListItem;         /*< Used to reference a task from an event list. */\r
280         UBaseType_t                     uxPriority;                     /*< The priority of the task.  0 is the lowest priority. */\r
281         StackType_t                     *pxStack;                       /*< Points to the start of the stack. */\r
282         char                            pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created.  Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
283 \r
284         #if ( portSTACK_GROWTH > 0 )\r
285                 StackType_t             *pxEndOfStack;          /*< Points to the end of the stack on architectures where the stack grows up from low memory. */\r
286         #endif\r
287 \r
288         #if ( portCRITICAL_NESTING_IN_TCB == 1 )\r
289                 UBaseType_t             uxCriticalNesting;      /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */\r
290         #endif\r
291 \r
292         #if ( configUSE_TRACE_FACILITY == 1 )\r
293                 UBaseType_t             uxTCBNumber;            /*< Stores a number that increments each time a TCB is created.  It allows debuggers to determine when a task has been deleted and then recreated. */\r
294                 UBaseType_t             uxTaskNumber;           /*< Stores a number specifically for use by third party trace code. */\r
295         #endif\r
296 \r
297         #if ( configUSE_MUTEXES == 1 )\r
298                 UBaseType_t             uxBasePriority;         /*< The priority last assigned to the task - used by the priority inheritance mechanism. */\r
299                 UBaseType_t             uxMutexesHeld;\r
300         #endif\r
301 \r
302         #if ( configUSE_APPLICATION_TASK_TAG == 1 )\r
303                 TaskHookFunction_t pxTaskTag;\r
304         #endif\r
305 \r
306         #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )\r
307                 void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];\r
308         #endif\r
309 \r
310         #if( configGENERATE_RUN_TIME_STATS == 1 )\r
311                 uint32_t                ulRunTimeCounter;       /*< Stores the amount of time the task has spent in the Running state. */\r
312         #endif\r
313 \r
314         #if ( configUSE_NEWLIB_REENTRANT == 1 )\r
315                 /* Allocate a Newlib reent structure that is specific to this task.\r
316                 Note Newlib support has been included by popular demand, but is not\r
317                 used by the FreeRTOS maintainers themselves.  FreeRTOS is not\r
318                 responsible for resulting newlib operation.  User must be familiar with\r
319                 newlib and must provide system-wide implementations of the necessary\r
320                 stubs. Be warned that (at the time of writing) the current newlib design\r
321                 implements a system-wide malloc() that must be provided with locks. */\r
322                 struct  _reent xNewLib_reent;\r
323         #endif\r
324 \r
325         #if( configUSE_TASK_NOTIFICATIONS == 1 )\r
326                 volatile uint32_t ulNotifiedValue;\r
327                 volatile uint8_t ucNotifyState;\r
328         #endif\r
329 \r
330         #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )\r
331                 uint8_t ucStaticallyAllocated; /* Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */\r
332         #endif\r
333 \r
334         #if( INCLUDE_xTaskAbortDelay == 1 )\r
335                 uint8_t ucDelayAborted;\r
336         #endif\r
337 \r
338 } tskTCB;\r
339 \r
340 /* The old tskTCB name is maintained above then typedefed to the new TCB_t name\r
341 below to enable the use of older kernel aware debuggers. */\r
342 typedef tskTCB TCB_t;\r
343 \r
344 /*lint -e956 A manual analysis and inspection has been used to determine which\r
345 static variables must be declared volatile. */\r
346 \r
347 PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;\r
348 \r
349 /* Lists for ready and blocked tasks. --------------------*/\r
350 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */\r
351 PRIVILEGED_DATA static List_t xDelayedTaskList1;                                                /*< Delayed tasks. */\r
352 PRIVILEGED_DATA static List_t xDelayedTaskList2;                                                /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */\r
353 PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList;                             /*< Points to the delayed task list currently being used. */\r
354 PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList;             /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */\r
355 PRIVILEGED_DATA static List_t xPendingReadyList;                                                /*< Tasks that have been readied while the scheduler was suspended.  They will be moved to the ready list when the scheduler is resumed. */\r
356 \r
357 #if( ( INCLUDE_vTaskDelete == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )\r
358 \r
359         PRIVILEGED_DATA static List_t xTasksWaitingTermination;                         /*< Tasks that have been deleted - but their memory not yet freed. */\r
360         PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;\r
361 \r
362 #endif\r
363 \r
364 #if ( INCLUDE_vTaskSuspend == 1 )\r
365 \r
366         PRIVILEGED_DATA static List_t xSuspendedTaskList;                                       /*< Tasks that are currently suspended. */\r
367 \r
368 #endif\r
369 \r
370 /* Other file private variables. --------------------------------*/\r
371 PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks      = ( UBaseType_t ) 0U;\r
372 PRIVILEGED_DATA static volatile TickType_t xTickCount                           = ( TickType_t ) 0U;\r
373 PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority          = tskIDLE_PRIORITY;\r
374 PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning            = pdFALSE;\r
375 PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks                       = ( UBaseType_t ) 0U;\r
376 PRIVILEGED_DATA static volatile BaseType_t xYieldPending                        = pdFALSE;\r
377 PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows                      = ( BaseType_t ) 0;\r
378 PRIVILEGED_DATA static UBaseType_t uxTaskNumber                                         = ( UBaseType_t ) 0U;\r
379 PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime         = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */\r
380 PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle                                     = NULL;                 /*< Holds the handle of the idle task.  The idle task is created automatically when the scheduler is started. */\r
381 \r
382 /* Context switches are held pending while the scheduler is suspended.  Also,\r
383 interrupts must not manipulate the xStateListItem of a TCB, or any of the\r
384 lists the xStateListItem can be referenced from, if the scheduler is suspended.\r
385 If an interrupt needs to unblock a task while the scheduler is suspended then it\r
386 moves the task's event list item into the xPendingReadyList, ready for the\r
387 kernel to move the task from the pending ready list into the real ready list\r
388 when the scheduler is unsuspended.  The pending ready list itself can only be\r
389 accessed from a critical section. */\r
390 PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended        = ( UBaseType_t ) pdFALSE;\r
391 \r
392 #if ( configGENERATE_RUN_TIME_STATS == 1 )\r
393 \r
394         PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL;     /*< Holds the value of a timer/counter the last time a task was switched in. */\r
395         PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL;           /*< Holds the total amount of execution time as defined by the run time counter clock. */\r
396 \r
397 #endif\r
398 \r
399 /*lint +e956 */\r
400 \r
401 /*-----------------------------------------------------------*/\r
402 \r
403 /* Callback function prototypes. --------------------------*/\r
404 #if(  configCHECK_FOR_STACK_OVERFLOW > 0 )\r
405         extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName );\r
406 #endif\r
407 \r
408 #if( configUSE_TICK_HOOK > 0 )\r
409         extern void vApplicationTickHook( void );\r
410 #endif\r
411 \r
412 #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
413         extern void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize );\r
414 #endif\r
415 \r
416 /* File private functions. --------------------------------*/\r
417 \r
418 /**\r
419  * Utility task that simply returns pdTRUE if the task referenced by xTask is\r
420  * currently in the Suspended state, or pdFALSE if the task referenced by xTask\r
421  * is in any other state.\r
422  */\r
423 #if ( INCLUDE_vTaskSuspend == 1 )\r
424         static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;\r
425 #endif /* INCLUDE_vTaskSuspend */\r
426 \r
427 /*\r
428  * Utility to ready all the lists used by the scheduler.  This is called\r
429  * automatically upon the creation of the first task.\r
430  */\r
431 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;\r
432 \r
433 /*\r
434  * The idle task, which as all tasks is implemented as a never ending loop.\r
435  * The idle task is automatically created and added to the ready lists upon\r
436  * creation of the first user task.\r
437  *\r
438  * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific\r
439  * language extensions.  The equivalent prototype for this function is:\r
440  *\r
441  * void prvIdleTask( void *pvParameters );\r
442  *\r
443  */\r
444 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );\r
445 \r
446 /*\r
447  * Utility to free all memory allocated by the scheduler to hold a TCB,\r
448  * including the stack pointed to by the TCB.\r
449  *\r
450  * This does not free memory allocated by the task itself (i.e. memory\r
451  * allocated by calls to pvPortMalloc from within the tasks application code).\r
452  */\r
453 #if ( INCLUDE_vTaskDelete == 1 )\r
454 \r
455         static void prvDeleteTCB( TCB_t *pxTCB ) PRIVILEGED_FUNCTION;\r
456 \r
457 #endif\r
458 \r
459 /*\r
460  * Used only by the idle task.  This checks to see if anything has been placed\r
461  * in the list of tasks waiting to be deleted.  If so the task is cleaned up\r
462  * and its TCB deleted.\r
463  */\r
464 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;\r
465 \r
466 /*\r
467  * The currently executing task is entering the Blocked state.  Add the task to\r
468  * either the current or the overflow delayed task list.\r
469  */\r
470 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION;\r
471 \r
472 /*\r
473  * Fills an TaskStatus_t structure with information on each task that is\r
474  * referenced from the pxList list (which may be a ready list, a delayed list,\r
475  * a suspended list, etc.).\r
476  *\r
477  * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM\r
478  * NORMAL APPLICATION CODE.\r
479  */\r
480 #if ( configUSE_TRACE_FACILITY == 1 )\r
481 \r
482         static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;\r
483 \r
484 #endif\r
485 \r
486 /*\r
487  * Searches pxList for a task with name pcNameToQuery - returning a handle to\r
488  * the task if it is found, or NULL if the task is not found.\r
489  */\r
490 #if ( INCLUDE_xTaskGetTaskHandle == 1 )\r
491 \r
492         static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] ) PRIVILEGED_FUNCTION;\r
493 \r
494 #endif\r
495 \r
496 /*\r
497  * When a task is created, the stack of the task is filled with a known value.\r
498  * This function determines the 'high water mark' of the task stack by\r
499  * determining how much of the stack remains at the original preset value.\r
500  */\r
501 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )\r
502 \r
503         static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;\r
504 \r
505 #endif\r
506 \r
507 /*\r
508  * Return the amount of time, in ticks, that will pass before the kernel will\r
509  * next move a task from the Blocked state to the Running state.\r
510  *\r
511  * This conditional compilation should use inequality to 0, not equality to 1.\r
512  * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user\r
513  * defined low power mode implementations require configUSE_TICKLESS_IDLE to be\r
514  * set to a value other than 1.\r
515  */\r
516 #if ( configUSE_TICKLESS_IDLE != 0 )\r
517 \r
518         static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;\r
519 \r
520 #endif\r
521 \r
522 /*\r
523  * Set xNextTaskUnblockTime to the time at which the next Blocked state task\r
524  * will exit the Blocked state.\r
525  */\r
526 static void prvResetNextTaskUnblockTime( void );\r
527 \r
528 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )\r
529 \r
530         /*\r
531          * Helper function used to pad task names with spaces when printing out\r
532          * human readable tables of task information.\r
533          */\r
534         static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName ) PRIVILEGED_FUNCTION;\r
535 \r
536 #endif\r
537 \r
538 /*\r
539  * Called after a Task_t structure has been allocated either statically or\r
540  * dynamically to fill in the structure's members.\r
541  */\r
542 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
543 \r
544 /*\r
545  * Called after a new task has been created and initialised to place the task\r
546  * under the control of the scheduler.\r
547  */\r
548 static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;\r
549 \r
550 /*-----------------------------------------------------------*/\r
551 \r
552 #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
553 \r
554         BaseType_t xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
555         {\r
556         TCB_t *pxNewTCB;\r
557         BaseType_t xReturn;\r
558 \r
559                 configASSERT( puxStackBuffer != NULL );\r
560                 configASSERT( pxTaskBuffer != NULL );\r
561 \r
562                 /* The memory used for the task's TCB and stack are passed into this\r
563                 function - use them. */\r
564                 pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */\r
565 \r
566                 if( pxNewTCB != NULL )\r
567                 {\r
568                         pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;\r
569 \r
570                         #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
571                         {\r
572                                 /* Tasks can be created statically or dynamically, so note this\r
573                                 task was created statically in case the task is later deleted. */\r
574                                 pxNewTCB->ucStaticallyAllocated = pdTRUE;\r
575                         }\r
576                         #endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
577 \r
578                         prvInitialiseNewTask( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB );\r
579                         prvAddNewTaskToReadyList( pxNewTCB );\r
580                         xReturn = pdPASS;\r
581                 }\r
582                 else\r
583                 {\r
584                         xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;\r
585                 }\r
586 \r
587                 return xReturn;\r
588         }\r
589 \r
590 #endif /* SUPPORT_STATIC_ALLOCATION */\r
591 /*-----------------------------------------------------------*/\r
592 \r
593 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )\r
594 \r
595         BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
596         {\r
597         TCB_t *pxNewTCB;\r
598         BaseType_t xReturn;\r
599 \r
600                 /* If the stack grows down then allocate the stack then the TCB so the stack\r
601                 does not grow into the TCB.  Likewise if the stack grows up then allocate\r
602                 the TCB then the stack. */\r
603                 #if( portSTACK_GROWTH > 0 )\r
604                 {\r
605                         /* Allocate space for the TCB.  Where the memory comes from depends on\r
606                         the implementation of the port malloc function and whether or not static\r
607                         allocation is being used. */\r
608                         pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );\r
609 \r
610                         if( pxNewTCB != NULL )\r
611                         {\r
612                                 /* Allocate space for the stack used by the task being created.\r
613                                 The base of the stack memory stored in the TCB so the task can\r
614                                 be deleted later if required. */\r
615                                 pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
616 \r
617                                 if( pxNewTCB->pxStack == NULL )\r
618                                 {\r
619                                         /* Could not allocate the stack.  Delete the allocated TCB. */\r
620                                         vPortFree( pxNewTCB );\r
621                                         pxNewTCB = NULL;\r
622                                 }\r
623                         }\r
624                 }\r
625                 #else /* portSTACK_GROWTH */\r
626                 {\r
627                 StackType_t *pxStack;\r
628 \r
629                         /* Allocate space for the stack used by the task being created. */\r
630                         pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
631 \r
632                         if( pxStack != NULL )\r
633                         {\r
634                                 /* Allocate space for the TCB. */\r
635                                 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e961 MISRA exception as the casts are only redundant for some paths. */\r
636 \r
637                                 if( pxNewTCB != NULL )\r
638                                 {\r
639                                         /* Store the stack location in the TCB. */\r
640                                         pxNewTCB->pxStack = pxStack;\r
641                                 }\r
642                                 else\r
643                                 {\r
644                                         /* The stack cannot be used as the TCB was not created.  Free\r
645                                         it again. */\r
646                                         vPortFree( pxStack );\r
647                                 }\r
648                         }\r
649                         else\r
650                         {\r
651                                 pxNewTCB = NULL;\r
652                         }\r
653                 }\r
654                 #endif /* portSTACK_GROWTH */\r
655 \r
656                 if( pxNewTCB != NULL )\r
657                 {\r
658                         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
659                         {\r
660                                 /* Tasks can be created statically or dynamically, so note this\r
661                                 task was created dynamically in case it is later deleted. */\r
662                                 pxNewTCB->ucStaticallyAllocated = pdFALSE;\r
663                         }\r
664                         #endif /* configSUPPORT_STATIC_ALLOCATION */\r
665 \r
666                         prvInitialiseNewTask( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB );\r
667                         prvAddNewTaskToReadyList( pxNewTCB );\r
668                         xReturn = pdPASS;\r
669                 }\r
670                 else\r
671                 {\r
672                         xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;\r
673                 }\r
674 \r
675                 return xReturn;\r
676         }\r
677 \r
678 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
679 /*-----------------------------------------------------------*/\r
680 \r
681 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, TCB_t *pxNewTCB ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
682 {\r
683 StackType_t *pxTopOfStack;\r
684 UBaseType_t x;\r
685 \r
686         #if( portUSING_MPU_WRAPPERS == 1 )\r
687                 /* Should the task be created in privileged mode? */\r
688                 BaseType_t xRunPrivileged;\r
689                 if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )\r
690                 {\r
691                         xRunPrivileged = pdTRUE;\r
692                 }\r
693                 else\r
694                 {\r
695                         xRunPrivileged = pdFALSE;\r
696                 }\r
697                 uxPriority &= ~portPRIVILEGE_BIT;\r
698         #endif /* portUSING_MPU_WRAPPERS == 1 */\r
699 \r
700         /* Avoid dependency on memset() if it is not required. */\r
701         #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )\r
702         {\r
703                 /* Fill the stack with a known value to assist debugging. */\r
704                 ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( StackType_t ) );\r
705         }\r
706         #endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */\r
707 \r
708         /* Calculate the top of stack address.  This depends on whether the stack\r
709         grows from high memory to low (as per the 80x86) or vice versa.\r
710         portSTACK_GROWTH is used to make the result positive or negative as required\r
711         by the port. */\r
712         #if( portSTACK_GROWTH < 0 )\r
713         {\r
714                 pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( uint16_t ) 1 );\r
715                 pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 MISRA exception.  Avoiding casts between pointers and integers is not practical.  Size differences accounted for using portPOINTER_SIZE_TYPE type. */\r
716 \r
717                 /* Check the alignment of the calculated top of stack is correct. */\r
718                 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );\r
719         }\r
720         #else /* portSTACK_GROWTH */\r
721         {\r
722                 pxTopOfStack = pxNewTCB->pxStack;\r
723 \r
724                 /* Check the alignment of the stack buffer is correct. */\r
725                 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );\r
726 \r
727                 /* The other extreme of the stack space is required if stack checking is\r
728                 performed. */\r
729                 pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - ( uint16_t ) 1 );\r
730         }\r
731         #endif /* portSTACK_GROWTH */\r
732 \r
733         /* Store the task name in the TCB. */\r
734         for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )\r
735         {\r
736                 pxNewTCB->pcTaskName[ x ] = pcName[ x ];\r
737 \r
738                 /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than\r
739                 configMAX_TASK_NAME_LEN characters just in case the memory after the\r
740                 string is not accessible (extremely unlikely). */\r
741                 if( pcName[ x ] == 0x00 )\r
742                 {\r
743                         break;\r
744                 }\r
745                 else\r
746                 {\r
747                         mtCOVERAGE_TEST_MARKER();\r
748                 }\r
749         }\r
750 \r
751         /* Ensure the name string is terminated in the case that the string length\r
752         was greater or equal to configMAX_TASK_NAME_LEN. */\r
753         pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';\r
754 \r
755         /* This is used as an array index so must ensure it's not too large.  First\r
756         remove the privilege bit if one is present. */\r
757         if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )\r
758         {\r
759                 uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;\r
760         }\r
761         else\r
762         {\r
763                 mtCOVERAGE_TEST_MARKER();\r
764         }\r
765 \r
766         pxNewTCB->uxPriority = uxPriority;\r
767         #if ( configUSE_MUTEXES == 1 )\r
768         {\r
769                 pxNewTCB->uxBasePriority = uxPriority;\r
770                 pxNewTCB->uxMutexesHeld = 0;\r
771         }\r
772         #endif /* configUSE_MUTEXES */\r
773 \r
774         vListInitialiseItem( &( pxNewTCB->xStateListItem ) );\r
775         vListInitialiseItem( &( pxNewTCB->xEventListItem ) );\r
776 \r
777         /* Set the pxNewTCB as a link back from the ListItem_t.  This is so we can get\r
778         back to the containing TCB from a generic item in a list. */\r
779         listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );\r
780 \r
781         /* Event lists are always in priority order. */\r
782         listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
783         listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );\r
784 \r
785         #if ( portCRITICAL_NESTING_IN_TCB == 1 )\r
786         {\r
787                 pxNewTCB->uxCriticalNesting = ( UBaseType_t ) 0U;\r
788         }\r
789         #endif /* portCRITICAL_NESTING_IN_TCB */\r
790 \r
791         #if ( configUSE_APPLICATION_TASK_TAG == 1 )\r
792         {\r
793                 pxNewTCB->pxTaskTag = NULL;\r
794         }\r
795         #endif /* configUSE_APPLICATION_TASK_TAG */\r
796 \r
797         #if ( configGENERATE_RUN_TIME_STATS == 1 )\r
798         {\r
799                 pxNewTCB->ulRunTimeCounter = 0UL;\r
800         }\r
801         #endif /* configGENERATE_RUN_TIME_STATS */\r
802 \r
803         #if ( portUSING_MPU_WRAPPERS == 1 )\r
804         {\r
805                 vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, usStackDepth );\r
806         }\r
807         #endif\r
808 \r
809         #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )\r
810         {\r
811                 for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ )\r
812                 {\r
813                         pxNewTCB->pvThreadLocalStoragePointers[ x ] = NULL;\r
814                 }\r
815         }\r
816         #endif\r
817 \r
818         #if ( configUSE_TASK_NOTIFICATIONS == 1 )\r
819         {\r
820                 pxNewTCB->ulNotifiedValue = 0;\r
821                 pxNewTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;\r
822         }\r
823         #endif\r
824 \r
825         #if ( configUSE_NEWLIB_REENTRANT == 1 )\r
826         {\r
827                 /* Initialise this task's Newlib reent structure. */\r
828                 _REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) );\r
829         }\r
830         #endif\r
831 \r
832         #if( INCLUDE_xTaskAbortDelay == 1 )\r
833         {\r
834                 pxNewTCB->ucDelayAborted = pdFALSE;\r
835         }\r
836         #endif\r
837 \r
838         /* Initialize the TCB stack to look as if the task was already running,\r
839         but had been interrupted by the scheduler.  The return address is set\r
840         to the start of the task function. Once the stack has been initialised\r
841         the     top of stack variable is updated. */\r
842         #if( portUSING_MPU_WRAPPERS == 1 )\r
843         {\r
844                 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );\r
845         }\r
846         #else /* portUSING_MPU_WRAPPERS */\r
847         {\r
848                 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );\r
849         }\r
850         #endif /* portUSING_MPU_WRAPPERS */\r
851 \r
852         if( ( void * ) pxCreatedTask != NULL )\r
853         {\r
854                 /* Pass the handle out in an anonymous way.  The handle can be used to\r
855                 change the created task's priority, delete the created task, etc.*/\r
856                 *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;\r
857         }\r
858         else\r
859         {\r
860                 mtCOVERAGE_TEST_MARKER();\r
861         }\r
862 }\r
863 /*-----------------------------------------------------------*/\r
864 \r
865 static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )\r
866 {\r
867         /* Ensure interrupts don't access the task lists while the lists are being\r
868         updated. */\r
869         taskENTER_CRITICAL();\r
870         {\r
871                 uxCurrentNumberOfTasks++;\r
872                 if( pxCurrentTCB == NULL )\r
873                 {\r
874                         /* There are no other tasks, or all the other tasks are in\r
875                         the suspended state - make this the current task. */\r
876                         pxCurrentTCB = pxNewTCB;\r
877 \r
878                         if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )\r
879                         {\r
880                                 /* This is the first task to be created so do the preliminary\r
881                                 initialisation required.  We will not recover if this call\r
882                                 fails, but we will report the failure. */\r
883                                 prvInitialiseTaskLists();\r
884                         }\r
885                         else\r
886                         {\r
887                                 mtCOVERAGE_TEST_MARKER();\r
888                         }\r
889                 }\r
890                 else\r
891                 {\r
892                         /* If the scheduler is not already running, make this task the\r
893                         current task if it is the highest priority task to be created\r
894                         so far. */\r
895                         if( xSchedulerRunning == pdFALSE )\r
896                         {\r
897                                 if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )\r
898                                 {\r
899                                         pxCurrentTCB = pxNewTCB;\r
900                                 }\r
901                                 else\r
902                                 {\r
903                                         mtCOVERAGE_TEST_MARKER();\r
904                                 }\r
905                         }\r
906                         else\r
907                         {\r
908                                 mtCOVERAGE_TEST_MARKER();\r
909                         }\r
910                 }\r
911 \r
912                 uxTaskNumber++;\r
913 \r
914                 #if ( configUSE_TRACE_FACILITY == 1 )\r
915                 {\r
916                         /* Add a counter into the TCB for tracing only. */\r
917                         pxNewTCB->uxTCBNumber = uxTaskNumber;\r
918                 }\r
919                 #endif /* configUSE_TRACE_FACILITY */\r
920                 traceTASK_CREATE( pxNewTCB );\r
921 \r
922                 prvAddTaskToReadyList( pxNewTCB );\r
923 \r
924                 portSETUP_TCB( pxNewTCB );\r
925         }\r
926         taskEXIT_CRITICAL();\r
927 \r
928         if( xSchedulerRunning != pdFALSE )\r
929         {\r
930                 /* If the created task is of a higher priority than the current task\r
931                 then it should run now. */\r
932                 if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority )\r
933                 {\r
934                         taskYIELD_IF_USING_PREEMPTION();\r
935                 }\r
936                 else\r
937                 {\r
938                         mtCOVERAGE_TEST_MARKER();\r
939                 }\r
940         }\r
941         else\r
942         {\r
943                 mtCOVERAGE_TEST_MARKER();\r
944         }\r
945 }\r
946 /*-----------------------------------------------------------*/\r
947 \r
948 #if ( INCLUDE_vTaskDelete == 1 )\r
949 \r
950         void vTaskDelete( TaskHandle_t xTaskToDelete )\r
951         {\r
952         TCB_t *pxTCB;\r
953 \r
954                 taskENTER_CRITICAL();\r
955                 {\r
956                         /* If null is passed in here then it is the calling task that is\r
957                         being deleted. */\r
958                         pxTCB = prvGetTCBFromHandle( xTaskToDelete );\r
959 \r
960                         /* Remove task from the ready list. */\r
961                         if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )\r
962                         {\r
963                                 taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
964                         }\r
965                         else\r
966                         {\r
967                                 mtCOVERAGE_TEST_MARKER();\r
968                         }\r
969 \r
970                         /* Is the task waiting on an event also? */\r
971                         if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )\r
972                         {\r
973                                 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );\r
974                         }\r
975                         else\r
976                         {\r
977                                 mtCOVERAGE_TEST_MARKER();\r
978                         }\r
979 \r
980                         if( pxTCB == pxCurrentTCB )\r
981                         {\r
982                                 /* A task is deleting itself.  This cannot complete within the\r
983                                 task itself, as a context switch to another task is required.\r
984                                 Place the task in the termination list.  The idle task will\r
985                                 check the termination list and free up any memory allocated by\r
986                                 the scheduler for the TCB and stack of the deleted task. */\r
987                                 vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );\r
988 \r
989                                 /* Increment the ucTasksDeleted variable so the idle task knows\r
990                                 there is a task that has been deleted and that it should therefore\r
991                                 check the xTasksWaitingTermination list. */\r
992                                 ++uxDeletedTasksWaitingCleanUp;\r
993                         }\r
994                         else\r
995                         {\r
996                                 --uxCurrentNumberOfTasks;\r
997                                 prvDeleteTCB( pxTCB );\r
998                         }\r
999 \r
1000                         /* Increment the uxTaskNumber also so kernel aware debuggers can\r
1001                         detect that the task lists need re-generating. */\r
1002                         uxTaskNumber++;\r
1003 \r
1004                         traceTASK_DELETE( pxTCB );\r
1005                 }\r
1006                 taskEXIT_CRITICAL();\r
1007 \r
1008                 /* Force a reschedule if it is the currently running task that has just\r
1009                 been deleted. */\r
1010                 if( xSchedulerRunning != pdFALSE )\r
1011                 {\r
1012                         if( pxTCB == pxCurrentTCB )\r
1013                         {\r
1014                                 configASSERT( uxSchedulerSuspended == 0 );\r
1015 \r
1016                                 /* The pre-delete hook is primarily for the Windows simulator,\r
1017                                 in which Windows specific clean up operations are performed,\r
1018                                 after which it is not possible to yield away from this task -\r
1019                                 hence xYieldPending is used to latch that a context switch is\r
1020                                 required. */\r
1021                                 portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );\r
1022                                 portYIELD_WITHIN_API();\r
1023                         }\r
1024                         else\r
1025                         {\r
1026                                 /* Reset the next expected unblock time in case it referred to\r
1027                                 the task that has just been deleted. */\r
1028                                 taskENTER_CRITICAL();\r
1029                                 {\r
1030                                         prvResetNextTaskUnblockTime();\r
1031                                 }\r
1032                                 taskEXIT_CRITICAL();\r
1033                         }\r
1034                 }\r
1035         }\r
1036 \r
1037 #endif /* INCLUDE_vTaskDelete */\r
1038 /*-----------------------------------------------------------*/\r
1039 \r
1040 #if ( INCLUDE_vTaskDelayUntil == 1 )\r
1041 \r
1042         void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )\r
1043         {\r
1044         TickType_t xTimeToWake;\r
1045         BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;\r
1046 \r
1047                 configASSERT( pxPreviousWakeTime );\r
1048                 configASSERT( ( xTimeIncrement > 0U ) );\r
1049                 configASSERT( uxSchedulerSuspended == 0 );\r
1050 \r
1051                 vTaskSuspendAll();\r
1052                 {\r
1053                         /* Minor optimisation.  The tick count cannot change in this\r
1054                         block. */\r
1055                         const TickType_t xConstTickCount = xTickCount;\r
1056 \r
1057                         /* Generate the tick time at which the task wants to wake. */\r
1058                         xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;\r
1059 \r
1060                         if( xConstTickCount < *pxPreviousWakeTime )\r
1061                         {\r
1062                                 /* The tick count has overflowed since this function was\r
1063                                 lasted called.  In this case the only time we should ever\r
1064                                 actually delay is if the wake time has also     overflowed,\r
1065                                 and the wake time is greater than the tick time.  When this\r
1066                                 is the case it is as if neither time had overflowed. */\r
1067                                 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )\r
1068                                 {\r
1069                                         xShouldDelay = pdTRUE;\r
1070                                 }\r
1071                                 else\r
1072                                 {\r
1073                                         mtCOVERAGE_TEST_MARKER();\r
1074                                 }\r
1075                         }\r
1076                         else\r
1077                         {\r
1078                                 /* The tick time has not overflowed.  In this case we will\r
1079                                 delay if either the wake time has overflowed, and/or the\r
1080                                 tick time is less than the wake time. */\r
1081                                 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )\r
1082                                 {\r
1083                                         xShouldDelay = pdTRUE;\r
1084                                 }\r
1085                                 else\r
1086                                 {\r
1087                                         mtCOVERAGE_TEST_MARKER();\r
1088                                 }\r
1089                         }\r
1090 \r
1091                         /* Update the wake time ready for the next call. */\r
1092                         *pxPreviousWakeTime = xTimeToWake;\r
1093 \r
1094                         if( xShouldDelay != pdFALSE )\r
1095                         {\r
1096                                 traceTASK_DELAY_UNTIL( xTimeToWake );\r
1097 \r
1098                                 /* prvAddCurrentTaskToDelayedList() needs the block time, not\r
1099                                 the time to wake, so subtract the current tick count. */\r
1100                                 prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE );\r
1101                         }\r
1102                         else\r
1103                         {\r
1104                                 mtCOVERAGE_TEST_MARKER();\r
1105                         }\r
1106                 }\r
1107                 xAlreadyYielded = xTaskResumeAll();\r
1108 \r
1109                 /* Force a reschedule if xTaskResumeAll has not already done so, we may\r
1110                 have put ourselves to sleep. */\r
1111                 if( xAlreadyYielded == pdFALSE )\r
1112                 {\r
1113                         portYIELD_WITHIN_API();\r
1114                 }\r
1115                 else\r
1116                 {\r
1117                         mtCOVERAGE_TEST_MARKER();\r
1118                 }\r
1119         }\r
1120 \r
1121 #endif /* INCLUDE_vTaskDelayUntil */\r
1122 /*-----------------------------------------------------------*/\r
1123 \r
1124 #if ( INCLUDE_vTaskDelay == 1 )\r
1125 \r
1126         void vTaskDelay( const TickType_t xTicksToDelay )\r
1127         {\r
1128         BaseType_t xAlreadyYielded = pdFALSE;\r
1129 \r
1130                 /* A delay time of zero just forces a reschedule. */\r
1131                 if( xTicksToDelay > ( TickType_t ) 0U )\r
1132                 {\r
1133                         configASSERT( uxSchedulerSuspended == 0 );\r
1134                         vTaskSuspendAll();\r
1135                         {\r
1136                                 traceTASK_DELAY();\r
1137 \r
1138                                 /* A task that is removed from the event list while the\r
1139                                 scheduler is suspended will not get placed in the ready\r
1140                                 list or removed from the blocked list until the scheduler\r
1141                                 is resumed.\r
1142 \r
1143                                 This task cannot be in an event list as it is the currently\r
1144                                 executing task. */\r
1145                                 prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );\r
1146                         }\r
1147                         xAlreadyYielded = xTaskResumeAll();\r
1148                 }\r
1149                 else\r
1150                 {\r
1151                         mtCOVERAGE_TEST_MARKER();\r
1152                 }\r
1153 \r
1154                 /* Force a reschedule if xTaskResumeAll has not already done so, we may\r
1155                 have put ourselves to sleep. */\r
1156                 if( xAlreadyYielded == pdFALSE )\r
1157                 {\r
1158                         portYIELD_WITHIN_API();\r
1159                 }\r
1160                 else\r
1161                 {\r
1162                         mtCOVERAGE_TEST_MARKER();\r
1163                 }\r
1164         }\r
1165 \r
1166 #endif /* INCLUDE_vTaskDelay */\r
1167 /*-----------------------------------------------------------*/\r
1168 \r
1169 #if( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) )\r
1170 \r
1171         eTaskState eTaskGetState( TaskHandle_t xTask )\r
1172         {\r
1173         eTaskState eReturn;\r
1174         List_t *pxStateList;\r
1175         const TCB_t * const pxTCB = ( TCB_t * ) xTask;\r
1176 \r
1177                 configASSERT( pxTCB );\r
1178 \r
1179                 if( pxTCB == pxCurrentTCB )\r
1180                 {\r
1181                         /* The task calling this function is querying its own state. */\r
1182                         eReturn = eRunning;\r
1183                 }\r
1184                 else\r
1185                 {\r
1186                         taskENTER_CRITICAL();\r
1187                         {\r
1188                                 pxStateList = ( List_t * ) listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) );\r
1189                         }\r
1190                         taskEXIT_CRITICAL();\r
1191 \r
1192                         if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) )\r
1193                         {\r
1194                                 /* The task being queried is referenced from one of the Blocked\r
1195                                 lists. */\r
1196                                 eReturn = eBlocked;\r
1197                         }\r
1198 \r
1199                         #if ( INCLUDE_vTaskSuspend == 1 )\r
1200                                 else if( pxStateList == &xSuspendedTaskList )\r
1201                                 {\r
1202                                         /* The task being queried is referenced from the suspended\r
1203                                         list.  Is it genuinely suspended or is it block\r
1204                                         indefinitely? */\r
1205                                         if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )\r
1206                                         {\r
1207                                                 eReturn = eSuspended;\r
1208                                         }\r
1209                                         else\r
1210                                         {\r
1211                                                 eReturn = eBlocked;\r
1212                                         }\r
1213                                 }\r
1214                         #endif\r
1215 \r
1216                         #if ( INCLUDE_vTaskDelete == 1 )\r
1217                                 else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) )\r
1218                                 {\r
1219                                         /* The task being queried is referenced from the deleted\r
1220                                         tasks list, or it is not referenced from any lists at\r
1221                                         all. */\r
1222                                         eReturn = eDeleted;\r
1223                                 }\r
1224                         #endif\r
1225 \r
1226                         else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */\r
1227                         {\r
1228                                 /* If the task is not in any other state, it must be in the\r
1229                                 Ready (including pending ready) state. */\r
1230                                 eReturn = eReady;\r
1231                         }\r
1232                 }\r
1233 \r
1234                 return eReturn;\r
1235         } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */\r
1236 \r
1237 #endif /* INCLUDE_eTaskGetState */\r
1238 /*-----------------------------------------------------------*/\r
1239 \r
1240 #if ( INCLUDE_uxTaskPriorityGet == 1 )\r
1241 \r
1242         UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask )\r
1243         {\r
1244         TCB_t *pxTCB;\r
1245         UBaseType_t uxReturn;\r
1246 \r
1247                 taskENTER_CRITICAL();\r
1248                 {\r
1249                         /* If null is passed in here then it is the priority of the that\r
1250                         called uxTaskPriorityGet() that is being queried. */\r
1251                         pxTCB = prvGetTCBFromHandle( xTask );\r
1252                         uxReturn = pxTCB->uxPriority;\r
1253                 }\r
1254                 taskEXIT_CRITICAL();\r
1255 \r
1256                 return uxReturn;\r
1257         }\r
1258 \r
1259 #endif /* INCLUDE_uxTaskPriorityGet */\r
1260 /*-----------------------------------------------------------*/\r
1261 \r
1262 #if ( INCLUDE_uxTaskPriorityGet == 1 )\r
1263 \r
1264         UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask )\r
1265         {\r
1266         TCB_t *pxTCB;\r
1267         UBaseType_t uxReturn, uxSavedInterruptState;\r
1268 \r
1269                 /* RTOS ports that support interrupt nesting have the concept of a\r
1270                 maximum system call (or maximum API call) interrupt priority.\r
1271                 Interrupts that are     above the maximum system call priority are keep\r
1272                 permanently enabled, even when the RTOS kernel is in a critical section,\r
1273                 but cannot make any calls to FreeRTOS API functions.  If configASSERT()\r
1274                 is defined in FreeRTOSConfig.h then\r
1275                 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
1276                 failure if a FreeRTOS API function is called from an interrupt that has\r
1277                 been assigned a priority above the configured maximum system call\r
1278                 priority.  Only FreeRTOS functions that end in FromISR can be called\r
1279                 from interrupts that have been assigned a priority at or (logically)\r
1280                 below the maximum system call interrupt priority.  FreeRTOS maintains a\r
1281                 separate interrupt safe API to ensure interrupt entry is as fast and as\r
1282                 simple as possible.  More information (albeit Cortex-M specific) is\r
1283                 provided on the following link:\r
1284                 http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
1285                 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
1286 \r
1287                 uxSavedInterruptState = portSET_INTERRUPT_MASK_FROM_ISR();\r
1288                 {\r
1289                         /* If null is passed in here then it is the priority of the calling\r
1290                         task that is being queried. */\r
1291                         pxTCB = prvGetTCBFromHandle( xTask );\r
1292                         uxReturn = pxTCB->uxPriority;\r
1293                 }\r
1294                 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState );\r
1295 \r
1296                 return uxReturn;\r
1297         }\r
1298 \r
1299 #endif /* INCLUDE_uxTaskPriorityGet */\r
1300 /*-----------------------------------------------------------*/\r
1301 \r
1302 #if ( INCLUDE_vTaskPrioritySet == 1 )\r
1303 \r
1304         void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )\r
1305         {\r
1306         TCB_t *pxTCB;\r
1307         UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;\r
1308         BaseType_t xYieldRequired = pdFALSE;\r
1309 \r
1310                 configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );\r
1311 \r
1312                 /* Ensure the new priority is valid. */\r
1313                 if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )\r
1314                 {\r
1315                         uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;\r
1316                 }\r
1317                 else\r
1318                 {\r
1319                         mtCOVERAGE_TEST_MARKER();\r
1320                 }\r
1321 \r
1322                 taskENTER_CRITICAL();\r
1323                 {\r
1324                         /* If null is passed in here then it is the priority of the calling\r
1325                         task that is being changed. */\r
1326                         pxTCB = prvGetTCBFromHandle( xTask );\r
1327 \r
1328                         traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );\r
1329 \r
1330                         #if ( configUSE_MUTEXES == 1 )\r
1331                         {\r
1332                                 uxCurrentBasePriority = pxTCB->uxBasePriority;\r
1333                         }\r
1334                         #else\r
1335                         {\r
1336                                 uxCurrentBasePriority = pxTCB->uxPriority;\r
1337                         }\r
1338                         #endif\r
1339 \r
1340                         if( uxCurrentBasePriority != uxNewPriority )\r
1341                         {\r
1342                                 /* The priority change may have readied a task of higher\r
1343                                 priority than the calling task. */\r
1344                                 if( uxNewPriority > uxCurrentBasePriority )\r
1345                                 {\r
1346                                         if( pxTCB != pxCurrentTCB )\r
1347                                         {\r
1348                                                 /* The priority of a task other than the currently\r
1349                                                 running task is being raised.  Is the priority being\r
1350                                                 raised above that of the running task? */\r
1351                                                 if( uxNewPriority >= pxCurrentTCB->uxPriority )\r
1352                                                 {\r
1353                                                         xYieldRequired = pdTRUE;\r
1354                                                 }\r
1355                                                 else\r
1356                                                 {\r
1357                                                         mtCOVERAGE_TEST_MARKER();\r
1358                                                 }\r
1359                                         }\r
1360                                         else\r
1361                                         {\r
1362                                                 /* The priority of the running task is being raised,\r
1363                                                 but the running task must already be the highest\r
1364                                                 priority task able to run so no yield is required. */\r
1365                                         }\r
1366                                 }\r
1367                                 else if( pxTCB == pxCurrentTCB )\r
1368                                 {\r
1369                                         /* Setting the priority of the running task down means\r
1370                                         there may now be another task of higher priority that\r
1371                                         is ready to execute. */\r
1372                                         xYieldRequired = pdTRUE;\r
1373                                 }\r
1374                                 else\r
1375                                 {\r
1376                                         /* Setting the priority of any other task down does not\r
1377                                         require a yield as the running task must be above the\r
1378                                         new priority of the task being modified. */\r
1379                                 }\r
1380 \r
1381                                 /* Remember the ready list the task might be referenced from\r
1382                                 before its uxPriority member is changed so the\r
1383                                 taskRESET_READY_PRIORITY() macro can function correctly. */\r
1384                                 uxPriorityUsedOnEntry = pxTCB->uxPriority;\r
1385 \r
1386                                 #if ( configUSE_MUTEXES == 1 )\r
1387                                 {\r
1388                                         /* Only change the priority being used if the task is not\r
1389                                         currently using an inherited priority. */\r
1390                                         if( pxTCB->uxBasePriority == pxTCB->uxPriority )\r
1391                                         {\r
1392                                                 pxTCB->uxPriority = uxNewPriority;\r
1393                                         }\r
1394                                         else\r
1395                                         {\r
1396                                                 mtCOVERAGE_TEST_MARKER();\r
1397                                         }\r
1398 \r
1399                                         /* The base priority gets set whatever. */\r
1400                                         pxTCB->uxBasePriority = uxNewPriority;\r
1401                                 }\r
1402                                 #else\r
1403                                 {\r
1404                                         pxTCB->uxPriority = uxNewPriority;\r
1405                                 }\r
1406                                 #endif\r
1407 \r
1408                                 /* Only reset the event list item value if the value is not\r
1409                                 being used for anything else. */\r
1410                                 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )\r
1411                                 {\r
1412                                         listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
1413                                 }\r
1414                                 else\r
1415                                 {\r
1416                                         mtCOVERAGE_TEST_MARKER();\r
1417                                 }\r
1418 \r
1419                                 /* If the task is in the blocked or suspended list we need do\r
1420                                 nothing more than change it's priority variable. However, if\r
1421                                 the task is in a ready list it needs to be removed and placed\r
1422                                 in the list appropriate to its new priority. */\r
1423                                 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )\r
1424                                 {\r
1425                                         /* The task is currently in its ready list - remove before adding\r
1426                                         it to it's new ready list.  As we are in a critical section we\r
1427                                         can do this even if the scheduler is suspended. */\r
1428                                         if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )\r
1429                                         {\r
1430                                                 /* It is known that the task is in its ready list so\r
1431                                                 there is no need to check again and the port level\r
1432                                                 reset macro can be called directly. */\r
1433                                                 portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );\r
1434                                         }\r
1435                                         else\r
1436                                         {\r
1437                                                 mtCOVERAGE_TEST_MARKER();\r
1438                                         }\r
1439                                         prvAddTaskToReadyList( pxTCB );\r
1440                                 }\r
1441                                 else\r
1442                                 {\r
1443                                         mtCOVERAGE_TEST_MARKER();\r
1444                                 }\r
1445 \r
1446                                 if( xYieldRequired != pdFALSE )\r
1447                                 {\r
1448                                         taskYIELD_IF_USING_PREEMPTION();\r
1449                                 }\r
1450                                 else\r
1451                                 {\r
1452                                         mtCOVERAGE_TEST_MARKER();\r
1453                                 }\r
1454 \r
1455                                 /* Remove compiler warning about unused variables when the port\r
1456                                 optimised task selection is not being used. */\r
1457                                 ( void ) uxPriorityUsedOnEntry;\r
1458                         }\r
1459                 }\r
1460                 taskEXIT_CRITICAL();\r
1461         }\r
1462 \r
1463 #endif /* INCLUDE_vTaskPrioritySet */\r
1464 /*-----------------------------------------------------------*/\r
1465 \r
1466 #if ( INCLUDE_vTaskSuspend == 1 )\r
1467 \r
1468         void vTaskSuspend( TaskHandle_t xTaskToSuspend )\r
1469         {\r
1470         TCB_t *pxTCB;\r
1471 \r
1472                 taskENTER_CRITICAL();\r
1473                 {\r
1474                         /* If null is passed in here then it is the running task that is\r
1475                         being suspended. */\r
1476                         pxTCB = prvGetTCBFromHandle( xTaskToSuspend );\r
1477 \r
1478                         traceTASK_SUSPEND( pxTCB );\r
1479 \r
1480                         /* Remove task from the ready/delayed list and place in the\r
1481                         suspended list. */\r
1482                         if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )\r
1483                         {\r
1484                                 taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
1485                         }\r
1486                         else\r
1487                         {\r
1488                                 mtCOVERAGE_TEST_MARKER();\r
1489                         }\r
1490 \r
1491                         /* Is the task waiting on an event also? */\r
1492                         if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )\r
1493                         {\r
1494                                 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );\r
1495                         }\r
1496                         else\r
1497                         {\r
1498                                 mtCOVERAGE_TEST_MARKER();\r
1499                         }\r
1500 \r
1501                         vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );\r
1502                 }\r
1503                 taskEXIT_CRITICAL();\r
1504 \r
1505                 if( xSchedulerRunning != pdFALSE )\r
1506                 {\r
1507                         /* Reset the next expected unblock time in case it referred to the\r
1508                         task that is now in the Suspended state. */\r
1509                         taskENTER_CRITICAL();\r
1510                         {\r
1511                                 prvResetNextTaskUnblockTime();\r
1512                         }\r
1513                         taskEXIT_CRITICAL();\r
1514                 }\r
1515                 else\r
1516                 {\r
1517                         mtCOVERAGE_TEST_MARKER();\r
1518                 }\r
1519 \r
1520                 if( pxTCB == pxCurrentTCB )\r
1521                 {\r
1522                         if( xSchedulerRunning != pdFALSE )\r
1523                         {\r
1524                                 /* The current task has just been suspended. */\r
1525                                 configASSERT( uxSchedulerSuspended == 0 );\r
1526                                 portYIELD_WITHIN_API();\r
1527                         }\r
1528                         else\r
1529                         {\r
1530                                 /* The scheduler is not running, but the task that was pointed\r
1531                                 to by pxCurrentTCB has just been suspended and pxCurrentTCB\r
1532                                 must be adjusted to point to a different task. */\r
1533                                 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )\r
1534                                 {\r
1535                                         /* No other tasks are ready, so set pxCurrentTCB back to\r
1536                                         NULL so when the next task is created pxCurrentTCB will\r
1537                                         be set to point to it no matter what its relative priority\r
1538                                         is. */\r
1539                                         pxCurrentTCB = NULL;\r
1540                                 }\r
1541                                 else\r
1542                                 {\r
1543                                         vTaskSwitchContext();\r
1544                                 }\r
1545                         }\r
1546                 }\r
1547                 else\r
1548                 {\r
1549                         mtCOVERAGE_TEST_MARKER();\r
1550                 }\r
1551         }\r
1552 \r
1553 #endif /* INCLUDE_vTaskSuspend */\r
1554 /*-----------------------------------------------------------*/\r
1555 \r
1556 #if ( INCLUDE_vTaskSuspend == 1 )\r
1557 \r
1558         static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )\r
1559         {\r
1560         BaseType_t xReturn = pdFALSE;\r
1561         const TCB_t * const pxTCB = ( TCB_t * ) xTask;\r
1562 \r
1563                 /* Accesses xPendingReadyList so must be called from a critical\r
1564                 section. */\r
1565 \r
1566                 /* It does not make sense to check if the calling task is suspended. */\r
1567                 configASSERT( xTask );\r
1568 \r
1569                 /* Is the task being resumed actually in the suspended list? */\r
1570                 if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE )\r
1571                 {\r
1572                         /* Has the task already been resumed from within an ISR? */\r
1573                         if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )\r
1574                         {\r
1575                                 /* Is it in the suspended list because it is in the     Suspended\r
1576                                 state, or because is is blocked with no timeout? */\r
1577                                 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )\r
1578                                 {\r
1579                                         xReturn = pdTRUE;\r
1580                                 }\r
1581                                 else\r
1582                                 {\r
1583                                         mtCOVERAGE_TEST_MARKER();\r
1584                                 }\r
1585                         }\r
1586                         else\r
1587                         {\r
1588                                 mtCOVERAGE_TEST_MARKER();\r
1589                         }\r
1590                 }\r
1591                 else\r
1592                 {\r
1593                         mtCOVERAGE_TEST_MARKER();\r
1594                 }\r
1595 \r
1596                 return xReturn;\r
1597         } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */\r
1598 \r
1599 #endif /* INCLUDE_vTaskSuspend */\r
1600 /*-----------------------------------------------------------*/\r
1601 \r
1602 #if ( INCLUDE_vTaskSuspend == 1 )\r
1603 \r
1604         void vTaskResume( TaskHandle_t xTaskToResume )\r
1605         {\r
1606         TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;\r
1607 \r
1608                 /* It does not make sense to resume the calling task. */\r
1609                 configASSERT( xTaskToResume );\r
1610 \r
1611                 /* The parameter cannot be NULL as it is impossible to resume the\r
1612                 currently executing task. */\r
1613                 if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )\r
1614                 {\r
1615                         taskENTER_CRITICAL();\r
1616                         {\r
1617                                 if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )\r
1618                                 {\r
1619                                         traceTASK_RESUME( pxTCB );\r
1620 \r
1621                                         /* As we are in a critical section we can access the ready\r
1622                                         lists even if the scheduler is suspended. */\r
1623                                         ( void ) uxListRemove(  &( pxTCB->xStateListItem ) );\r
1624                                         prvAddTaskToReadyList( pxTCB );\r
1625 \r
1626                                         /* We may have just resumed a higher priority task. */\r
1627                                         if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )\r
1628                                         {\r
1629                                                 /* This yield may not cause the task just resumed to run,\r
1630                                                 but will leave the lists in the correct state for the\r
1631                                                 next yield. */\r
1632                                                 taskYIELD_IF_USING_PREEMPTION();\r
1633                                         }\r
1634                                         else\r
1635                                         {\r
1636                                                 mtCOVERAGE_TEST_MARKER();\r
1637                                         }\r
1638                                 }\r
1639                                 else\r
1640                                 {\r
1641                                         mtCOVERAGE_TEST_MARKER();\r
1642                                 }\r
1643                         }\r
1644                         taskEXIT_CRITICAL();\r
1645                 }\r
1646                 else\r
1647                 {\r
1648                         mtCOVERAGE_TEST_MARKER();\r
1649                 }\r
1650         }\r
1651 \r
1652 #endif /* INCLUDE_vTaskSuspend */\r
1653 \r
1654 /*-----------------------------------------------------------*/\r
1655 \r
1656 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )\r
1657 \r
1658         BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )\r
1659         {\r
1660         BaseType_t xYieldRequired = pdFALSE;\r
1661         TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;\r
1662         UBaseType_t uxSavedInterruptStatus;\r
1663 \r
1664                 configASSERT( xTaskToResume );\r
1665 \r
1666                 /* RTOS ports that support interrupt nesting have the concept of a\r
1667                 maximum system call (or maximum API call) interrupt priority.\r
1668                 Interrupts that are     above the maximum system call priority are keep\r
1669                 permanently enabled, even when the RTOS kernel is in a critical section,\r
1670                 but cannot make any calls to FreeRTOS API functions.  If configASSERT()\r
1671                 is defined in FreeRTOSConfig.h then\r
1672                 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
1673                 failure if a FreeRTOS API function is called from an interrupt that has\r
1674                 been assigned a priority above the configured maximum system call\r
1675                 priority.  Only FreeRTOS functions that end in FromISR can be called\r
1676                 from interrupts that have been assigned a priority at or (logically)\r
1677                 below the maximum system call interrupt priority.  FreeRTOS maintains a\r
1678                 separate interrupt safe API to ensure interrupt entry is as fast and as\r
1679                 simple as possible.  More information (albeit Cortex-M specific) is\r
1680                 provided on the following link:\r
1681                 http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
1682                 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
1683 \r
1684                 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
1685                 {\r
1686                         if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )\r
1687                         {\r
1688                                 traceTASK_RESUME_FROM_ISR( pxTCB );\r
1689 \r
1690                                 /* Check the ready lists can be accessed. */\r
1691                                 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )\r
1692                                 {\r
1693                                         /* Ready lists can be accessed so move the task from the\r
1694                                         suspended list to the ready list directly. */\r
1695                                         if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )\r
1696                                         {\r
1697                                                 xYieldRequired = pdTRUE;\r
1698                                         }\r
1699                                         else\r
1700                                         {\r
1701                                                 mtCOVERAGE_TEST_MARKER();\r
1702                                         }\r
1703 \r
1704                                         ( void ) uxListRemove( &( pxTCB->xStateListItem ) );\r
1705                                         prvAddTaskToReadyList( pxTCB );\r
1706                                 }\r
1707                                 else\r
1708                                 {\r
1709                                         /* The delayed or ready lists cannot be accessed so the task\r
1710                                         is held in the pending ready list until the scheduler is\r
1711                                         unsuspended. */\r
1712                                         vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );\r
1713                                 }\r
1714                         }\r
1715                         else\r
1716                         {\r
1717                                 mtCOVERAGE_TEST_MARKER();\r
1718                         }\r
1719                 }\r
1720                 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
1721 \r
1722                 return xYieldRequired;\r
1723         }\r
1724 \r
1725 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */\r
1726 /*-----------------------------------------------------------*/\r
1727 \r
1728 void vTaskStartScheduler( void )\r
1729 {\r
1730 BaseType_t xReturn;\r
1731 uint16_t usIdleTaskStackSize = configMINIMAL_STACK_SIZE;\r
1732 \r
1733         /* Add the idle task at the lowest priority. */\r
1734         #if( configSUPPORT_STATIC_ALLOCATION == 1 )\r
1735         {\r
1736                 StaticTask_t *pxIdleTaskTCBBuffer = NULL;\r
1737                 StackType_t *pxIdleTaskStackBuffer = NULL;\r
1738 \r
1739                 /* The Idle task is created using user provided RAM - obtain the\r
1740                 address of the RAM then create the idle task. */\r
1741                 vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &usIdleTaskStackSize );\r
1742                 xReturn = xTaskCreateStatic( prvIdleTask, "IDLE", usIdleTaskStackSize, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle, pxIdleTaskStackBuffer, pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */\r
1743         }\r
1744         #else\r
1745         {\r
1746                 /* The Idle task is being created using dynamically allocated RAM. */\r
1747                 xReturn = xTaskCreate( prvIdleTask, "IDLE", usIdleTaskStackSize, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */\r
1748         }\r
1749         #endif /* configSUPPORT_STATIC_ALLOCATION */\r
1750 \r
1751         #if ( configUSE_TIMERS == 1 )\r
1752         {\r
1753                 if( xReturn == pdPASS )\r
1754                 {\r
1755                         xReturn = xTimerCreateTimerTask();\r
1756                 }\r
1757                 else\r
1758                 {\r
1759                         mtCOVERAGE_TEST_MARKER();\r
1760                 }\r
1761         }\r
1762         #endif /* configUSE_TIMERS */\r
1763 \r
1764         if( xReturn == pdPASS )\r
1765         {\r
1766                 /* Interrupts are turned off here, to ensure a tick does not occur\r
1767                 before or during the call to xPortStartScheduler().  The stacks of\r
1768                 the created tasks contain a status word with interrupts switched on\r
1769                 so interrupts will automatically get re-enabled when the first task\r
1770                 starts to run. */\r
1771                 portDISABLE_INTERRUPTS();\r
1772 \r
1773                 #if ( configUSE_NEWLIB_REENTRANT == 1 )\r
1774                 {\r
1775                         /* Switch Newlib's _impure_ptr variable to point to the _reent\r
1776                         structure specific to the task that will run first. */\r
1777                         _impure_ptr = &( pxCurrentTCB->xNewLib_reent );\r
1778                 }\r
1779                 #endif /* configUSE_NEWLIB_REENTRANT */\r
1780 \r
1781                 xNextTaskUnblockTime = portMAX_DELAY;\r
1782                 xSchedulerRunning = pdTRUE;\r
1783                 xTickCount = ( TickType_t ) 0U;\r
1784 \r
1785                 /* If configGENERATE_RUN_TIME_STATS is defined then the following\r
1786                 macro must be defined to configure the timer/counter used to generate\r
1787                 the run time counter time base. */\r
1788                 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();\r
1789 \r
1790                 /* Setting up the timer tick is hardware specific and thus in the\r
1791                 portable interface. */\r
1792                 if( xPortStartScheduler() != pdFALSE )\r
1793                 {\r
1794                         /* Should not reach here as if the scheduler is running the\r
1795                         function will not return. */\r
1796                 }\r
1797                 else\r
1798                 {\r
1799                         /* Should only reach here if a task calls xTaskEndScheduler(). */\r
1800                 }\r
1801         }\r
1802         else\r
1803         {\r
1804                 /* This line will only be reached if the kernel could not be started,\r
1805                 because there was not enough FreeRTOS heap to create the idle task\r
1806                 or the timer task. */\r
1807                 configASSERT( xReturn );\r
1808         }\r
1809 \r
1810         /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,\r
1811         meaning xIdleTaskHandle is not used anywhere else. */\r
1812         ( void ) xIdleTaskHandle;\r
1813 }\r
1814 /*-----------------------------------------------------------*/\r
1815 \r
1816 void vTaskEndScheduler( void )\r
1817 {\r
1818         /* Stop the scheduler interrupts and call the portable scheduler end\r
1819         routine so the original ISRs can be restored if necessary.  The port\r
1820         layer must ensure interrupts enable     bit is left in the correct state. */\r
1821         portDISABLE_INTERRUPTS();\r
1822         xSchedulerRunning = pdFALSE;\r
1823         vPortEndScheduler();\r
1824 }\r
1825 /*----------------------------------------------------------*/\r
1826 \r
1827 void vTaskSuspendAll( void )\r
1828 {\r
1829         /* A critical section is not required as the variable is of type\r
1830         BaseType_t.  Please read Richard Barry's reply in the following link to a\r
1831         post in the FreeRTOS support forum before reporting this as a bug! -\r
1832         http://goo.gl/wu4acr */\r
1833         ++uxSchedulerSuspended;\r
1834 }\r
1835 /*----------------------------------------------------------*/\r
1836 \r
1837 #if ( configUSE_TICKLESS_IDLE != 0 )\r
1838 \r
1839         static TickType_t prvGetExpectedIdleTime( void )\r
1840         {\r
1841         TickType_t xReturn;\r
1842         UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;\r
1843 \r
1844                 /* uxHigherPriorityReadyTasks takes care of the case where\r
1845                 configUSE_PREEMPTION is 0, so there may be tasks above the idle priority\r
1846                 task that are in the Ready state, even though the idle task is\r
1847                 running. */\r
1848                 #if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )\r
1849                 {\r
1850                         if( uxTopReadyPriority > tskIDLE_PRIORITY )\r
1851                         {\r
1852                                 uxHigherPriorityReadyTasks = pdTRUE;\r
1853                         }\r
1854                 }\r
1855                 #else\r
1856                 {\r
1857                         const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;\r
1858 \r
1859                         /* When port optimised task selection is used the uxTopReadyPriority\r
1860                         variable is used as a bit map.  If bits other than the least\r
1861                         significant bit are set then there are tasks that have a priority\r
1862                         above the idle priority that are in the Ready state.  This takes\r
1863                         care of the case where the co-operative scheduler is in use. */\r
1864                         if( uxTopReadyPriority > uxLeastSignificantBit )\r
1865                         {\r
1866                                 uxHigherPriorityReadyTasks = pdTRUE;\r
1867                         }\r
1868                 }\r
1869                 #endif\r
1870 \r
1871                 if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )\r
1872                 {\r
1873                         xReturn = 0;\r
1874                 }\r
1875                 else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )\r
1876                 {\r
1877                         /* There are other idle priority tasks in the ready state.  If\r
1878                         time slicing is used then the very next tick interrupt must be\r
1879                         processed. */\r
1880                         xReturn = 0;\r
1881                 }\r
1882                 else if( uxHigherPriorityReadyTasks != pdFALSE )\r
1883                 {\r
1884                         /* There are tasks in the Ready state that have a priority above the\r
1885                         idle priority.  This path can only be reached if\r
1886                         configUSE_PREEMPTION is 0. */\r
1887                         xReturn = 0;\r
1888                 }\r
1889                 else\r
1890                 {\r
1891                         xReturn = xNextTaskUnblockTime - xTickCount;\r
1892                 }\r
1893 \r
1894                 return xReturn;\r
1895         }\r
1896 \r
1897 #endif /* configUSE_TICKLESS_IDLE */\r
1898 /*----------------------------------------------------------*/\r
1899 \r
1900 BaseType_t xTaskResumeAll( void )\r
1901 {\r
1902 TCB_t *pxTCB = NULL;\r
1903 BaseType_t xAlreadyYielded = pdFALSE;\r
1904 \r
1905         /* If uxSchedulerSuspended is zero then this function does not match a\r
1906         previous call to vTaskSuspendAll(). */\r
1907         configASSERT( uxSchedulerSuspended );\r
1908 \r
1909         /* It is possible that an ISR caused a task to be removed from an event\r
1910         list while the scheduler was suspended.  If this was the case then the\r
1911         removed task will have been added to the xPendingReadyList.  Once the\r
1912         scheduler has been resumed it is safe to move all the pending ready\r
1913         tasks from this list into their appropriate ready list. */\r
1914         taskENTER_CRITICAL();\r
1915         {\r
1916                 --uxSchedulerSuspended;\r
1917 \r
1918                 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )\r
1919                 {\r
1920                         if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )\r
1921                         {\r
1922                                 /* Move any readied tasks from the pending list into the\r
1923                                 appropriate ready list. */\r
1924                                 while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )\r
1925                                 {\r
1926                                         pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );\r
1927                                         ( void ) uxListRemove( &( pxTCB->xEventListItem ) );\r
1928                                         ( void ) uxListRemove( &( pxTCB->xStateListItem ) );\r
1929                                         prvAddTaskToReadyList( pxTCB );\r
1930 \r
1931                                         /* If the moved task has a priority higher than the current\r
1932                                         task then a yield must be performed. */\r
1933                                         if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )\r
1934                                         {\r
1935                                                 xYieldPending = pdTRUE;\r
1936                                         }\r
1937                                         else\r
1938                                         {\r
1939                                                 mtCOVERAGE_TEST_MARKER();\r
1940                                         }\r
1941                                 }\r
1942 \r
1943                                 if( pxTCB != NULL )\r
1944                                 {\r
1945                                         /* A task was unblocked while the scheduler was suspended,\r
1946                                         which may have prevented the next unblock time from being\r
1947                                         re-calculated, in which case re-calculate it now.  Mainly\r
1948                                         important for low power tickless implementations, where\r
1949                                         this can prevent an unnecessary exit from low power\r
1950                                         state. */\r
1951                                         prvResetNextTaskUnblockTime();\r
1952                                 }\r
1953 \r
1954                                 /* If any ticks occurred while the scheduler was suspended then\r
1955                                 they should be processed now.  This ensures the tick count does\r
1956                                 not     slip, and that any delayed tasks are resumed at the correct\r
1957                                 time. */\r
1958                                 if( uxPendedTicks > ( UBaseType_t ) 0U )\r
1959                                 {\r
1960                                         while( uxPendedTicks > ( UBaseType_t ) 0U )\r
1961                                         {\r
1962                                                 if( xTaskIncrementTick() != pdFALSE )\r
1963                                                 {\r
1964                                                         xYieldPending = pdTRUE;\r
1965                                                 }\r
1966                                                 else\r
1967                                                 {\r
1968                                                         mtCOVERAGE_TEST_MARKER();\r
1969                                                 }\r
1970                                                 --uxPendedTicks;\r
1971                                         }\r
1972                                 }\r
1973                                 else\r
1974                                 {\r
1975                                         mtCOVERAGE_TEST_MARKER();\r
1976                                 }\r
1977 \r
1978                                 if( xYieldPending != pdFALSE )\r
1979                                 {\r
1980                                         #if( configUSE_PREEMPTION != 0 )\r
1981                                         {\r
1982                                                 xAlreadyYielded = pdTRUE;\r
1983                                         }\r
1984                                         #endif\r
1985                                         taskYIELD_IF_USING_PREEMPTION();\r
1986                                 }\r
1987                                 else\r
1988                                 {\r
1989                                         mtCOVERAGE_TEST_MARKER();\r
1990                                 }\r
1991                         }\r
1992                 }\r
1993                 else\r
1994                 {\r
1995                         mtCOVERAGE_TEST_MARKER();\r
1996                 }\r
1997         }\r
1998         taskEXIT_CRITICAL();\r
1999 \r
2000         return xAlreadyYielded;\r
2001 }\r
2002 /*-----------------------------------------------------------*/\r
2003 \r
2004 TickType_t xTaskGetTickCount( void )\r
2005 {\r
2006 TickType_t xTicks;\r
2007 \r
2008         /* Critical section required if running on a 16 bit processor. */\r
2009         portTICK_TYPE_ENTER_CRITICAL();\r
2010         {\r
2011                 xTicks = xTickCount;\r
2012         }\r
2013         portTICK_TYPE_EXIT_CRITICAL();\r
2014 \r
2015         return xTicks;\r
2016 }\r
2017 /*-----------------------------------------------------------*/\r
2018 \r
2019 TickType_t xTaskGetTickCountFromISR( void )\r
2020 {\r
2021 TickType_t xReturn;\r
2022 UBaseType_t uxSavedInterruptStatus;\r
2023 \r
2024         /* RTOS ports that support interrupt nesting have the concept of a maximum\r
2025         system call (or maximum API call) interrupt priority.  Interrupts that are\r
2026         above the maximum system call priority are kept permanently enabled, even\r
2027         when the RTOS kernel is in a critical section, but cannot make any calls to\r
2028         FreeRTOS API functions.  If configASSERT() is defined in FreeRTOSConfig.h\r
2029         then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
2030         failure if a FreeRTOS API function is called from an interrupt that has been\r
2031         assigned a priority above the configured maximum system call priority.\r
2032         Only FreeRTOS functions that end in FromISR can be called from interrupts\r
2033         that have been assigned a priority at or (logically) below the maximum\r
2034         system call     interrupt priority.  FreeRTOS maintains a separate interrupt\r
2035         safe API to ensure interrupt entry is as fast and as simple as possible.\r
2036         More information (albeit Cortex-M specific) is provided on the following\r
2037         link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
2038         portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
2039 \r
2040         uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR();\r
2041         {\r
2042                 xReturn = xTickCount;\r
2043         }\r
2044         portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
2045 \r
2046         return xReturn;\r
2047 }\r
2048 /*-----------------------------------------------------------*/\r
2049 \r
2050 UBaseType_t uxTaskGetNumberOfTasks( void )\r
2051 {\r
2052         /* A critical section is not required because the variables are of type\r
2053         BaseType_t. */\r
2054         return uxCurrentNumberOfTasks;\r
2055 }\r
2056 /*-----------------------------------------------------------*/\r
2057 \r
2058 #if ( INCLUDE_pcTaskGetTaskName == 1 )\r
2059 \r
2060         char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
2061         {\r
2062         TCB_t *pxTCB;\r
2063 \r
2064                 /* If null is passed in here then the name of the calling task is being\r
2065                 queried. */\r
2066                 pxTCB = prvGetTCBFromHandle( xTaskToQuery );\r
2067                 configASSERT( pxTCB );\r
2068                 return &( pxTCB->pcTaskName[ 0 ] );\r
2069         }\r
2070 \r
2071 #endif /* INCLUDE_pcTaskGetTaskName */\r
2072 /*-----------------------------------------------------------*/\r
2073 \r
2074 #if ( INCLUDE_xTaskGetTaskHandle == 1 )\r
2075 \r
2076         static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] )\r
2077         {\r
2078         TCB_t *pxNextTCB, *pxFirstTCB, *pxReturn = NULL;\r
2079         UBaseType_t x;\r
2080         char cNextChar;\r
2081 \r
2082                 /* This function is called with the scheduler suspended. */\r
2083 \r
2084                 if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )\r
2085                 {\r
2086                         listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );\r
2087 \r
2088                         do\r
2089                         {\r
2090                                 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );\r
2091 \r
2092                                 /* Check each character in the name looking for a match or\r
2093                                 mismatch. */\r
2094                                 for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )\r
2095                                 {\r
2096                                         cNextChar = pxNextTCB->pcTaskName[ x ];\r
2097 \r
2098                                         if( cNextChar != pcNameToQuery[ x ] )\r
2099                                         {\r
2100                                                 /* Characters didn't match. */\r
2101                                                 break;\r
2102                                         }\r
2103                                         else if( cNextChar == 0x00 )\r
2104                                         {\r
2105                                                 /* Both strings terminated, a match must have been\r
2106                                                 found. */\r
2107                                                 pxReturn = pxNextTCB;\r
2108                                                 break;\r
2109                                         }\r
2110                                         else\r
2111                                         {\r
2112                                                 mtCOVERAGE_TEST_MARKER();\r
2113                                         }\r
2114                                 }\r
2115 \r
2116                                 if( pxReturn != NULL )\r
2117                                 {\r
2118                                         /* The handle has been found. */\r
2119                                         break;\r
2120                                 }\r
2121 \r
2122                         } while( pxNextTCB != pxFirstTCB );\r
2123                 }\r
2124                 else\r
2125                 {\r
2126                         mtCOVERAGE_TEST_MARKER();\r
2127                 }\r
2128 \r
2129                 return pxReturn;\r
2130         }\r
2131 \r
2132 #endif /* INCLUDE_xTaskGetTaskHandle */\r
2133 /*-----------------------------------------------------------*/\r
2134 \r
2135 #if ( INCLUDE_xTaskGetTaskHandle == 1 )\r
2136 \r
2137         TaskHandle_t xTaskGetTaskHandle( const char *pcNameToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */\r
2138         {\r
2139         UBaseType_t uxQueue = configMAX_PRIORITIES;\r
2140         TCB_t* pxTCB;\r
2141 \r
2142                 /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */\r
2143                 configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN );\r
2144 \r
2145                 vTaskSuspendAll();\r
2146                 {\r
2147                         /* Search the ready lists. */\r
2148                         do\r
2149                         {\r
2150                                 uxQueue--;\r
2151                                 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery );\r
2152 \r
2153                                 if( pxTCB != NULL )\r
2154                                 {\r
2155                                         /* Found the handle. */\r
2156                                         break;\r
2157                                 }\r
2158 \r
2159                         } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
2160 \r
2161                         /* Search the delayed lists. */\r
2162                         if( pxTCB == NULL )\r
2163                         {\r
2164                                 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery );\r
2165                         }\r
2166 \r
2167                         if( pxTCB == NULL )\r
2168                         {\r
2169                                 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery );\r
2170                         }\r
2171 \r
2172                         #if ( INCLUDE_vTaskSuspend == 1 )\r
2173                         {\r
2174                                 if( pxTCB == NULL )\r
2175                                 {\r
2176                                         /* Search the suspended list. */\r
2177                                         pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery );\r
2178                                 }\r
2179                         }\r
2180                         #endif\r
2181 \r
2182                         #if( INCLUDE_vTaskDelete == 1 )\r
2183                         {\r
2184                                 if( pxTCB == NULL )\r
2185                                 {\r
2186                                         /* Search the deleted list. */\r
2187                                         pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery );\r
2188                                 }\r
2189                         }\r
2190                         #endif\r
2191                 }\r
2192                 ( void ) xTaskResumeAll();\r
2193 \r
2194                 return ( TaskHandle_t ) pxTCB;\r
2195         }\r
2196 \r
2197 #endif /* INCLUDE_xTaskGetTaskHandle */\r
2198 /*-----------------------------------------------------------*/\r
2199 \r
2200 #if ( configUSE_TRACE_FACILITY == 1 )\r
2201 \r
2202         UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime )\r
2203         {\r
2204         UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;\r
2205 \r
2206                 vTaskSuspendAll();\r
2207                 {\r
2208                         /* Is there a space in the array for each task in the system? */\r
2209                         if( uxArraySize >= uxCurrentNumberOfTasks )\r
2210                         {\r
2211                                 /* Fill in an TaskStatus_t structure with information on each\r
2212                                 task in the Ready state. */\r
2213                                 do\r
2214                                 {\r
2215                                         uxQueue--;\r
2216                                         uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );\r
2217 \r
2218                                 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
2219 \r
2220                                 /* Fill in an TaskStatus_t structure with information on each\r
2221                                 task in the Blocked state. */\r
2222                                 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );\r
2223                                 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );\r
2224 \r
2225                                 #if( INCLUDE_vTaskDelete == 1 )\r
2226                                 {\r
2227                                         /* Fill in an TaskStatus_t structure with information on\r
2228                                         each task that has been deleted but not yet cleaned up. */\r
2229                                         uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );\r
2230                                 }\r
2231                                 #endif\r
2232 \r
2233                                 #if ( INCLUDE_vTaskSuspend == 1 )\r
2234                                 {\r
2235                                         /* Fill in an TaskStatus_t structure with information on\r
2236                                         each task in the Suspended state. */\r
2237                                         uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );\r
2238                                 }\r
2239                                 #endif\r
2240 \r
2241                                 #if ( configGENERATE_RUN_TIME_STATS == 1)\r
2242                                 {\r
2243                                         if( pulTotalRunTime != NULL )\r
2244                                         {\r
2245                                                 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE\r
2246                                                         portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );\r
2247                                                 #else\r
2248                                                         *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();\r
2249                                                 #endif\r
2250                                         }\r
2251                                 }\r
2252                                 #else\r
2253                                 {\r
2254                                         if( pulTotalRunTime != NULL )\r
2255                                         {\r
2256                                                 *pulTotalRunTime = 0;\r
2257                                         }\r
2258                                 }\r
2259                                 #endif\r
2260                         }\r
2261                         else\r
2262                         {\r
2263                                 mtCOVERAGE_TEST_MARKER();\r
2264                         }\r
2265                 }\r
2266                 ( void ) xTaskResumeAll();\r
2267 \r
2268                 return uxTask;\r
2269         }\r
2270 \r
2271 #endif /* configUSE_TRACE_FACILITY */\r
2272 /*----------------------------------------------------------*/\r
2273 \r
2274 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )\r
2275 \r
2276         TaskHandle_t xTaskGetIdleTaskHandle( void )\r
2277         {\r
2278                 /* If xTaskGetIdleTaskHandle() is called before the scheduler has been\r
2279                 started, then xIdleTaskHandle will be NULL. */\r
2280                 configASSERT( ( xIdleTaskHandle != NULL ) );\r
2281                 return xIdleTaskHandle;\r
2282         }\r
2283 \r
2284 #endif /* INCLUDE_xTaskGetIdleTaskHandle */\r
2285 /*----------------------------------------------------------*/\r
2286 \r
2287 /* This conditional compilation should use inequality to 0, not equality to 1.\r
2288 This is to ensure vTaskStepTick() is available when user defined low power mode\r
2289 implementations require configUSE_TICKLESS_IDLE to be set to a value other than\r
2290 1. */\r
2291 #if ( configUSE_TICKLESS_IDLE != 0 )\r
2292 \r
2293         void vTaskStepTick( const TickType_t xTicksToJump )\r
2294         {\r
2295                 /* Correct the tick count value after a period during which the tick\r
2296                 was suppressed.  Note this does *not* call the tick hook function for\r
2297                 each stepped tick. */\r
2298                 configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );\r
2299                 xTickCount += xTicksToJump;\r
2300                 traceINCREASE_TICK_COUNT( xTicksToJump );\r
2301         }\r
2302 \r
2303 #endif /* configUSE_TICKLESS_IDLE */\r
2304 /*----------------------------------------------------------*/\r
2305 \r
2306 #if ( INCLUDE_xTaskAbortDelay == 1 )\r
2307 \r
2308         BaseType_t xTaskAbortDelay( TaskHandle_t xTask )\r
2309         {\r
2310         TCB_t *pxTCB = ( TCB_t * ) xTask;\r
2311         BaseType_t xReturn = pdFALSE;\r
2312 \r
2313                 configASSERT( pxTCB );\r
2314 \r
2315                 vTaskSuspendAll();\r
2316                 {\r
2317                         /* A task can only be prematurely removed from the Blocked state if\r
2318                         it is actually in the Blocked state. */\r
2319                         if( eTaskGetState( xTask ) == eBlocked )\r
2320                         {\r
2321                                 /* Remove the reference to the task from the blocked list.  An\r
2322                                 interrupt won't touch the xStateListItem because the\r
2323                                 scheduler is suspended. */\r
2324                                 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );\r
2325 \r
2326                                 /* Is the task waiting on an event also?  If so remove it from\r
2327                                 the event list too.  Interrupts can touch the event list item,\r
2328                                 even though the scheduler is suspended, so a critical section\r
2329                                 is used. */\r
2330                                 taskENTER_CRITICAL();\r
2331                                 {\r
2332                                         if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )\r
2333                                         {\r
2334                                                 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );\r
2335                                                 pxTCB->ucDelayAborted = pdTRUE;\r
2336                                         }\r
2337                                         else\r
2338                                         {\r
2339                                                 mtCOVERAGE_TEST_MARKER();\r
2340                                         }\r
2341                                 }\r
2342                                 taskEXIT_CRITICAL();\r
2343 \r
2344                                 /* Place the unblocked task into the appropriate ready list. */\r
2345                                 prvAddTaskToReadyList( pxTCB );\r
2346 \r
2347                                 /* A task being unblocked cannot cause an immediate context\r
2348                                 switch if preemption is turned off. */\r
2349                                 #if (  configUSE_PREEMPTION == 1 )\r
2350                                 {\r
2351                                         /* Preemption is on, but a context switch should only be\r
2352                                         performed if the unblocked task has a priority that is\r
2353                                         equal to or higher than the currently executing task. */\r
2354                                         if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )\r
2355                                         {\r
2356                                                 /* Pend the yield to be performed when the scheduler\r
2357                                                 is unsuspended. */\r
2358                                                 xYieldPending = pdTRUE;\r
2359                                         }\r
2360                                         else\r
2361                                         {\r
2362                                                 mtCOVERAGE_TEST_MARKER();\r
2363                                         }\r
2364                                 }\r
2365                                 #endif /* configUSE_PREEMPTION */\r
2366                         }\r
2367                         else\r
2368                         {\r
2369                                 mtCOVERAGE_TEST_MARKER();\r
2370                         }\r
2371                 }\r
2372                 xTaskResumeAll();\r
2373 \r
2374                 return xReturn;\r
2375         }\r
2376 \r
2377 #endif /* INCLUDE_xTaskAbortDelay */\r
2378 /*----------------------------------------------------------*/\r
2379 \r
2380 BaseType_t xTaskIncrementTick( void )\r
2381 {\r
2382 TCB_t * pxTCB;\r
2383 TickType_t xItemValue;\r
2384 BaseType_t xSwitchRequired = pdFALSE;\r
2385 \r
2386         /* Called by the portable layer each time a tick interrupt occurs.\r
2387         Increments the tick then checks to see if the new tick value will cause any\r
2388         tasks to be unblocked. */\r
2389         traceTASK_INCREMENT_TICK( xTickCount );\r
2390         if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )\r
2391         {\r
2392                 /* Increment the RTOS tick, switching the delayed and overflowed\r
2393                 delayed lists if it wraps to 0. */\r
2394                 ++xTickCount;\r
2395 \r
2396                 {\r
2397                         /* Minor optimisation.  The tick count cannot change in this\r
2398                         block. */\r
2399                         const TickType_t xConstTickCount = xTickCount;\r
2400 \r
2401                         if( xConstTickCount == ( TickType_t ) 0U )\r
2402                         {\r
2403                                 taskSWITCH_DELAYED_LISTS();\r
2404                         }\r
2405                         else\r
2406                         {\r
2407                                 mtCOVERAGE_TEST_MARKER();\r
2408                         }\r
2409 \r
2410                         /* See if this tick has made a timeout expire.  Tasks are stored in\r
2411                         the     queue in the order of their wake time - meaning once one task\r
2412                         has been found whose block time has not expired there is no need to\r
2413                         look any further down the list. */\r
2414                         if( xConstTickCount >= xNextTaskUnblockTime )\r
2415                         {\r
2416                                 for( ;; )\r
2417                                 {\r
2418                                         if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )\r
2419                                         {\r
2420                                                 /* The delayed list is empty.  Set xNextTaskUnblockTime\r
2421                                                 to the maximum possible value so it is extremely\r
2422                                                 unlikely that the\r
2423                                                 if( xTickCount >= xNextTaskUnblockTime ) test will pass\r
2424                                                 next time through. */\r
2425                                                 xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
2426                                                 break;\r
2427                                         }\r
2428                                         else\r
2429                                         {\r
2430                                                 /* The delayed list is not empty, get the value of the\r
2431                                                 item at the head of the delayed list.  This is the time\r
2432                                                 at which the task at the head of the delayed list must\r
2433                                                 be removed from the Blocked state. */\r
2434                                                 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );\r
2435                                                 xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );\r
2436 \r
2437                                                 if( xConstTickCount < xItemValue )\r
2438                                                 {\r
2439                                                         /* It is not time to unblock this item yet, but the\r
2440                                                         item value is the time at which the task at the head\r
2441                                                         of the blocked list must be removed from the Blocked\r
2442                                                         state - so record the item value in\r
2443                                                         xNextTaskUnblockTime. */\r
2444                                                         xNextTaskUnblockTime = xItemValue;\r
2445                                                         break;\r
2446                                                 }\r
2447                                                 else\r
2448                                                 {\r
2449                                                         mtCOVERAGE_TEST_MARKER();\r
2450                                                 }\r
2451 \r
2452                                                 /* It is time to remove the item from the Blocked state. */\r
2453                                                 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );\r
2454 \r
2455                                                 /* Is the task waiting on an event also?  If so remove\r
2456                                                 it from the event list. */\r
2457                                                 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )\r
2458                                                 {\r
2459                                                         ( void ) uxListRemove( &( pxTCB->xEventListItem ) );\r
2460                                                 }\r
2461                                                 else\r
2462                                                 {\r
2463                                                         mtCOVERAGE_TEST_MARKER();\r
2464                                                 }\r
2465 \r
2466                                                 /* Place the unblocked task into the appropriate ready\r
2467                                                 list. */\r
2468                                                 prvAddTaskToReadyList( pxTCB );\r
2469 \r
2470                                                 /* A task being unblocked cannot cause an immediate\r
2471                                                 context switch if preemption is turned off. */\r
2472                                                 #if (  configUSE_PREEMPTION == 1 )\r
2473                                                 {\r
2474                                                         /* Preemption is on, but a context switch should\r
2475                                                         only be performed if the unblocked task has a\r
2476                                                         priority that is equal to or higher than the\r
2477                                                         currently executing task. */\r
2478                                                         if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )\r
2479                                                         {\r
2480                                                                 xSwitchRequired = pdTRUE;\r
2481                                                         }\r
2482                                                         else\r
2483                                                         {\r
2484                                                                 mtCOVERAGE_TEST_MARKER();\r
2485                                                         }\r
2486                                                 }\r
2487                                                 #endif /* configUSE_PREEMPTION */\r
2488                                         }\r
2489                                 }\r
2490                         }\r
2491                 }\r
2492 \r
2493                 /* Tasks of equal priority to the currently running task will share\r
2494                 processing time (time slice) if preemption is on, and the application\r
2495                 writer has not explicitly turned time slicing off. */\r
2496                 #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )\r
2497                 {\r
2498                         if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )\r
2499                         {\r
2500                                 xSwitchRequired = pdTRUE;\r
2501                         }\r
2502                         else\r
2503                         {\r
2504                                 mtCOVERAGE_TEST_MARKER();\r
2505                         }\r
2506                 }\r
2507                 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */\r
2508 \r
2509                 #if ( configUSE_TICK_HOOK == 1 )\r
2510                 {\r
2511                         /* Guard against the tick hook being called when the pended tick\r
2512                         count is being unwound (when the scheduler is being unlocked). */\r
2513                         if( uxPendedTicks == ( UBaseType_t ) 0U )\r
2514                         {\r
2515                                 vApplicationTickHook();\r
2516                         }\r
2517                         else\r
2518                         {\r
2519                                 mtCOVERAGE_TEST_MARKER();\r
2520                         }\r
2521                 }\r
2522                 #endif /* configUSE_TICK_HOOK */\r
2523         }\r
2524         else\r
2525         {\r
2526                 ++uxPendedTicks;\r
2527 \r
2528                 /* The tick hook gets called at regular intervals, even if the\r
2529                 scheduler is locked. */\r
2530                 #if ( configUSE_TICK_HOOK == 1 )\r
2531                 {\r
2532                         vApplicationTickHook();\r
2533                 }\r
2534                 #endif\r
2535         }\r
2536 \r
2537         #if ( configUSE_PREEMPTION == 1 )\r
2538         {\r
2539                 if( xYieldPending != pdFALSE )\r
2540                 {\r
2541                         xSwitchRequired = pdTRUE;\r
2542                 }\r
2543                 else\r
2544                 {\r
2545                         mtCOVERAGE_TEST_MARKER();\r
2546                 }\r
2547         }\r
2548         #endif /* configUSE_PREEMPTION */\r
2549 \r
2550         return xSwitchRequired;\r
2551 }\r
2552 /*-----------------------------------------------------------*/\r
2553 \r
2554 #if ( configUSE_APPLICATION_TASK_TAG == 1 )\r
2555 \r
2556         void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction )\r
2557         {\r
2558         TCB_t *xTCB;\r
2559 \r
2560                 /* If xTask is NULL then it is the task hook of the calling task that is\r
2561                 getting set. */\r
2562                 if( xTask == NULL )\r
2563                 {\r
2564                         xTCB = ( TCB_t * ) pxCurrentTCB;\r
2565                 }\r
2566                 else\r
2567                 {\r
2568                         xTCB = ( TCB_t * ) xTask;\r
2569                 }\r
2570 \r
2571                 /* Save the hook function in the TCB.  A critical section is required as\r
2572                 the value can be accessed from an interrupt. */\r
2573                 taskENTER_CRITICAL();\r
2574                         xTCB->pxTaskTag = pxHookFunction;\r
2575                 taskEXIT_CRITICAL();\r
2576         }\r
2577 \r
2578 #endif /* configUSE_APPLICATION_TASK_TAG */\r
2579 /*-----------------------------------------------------------*/\r
2580 \r
2581 #if ( configUSE_APPLICATION_TASK_TAG == 1 )\r
2582 \r
2583         TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )\r
2584         {\r
2585         TCB_t *xTCB;\r
2586         TaskHookFunction_t xReturn;\r
2587 \r
2588                 /* If xTask is NULL then we are setting our own task hook. */\r
2589                 if( xTask == NULL )\r
2590                 {\r
2591                         xTCB = ( TCB_t * ) pxCurrentTCB;\r
2592                 }\r
2593                 else\r
2594                 {\r
2595                         xTCB = ( TCB_t * ) xTask;\r
2596                 }\r
2597 \r
2598                 /* Save the hook function in the TCB.  A critical section is required as\r
2599                 the value can be accessed from an interrupt. */\r
2600                 taskENTER_CRITICAL();\r
2601                 {\r
2602                         xReturn = xTCB->pxTaskTag;\r
2603                 }\r
2604                 taskEXIT_CRITICAL();\r
2605 \r
2606                 return xReturn;\r
2607         }\r
2608 \r
2609 #endif /* configUSE_APPLICATION_TASK_TAG */\r
2610 /*-----------------------------------------------------------*/\r
2611 \r
2612 #if ( configUSE_APPLICATION_TASK_TAG == 1 )\r
2613 \r
2614         BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter )\r
2615         {\r
2616         TCB_t *xTCB;\r
2617         BaseType_t xReturn;\r
2618 \r
2619                 /* If xTask is NULL then we are calling our own task hook. */\r
2620                 if( xTask == NULL )\r
2621                 {\r
2622                         xTCB = ( TCB_t * ) pxCurrentTCB;\r
2623                 }\r
2624                 else\r
2625                 {\r
2626                         xTCB = ( TCB_t * ) xTask;\r
2627                 }\r
2628 \r
2629                 if( xTCB->pxTaskTag != NULL )\r
2630                 {\r
2631                         xReturn = xTCB->pxTaskTag( pvParameter );\r
2632                 }\r
2633                 else\r
2634                 {\r
2635                         xReturn = pdFAIL;\r
2636                 }\r
2637 \r
2638                 return xReturn;\r
2639         }\r
2640 \r
2641 #endif /* configUSE_APPLICATION_TASK_TAG */\r
2642 /*-----------------------------------------------------------*/\r
2643 \r
2644 void vTaskSwitchContext( void )\r
2645 {\r
2646         if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )\r
2647         {\r
2648                 /* The scheduler is currently suspended - do not allow a context\r
2649                 switch. */\r
2650                 xYieldPending = pdTRUE;\r
2651         }\r
2652         else\r
2653         {\r
2654                 xYieldPending = pdFALSE;\r
2655                 traceTASK_SWITCHED_OUT();\r
2656 \r
2657                 #if ( configGENERATE_RUN_TIME_STATS == 1 )\r
2658                 {\r
2659                                 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE\r
2660                                         portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );\r
2661                                 #else\r
2662                                         ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();\r
2663                                 #endif\r
2664 \r
2665                                 /* Add the amount of time the task has been running to the\r
2666                                 accumulated time so far.  The time the task started running was\r
2667                                 stored in ulTaskSwitchedInTime.  Note that there is no overflow\r
2668                                 protection here so count values are only valid until the timer\r
2669                                 overflows.  The guard against negative values is to protect\r
2670                                 against suspect run time stat counter implementations - which\r
2671                                 are provided by the application, not the kernel. */\r
2672                                 if( ulTotalRunTime > ulTaskSwitchedInTime )\r
2673                                 {\r
2674                                         pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );\r
2675                                 }\r
2676                                 else\r
2677                                 {\r
2678                                         mtCOVERAGE_TEST_MARKER();\r
2679                                 }\r
2680                                 ulTaskSwitchedInTime = ulTotalRunTime;\r
2681                 }\r
2682                 #endif /* configGENERATE_RUN_TIME_STATS */\r
2683 \r
2684                 /* Check for stack overflow, if configured. */\r
2685                 taskCHECK_FOR_STACK_OVERFLOW();\r
2686 \r
2687                 /* Select a new task to run using either the generic C or port\r
2688                 optimised asm code. */\r
2689                 taskSELECT_HIGHEST_PRIORITY_TASK();\r
2690                 traceTASK_SWITCHED_IN();\r
2691 \r
2692                 #if ( configUSE_NEWLIB_REENTRANT == 1 )\r
2693                 {\r
2694                         /* Switch Newlib's _impure_ptr variable to point to the _reent\r
2695                         structure specific to this task. */\r
2696                         _impure_ptr = &( pxCurrentTCB->xNewLib_reent );\r
2697                 }\r
2698                 #endif /* configUSE_NEWLIB_REENTRANT */\r
2699         }\r
2700 }\r
2701 /*-----------------------------------------------------------*/\r
2702 \r
2703 void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )\r
2704 {\r
2705         configASSERT( pxEventList );\r
2706 \r
2707         /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE\r
2708         SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */\r
2709 \r
2710         /* Place the event list item of the TCB in the appropriate event list.\r
2711         This is placed in the list in priority order so the highest priority task\r
2712         is the first to be woken by the event.  The queue that contains the event\r
2713         list is locked, preventing simultaneous access from interrupts. */\r
2714         vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );\r
2715 \r
2716         prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );\r
2717 }\r
2718 /*-----------------------------------------------------------*/\r
2719 \r
2720 void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait )\r
2721 {\r
2722         configASSERT( pxEventList );\r
2723 \r
2724         /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by\r
2725         the event groups implementation. */\r
2726         configASSERT( uxSchedulerSuspended != 0 );\r
2727 \r
2728         /* Store the item value in the event list item.  It is safe to access the\r
2729         event list item here as interrupts won't access the event list item of a\r
2730         task that is not in the Blocked state. */\r
2731         listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );\r
2732 \r
2733         /* Place the event list item of the TCB at the end of the appropriate event\r
2734         list.  It is safe to access the event list here because it is part of an\r
2735         event group implementation - and interrupts don't access event groups\r
2736         directly (instead they access them indirectly by pending function calls to\r
2737         the task level). */\r
2738         vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );\r
2739 \r
2740         prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );\r
2741 }\r
2742 /*-----------------------------------------------------------*/\r
2743 \r
2744 #if( configUSE_TIMERS == 1 )\r
2745 \r
2746         void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely )\r
2747         {\r
2748                 configASSERT( pxEventList );\r
2749 \r
2750                 /* This function should not be called by application code hence the\r
2751                 'Restricted' in its name.  It is not part of the public API.  It is\r
2752                 designed for use by kernel code, and has special calling requirements -\r
2753                 it should be called with the scheduler suspended. */\r
2754 \r
2755 \r
2756                 /* Place the event list item of the TCB in the appropriate event list.\r
2757                 In this case it is assume that this is the only task that is going to\r
2758                 be waiting on this event list, so the faster vListInsertEnd() function\r
2759                 can be used in place of vListInsert. */\r
2760                 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );\r
2761 \r
2762                 /* If the task should block indefinitely then set the block time to a\r
2763                 value that will be recognised as an indefinite delay inside the\r
2764                 prvAddCurrentTaskToDelayedList() function. */\r
2765                 if( xWaitIndefinitely != pdFALSE )\r
2766                 {\r
2767                         xTicksToWait = portMAX_DELAY;\r
2768                 }\r
2769 \r
2770                 traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) );\r
2771                 prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely );\r
2772         }\r
2773 \r
2774 #endif /* configUSE_TIMERS */\r
2775 /*-----------------------------------------------------------*/\r
2776 \r
2777 BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )\r
2778 {\r
2779 TCB_t *pxUnblockedTCB;\r
2780 BaseType_t xReturn;\r
2781 \r
2782         /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION.  It can also be\r
2783         called from a critical section within an ISR. */\r
2784 \r
2785         /* The event list is sorted in priority order, so the first in the list can\r
2786         be removed as it is known to be the highest priority.  Remove the TCB from\r
2787         the delayed list, and add it to the ready list.\r
2788 \r
2789         If an event is for a queue that is locked then this function will never\r
2790         get called - the lock count on the queue will get modified instead.  This\r
2791         means exclusive access to the event list is guaranteed here.\r
2792 \r
2793         This function assumes that a check has already been made to ensure that\r
2794         pxEventList is not empty. */\r
2795         pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );\r
2796         configASSERT( pxUnblockedTCB );\r
2797         ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );\r
2798 \r
2799         if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )\r
2800         {\r
2801                 ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );\r
2802                 prvAddTaskToReadyList( pxUnblockedTCB );\r
2803         }\r
2804         else\r
2805         {\r
2806                 /* The delayed and ready lists cannot be accessed, so hold this task\r
2807                 pending until the scheduler is resumed. */\r
2808                 vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );\r
2809         }\r
2810 \r
2811         if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )\r
2812         {\r
2813                 /* Return true if the task removed from the event list has a higher\r
2814                 priority than the calling task.  This allows the calling task to know if\r
2815                 it should force a context switch now. */\r
2816                 xReturn = pdTRUE;\r
2817 \r
2818                 /* Mark that a yield is pending in case the user is not using the\r
2819                 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */\r
2820                 xYieldPending = pdTRUE;\r
2821         }\r
2822         else\r
2823         {\r
2824                 xReturn = pdFALSE;\r
2825         }\r
2826 \r
2827         #if( configUSE_TICKLESS_IDLE != 0 )\r
2828         {\r
2829                 /* If a task is blocked on a kernel object then xNextTaskUnblockTime\r
2830                 might be set to the blocked task's time out time.  If the task is\r
2831                 unblocked for a reason other than a timeout xNextTaskUnblockTime is\r
2832                 normally left unchanged, because it is automatically reset to a new\r
2833                 value when the tick count equals xNextTaskUnblockTime.  However if\r
2834                 tickless idling is used it might be more important to enter sleep mode\r
2835                 at the earliest possible time - so reset xNextTaskUnblockTime here to\r
2836                 ensure it is updated at the earliest possible time. */\r
2837                 prvResetNextTaskUnblockTime();\r
2838         }\r
2839         #endif\r
2840 \r
2841         return xReturn;\r
2842 }\r
2843 /*-----------------------------------------------------------*/\r
2844 \r
2845 BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )\r
2846 {\r
2847 TCB_t *pxUnblockedTCB;\r
2848 BaseType_t xReturn;\r
2849 \r
2850         /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by\r
2851         the event flags implementation. */\r
2852         configASSERT( uxSchedulerSuspended != pdFALSE );\r
2853 \r
2854         /* Store the new item value in the event list. */\r
2855         listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );\r
2856 \r
2857         /* Remove the event list form the event flag.  Interrupts do not access\r
2858         event flags. */\r
2859         pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem );\r
2860         configASSERT( pxUnblockedTCB );\r
2861         ( void ) uxListRemove( pxEventListItem );\r
2862 \r
2863         /* Remove the task from the delayed list and add it to the ready list.  The\r
2864         scheduler is suspended so interrupts will not be accessing the ready\r
2865         lists. */\r
2866         ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );\r
2867         prvAddTaskToReadyList( pxUnblockedTCB );\r
2868 \r
2869         if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )\r
2870         {\r
2871                 /* Return true if the task removed from the event list has\r
2872                 a higher priority than the calling task.  This allows\r
2873                 the calling task to know if it should force a context\r
2874                 switch now. */\r
2875                 xReturn = pdTRUE;\r
2876 \r
2877                 /* Mark that a yield is pending in case the user is not using the\r
2878                 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */\r
2879                 xYieldPending = pdTRUE;\r
2880         }\r
2881         else\r
2882         {\r
2883                 xReturn = pdFALSE;\r
2884         }\r
2885 \r
2886         return xReturn;\r
2887 }\r
2888 /*-----------------------------------------------------------*/\r
2889 \r
2890 void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )\r
2891 {\r
2892         configASSERT( pxTimeOut );\r
2893         pxTimeOut->xOverflowCount = xNumOfOverflows;\r
2894         pxTimeOut->xTimeOnEntering = xTickCount;\r
2895 }\r
2896 /*-----------------------------------------------------------*/\r
2897 \r
2898 BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait )\r
2899 {\r
2900 BaseType_t xReturn;\r
2901 \r
2902         configASSERT( pxTimeOut );\r
2903         configASSERT( pxTicksToWait );\r
2904 \r
2905         taskENTER_CRITICAL();\r
2906         {\r
2907                 /* Minor optimisation.  The tick count cannot change in this block. */\r
2908                 const TickType_t xConstTickCount = xTickCount;\r
2909 \r
2910                 #if( INCLUDE_xTaskAbortDelay == 1 )\r
2911                         if( pxCurrentTCB->ucDelayAborted != pdFALSE )\r
2912                         {\r
2913                                 /* The delay was aborted, which is not the same as a time out,\r
2914                                 but has the same result. */\r
2915                                 pxCurrentTCB->ucDelayAborted = pdFALSE;\r
2916                                 xReturn = pdTRUE;\r
2917                         }\r
2918                         else\r
2919                 #endif\r
2920 \r
2921                 #if ( INCLUDE_vTaskSuspend == 1 )\r
2922                         if( *pxTicksToWait == portMAX_DELAY )\r
2923                         {\r
2924                                 /* If INCLUDE_vTaskSuspend is set to 1 and the block time\r
2925                                 specified is the maximum block time then the task should block\r
2926                                 indefinitely, and therefore never time out. */\r
2927                                 xReturn = pdFALSE;\r
2928                         }\r
2929                         else\r
2930                 #endif\r
2931 \r
2932                 if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */\r
2933                 {\r
2934                         /* The tick count is greater than the time at which\r
2935                         vTaskSetTimeout() was called, but has also overflowed since\r
2936                         vTaskSetTimeOut() was called.  It must have wrapped all the way\r
2937                         around and gone past again. This passed since vTaskSetTimeout()\r
2938                         was called. */\r
2939                         xReturn = pdTRUE;\r
2940                 }\r
2941                 else if( ( ( TickType_t ) ( xConstTickCount - pxTimeOut->xTimeOnEntering ) ) < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */\r
2942                 {\r
2943                         /* Not a genuine timeout. Adjust parameters for time remaining. */\r
2944                         *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );\r
2945                         vTaskSetTimeOutState( pxTimeOut );\r
2946                         xReturn = pdFALSE;\r
2947                 }\r
2948                 else\r
2949                 {\r
2950                         xReturn = pdTRUE;\r
2951                 }\r
2952         }\r
2953         taskEXIT_CRITICAL();\r
2954 \r
2955         return xReturn;\r
2956 }\r
2957 /*-----------------------------------------------------------*/\r
2958 \r
2959 void vTaskMissedYield( void )\r
2960 {\r
2961         xYieldPending = pdTRUE;\r
2962 }\r
2963 /*-----------------------------------------------------------*/\r
2964 \r
2965 #if ( configUSE_TRACE_FACILITY == 1 )\r
2966 \r
2967         UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )\r
2968         {\r
2969         UBaseType_t uxReturn;\r
2970         TCB_t *pxTCB;\r
2971 \r
2972                 if( xTask != NULL )\r
2973                 {\r
2974                         pxTCB = ( TCB_t * ) xTask;\r
2975                         uxReturn = pxTCB->uxTaskNumber;\r
2976                 }\r
2977                 else\r
2978                 {\r
2979                         uxReturn = 0U;\r
2980                 }\r
2981 \r
2982                 return uxReturn;\r
2983         }\r
2984 \r
2985 #endif /* configUSE_TRACE_FACILITY */\r
2986 /*-----------------------------------------------------------*/\r
2987 \r
2988 #if ( configUSE_TRACE_FACILITY == 1 )\r
2989 \r
2990         void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle )\r
2991         {\r
2992         TCB_t *pxTCB;\r
2993 \r
2994                 if( xTask != NULL )\r
2995                 {\r
2996                         pxTCB = ( TCB_t * ) xTask;\r
2997                         pxTCB->uxTaskNumber = uxHandle;\r
2998                 }\r
2999         }\r
3000 \r
3001 #endif /* configUSE_TRACE_FACILITY */\r
3002 \r
3003 /*\r
3004  * -----------------------------------------------------------\r
3005  * The Idle task.\r
3006  * ----------------------------------------------------------\r
3007  *\r
3008  * The portTASK_FUNCTION() macro is used to allow port/compiler specific\r
3009  * language extensions.  The equivalent prototype for this function is:\r
3010  *\r
3011  * void prvIdleTask( void *pvParameters );\r
3012  *\r
3013  */\r
3014 static portTASK_FUNCTION( prvIdleTask, pvParameters )\r
3015 {\r
3016         /* Stop warnings. */\r
3017         ( void ) pvParameters;\r
3018 \r
3019         /** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE\r
3020         SCHEDULER IS STARTED. **/\r
3021 \r
3022         for( ;; )\r
3023         {\r
3024                 /* See if any tasks have deleted themselves - if so then the idle task\r
3025                 is responsible for freeing the deleted task's TCB and stack. */\r
3026                 prvCheckTasksWaitingTermination();\r
3027 \r
3028                 #if ( configUSE_PREEMPTION == 0 )\r
3029                 {\r
3030                         /* If we are not using preemption we keep forcing a task switch to\r
3031                         see if any other task has become available.  If we are using\r
3032                         preemption we don't need to do this as any task becoming available\r
3033                         will automatically get the processor anyway. */\r
3034                         taskYIELD();\r
3035                 }\r
3036                 #endif /* configUSE_PREEMPTION */\r
3037 \r
3038                 #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )\r
3039                 {\r
3040                         /* When using preemption tasks of equal priority will be\r
3041                         timesliced.  If a task that is sharing the idle priority is ready\r
3042                         to run then the idle task should yield before the end of the\r
3043                         timeslice.\r
3044 \r
3045                         A critical region is not required here as we are just reading from\r
3046                         the list, and an occasional incorrect value will not matter.  If\r
3047                         the ready list at the idle priority contains more than one task\r
3048                         then a task other than the idle task is ready to execute. */\r
3049                         if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )\r
3050                         {\r
3051                                 taskYIELD();\r
3052                         }\r
3053                         else\r
3054                         {\r
3055                                 mtCOVERAGE_TEST_MARKER();\r
3056                         }\r
3057                 }\r
3058                 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */\r
3059 \r
3060                 #if ( configUSE_IDLE_HOOK == 1 )\r
3061                 {\r
3062                         extern void vApplicationIdleHook( void );\r
3063 \r
3064                         /* Call the user defined function from within the idle task.  This\r
3065                         allows the application designer to add background functionality\r
3066                         without the overhead of a separate task.\r
3067                         NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,\r
3068                         CALL A FUNCTION THAT MIGHT BLOCK. */\r
3069                         vApplicationIdleHook();\r
3070                 }\r
3071                 #endif /* configUSE_IDLE_HOOK */\r
3072 \r
3073                 /* This conditional compilation should use inequality to 0, not equality\r
3074                 to 1.  This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when\r
3075                 user defined low power mode     implementations require\r
3076                 configUSE_TICKLESS_IDLE to be set to a value other than 1. */\r
3077                 #if ( configUSE_TICKLESS_IDLE != 0 )\r
3078                 {\r
3079                 TickType_t xExpectedIdleTime;\r
3080 \r
3081                         /* It is not desirable to suspend then resume the scheduler on\r
3082                         each iteration of the idle task.  Therefore, a preliminary\r
3083                         test of the expected idle time is performed without the\r
3084                         scheduler suspended.  The result here is not necessarily\r
3085                         valid. */\r
3086                         xExpectedIdleTime = prvGetExpectedIdleTime();\r
3087 \r
3088                         if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )\r
3089                         {\r
3090                                 vTaskSuspendAll();\r
3091                                 {\r
3092                                         /* Now the scheduler is suspended, the expected idle\r
3093                                         time can be sampled again, and this time its value can\r
3094                                         be used. */\r
3095                                         configASSERT( xNextTaskUnblockTime >= xTickCount );\r
3096                                         xExpectedIdleTime = prvGetExpectedIdleTime();\r
3097 \r
3098                                         if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )\r
3099                                         {\r
3100                                                 traceLOW_POWER_IDLE_BEGIN();\r
3101                                                 portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );\r
3102                                                 traceLOW_POWER_IDLE_END();\r
3103                                         }\r
3104                                         else\r
3105                                         {\r
3106                                                 mtCOVERAGE_TEST_MARKER();\r
3107                                         }\r
3108                                 }\r
3109                                 ( void ) xTaskResumeAll();\r
3110                         }\r
3111                         else\r
3112                         {\r
3113                                 mtCOVERAGE_TEST_MARKER();\r
3114                         }\r
3115                 }\r
3116                 #endif /* configUSE_TICKLESS_IDLE */\r
3117         }\r
3118 }\r
3119 /*-----------------------------------------------------------*/\r
3120 \r
3121 #if( configUSE_TICKLESS_IDLE != 0 )\r
3122 \r
3123         eSleepModeStatus eTaskConfirmSleepModeStatus( void )\r
3124         {\r
3125         /* The idle task exists in addition to the application tasks. */\r
3126         const UBaseType_t uxNonApplicationTasks = 1;\r
3127         eSleepModeStatus eReturn = eStandardSleep;\r
3128 \r
3129                 if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )\r
3130                 {\r
3131                         /* A task was made ready while the scheduler was suspended. */\r
3132                         eReturn = eAbortSleep;\r
3133                 }\r
3134                 else if( xYieldPending != pdFALSE )\r
3135                 {\r
3136                         /* A yield was pended while the scheduler was suspended. */\r
3137                         eReturn = eAbortSleep;\r
3138                 }\r
3139                 else\r
3140                 {\r
3141                         /* If all the tasks are in the suspended list (which might mean they\r
3142                         have an infinite block time rather than actually being suspended)\r
3143                         then it is safe to turn all clocks off and just wait for external\r
3144                         interrupts. */\r
3145                         if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )\r
3146                         {\r
3147                                 eReturn = eNoTasksWaitingTimeout;\r
3148                         }\r
3149                         else\r
3150                         {\r
3151                                 mtCOVERAGE_TEST_MARKER();\r
3152                         }\r
3153                 }\r
3154 \r
3155                 return eReturn;\r
3156         }\r
3157 \r
3158 #endif /* configUSE_TICKLESS_IDLE */\r
3159 /*-----------------------------------------------------------*/\r
3160 \r
3161 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )\r
3162 \r
3163         void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue )\r
3164         {\r
3165         TCB_t *pxTCB;\r
3166 \r
3167                 if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS )\r
3168                 {\r
3169                         pxTCB = prvGetTCBFromHandle( xTaskToSet );\r
3170                         pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue;\r
3171                 }\r
3172         }\r
3173 \r
3174 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */\r
3175 /*-----------------------------------------------------------*/\r
3176 \r
3177 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )\r
3178 \r
3179         void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex )\r
3180         {\r
3181         void *pvReturn = NULL;\r
3182         TCB_t *pxTCB;\r
3183 \r
3184                 if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS )\r
3185                 {\r
3186                         pxTCB = prvGetTCBFromHandle( xTaskToQuery );\r
3187                         pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ];\r
3188                 }\r
3189                 else\r
3190                 {\r
3191                         pvReturn = NULL;\r
3192                 }\r
3193 \r
3194                 return pvReturn;\r
3195         }\r
3196 \r
3197 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */\r
3198 /*-----------------------------------------------------------*/\r
3199 \r
3200 #if ( portUSING_MPU_WRAPPERS == 1 )\r
3201 \r
3202         void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions )\r
3203         {\r
3204         TCB_t *pxTCB;\r
3205 \r
3206                 /* If null is passed in here then we are modifying the MPU settings of\r
3207                 the calling task. */\r
3208                 pxTCB = prvGetTCBFromHandle( xTaskToModify );\r
3209 \r
3210                 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );\r
3211         }\r
3212 \r
3213 #endif /* portUSING_MPU_WRAPPERS */\r
3214 /*-----------------------------------------------------------*/\r
3215 \r
3216 static void prvInitialiseTaskLists( void )\r
3217 {\r
3218 UBaseType_t uxPriority;\r
3219 \r
3220         for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )\r
3221         {\r
3222                 vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );\r
3223         }\r
3224 \r
3225         vListInitialise( &xDelayedTaskList1 );\r
3226         vListInitialise( &xDelayedTaskList2 );\r
3227         vListInitialise( &xPendingReadyList );\r
3228 \r
3229         #if ( INCLUDE_vTaskDelete == 1 )\r
3230         {\r
3231                 vListInitialise( &xTasksWaitingTermination );\r
3232         }\r
3233         #endif /* INCLUDE_vTaskDelete */\r
3234 \r
3235         #if ( INCLUDE_vTaskSuspend == 1 )\r
3236         {\r
3237                 vListInitialise( &xSuspendedTaskList );\r
3238         }\r
3239         #endif /* INCLUDE_vTaskSuspend */\r
3240 \r
3241         /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList\r
3242         using list2. */\r
3243         pxDelayedTaskList = &xDelayedTaskList1;\r
3244         pxOverflowDelayedTaskList = &xDelayedTaskList2;\r
3245 }\r
3246 /*-----------------------------------------------------------*/\r
3247 \r
3248 static void prvCheckTasksWaitingTermination( void )\r
3249 {\r
3250 \r
3251         /** THIS FUNCTION IS CALLED FROM  THE RTOS IDLE TASK **/\r
3252 \r
3253         #if ( INCLUDE_vTaskDelete == 1 )\r
3254         {\r
3255                 BaseType_t xListIsEmpty;\r
3256 \r
3257                 /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called\r
3258                 too often in the idle task. */\r
3259                 while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )\r
3260                 {\r
3261                         vTaskSuspendAll();\r
3262                         {\r
3263                                 xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );\r
3264                         }\r
3265                         ( void ) xTaskResumeAll();\r
3266 \r
3267                         if( xListIsEmpty == pdFALSE )\r
3268                         {\r
3269                                 TCB_t *pxTCB;\r
3270 \r
3271                                 taskENTER_CRITICAL();\r
3272                                 {\r
3273                                         pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );\r
3274                                         ( void ) uxListRemove( &( pxTCB->xStateListItem ) );\r
3275                                         --uxCurrentNumberOfTasks;\r
3276                                         --uxDeletedTasksWaitingCleanUp;\r
3277                                 }\r
3278                                 taskEXIT_CRITICAL();\r
3279 \r
3280                                 prvDeleteTCB( pxTCB );\r
3281                         }\r
3282                         else\r
3283                         {\r
3284                                 mtCOVERAGE_TEST_MARKER();\r
3285                         }\r
3286                 }\r
3287         }\r
3288         #endif /* INCLUDE_vTaskDelete */\r
3289 }\r
3290 /*-----------------------------------------------------------*/\r
3291 \r
3292 #if( configUSE_TRACE_FACILITY == 1 )\r
3293 \r
3294         void vTaskGetTaskInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState )\r
3295         {\r
3296         TCB_t *pxTCB;\r
3297 \r
3298                 /* xTask is NULL then get the state of the calling task. */\r
3299                 pxTCB = prvGetTCBFromHandle( xTask );\r
3300 \r
3301                 pxTaskStatus->xHandle = ( TaskHandle_t ) pxTCB;\r
3302                 pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName [ 0 ] );\r
3303                 pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority;\r
3304                 pxTaskStatus->pxStackBase = pxTCB->pxStack;\r
3305                 pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber;\r
3306 \r
3307                 #if ( INCLUDE_vTaskSuspend == 1 )\r
3308                 {\r
3309                         /* If the task is in the suspended list then there is a chance it is\r
3310                         actually just blocked indefinitely - so really it should be reported as\r
3311                         being in the Blocked state. */\r
3312                         if( pxTaskStatus->eCurrentState == eSuspended )\r
3313                         {\r
3314                                 vTaskSuspendAll();\r
3315                                 {\r
3316                                         if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )\r
3317                                         {\r
3318                                                 pxTaskStatus->eCurrentState = eBlocked;\r
3319                                         }\r
3320                                 }\r
3321                                 xTaskResumeAll();\r
3322                         }\r
3323                 }\r
3324                 #endif /* INCLUDE_vTaskSuspend */\r
3325 \r
3326                 #if ( configUSE_MUTEXES == 1 )\r
3327                 {\r
3328                         pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;\r
3329                 }\r
3330                 #else\r
3331                 {\r
3332                         pxTaskStatus->uxBasePriority = 0;\r
3333                 }\r
3334                 #endif\r
3335 \r
3336                 #if ( configGENERATE_RUN_TIME_STATS == 1 )\r
3337                 {\r
3338                         pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter;\r
3339                 }\r
3340                 #else\r
3341                 {\r
3342                         pxTaskStatus->ulRunTimeCounter = 0;\r
3343                 }\r
3344                 #endif\r
3345 \r
3346                 /* Obtaining the task state is a little fiddly, so is only done if the value\r
3347                 of eState passed into this function is eInvalid - otherwise the state is\r
3348                 just set to whatever is passed in. */\r
3349                 if( eState != eInvalid )\r
3350                 {\r
3351                         pxTaskStatus->eCurrentState = eState;\r
3352                 }\r
3353                 else\r
3354                 {\r
3355                         pxTaskStatus->eCurrentState = eTaskGetState( xTask );\r
3356                 }\r
3357 \r
3358                 /* Obtaining the stack space takes some time, so the xGetFreeStackSpace\r
3359                 parameter is provided to allow it to be skipped. */\r
3360                 if( xGetFreeStackSpace != pdFALSE )\r
3361                 {\r
3362                         #if ( portSTACK_GROWTH > 0 )\r
3363                         {\r
3364                                 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack );\r
3365                         }\r
3366                         #else\r
3367                         {\r
3368                                 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack );\r
3369                         }\r
3370                         #endif\r
3371                 }\r
3372                 else\r
3373                 {\r
3374                         pxTaskStatus->usStackHighWaterMark = 0;\r
3375                 }\r
3376         }\r
3377 \r
3378 #endif /* configUSE_TRACE_FACILITY */\r
3379 /*-----------------------------------------------------------*/\r
3380 \r
3381 #if ( configUSE_TRACE_FACILITY == 1 )\r
3382 \r
3383         static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )\r
3384         {\r
3385         volatile TCB_t *pxNextTCB, *pxFirstTCB;\r
3386         UBaseType_t uxTask = 0;\r
3387 \r
3388                 if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )\r
3389                 {\r
3390                         listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );\r
3391 \r
3392                         /* Populate an TaskStatus_t structure within the\r
3393                         pxTaskStatusArray array for each task that is referenced from\r
3394                         pxList.  See the definition of TaskStatus_t in task.h for the\r
3395                         meaning of each TaskStatus_t structure member. */\r
3396                         do\r
3397                         {\r
3398                                 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );\r
3399                                 vTaskGetTaskInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState );\r
3400                                 uxTask++;\r
3401                         } while( pxNextTCB != pxFirstTCB );\r
3402                 }\r
3403                 else\r
3404                 {\r
3405                         mtCOVERAGE_TEST_MARKER();\r
3406                 }\r
3407 \r
3408                 return uxTask;\r
3409         }\r
3410 \r
3411 #endif /* configUSE_TRACE_FACILITY */\r
3412 /*-----------------------------------------------------------*/\r
3413 \r
3414 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )\r
3415 \r
3416         static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )\r
3417         {\r
3418         uint32_t ulCount = 0U;\r
3419 \r
3420                 while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE )\r
3421                 {\r
3422                         pucStackByte -= portSTACK_GROWTH;\r
3423                         ulCount++;\r
3424                 }\r
3425 \r
3426                 ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */\r
3427 \r
3428                 return ( uint16_t ) ulCount;\r
3429         }\r
3430 \r
3431 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */\r
3432 /*-----------------------------------------------------------*/\r
3433 \r
3434 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )\r
3435 \r
3436         UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )\r
3437         {\r
3438         TCB_t *pxTCB;\r
3439         uint8_t *pucEndOfStack;\r
3440         UBaseType_t uxReturn;\r
3441 \r
3442                 pxTCB = prvGetTCBFromHandle( xTask );\r
3443 \r
3444                 #if portSTACK_GROWTH < 0\r
3445                 {\r
3446                         pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;\r
3447                 }\r
3448                 #else\r
3449                 {\r
3450                         pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;\r
3451                 }\r
3452                 #endif\r
3453 \r
3454                 uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );\r
3455 \r
3456                 return uxReturn;\r
3457         }\r
3458 \r
3459 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */\r
3460 /*-----------------------------------------------------------*/\r
3461 \r
3462 #if ( INCLUDE_vTaskDelete == 1 )\r
3463 \r
3464         static void prvDeleteTCB( TCB_t *pxTCB )\r
3465         {\r
3466                 /* This call is required specifically for the TriCore port.  It must be\r
3467                 above the vPortFree() calls.  The call is also used by ports/demos that\r
3468                 want to allocate and clean RAM statically. */\r
3469                 portCLEAN_UP_TCB( pxTCB );\r
3470 \r
3471                 /* Free up the memory allocated by the scheduler for the task.  It is up\r
3472                 to the task to free any memory allocated at the application level. */\r
3473                 #if ( configUSE_NEWLIB_REENTRANT == 1 )\r
3474                 {\r
3475                         _reclaim_reent( &( pxTCB->xNewLib_reent ) );\r
3476                 }\r
3477                 #endif /* configUSE_NEWLIB_REENTRANT */\r
3478 \r
3479                 #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )\r
3480                 {\r
3481                         /* The task can only have been allocated dynamically - free it\r
3482                         again. */\r
3483                         vPortFree( pxTCB->pxStack );\r
3484                         vPortFree( pxTCB );\r
3485                 }\r
3486                 #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )\r
3487                 {\r
3488                         /* The task could have been allocated statically or dynamically, so\r
3489                         check before attempting to free the memory. */\r
3490                         if( pxTCB->ucStaticallyAllocated == ( uint8_t ) pdFALSE )\r
3491                         {\r
3492                                 vPortFree( pxTCB->pxStack );\r
3493                                 vPortFree( pxTCB );\r
3494                         }\r
3495                         else\r
3496                         {\r
3497                                 mtCOVERAGE_TEST_MARKER();\r
3498                         }\r
3499                 }\r
3500                 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */\r
3501         }\r
3502 \r
3503 #endif /* INCLUDE_vTaskDelete */\r
3504 /*-----------------------------------------------------------*/\r
3505 \r
3506 static void prvResetNextTaskUnblockTime( void )\r
3507 {\r
3508 TCB_t *pxTCB;\r
3509 \r
3510         if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )\r
3511         {\r
3512                 /* The new current delayed list is empty.  Set xNextTaskUnblockTime to\r
3513                 the maximum possible value so it is     extremely unlikely that the\r
3514                 if( xTickCount >= xNextTaskUnblockTime ) test will pass until\r
3515                 there is an item in the delayed list. */\r
3516                 xNextTaskUnblockTime = portMAX_DELAY;\r
3517         }\r
3518         else\r
3519         {\r
3520                 /* The new current delayed list is not empty, get the value of\r
3521                 the item at the head of the delayed list.  This is the time at\r
3522                 which the task at the head of the delayed list should be removed\r
3523                 from the Blocked state. */\r
3524                 ( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );\r
3525                 xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xStateListItem ) );\r
3526         }\r
3527 }\r
3528 /*-----------------------------------------------------------*/\r
3529 \r
3530 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )\r
3531 \r
3532         TaskHandle_t xTaskGetCurrentTaskHandle( void )\r
3533         {\r
3534         TaskHandle_t xReturn;\r
3535 \r
3536                 /* A critical section is not required as this is not called from\r
3537                 an interrupt and the current TCB will always be the same for any\r
3538                 individual execution thread. */\r
3539                 xReturn = pxCurrentTCB;\r
3540 \r
3541                 return xReturn;\r
3542         }\r
3543 \r
3544 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */\r
3545 /*-----------------------------------------------------------*/\r
3546 \r
3547 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )\r
3548 \r
3549         BaseType_t xTaskGetSchedulerState( void )\r
3550         {\r
3551         BaseType_t xReturn;\r
3552 \r
3553                 if( xSchedulerRunning == pdFALSE )\r
3554                 {\r
3555                         xReturn = taskSCHEDULER_NOT_STARTED;\r
3556                 }\r
3557                 else\r
3558                 {\r
3559                         if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )\r
3560                         {\r
3561                                 xReturn = taskSCHEDULER_RUNNING;\r
3562                         }\r
3563                         else\r
3564                         {\r
3565                                 xReturn = taskSCHEDULER_SUSPENDED;\r
3566                         }\r
3567                 }\r
3568 \r
3569                 return xReturn;\r
3570         }\r
3571 \r
3572 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */\r
3573 /*-----------------------------------------------------------*/\r
3574 \r
3575 #if ( configUSE_MUTEXES == 1 )\r
3576 \r
3577         void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder )\r
3578         {\r
3579         TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;\r
3580 \r
3581                 /* If the mutex was given back by an interrupt while the queue was\r
3582                 locked then the mutex holder might now be NULL. */\r
3583                 if( pxMutexHolder != NULL )\r
3584                 {\r
3585                         /* If the holder of the mutex has a priority below the priority of\r
3586                         the task attempting to obtain the mutex then it will temporarily\r
3587                         inherit the priority of the task attempting to obtain the mutex. */\r
3588                         if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )\r
3589                         {\r
3590                                 /* Adjust the mutex holder state to account for its new\r
3591                                 priority.  Only reset the event list item value if the value is\r
3592                                 not     being used for anything else. */\r
3593                                 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )\r
3594                                 {\r
3595                                         listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
3596                                 }\r
3597                                 else\r
3598                                 {\r
3599                                         mtCOVERAGE_TEST_MARKER();\r
3600                                 }\r
3601 \r
3602                                 /* If the task being modified is in the ready state it will need\r
3603                                 to be moved into a new list. */\r
3604                                 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )\r
3605                                 {\r
3606                                         if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )\r
3607                                         {\r
3608                                                 taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
3609                                         }\r
3610                                         else\r
3611                                         {\r
3612                                                 mtCOVERAGE_TEST_MARKER();\r
3613                                         }\r
3614 \r
3615                                         /* Inherit the priority before being moved into the new list. */\r
3616                                         pxTCB->uxPriority = pxCurrentTCB->uxPriority;\r
3617                                         prvAddTaskToReadyList( pxTCB );\r
3618                                 }\r
3619                                 else\r
3620                                 {\r
3621                                         /* Just inherit the priority. */\r
3622                                         pxTCB->uxPriority = pxCurrentTCB->uxPriority;\r
3623                                 }\r
3624 \r
3625                                 traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );\r
3626                         }\r
3627                         else\r
3628                         {\r
3629                                 mtCOVERAGE_TEST_MARKER();\r
3630                         }\r
3631                 }\r
3632                 else\r
3633                 {\r
3634                         mtCOVERAGE_TEST_MARKER();\r
3635                 }\r
3636         }\r
3637 \r
3638 #endif /* configUSE_MUTEXES */\r
3639 /*-----------------------------------------------------------*/\r
3640 \r
3641 #if ( configUSE_MUTEXES == 1 )\r
3642 \r
3643         BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )\r
3644         {\r
3645         TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;\r
3646         BaseType_t xReturn = pdFALSE;\r
3647 \r
3648                 if( pxMutexHolder != NULL )\r
3649                 {\r
3650                         /* A task can only have an inherited priority if it holds the mutex.\r
3651                         If the mutex is held by a task then it cannot be given from an\r
3652                         interrupt, and if a mutex is given by the holding task then it must\r
3653                         be the running state task. */\r
3654                         configASSERT( pxTCB == pxCurrentTCB );\r
3655 \r
3656                         configASSERT( pxTCB->uxMutexesHeld );\r
3657                         ( pxTCB->uxMutexesHeld )--;\r
3658 \r
3659                         /* Has the holder of the mutex inherited the priority of another\r
3660                         task? */\r
3661                         if( pxTCB->uxPriority != pxTCB->uxBasePriority )\r
3662                         {\r
3663                                 /* Only disinherit if no other mutexes are held. */\r
3664                                 if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )\r
3665                                 {\r
3666                                         /* A task can only have an inherited priority if it holds\r
3667                                         the mutex.  If the mutex is held by a task then it cannot be\r
3668                                         given from an interrupt, and if a mutex is given by the\r
3669                                         holding task then it must be the running state task.  Remove\r
3670                                         the     holding task from the ready     list. */\r
3671                                         if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )\r
3672                                         {\r
3673                                                 taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
3674                                         }\r
3675                                         else\r
3676                                         {\r
3677                                                 mtCOVERAGE_TEST_MARKER();\r
3678                                         }\r
3679 \r
3680                                         /* Disinherit the priority before adding the task into the\r
3681                                         new     ready list. */\r
3682                                         traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );\r
3683                                         pxTCB->uxPriority = pxTCB->uxBasePriority;\r
3684 \r
3685                                         /* Reset the event list item value.  It cannot be in use for\r
3686                                         any other purpose if this task is running, and it must be\r
3687                                         running to give back the mutex. */\r
3688                                         listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
3689                                         prvAddTaskToReadyList( pxTCB );\r
3690 \r
3691                                         /* Return true to indicate that a context switch is required.\r
3692                                         This is only actually required in the corner case whereby\r
3693                                         multiple mutexes were held and the mutexes were given back\r
3694                                         in an order different to that in which they were taken.\r
3695                                         If a context switch did not occur when the first mutex was\r
3696                                         returned, even if a task was waiting on it, then a context\r
3697                                         switch should occur when the last mutex is returned whether\r
3698                                         a task is waiting on it or not. */\r
3699                                         xReturn = pdTRUE;\r
3700                                 }\r
3701                                 else\r
3702                                 {\r
3703                                         mtCOVERAGE_TEST_MARKER();\r
3704                                 }\r
3705                         }\r
3706                         else\r
3707                         {\r
3708                                 mtCOVERAGE_TEST_MARKER();\r
3709                         }\r
3710                 }\r
3711                 else\r
3712                 {\r
3713                         mtCOVERAGE_TEST_MARKER();\r
3714                 }\r
3715 \r
3716                 return xReturn;\r
3717         }\r
3718 \r
3719 #endif /* configUSE_MUTEXES */\r
3720 /*-----------------------------------------------------------*/\r
3721 \r
3722 #if ( portCRITICAL_NESTING_IN_TCB == 1 )\r
3723 \r
3724         void vTaskEnterCritical( void )\r
3725         {\r
3726                 portDISABLE_INTERRUPTS();\r
3727 \r
3728                 if( xSchedulerRunning != pdFALSE )\r
3729                 {\r
3730                         ( pxCurrentTCB->uxCriticalNesting )++;\r
3731 \r
3732                         /* This is not the interrupt safe version of the enter critical\r
3733                         function so     assert() if it is being called from an interrupt\r
3734                         context.  Only API functions that end in "FromISR" can be used in an\r
3735                         interrupt.  Only assert if the critical nesting count is 1 to\r
3736                         protect against recursive calls if the assert function also uses a\r
3737                         critical section. */\r
3738                         if( pxCurrentTCB->uxCriticalNesting == 1 )\r
3739                         {\r
3740                                 portASSERT_IF_IN_ISR();\r
3741                         }\r
3742                 }\r
3743                 else\r
3744                 {\r
3745                         mtCOVERAGE_TEST_MARKER();\r
3746                 }\r
3747         }\r
3748 \r
3749 #endif /* portCRITICAL_NESTING_IN_TCB */\r
3750 /*-----------------------------------------------------------*/\r
3751 \r
3752 #if ( portCRITICAL_NESTING_IN_TCB == 1 )\r
3753 \r
3754         void vTaskExitCritical( void )\r
3755         {\r
3756                 if( xSchedulerRunning != pdFALSE )\r
3757                 {\r
3758                         if( pxCurrentTCB->uxCriticalNesting > 0U )\r
3759                         {\r
3760                                 ( pxCurrentTCB->uxCriticalNesting )--;\r
3761 \r
3762                                 if( pxCurrentTCB->uxCriticalNesting == 0U )\r
3763                                 {\r
3764                                         portENABLE_INTERRUPTS();\r
3765                                 }\r
3766                                 else\r
3767                                 {\r
3768                                         mtCOVERAGE_TEST_MARKER();\r
3769                                 }\r
3770                         }\r
3771                         else\r
3772                         {\r
3773                                 mtCOVERAGE_TEST_MARKER();\r
3774                         }\r
3775                 }\r
3776                 else\r
3777                 {\r
3778                         mtCOVERAGE_TEST_MARKER();\r
3779                 }\r
3780         }\r
3781 \r
3782 #endif /* portCRITICAL_NESTING_IN_TCB */\r
3783 /*-----------------------------------------------------------*/\r
3784 \r
3785 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )\r
3786 \r
3787         static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName )\r
3788         {\r
3789         size_t x;\r
3790 \r
3791                 /* Start by copying the entire string. */\r
3792                 strcpy( pcBuffer, pcTaskName );\r
3793 \r
3794                 /* Pad the end of the string with spaces to ensure columns line up when\r
3795                 printed out. */\r
3796                 for( x = strlen( pcBuffer ); x < ( size_t ) ( configMAX_TASK_NAME_LEN - 1 ); x++ )\r
3797                 {\r
3798                         pcBuffer[ x ] = ' ';\r
3799                 }\r
3800 \r
3801                 /* Terminate. */\r
3802                 pcBuffer[ x ] = 0x00;\r
3803 \r
3804                 /* Return the new end of string. */\r
3805                 return &( pcBuffer[ x ] );\r
3806         }\r
3807 \r
3808 #endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */\r
3809 /*-----------------------------------------------------------*/\r
3810 \r
3811 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )\r
3812 \r
3813         void vTaskList( char * pcWriteBuffer )\r
3814         {\r
3815         TaskStatus_t *pxTaskStatusArray;\r
3816         volatile UBaseType_t uxArraySize, x;\r
3817         char cStatus;\r
3818 \r
3819                 /*\r
3820                  * PLEASE NOTE:\r
3821                  *\r
3822                  * This function is provided for convenience only, and is used by many\r
3823                  * of the demo applications.  Do not consider it to be part of the\r
3824                  * scheduler.\r
3825                  *\r
3826                  * vTaskList() calls uxTaskGetSystemState(), then formats part of the\r
3827                  * uxTaskGetSystemState() output into a human readable table that\r
3828                  * displays task names, states and stack usage.\r
3829                  *\r
3830                  * vTaskList() has a dependency on the sprintf() C library function that\r
3831                  * might bloat the code size, use a lot of stack, and provide different\r
3832                  * results on different platforms.  An alternative, tiny, third party,\r
3833                  * and limited functionality implementation of sprintf() is provided in\r
3834                  * many of the FreeRTOS/Demo sub-directories in a file called\r
3835                  * printf-stdarg.c (note printf-stdarg.c does not provide a full\r
3836                  * snprintf() implementation!).\r
3837                  *\r
3838                  * It is recommended that production systems call uxTaskGetSystemState()\r
3839                  * directly to get access to raw stats data, rather than indirectly\r
3840                  * through a call to vTaskList().\r
3841                  */\r
3842 \r
3843 \r
3844                 /* Make sure the write buffer does not contain a string. */\r
3845                 *pcWriteBuffer = 0x00;\r
3846 \r
3847                 /* Take a snapshot of the number of tasks in case it changes while this\r
3848                 function is executing. */\r
3849                 uxArraySize = uxCurrentNumberOfTasks;\r
3850 \r
3851                 /* Allocate an array index for each task.  NOTE!  if\r
3852                 configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will\r
3853                 equate to NULL. */\r
3854                 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );\r
3855 \r
3856                 if( pxTaskStatusArray != NULL )\r
3857                 {\r
3858                         /* Generate the (binary) data. */\r
3859                         uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );\r
3860 \r
3861                         /* Create a human readable table from the binary data. */\r
3862                         for( x = 0; x < uxArraySize; x++ )\r
3863                         {\r
3864                                 switch( pxTaskStatusArray[ x ].eCurrentState )\r
3865                                 {\r
3866                                         case eReady:            cStatus = tskREADY_CHAR;\r
3867                                                                                 break;\r
3868 \r
3869                                         case eBlocked:          cStatus = tskBLOCKED_CHAR;\r
3870                                                                                 break;\r
3871 \r
3872                                         case eSuspended:        cStatus = tskSUSPENDED_CHAR;\r
3873                                                                                 break;\r
3874 \r
3875                                         case eDeleted:          cStatus = tskDELETED_CHAR;\r
3876                                                                                 break;\r
3877 \r
3878                                         default:                        /* Should not get here, but it is included\r
3879                                                                                 to prevent static checking errors. */\r
3880                                                                                 cStatus = 0x00;\r
3881                                                                                 break;\r
3882                                 }\r
3883 \r
3884                                 /* Write the task name to the string, padding with spaces so it\r
3885                                 can be printed in tabular form more easily. */\r
3886                                 pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );\r
3887 \r
3888                                 /* Write the rest of the string. */\r
3889                                 sprintf( pcWriteBuffer, "\t%c\t%u\t%u\t%u\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber );\r
3890                                 pcWriteBuffer += strlen( pcWriteBuffer );\r
3891                         }\r
3892 \r
3893                         /* Free the array again.  NOTE!  If configSUPPORT_DYNAMIC_ALLOCATION\r
3894                         is 0 then vPortFree() will be #defined to nothing. */\r
3895                         vPortFree( pxTaskStatusArray );\r
3896                 }\r
3897                 else\r
3898                 {\r
3899                         mtCOVERAGE_TEST_MARKER();\r
3900                 }\r
3901         }\r
3902 \r
3903 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */\r
3904 /*----------------------------------------------------------*/\r
3905 \r
3906 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )\r
3907 \r
3908         void vTaskGetRunTimeStats( char *pcWriteBuffer )\r
3909         {\r
3910         TaskStatus_t *pxTaskStatusArray;\r
3911         volatile UBaseType_t uxArraySize, x;\r
3912         uint32_t ulTotalTime, ulStatsAsPercentage;\r
3913 \r
3914                 #if( configUSE_TRACE_FACILITY != 1 )\r
3915                 {\r
3916                         #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats().\r
3917                 }\r
3918                 #endif\r
3919 \r
3920                 /*\r
3921                  * PLEASE NOTE:\r
3922                  *\r
3923                  * This function is provided for convenience only, and is used by many\r
3924                  * of the demo applications.  Do not consider it to be part of the\r
3925                  * scheduler.\r
3926                  *\r
3927                  * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part\r
3928                  * of the uxTaskGetSystemState() output into a human readable table that\r
3929                  * displays the amount of time each task has spent in the Running state\r
3930                  * in both absolute and percentage terms.\r
3931                  *\r
3932                  * vTaskGetRunTimeStats() has a dependency on the sprintf() C library\r
3933                  * function that might bloat the code size, use a lot of stack, and\r
3934                  * provide different results on different platforms.  An alternative,\r
3935                  * tiny, third party, and limited functionality implementation of\r
3936                  * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in\r
3937                  * a file called printf-stdarg.c (note printf-stdarg.c does not provide\r
3938                  * a full snprintf() implementation!).\r
3939                  *\r
3940                  * It is recommended that production systems call uxTaskGetSystemState()\r
3941                  * directly to get access to raw stats data, rather than indirectly\r
3942                  * through a call to vTaskGetRunTimeStats().\r
3943                  */\r
3944 \r
3945                 /* Make sure the write buffer does not contain a string. */\r
3946                 *pcWriteBuffer = 0x00;\r
3947 \r
3948                 /* Take a snapshot of the number of tasks in case it changes while this\r
3949                 function is executing. */\r
3950                 uxArraySize = uxCurrentNumberOfTasks;\r
3951 \r
3952                 /* Allocate an array index for each task.  NOTE!  If\r
3953                 configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will\r
3954                 equate to NULL. */\r
3955                 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );\r
3956 \r
3957                 if( pxTaskStatusArray != NULL )\r
3958                 {\r
3959                         /* Generate the (binary) data. */\r
3960                         uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );\r
3961 \r
3962                         /* For percentage calculations. */\r
3963                         ulTotalTime /= 100UL;\r
3964 \r
3965                         /* Avoid divide by zero errors. */\r
3966                         if( ulTotalTime > 0 )\r
3967                         {\r
3968                                 /* Create a human readable table from the binary data. */\r
3969                                 for( x = 0; x < uxArraySize; x++ )\r
3970                                 {\r
3971                                         /* What percentage of the total run time has the task used?\r
3972                                         This will always be rounded down to the nearest integer.\r
3973                                         ulTotalRunTimeDiv100 has already been divided by 100. */\r
3974                                         ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;\r
3975 \r
3976                                         /* Write the task name to the string, padding with\r
3977                                         spaces so it can be printed in tabular form more\r
3978                                         easily. */\r
3979                                         pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );\r
3980 \r
3981                                         if( ulStatsAsPercentage > 0UL )\r
3982                                         {\r
3983                                                 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED\r
3984                                                 {\r
3985                                                         sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );\r
3986                                                 }\r
3987                                                 #else\r
3988                                                 {\r
3989                                                         /* sizeof( int ) == sizeof( long ) so a smaller\r
3990                                                         printf() library can be used. */\r
3991                                                         sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );\r
3992                                                 }\r
3993                                                 #endif\r
3994                                         }\r
3995                                         else\r
3996                                         {\r
3997                                                 /* If the percentage is zero here then the task has\r
3998                                                 consumed less than 1% of the total run time. */\r
3999                                                 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED\r
4000                                                 {\r
4001                                                         sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter );\r
4002                                                 }\r
4003                                                 #else\r
4004                                                 {\r
4005                                                         /* sizeof( int ) == sizeof( long ) so a smaller\r
4006                                                         printf() library can be used. */\r
4007                                                         sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter );\r
4008                                                 }\r
4009                                                 #endif\r
4010                                         }\r
4011 \r
4012                                         pcWriteBuffer += strlen( pcWriteBuffer );\r
4013                                 }\r
4014                         }\r
4015                         else\r
4016                         {\r
4017                                 mtCOVERAGE_TEST_MARKER();\r
4018                         }\r
4019 \r
4020                         /* Free the array again.  NOTE!  If configSUPPORT_DYNAMIC_ALLOCATION\r
4021                         is 0 then vPortFree() will be #defined to nothing. */\r
4022                         vPortFree( pxTaskStatusArray );\r
4023                 }\r
4024                 else\r
4025                 {\r
4026                         mtCOVERAGE_TEST_MARKER();\r
4027                 }\r
4028         }\r
4029 \r
4030 #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */\r
4031 /*-----------------------------------------------------------*/\r
4032 \r
4033 TickType_t uxTaskResetEventItemValue( void )\r
4034 {\r
4035 TickType_t uxReturn;\r
4036 \r
4037         uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );\r
4038 \r
4039         /* Reset the event list item to its normal value - so it can be used with\r
4040         queues and semaphores. */\r
4041         listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */\r
4042 \r
4043         return uxReturn;\r
4044 }\r
4045 /*-----------------------------------------------------------*/\r
4046 \r
4047 #if ( configUSE_MUTEXES == 1 )\r
4048 \r
4049         void *pvTaskIncrementMutexHeldCount( void )\r
4050         {\r
4051                 /* If xSemaphoreCreateMutex() is called before any tasks have been created\r
4052                 then pxCurrentTCB will be NULL. */\r
4053                 if( pxCurrentTCB != NULL )\r
4054                 {\r
4055                         ( pxCurrentTCB->uxMutexesHeld )++;\r
4056                 }\r
4057 \r
4058                 return pxCurrentTCB;\r
4059         }\r
4060 \r
4061 #endif /* configUSE_MUTEXES */\r
4062 /*-----------------------------------------------------------*/\r
4063 \r
4064 #if( configUSE_TASK_NOTIFICATIONS == 1 )\r
4065 \r
4066         uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )\r
4067         {\r
4068         uint32_t ulReturn;\r
4069 \r
4070                 taskENTER_CRITICAL();\r
4071                 {\r
4072                         /* Only block if the notification count is not already non-zero. */\r
4073                         if( pxCurrentTCB->ulNotifiedValue == 0UL )\r
4074                         {\r
4075                                 /* Mark this task as waiting for a notification. */\r
4076                                 pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;\r
4077 \r
4078                                 if( xTicksToWait > ( TickType_t ) 0 )\r
4079                                 {\r
4080                                         prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );\r
4081                                         traceTASK_NOTIFY_TAKE_BLOCK();\r
4082 \r
4083                                         /* All ports are written to allow a yield in a critical\r
4084                                         section (some will yield immediately, others wait until the\r
4085                                         critical section exits) - but it is not something that\r
4086                                         application code should ever do. */\r
4087                                         portYIELD_WITHIN_API();\r
4088                                 }\r
4089                                 else\r
4090                                 {\r
4091                                         mtCOVERAGE_TEST_MARKER();\r
4092                                 }\r
4093                         }\r
4094                         else\r
4095                         {\r
4096                                 mtCOVERAGE_TEST_MARKER();\r
4097                         }\r
4098                 }\r
4099                 taskEXIT_CRITICAL();\r
4100 \r
4101                 taskENTER_CRITICAL();\r
4102                 {\r
4103                         traceTASK_NOTIFY_TAKE();\r
4104                         ulReturn = pxCurrentTCB->ulNotifiedValue;\r
4105 \r
4106                         if( ulReturn != 0UL )\r
4107                         {\r
4108                                 if( xClearCountOnExit != pdFALSE )\r
4109                                 {\r
4110                                         pxCurrentTCB->ulNotifiedValue = 0UL;\r
4111                                 }\r
4112                                 else\r
4113                                 {\r
4114                                         ( pxCurrentTCB->ulNotifiedValue )--;\r
4115                                 }\r
4116                         }\r
4117                         else\r
4118                         {\r
4119                                 mtCOVERAGE_TEST_MARKER();\r
4120                         }\r
4121 \r
4122                         pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;\r
4123                 }\r
4124                 taskEXIT_CRITICAL();\r
4125 \r
4126                 return ulReturn;\r
4127         }\r
4128 \r
4129 #endif /* configUSE_TASK_NOTIFICATIONS */\r
4130 /*-----------------------------------------------------------*/\r
4131 \r
4132 #if( configUSE_TASK_NOTIFICATIONS == 1 )\r
4133 \r
4134         BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait )\r
4135         {\r
4136         BaseType_t xReturn;\r
4137 \r
4138                 taskENTER_CRITICAL();\r
4139                 {\r
4140                         /* Only block if a notification is not already pending. */\r
4141                         if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED )\r
4142                         {\r
4143                                 /* Clear bits in the task's notification value as bits may get\r
4144                                 set     by the notifying task or interrupt.  This can be used to\r
4145                                 clear the value to zero. */\r
4146                                 pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry;\r
4147 \r
4148                                 /* Mark this task as waiting for a notification. */\r
4149                                 pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;\r
4150 \r
4151                                 if( xTicksToWait > ( TickType_t ) 0 )\r
4152                                 {\r
4153                                         prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );\r
4154                                         traceTASK_NOTIFY_WAIT_BLOCK();\r
4155 \r
4156                                         /* All ports are written to allow a yield in a critical\r
4157                                         section (some will yield immediately, others wait until the\r
4158                                         critical section exits) - but it is not something that\r
4159                                         application code should ever do. */\r
4160                                         portYIELD_WITHIN_API();\r
4161                                 }\r
4162                                 else\r
4163                                 {\r
4164                                         mtCOVERAGE_TEST_MARKER();\r
4165                                 }\r
4166                         }\r
4167                         else\r
4168                         {\r
4169                                 mtCOVERAGE_TEST_MARKER();\r
4170                         }\r
4171                 }\r
4172                 taskEXIT_CRITICAL();\r
4173 \r
4174                 taskENTER_CRITICAL();\r
4175                 {\r
4176                         traceTASK_NOTIFY_WAIT();\r
4177 \r
4178                         if( pulNotificationValue != NULL )\r
4179                         {\r
4180                                 /* Output the current notification value, which may or may not\r
4181                                 have changed. */\r
4182                                 *pulNotificationValue = pxCurrentTCB->ulNotifiedValue;\r
4183                         }\r
4184 \r
4185                         /* If ucNotifyValue is set then either the task never entered the\r
4186                         blocked state (because a notification was already pending) or the\r
4187                         task unblocked because of a notification.  Otherwise the task\r
4188                         unblocked because of a timeout. */\r
4189                         if( pxCurrentTCB->ucNotifyState == taskWAITING_NOTIFICATION )\r
4190                         {\r
4191                                 /* A notification was not received. */\r
4192                                 xReturn = pdFALSE;\r
4193                         }\r
4194                         else\r
4195                         {\r
4196                                 /* A notification was already pending or a notification was\r
4197                                 received while the task was waiting. */\r
4198                                 pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnExit;\r
4199                                 xReturn = pdTRUE;\r
4200                         }\r
4201 \r
4202                         pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;\r
4203                 }\r
4204                 taskEXIT_CRITICAL();\r
4205 \r
4206                 return xReturn;\r
4207         }\r
4208 \r
4209 #endif /* configUSE_TASK_NOTIFICATIONS */\r
4210 /*-----------------------------------------------------------*/\r
4211 \r
4212 #if( configUSE_TASK_NOTIFICATIONS == 1 )\r
4213 \r
4214         BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue )\r
4215         {\r
4216         TCB_t * pxTCB;\r
4217         BaseType_t xReturn = pdPASS;\r
4218         uint8_t ucOriginalNotifyState;\r
4219 \r
4220                 configASSERT( xTaskToNotify );\r
4221                 pxTCB = ( TCB_t * ) xTaskToNotify;\r
4222 \r
4223                 taskENTER_CRITICAL();\r
4224                 {\r
4225                         if( pulPreviousNotificationValue != NULL )\r
4226                         {\r
4227                                 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;\r
4228                         }\r
4229 \r
4230                         ucOriginalNotifyState = pxTCB->ucNotifyState;\r
4231 \r
4232                         pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;\r
4233 \r
4234                         switch( eAction )\r
4235                         {\r
4236                                 case eSetBits   :\r
4237                                         pxTCB->ulNotifiedValue |= ulValue;\r
4238                                         break;\r
4239 \r
4240                                 case eIncrement :\r
4241                                         ( pxTCB->ulNotifiedValue )++;\r
4242                                         break;\r
4243 \r
4244                                 case eSetValueWithOverwrite     :\r
4245                                         pxTCB->ulNotifiedValue = ulValue;\r
4246                                         break;\r
4247 \r
4248                                 case eSetValueWithoutOverwrite :\r
4249                                         if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )\r
4250                                         {\r
4251                                                 pxTCB->ulNotifiedValue = ulValue;\r
4252                                         }\r
4253                                         else\r
4254                                         {\r
4255                                                 /* The value could not be written to the task. */\r
4256                                                 xReturn = pdFAIL;\r
4257                                         }\r
4258                                         break;\r
4259 \r
4260                                 case eNoAction:\r
4261                                         /* The task is being notified without its notify value being\r
4262                                         updated. */\r
4263                                         break;\r
4264                         }\r
4265 \r
4266                         traceTASK_NOTIFY();\r
4267 \r
4268                         /* If the task is in the blocked state specifically to wait for a\r
4269                         notification then unblock it now. */\r
4270                         if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )\r
4271                         {\r
4272                                 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );\r
4273                                 prvAddTaskToReadyList( pxTCB );\r
4274 \r
4275                                 /* The task should not have been on an event list. */\r
4276                                 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );\r
4277 \r
4278                                 #if( configUSE_TICKLESS_IDLE != 0 )\r
4279                                 {\r
4280                                         /* If a task is blocked waiting for a notification then\r
4281                                         xNextTaskUnblockTime might be set to the blocked task's time\r
4282                                         out time.  If the task is unblocked for a reason other than\r
4283                                         a timeout xNextTaskUnblockTime is normally left unchanged,\r
4284                                         because it will automatically get reset to a new value when\r
4285                                         the tick count equals xNextTaskUnblockTime.  However if\r
4286                                         tickless idling is used it might be more important to enter\r
4287                                         sleep mode at the earliest possible time - so reset\r
4288                                         xNextTaskUnblockTime here to ensure it is updated at the\r
4289                                         earliest possible time. */\r
4290                                         prvResetNextTaskUnblockTime();\r
4291                                 }\r
4292                                 #endif\r
4293 \r
4294                                 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )\r
4295                                 {\r
4296                                         /* The notified task has a priority above the currently\r
4297                                         executing task so a yield is required. */\r
4298                                         taskYIELD_IF_USING_PREEMPTION();\r
4299                                 }\r
4300                                 else\r
4301                                 {\r
4302                                         mtCOVERAGE_TEST_MARKER();\r
4303                                 }\r
4304                         }\r
4305                         else\r
4306                         {\r
4307                                 mtCOVERAGE_TEST_MARKER();\r
4308                         }\r
4309                 }\r
4310                 taskEXIT_CRITICAL();\r
4311 \r
4312                 return xReturn;\r
4313         }\r
4314 \r
4315 #endif /* configUSE_TASK_NOTIFICATIONS */\r
4316 /*-----------------------------------------------------------*/\r
4317 \r
4318 #if( configUSE_TASK_NOTIFICATIONS == 1 )\r
4319 \r
4320         BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken )\r
4321         {\r
4322         TCB_t * pxTCB;\r
4323         uint8_t ucOriginalNotifyState;\r
4324         BaseType_t xReturn = pdPASS;\r
4325         UBaseType_t uxSavedInterruptStatus;\r
4326 \r
4327                 configASSERT( xTaskToNotify );\r
4328 \r
4329                 /* RTOS ports that support interrupt nesting have the concept of a\r
4330                 maximum system call (or maximum API call) interrupt priority.\r
4331                 Interrupts that are     above the maximum system call priority are keep\r
4332                 permanently enabled, even when the RTOS kernel is in a critical section,\r
4333                 but cannot make any calls to FreeRTOS API functions.  If configASSERT()\r
4334                 is defined in FreeRTOSConfig.h then\r
4335                 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
4336                 failure if a FreeRTOS API function is called from an interrupt that has\r
4337                 been assigned a priority above the configured maximum system call\r
4338                 priority.  Only FreeRTOS functions that end in FromISR can be called\r
4339                 from interrupts that have been assigned a priority at or (logically)\r
4340                 below the maximum system call interrupt priority.  FreeRTOS maintains a\r
4341                 separate interrupt safe API to ensure interrupt entry is as fast and as\r
4342                 simple as possible.  More information (albeit Cortex-M specific) is\r
4343                 provided on the following link:\r
4344                 http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
4345                 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
4346 \r
4347                 pxTCB = ( TCB_t * ) xTaskToNotify;\r
4348 \r
4349                 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
4350                 {\r
4351                         if( pulPreviousNotificationValue != NULL )\r
4352                         {\r
4353                                 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;\r
4354                         }\r
4355 \r
4356                         ucOriginalNotifyState = pxTCB->ucNotifyState;\r
4357                         pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;\r
4358 \r
4359                         switch( eAction )\r
4360                         {\r
4361                                 case eSetBits   :\r
4362                                         pxTCB->ulNotifiedValue |= ulValue;\r
4363                                         break;\r
4364 \r
4365                                 case eIncrement :\r
4366                                         ( pxTCB->ulNotifiedValue )++;\r
4367                                         break;\r
4368 \r
4369                                 case eSetValueWithOverwrite     :\r
4370                                         pxTCB->ulNotifiedValue = ulValue;\r
4371                                         break;\r
4372 \r
4373                                 case eSetValueWithoutOverwrite :\r
4374                                         if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )\r
4375                                         {\r
4376                                                 pxTCB->ulNotifiedValue = ulValue;\r
4377                                         }\r
4378                                         else\r
4379                                         {\r
4380                                                 /* The value could not be written to the task. */\r
4381                                                 xReturn = pdFAIL;\r
4382                                         }\r
4383                                         break;\r
4384 \r
4385                                 case eNoAction :\r
4386                                         /* The task is being notified without its notify value being\r
4387                                         updated. */\r
4388                                         break;\r
4389                         }\r
4390 \r
4391                         traceTASK_NOTIFY_FROM_ISR();\r
4392 \r
4393                         /* If the task is in the blocked state specifically to wait for a\r
4394                         notification then unblock it now. */\r
4395                         if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )\r
4396                         {\r
4397                                 /* The task should not have been on an event list. */\r
4398                                 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );\r
4399 \r
4400                                 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )\r
4401                                 {\r
4402                                         ( void ) uxListRemove( &( pxTCB->xStateListItem ) );\r
4403                                         prvAddTaskToReadyList( pxTCB );\r
4404                                 }\r
4405                                 else\r
4406                                 {\r
4407                                         /* The delayed and ready lists cannot be accessed, so hold\r
4408                                         this task pending until the scheduler is resumed. */\r
4409                                         vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );\r
4410                                 }\r
4411 \r
4412                                 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )\r
4413                                 {\r
4414                                         /* The notified task has a priority above the currently\r
4415                                         executing task so a yield is required. */\r
4416                                         if( pxHigherPriorityTaskWoken != NULL )\r
4417                                         {\r
4418                                                 *pxHigherPriorityTaskWoken = pdTRUE;\r
4419                                         }\r
4420                                         else\r
4421                                         {\r
4422                                                 /* Mark that a yield is pending in case the user is not\r
4423                                                 using the "xHigherPriorityTaskWoken" parameter to an ISR\r
4424                                                 safe FreeRTOS function. */\r
4425                                                 xYieldPending = pdTRUE;\r
4426                                         }\r
4427                                 }\r
4428                                 else\r
4429                                 {\r
4430                                         mtCOVERAGE_TEST_MARKER();\r
4431                                 }\r
4432                         }\r
4433                 }\r
4434                 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
4435 \r
4436                 return xReturn;\r
4437         }\r
4438 \r
4439 #endif /* configUSE_TASK_NOTIFICATIONS */\r
4440 /*-----------------------------------------------------------*/\r
4441 \r
4442 #if( configUSE_TASK_NOTIFICATIONS == 1 )\r
4443 \r
4444         void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken )\r
4445         {\r
4446         TCB_t * pxTCB;\r
4447         uint8_t ucOriginalNotifyState;\r
4448         UBaseType_t uxSavedInterruptStatus;\r
4449 \r
4450                 configASSERT( xTaskToNotify );\r
4451 \r
4452                 /* RTOS ports that support interrupt nesting have the concept of a\r
4453                 maximum system call (or maximum API call) interrupt priority.\r
4454                 Interrupts that are     above the maximum system call priority are keep\r
4455                 permanently enabled, even when the RTOS kernel is in a critical section,\r
4456                 but cannot make any calls to FreeRTOS API functions.  If configASSERT()\r
4457                 is defined in FreeRTOSConfig.h then\r
4458                 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
4459                 failure if a FreeRTOS API function is called from an interrupt that has\r
4460                 been assigned a priority above the configured maximum system call\r
4461                 priority.  Only FreeRTOS functions that end in FromISR can be called\r
4462                 from interrupts that have been assigned a priority at or (logically)\r
4463                 below the maximum system call interrupt priority.  FreeRTOS maintains a\r
4464                 separate interrupt safe API to ensure interrupt entry is as fast and as\r
4465                 simple as possible.  More information (albeit Cortex-M specific) is\r
4466                 provided on the following link:\r
4467                 http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
4468                 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
4469 \r
4470                 pxTCB = ( TCB_t * ) xTaskToNotify;\r
4471 \r
4472                 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
4473                 {\r
4474                         ucOriginalNotifyState = pxTCB->ucNotifyState;\r
4475                         pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;\r
4476 \r
4477                         /* 'Giving' is equivalent to incrementing a count in a counting\r
4478                         semaphore. */\r
4479                         ( pxTCB->ulNotifiedValue )++;\r
4480 \r
4481                         traceTASK_NOTIFY_GIVE_FROM_ISR();\r
4482 \r
4483                         /* If the task is in the blocked state specifically to wait for a\r
4484                         notification then unblock it now. */\r
4485                         if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )\r
4486                         {\r
4487                                 /* The task should not have been on an event list. */\r
4488                                 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );\r
4489 \r
4490                                 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )\r
4491                                 {\r
4492                                         ( void ) uxListRemove( &( pxTCB->xStateListItem ) );\r
4493                                         prvAddTaskToReadyList( pxTCB );\r
4494                                 }\r
4495                                 else\r
4496                                 {\r
4497                                         /* The delayed and ready lists cannot be accessed, so hold\r
4498                                         this task pending until the scheduler is resumed. */\r
4499                                         vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );\r
4500                                 }\r
4501 \r
4502                                 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )\r
4503                                 {\r
4504                                         /* The notified task has a priority above the currently\r
4505                                         executing task so a yield is required. */\r
4506                                         if( pxHigherPriorityTaskWoken != NULL )\r
4507                                         {\r
4508                                                 *pxHigherPriorityTaskWoken = pdTRUE;\r
4509                                         }\r
4510                                         else\r
4511                                         {\r
4512                                                 /* Mark that a yield is pending in case the user is not\r
4513                                                 using the "xHigherPriorityTaskWoken" parameter in an ISR\r
4514                                                 safe FreeRTOS function. */\r
4515                                                 xYieldPending = pdTRUE;\r
4516                                         }\r
4517                                 }\r
4518                                 else\r
4519                                 {\r
4520                                         mtCOVERAGE_TEST_MARKER();\r
4521                                 }\r
4522                         }\r
4523                 }\r
4524                 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
4525         }\r
4526 \r
4527 #endif /* configUSE_TASK_NOTIFICATIONS */\r
4528 \r
4529 /*-----------------------------------------------------------*/\r
4530 \r
4531 #if( configUSE_TASK_NOTIFICATIONS == 1 )\r
4532 \r
4533         BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask )\r
4534         {\r
4535         TCB_t *pxTCB;\r
4536         BaseType_t xReturn;\r
4537 \r
4538                 /* If null is passed in here then it is the calling task that is having\r
4539                 its notification state cleared. */\r
4540                 pxTCB = prvGetTCBFromHandle( xTask );\r
4541 \r
4542                 taskENTER_CRITICAL();\r
4543                 {\r
4544                         if( pxTCB->ucNotifyState == taskNOTIFICATION_RECEIVED )\r
4545                         {\r
4546                                 pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;\r
4547                                 xReturn = pdPASS;\r
4548                         }\r
4549                         else\r
4550                         {\r
4551                                 xReturn = pdFAIL;\r
4552                         }\r
4553                 }\r
4554                 taskEXIT_CRITICAL();\r
4555 \r
4556                 return xReturn;\r
4557         }\r
4558 \r
4559 #endif /* configUSE_TASK_NOTIFICATIONS */\r
4560 /*-----------------------------------------------------------*/\r
4561 \r
4562 \r
4563 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely )\r
4564 {\r
4565 TickType_t xTimeToWake;\r
4566 \r
4567         #if( INCLUDE_xTaskAbortDelay == 1 )\r
4568         {\r
4569                 /* About to enter a delayed list, so ensure the ucDelayAborted flag is\r
4570                 reset to pdFALSE so it can be detected as having been set to pdTRUE\r
4571                 when the task leaves the Blocked state. */\r
4572                 pxCurrentTCB->ucDelayAborted = pdFALSE;\r
4573         }\r
4574         #endif\r
4575 \r
4576         /* Remove the task from the ready list before adding it to the blocked list\r
4577         as the same list item is used for both lists. */\r
4578         if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )\r
4579         {\r
4580                 /* The current task must be in a ready list, so there is no need to\r
4581                 check, and the port reset macro can be called directly. */\r
4582                 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );\r
4583         }\r
4584         else\r
4585         {\r
4586                 mtCOVERAGE_TEST_MARKER();\r
4587         }\r
4588 \r
4589 \r
4590         #if ( INCLUDE_vTaskSuspend == 1 )\r
4591         {\r
4592                 if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )\r
4593                 {\r
4594                         /* Add the task to the suspended task list instead of a delayed task\r
4595                         list to ensure it is not woken by a timing event.  It will block\r
4596                         indefinitely. */\r
4597                         vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );\r
4598                 }\r
4599                 else\r
4600                 {\r
4601                         /* Calculate the time at which the task should be woken if the event\r
4602                         does not occur.  This may overflow but this doesn't matter, the\r
4603                         kernel will manage it correctly. */\r
4604                         xTimeToWake = xTickCount + xTicksToWait;\r
4605 \r
4606                         /* The list item will be inserted in wake time order. */\r
4607                         listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );\r
4608 \r
4609                         if( xTimeToWake < xTickCount )\r
4610                         {\r
4611                                 /* Wake time has overflowed.  Place this item in the overflow\r
4612                                 list. */\r
4613                                 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );\r
4614                         }\r
4615                         else\r
4616                         {\r
4617                                 /* The wake time has not overflowed, so the current block list\r
4618                                 is used. */\r
4619                                 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );\r
4620 \r
4621                                 /* If the task entering the blocked state was placed at the\r
4622                                 head of the list of blocked tasks then xNextTaskUnblockTime\r
4623                                 needs to be updated too. */\r
4624                                 if( xTimeToWake < xNextTaskUnblockTime )\r
4625                                 {\r
4626                                         xNextTaskUnblockTime = xTimeToWake;\r
4627                                 }\r
4628                                 else\r
4629                                 {\r
4630                                         mtCOVERAGE_TEST_MARKER();\r
4631                                 }\r
4632                         }\r
4633                 }\r
4634         }\r
4635         #else /* INCLUDE_vTaskSuspend */\r
4636         {\r
4637                 /* Calculate the time at which the task should be woken if the event\r
4638                 does not occur.  This may overflow but this doesn't matter, the kernel\r
4639                 will manage it correctly. */\r
4640                 xTimeToWake = xTickCount + xTicksToWait;\r
4641 \r
4642                 /* The list item will be inserted in wake time order. */\r
4643                 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );\r
4644 \r
4645                 if( xTimeToWake < xTickCount )\r
4646                 {\r
4647                         /* Wake time has overflowed.  Place this item in the overflow list. */\r
4648                         vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );\r
4649                 }\r
4650                 else\r
4651                 {\r
4652                         /* The wake time has not overflowed, so the current block list is used. */\r
4653                         vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );\r
4654 \r
4655                         /* If the task entering the blocked state was placed at the head of the\r
4656                         list of blocked tasks then xNextTaskUnblockTime needs to be updated\r
4657                         too. */\r
4658                         if( xTimeToWake < xNextTaskUnblockTime )\r
4659                         {\r
4660                                 xNextTaskUnblockTime = xTimeToWake;\r
4661                         }\r
4662                         else\r
4663                         {\r
4664                                 mtCOVERAGE_TEST_MARKER();\r
4665                         }\r
4666                 }\r
4667 \r
4668                 /* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */\r
4669                 ( void ) xCanBlockIndefinitely;\r
4670         }\r
4671         #endif /* INCLUDE_vTaskSuspend */\r
4672 }\r
4673 \r
4674 \r
4675 #ifdef FREERTOS_MODULE_TEST\r
4676         #include "tasks_test_access_functions.h"\r
4677 #endif\r
4678 \r