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