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