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