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


inertial_sense_ros
Author(s):
autogenerated on Sun Feb 28 2021 03:17:58