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