2 * FreeRTOS Kernel V10.1.0
\r
3 * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 * http://www.FreeRTOS.org
\r
23 * http://aws.amazon.com/freertos
\r
25 * 1 tab == 4 spaces!
\r
28 /* Standard includes. */
\r
32 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
\r
33 all the API functions to use the MPU wrappers. That should only be done when
\r
34 task.h is included from an application file. */
\r
35 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
37 /* FreeRTOS includes. */
\r
38 #include "FreeRTOS.h"
\r
41 #include "stack_macros.h"
\r
43 /* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified
\r
44 because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
\r
45 for the header files above, but not in this file, in order to generate the
\r
46 correct privileged Vs unprivileged linkage and placement. */
\r
47 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */
\r
49 /* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting
\r
50 functions but without including stdio.h here. */
\r
51 #if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 )
\r
52 /* At the bottom of this file are two optional functions that can be used
\r
53 to generate human readable text from the raw data generated by the
\r
54 uxTaskGetSystemState() function. Note the formatting functions are provided
\r
55 for convenience only, and are NOT considered part of the kernel. */
\r
57 #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
\r
59 #if( configUSE_PREEMPTION == 0 )
\r
60 /* If the cooperative scheduler is being used then a yield should not be
\r
61 performed just because a higher priority task has been woken. */
\r
62 #define taskYIELD_IF_USING_PREEMPTION()
\r
64 #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
\r
67 /* Values that can be assigned to the ucNotifyState member of the TCB. */
\r
68 #define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 )
\r
69 #define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 )
\r
70 #define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 )
\r
73 * The value used to fill the stack of a task when the task is created. This
\r
74 * is used purely for checking the high water mark for tasks.
\r
76 #define tskSTACK_FILL_BYTE ( 0xa5U )
\r
78 /* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using
\r
79 dynamically allocated RAM, in which case when any task is deleted it is known
\r
80 that both the task's stack and TCB need to be freed. Sometimes the
\r
81 FreeRTOSConfig.h settings only allow a task to be created using statically
\r
82 allocated RAM, in which case when any task is deleted it is known that neither
\r
83 the task's stack or TCB should be freed. Sometimes the FreeRTOSConfig.h
\r
84 settings allow a task to be created using either statically or dynamically
\r
85 allocated RAM, in which case a member of the TCB is used to record whether the
\r
86 stack and/or TCB were allocated statically or dynamically, so when a task is
\r
87 deleted the RAM that was allocated dynamically is freed again and no attempt is
\r
88 made to free the RAM that was allocated statically.
\r
89 tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is only true if it is possible for a
\r
90 task to be created using either statically or dynamically allocated RAM. Note
\r
91 that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with
\r
92 a statically allocated stack and a dynamically allocated TCB.
\r
93 !!!NOTE!!! If the definition of tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is
\r
94 changed then the definition of StaticTask_t must also be updated. */
\r
95 #define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
\r
96 #define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 0 )
\r
97 #define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 )
\r
98 #define tskSTATICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 2 )
\r
100 /* If any of the following are set then task stacks are filled with a known
\r
101 value so the high water mark can be determined. If none of the following are
\r
102 set then don't fill the stack so there is no unnecessary dependency on memset. */
\r
103 #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
104 #define tskSET_NEW_STACKS_TO_KNOWN_VALUE 1
\r
106 #define tskSET_NEW_STACKS_TO_KNOWN_VALUE 0
\r
110 * Macros used by vListTask to indicate which state a task is in.
\r
112 #define tskRUNNING_CHAR ( 'X' )
\r
113 #define tskBLOCKED_CHAR ( 'B' )
\r
114 #define tskREADY_CHAR ( 'R' )
\r
115 #define tskDELETED_CHAR ( 'D' )
\r
116 #define tskSUSPENDED_CHAR ( 'S' )
\r
119 * Some kernel aware debuggers require the data the debugger needs access to be
\r
120 * global, rather than file scope.
\r
122 #ifdef portREMOVE_STATIC_QUALIFIER
\r
126 /* The name allocated to the Idle task. This can be overridden by defining
\r
127 configIDLE_TASK_NAME in FreeRTOSConfig.h. */
\r
128 #ifndef configIDLE_TASK_NAME
\r
129 #define configIDLE_TASK_NAME "IDLE"
\r
132 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
\r
134 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
\r
135 performed in a generic way that is not optimised to any particular
\r
136 microcontroller architecture. */
\r
138 /* uxTopReadyPriority holds the priority of the highest priority ready
\r
140 #define taskRECORD_READY_PRIORITY( uxPriority ) \
\r
142 if( ( uxPriority ) > uxTopReadyPriority ) \
\r
144 uxTopReadyPriority = ( uxPriority ); \
\r
146 } /* taskRECORD_READY_PRIORITY */
\r
148 /*-----------------------------------------------------------*/
\r
150 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
152 UBaseType_t uxTopPriority = uxTopReadyPriority; \
\r
154 /* Find the highest priority queue that contains ready tasks. */ \
\r
155 while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \
\r
157 configASSERT( uxTopPriority ); \
\r
161 /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
\r
162 the same priority get an equal share of the processor time. */ \
\r
163 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
\r
164 uxTopReadyPriority = uxTopPriority; \
\r
165 } /* taskSELECT_HIGHEST_PRIORITY_TASK */
\r
167 /*-----------------------------------------------------------*/
\r
169 /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
\r
170 they are only required when a port optimised method of task selection is
\r
172 #define taskRESET_READY_PRIORITY( uxPriority )
\r
173 #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
175 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
177 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
\r
178 performed in a way that is tailored to the particular microcontroller
\r
179 architecture being used. */
\r
181 /* A port optimised version is provided. Call the port defined macros. */
\r
182 #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
184 /*-----------------------------------------------------------*/
\r
186 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
188 UBaseType_t uxTopPriority; \
\r
190 /* Find the highest priority list that contains ready tasks. */ \
\r
191 portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
\r
192 configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
\r
193 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
\r
194 } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
\r
196 /*-----------------------------------------------------------*/
\r
198 /* A port optimised version is provided, call it only if the TCB being reset
\r
199 is being referenced from a ready list. If it is referenced from a delayed
\r
200 or suspended list then it won't be in a ready list. */
\r
201 #define taskRESET_READY_PRIORITY( uxPriority ) \
\r
203 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \
\r
205 portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \
\r
209 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
211 /*-----------------------------------------------------------*/
\r
213 /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
\r
214 count overflows. */
\r
215 #define taskSWITCH_DELAYED_LISTS() \
\r
219 /* The delayed tasks list should be empty when the lists are switched. */ \
\r
220 configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \
\r
222 pxTemp = pxDelayedTaskList; \
\r
223 pxDelayedTaskList = pxOverflowDelayedTaskList; \
\r
224 pxOverflowDelayedTaskList = pxTemp; \
\r
225 xNumOfOverflows++; \
\r
226 prvResetNextTaskUnblockTime(); \
\r
229 /*-----------------------------------------------------------*/
\r
232 * Place the task represented by pxTCB into the appropriate ready list for
\r
233 * the task. It is inserted at the end of the list.
\r
235 #define prvAddTaskToReadyList( pxTCB ) \
\r
236 traceMOVED_TASK_TO_READY_STATE( pxTCB ); \
\r
237 taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
\r
238 vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
\r
239 tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )
\r
240 /*-----------------------------------------------------------*/
\r
243 * Several functions take an TaskHandle_t parameter that can optionally be NULL,
\r
244 * where NULL is used to indicate that the handle of the currently executing
\r
245 * task should be used in place of the parameter. This macro simply checks to
\r
246 * see if the parameter is NULL and returns a pointer to the appropriate TCB.
\r
248 #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? pxCurrentTCB : ( pxHandle ) )
\r
250 /* The item value of the event list item is normally used to hold the priority
\r
251 of the task to which it belongs (coded to allow it to be held in reverse
\r
252 priority order). However, it is occasionally borrowed for other purposes. It
\r
253 is important its value is not updated due to a task priority change while it is
\r
254 being used for another purpose. The following bit definition is used to inform
\r
255 the scheduler that the value should not be changed - in which case it is the
\r
256 responsibility of whichever module is using the value to ensure it gets set back
\r
257 to its original value when it is released. */
\r
258 #if( configUSE_16_BIT_TICKS == 1 )
\r
259 #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U
\r
261 #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL
\r
265 * Task control block. A task control block (TCB) is allocated for each task,
\r
266 * and stores task state information, including a pointer to the task's context
\r
267 * (the task's run time environment, including register values)
\r
269 typedef struct tskTaskControlBlock
\r
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. */
\r
273 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
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. */
\r
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 ). */
\r
278 ListItem_t xEventListItem; /*< Used to reference a task from an event list. */
\r
279 UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */
\r
280 StackType_t *pxStack; /*< Points to the start of the stack. */
\r
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. */
\r
283 #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
\r
284 StackType_t *pxEndOfStack; /*< Points to the highest valid address for the stack. */
\r
287 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
288 UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
\r
291 #if ( configUSE_TRACE_FACILITY == 1 )
\r
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. */
\r
293 UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
\r
296 #if ( configUSE_MUTEXES == 1 )
\r
297 UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
\r
298 UBaseType_t uxMutexesHeld;
\r
301 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
302 TaskHookFunction_t pxTaskTag;
\r
305 #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
\r
306 void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
\r
309 #if( configGENERATE_RUN_TIME_STATS == 1 )
\r
310 uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
\r
313 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
314 /* Allocate a Newlib reent structure that is specific to this task.
\r
315 Note Newlib support has been included by popular demand, but is not
\r
316 used by the FreeRTOS maintainers themselves. FreeRTOS is not
\r
317 responsible for resulting newlib operation. User must be familiar with
\r
318 newlib and must provide system-wide implementations of the necessary
\r
319 stubs. Be warned that (at the time of writing) the current newlib design
\r
320 implements a system-wide malloc() that must be provided with locks. */
\r
321 struct _reent xNewLib_reent;
\r
324 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
325 volatile uint32_t ulNotifiedValue;
\r
326 volatile uint8_t ucNotifyState;
\r
329 /* See the comments above the definition of
\r
330 tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
\r
331 #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
\r
332 uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
\r
335 #if( INCLUDE_xTaskAbortDelay == 1 )
\r
336 uint8_t ucDelayAborted;
\r
339 #if( configUSE_POSIX_ERRNO == 1 )
\r
345 /* The old tskTCB name is maintained above then typedefed to the new TCB_t name
\r
346 below to enable the use of older kernel aware debuggers. */
\r
347 typedef tskTCB TCB_t;
\r
349 /*lint -save -e956 A manual analysis and inspection has been used to determine
\r
350 which static variables must be declared volatile. */
\r
351 PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
\r
353 /* Lists for ready and blocked tasks. --------------------*/
\r
354 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */
\r
355 PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */
\r
356 PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
\r
357 PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */
\r
358 PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */
\r
359 PRIVILEGED_DATA static List_t xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */
\r
361 #if( INCLUDE_vTaskDelete == 1 )
\r
363 PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */
\r
364 PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;
\r
368 #if ( INCLUDE_vTaskSuspend == 1 )
\r
370 PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */
\r
374 /* Global POSIX errno. Its value is changed upon context switching to match
\r
375 the errno of the currently running task. */
\r
376 #if ( configUSE_POSIX_ERRNO == 1 )
\r
377 int FreeRTOS_errno = 0;
\r
380 /* Other file private variables. --------------------------------*/
\r
381 PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
\r
382 PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
\r
383 PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
\r
384 PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
\r
385 PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U;
\r
386 PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE;
\r
387 PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
\r
388 PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
\r
389 PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */
\r
390 PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle = NULL; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */
\r
392 /* Context switches are held pending while the scheduler is suspended. Also,
\r
393 interrupts must not manipulate the xStateListItem of a TCB, or any of the
\r
394 lists the xStateListItem can be referenced from, if the scheduler is suspended.
\r
395 If an interrupt needs to unblock a task while the scheduler is suspended then it
\r
396 moves the task's event list item into the xPendingReadyList, ready for the
\r
397 kernel to move the task from the pending ready list into the real ready list
\r
398 when the scheduler is unsuspended. The pending ready list itself can only be
\r
399 accessed from a critical section. */
\r
400 PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE;
\r
402 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
404 PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
\r
405 PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */
\r
411 /*-----------------------------------------------------------*/
\r
413 /* Callback function prototypes. --------------------------*/
\r
414 #if( configCHECK_FOR_STACK_OVERFLOW > 0 )
\r
416 extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName );
\r
420 #if( configUSE_TICK_HOOK > 0 )
\r
422 extern void vApplicationTickHook( void ); /*lint !e526 Symbol not defined as it is an application callback. */
\r
426 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
428 extern void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ); /*lint !e526 Symbol not defined as it is an application callback. */
\r
432 /* File private functions. --------------------------------*/
\r
435 * Utility task that simply returns pdTRUE if the task referenced by xTask is
\r
436 * currently in the Suspended state, or pdFALSE if the task referenced by xTask
\r
437 * is in any other state.
\r
439 #if ( INCLUDE_vTaskSuspend == 1 )
\r
441 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
\r
443 #endif /* INCLUDE_vTaskSuspend */
\r
446 * Utility to ready all the lists used by the scheduler. This is called
\r
447 * automatically upon the creation of the first task.
\r
449 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
\r
452 * The idle task, which as all tasks is implemented as a never ending loop.
\r
453 * The idle task is automatically created and added to the ready lists upon
\r
454 * creation of the first user task.
\r
456 * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
\r
457 * language extensions. The equivalent prototype for this function is:
\r
459 * void prvIdleTask( void *pvParameters );
\r
462 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
\r
465 * Utility to free all memory allocated by the scheduler to hold a TCB,
\r
466 * including the stack pointed to by the TCB.
\r
468 * This does not free memory allocated by the task itself (i.e. memory
\r
469 * allocated by calls to pvPortMalloc from within the tasks application code).
\r
471 #if ( INCLUDE_vTaskDelete == 1 )
\r
473 static void prvDeleteTCB( TCB_t *pxTCB ) PRIVILEGED_FUNCTION;
\r
478 * Used only by the idle task. This checks to see if anything has been placed
\r
479 * in the list of tasks waiting to be deleted. If so the task is cleaned up
\r
480 * and its TCB deleted.
\r
482 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
\r
485 * The currently executing task is entering the Blocked state. Add the task to
\r
486 * either the current or the overflow delayed task list.
\r
488 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION;
\r
491 * Fills an TaskStatus_t structure with information on each task that is
\r
492 * referenced from the pxList list (which may be a ready list, a delayed list,
\r
493 * a suspended list, etc.).
\r
495 * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
\r
496 * NORMAL APPLICATION CODE.
\r
498 #if ( configUSE_TRACE_FACILITY == 1 )
\r
500 static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;
\r
505 * Searches pxList for a task with name pcNameToQuery - returning a handle to
\r
506 * the task if it is found, or NULL if the task is not found.
\r
508 #if ( INCLUDE_xTaskGetHandle == 1 )
\r
510 static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] ) PRIVILEGED_FUNCTION;
\r
515 * When a task is created, the stack of the task is filled with a known value.
\r
516 * This function determines the 'high water mark' of the task stack by
\r
517 * determining how much of the stack remains at the original preset value.
\r
519 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
521 static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
\r
526 * Return the amount of time, in ticks, that will pass before the kernel will
\r
527 * next move a task from the Blocked state to the Running state.
\r
529 * This conditional compilation should use inequality to 0, not equality to 1.
\r
530 * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
\r
531 * defined low power mode implementations require configUSE_TICKLESS_IDLE to be
\r
532 * set to a value other than 1.
\r
534 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
536 static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
\r
541 * Set xNextTaskUnblockTime to the time at which the next Blocked state task
\r
542 * will exit the Blocked state.
\r
544 static void prvResetNextTaskUnblockTime( void );
\r
546 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
549 * Helper function used to pad task names with spaces when printing out
\r
550 * human readable tables of task information.
\r
552 static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName ) PRIVILEGED_FUNCTION;
\r
557 * Called after a Task_t structure has been allocated either statically or
\r
558 * dynamically to fill in the structure's members.
\r
560 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
\r
561 const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
562 const uint32_t ulStackDepth,
\r
563 void * const pvParameters,
\r
564 UBaseType_t uxPriority,
\r
565 TaskHandle_t * const pxCreatedTask,
\r
567 const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION;
\r
570 * Called after a new task has been created and initialised to place the task
\r
571 * under the control of the scheduler.
\r
573 static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
\r
576 * freertos_tasks_c_additions_init() should only be called if the user definable
\r
577 * macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is the only macro
\r
578 * called by the function.
\r
580 #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
\r
582 static void freertos_tasks_c_additions_init( void ) PRIVILEGED_FUNCTION;
\r
586 /*-----------------------------------------------------------*/
\r
588 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
590 TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
\r
591 const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
592 const uint32_t ulStackDepth,
\r
593 void * const pvParameters,
\r
594 UBaseType_t uxPriority,
\r
595 StackType_t * const puxStackBuffer,
\r
596 StaticTask_t * const pxTaskBuffer )
\r
599 TaskHandle_t xReturn;
\r
601 configASSERT( puxStackBuffer != NULL );
\r
602 configASSERT( pxTaskBuffer != NULL );
\r
604 #if( configASSERT_DEFINED == 1 )
\r
606 /* Sanity check that the size of the structure used to declare a
\r
607 variable of type StaticTask_t equals the size of the real task
\r
609 volatile size_t xSize = sizeof( StaticTask_t );
\r
610 configASSERT( xSize == sizeof( TCB_t ) );
\r
611 ( void ) xSize; /* Prevent lint warning when configASSERT() is not used. */
\r
613 #endif /* configASSERT_DEFINED */
\r
616 if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
\r
618 /* The memory used for the task's TCB and stack are passed into this
\r
619 function - use them. */
\r
620 pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
\r
621 pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;
\r
623 #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
\r
625 /* Tasks can be created statically or dynamically, so note this
\r
626 task was created statically in case the task is later deleted. */
\r
627 pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
\r
629 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
631 prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL );
\r
632 prvAddNewTaskToReadyList( pxNewTCB );
\r
642 #endif /* SUPPORT_STATIC_ALLOCATION */
\r
643 /*-----------------------------------------------------------*/
\r
645 #if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
\r
647 BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
\r
650 BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
\r
652 configASSERT( pxTaskDefinition->puxStackBuffer != NULL );
\r
653 configASSERT( pxTaskDefinition->pxTaskBuffer != NULL );
\r
655 if( ( pxTaskDefinition->puxStackBuffer != NULL ) && ( pxTaskDefinition->pxTaskBuffer != NULL ) )
\r
657 /* Allocate space for the TCB. Where the memory comes from depends
\r
658 on the implementation of the port malloc function and whether or
\r
659 not static allocation is being used. */
\r
660 pxNewTCB = ( TCB_t * ) pxTaskDefinition->pxTaskBuffer;
\r
662 /* Store the stack location in the TCB. */
\r
663 pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
\r
665 #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
\r
667 /* Tasks can be created statically or dynamically, so note this
\r
668 task was created statically in case the task is later deleted. */
\r
669 pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
\r
671 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
673 prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
\r
674 pxTaskDefinition->pcName,
\r
675 ( uint32_t ) pxTaskDefinition->usStackDepth,
\r
676 pxTaskDefinition->pvParameters,
\r
677 pxTaskDefinition->uxPriority,
\r
678 pxCreatedTask, pxNewTCB,
\r
679 pxTaskDefinition->xRegions );
\r
681 prvAddNewTaskToReadyList( pxNewTCB );
\r
688 #endif /* ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
\r
689 /*-----------------------------------------------------------*/
\r
691 #if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
\r
693 BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
\r
696 BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
\r
698 configASSERT( pxTaskDefinition->puxStackBuffer );
\r
700 if( pxTaskDefinition->puxStackBuffer != NULL )
\r
702 /* Allocate space for the TCB. Where the memory comes from depends
\r
703 on the implementation of the port malloc function and whether or
\r
704 not static allocation is being used. */
\r
705 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
\r
707 if( pxNewTCB != NULL )
\r
709 /* Store the stack location in the TCB. */
\r
710 pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
\r
712 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
714 /* Tasks can be created statically or dynamically, so note
\r
715 this task had a statically allocated stack in case it is
\r
716 later deleted. The TCB was allocated dynamically. */
\r
717 pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY;
\r
721 prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
\r
722 pxTaskDefinition->pcName,
\r
723 ( uint32_t ) pxTaskDefinition->usStackDepth,
\r
724 pxTaskDefinition->pvParameters,
\r
725 pxTaskDefinition->uxPriority,
\r
726 pxCreatedTask, pxNewTCB,
\r
727 pxTaskDefinition->xRegions );
\r
729 prvAddNewTaskToReadyList( pxNewTCB );
\r
737 #endif /* portUSING_MPU_WRAPPERS */
\r
738 /*-----------------------------------------------------------*/
\r
740 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
\r
742 BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
\r
743 const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
744 const configSTACK_DEPTH_TYPE usStackDepth,
\r
745 void * const pvParameters,
\r
746 UBaseType_t uxPriority,
\r
747 TaskHandle_t * const pxCreatedTask )
\r
750 BaseType_t xReturn;
\r
752 /* If the stack grows down then allocate the stack then the TCB so the stack
\r
753 does not grow into the TCB. Likewise if the stack grows up then allocate
\r
754 the TCB then the stack. */
\r
755 #if( portSTACK_GROWTH > 0 )
\r
757 /* Allocate space for the TCB. Where the memory comes from depends on
\r
758 the implementation of the port malloc function and whether or not static
\r
759 allocation is being used. */
\r
760 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
\r
762 if( pxNewTCB != NULL )
\r
764 /* Allocate space for the stack used by the task being created.
\r
765 The base of the stack memory stored in the TCB so the task can
\r
766 be deleted later if required. */
\r
767 pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
769 if( pxNewTCB->pxStack == NULL )
\r
771 /* Could not allocate the stack. Delete the allocated TCB. */
\r
772 vPortFree( pxNewTCB );
\r
777 #else /* portSTACK_GROWTH */
\r
779 StackType_t *pxStack;
\r
781 /* Allocate space for the stack used by the task being created. */
\r
782 pxStack = pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */
\r
784 if( pxStack != NULL )
\r
786 /* Allocate space for the TCB. */
\r
787 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */
\r
789 if( pxNewTCB != NULL )
\r
791 /* Store the stack location in the TCB. */
\r
792 pxNewTCB->pxStack = pxStack;
\r
796 /* The stack cannot be used as the TCB was not created. Free
\r
798 vPortFree( pxStack );
\r
806 #endif /* portSTACK_GROWTH */
\r
808 if( pxNewTCB != NULL )
\r
810 #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e9029 !e731 Macro has been consolidated for readability reasons. */
\r
812 /* Tasks can be created statically or dynamically, so note this
\r
813 task was created dynamically in case it is later deleted. */
\r
814 pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
\r
816 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
818 prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
\r
819 prvAddNewTaskToReadyList( pxNewTCB );
\r
824 xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
\r
830 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
831 /*-----------------------------------------------------------*/
\r
833 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
\r
834 const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
835 const uint32_t ulStackDepth,
\r
836 void * const pvParameters,
\r
837 UBaseType_t uxPriority,
\r
838 TaskHandle_t * const pxCreatedTask,
\r
840 const MemoryRegion_t * const xRegions )
\r
842 StackType_t *pxTopOfStack;
\r
845 #if( portUSING_MPU_WRAPPERS == 1 )
\r
846 /* Should the task be created in privileged mode? */
\r
847 BaseType_t xRunPrivileged;
\r
848 if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
\r
850 xRunPrivileged = pdTRUE;
\r
854 xRunPrivileged = pdFALSE;
\r
856 uxPriority &= ~portPRIVILEGE_BIT;
\r
857 #endif /* portUSING_MPU_WRAPPERS == 1 */
\r
859 configASSERT( pcName );
\r
861 /* Avoid dependency on memset() if it is not required. */
\r
862 #if( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 )
\r
864 /* Fill the stack with a known value to assist debugging. */
\r
865 ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );
\r
867 #endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */
\r
869 /* Calculate the top of stack address. This depends on whether the stack
\r
870 grows from high memory to low (as per the 80x86) or vice versa.
\r
871 portSTACK_GROWTH is used to make the result positive or negative as required
\r
873 #if( portSTACK_GROWTH < 0 )
\r
875 pxTopOfStack = &( pxNewTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] );
\r
876 pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 !e9033 !e9078 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. Checked by assert(). */
\r
878 /* Check the alignment of the calculated top of stack is correct. */
\r
879 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
881 #if( configRECORD_STACK_HIGH_ADDRESS == 1 )
\r
883 /* Also record the stack's high address, which may assist
\r
885 pxNewTCB->pxEndOfStack = pxTopOfStack;
\r
887 #endif /* configRECORD_STACK_HIGH_ADDRESS */
\r
889 #else /* portSTACK_GROWTH */
\r
891 pxTopOfStack = pxNewTCB->pxStack;
\r
893 /* Check the alignment of the stack buffer is correct. */
\r
894 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
896 /* The other extreme of the stack space is required if stack checking is
\r
898 pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
\r
900 #endif /* portSTACK_GROWTH */
\r
902 /* Store the task name in the TCB. */
\r
903 for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
\r
905 pxNewTCB->pcTaskName[ x ] = pcName[ x ];
\r
907 /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
\r
908 configMAX_TASK_NAME_LEN characters just in case the memory after the
\r
909 string is not accessible (extremely unlikely). */
\r
910 if( pcName[ x ] == ( char ) 0x00 )
\r
916 mtCOVERAGE_TEST_MARKER();
\r
920 /* Ensure the name string is terminated in the case that the string length
\r
921 was greater or equal to configMAX_TASK_NAME_LEN. */
\r
922 pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
\r
924 /* This is used as an array index so must ensure it's not too large. First
\r
925 remove the privilege bit if one is present. */
\r
926 if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
\r
928 uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
\r
932 mtCOVERAGE_TEST_MARKER();
\r
935 pxNewTCB->uxPriority = uxPriority;
\r
936 #if ( configUSE_MUTEXES == 1 )
\r
938 pxNewTCB->uxBasePriority = uxPriority;
\r
939 pxNewTCB->uxMutexesHeld = 0;
\r
941 #endif /* configUSE_MUTEXES */
\r
943 vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
\r
944 vListInitialiseItem( &( pxNewTCB->xEventListItem ) );
\r
946 /* Set the pxNewTCB as a link back from the ListItem_t. This is so we can get
\r
947 back to the containing TCB from a generic item in a list. */
\r
948 listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );
\r
950 /* Event lists are always in priority order. */
\r
951 listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
952 listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );
\r
954 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
956 pxNewTCB->uxCriticalNesting = ( UBaseType_t ) 0U;
\r
958 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
960 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
962 pxNewTCB->pxTaskTag = NULL;
\r
964 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
966 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
968 pxNewTCB->ulRunTimeCounter = 0UL;
\r
970 #endif /* configGENERATE_RUN_TIME_STATS */
\r
972 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
974 vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth );
\r
978 /* Avoid compiler warning about unreferenced parameter. */
\r
983 #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
\r
985 for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ )
\r
987 pxNewTCB->pvThreadLocalStoragePointers[ x ] = NULL;
\r
992 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
\r
994 pxNewTCB->ulNotifiedValue = 0;
\r
995 pxNewTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
\r
999 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
1001 /* Initialise this task's Newlib reent structure. */
\r
1002 _REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) );
\r
1006 #if( INCLUDE_xTaskAbortDelay == 1 )
\r
1008 pxNewTCB->ucDelayAborted = pdFALSE;
\r
1012 /* Initialize the TCB stack to look as if the task was already running,
\r
1013 but had been interrupted by the scheduler. The return address is set
\r
1014 to the start of the task function. Once the stack has been initialised
\r
1015 the top of stack variable is updated. */
\r
1016 #if( portUSING_MPU_WRAPPERS == 1 )
\r
1018 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
\r
1020 #else /* portUSING_MPU_WRAPPERS */
\r
1022 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
\r
1024 #endif /* portUSING_MPU_WRAPPERS */
\r
1026 if( pxCreatedTask != NULL )
\r
1028 /* Pass the handle out in an anonymous way. The handle can be used to
\r
1029 change the created task's priority, delete the created task, etc.*/
\r
1030 *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
\r
1034 mtCOVERAGE_TEST_MARKER();
\r
1037 /*-----------------------------------------------------------*/
\r
1039 static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
\r
1041 /* Ensure interrupts don't access the task lists while the lists are being
\r
1043 taskENTER_CRITICAL();
\r
1045 uxCurrentNumberOfTasks++;
\r
1046 if( pxCurrentTCB == NULL )
\r
1048 /* There are no other tasks, or all the other tasks are in
\r
1049 the suspended state - make this the current task. */
\r
1050 pxCurrentTCB = pxNewTCB;
\r
1052 if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
\r
1054 /* This is the first task to be created so do the preliminary
\r
1055 initialisation required. We will not recover if this call
\r
1056 fails, but we will report the failure. */
\r
1057 prvInitialiseTaskLists();
\r
1061 mtCOVERAGE_TEST_MARKER();
\r
1066 /* If the scheduler is not already running, make this task the
\r
1067 current task if it is the highest priority task to be created
\r
1069 if( xSchedulerRunning == pdFALSE )
\r
1071 if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )
\r
1073 pxCurrentTCB = pxNewTCB;
\r
1077 mtCOVERAGE_TEST_MARKER();
\r
1082 mtCOVERAGE_TEST_MARKER();
\r
1088 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1090 /* Add a counter into the TCB for tracing only. */
\r
1091 pxNewTCB->uxTCBNumber = uxTaskNumber;
\r
1093 #endif /* configUSE_TRACE_FACILITY */
\r
1094 traceTASK_CREATE( pxNewTCB );
\r
1096 prvAddTaskToReadyList( pxNewTCB );
\r
1098 portSETUP_TCB( pxNewTCB );
\r
1100 taskEXIT_CRITICAL();
\r
1102 if( xSchedulerRunning != pdFALSE )
\r
1104 /* If the created task is of a higher priority than the current task
\r
1105 then it should run now. */
\r
1106 if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority )
\r
1108 taskYIELD_IF_USING_PREEMPTION();
\r
1112 mtCOVERAGE_TEST_MARKER();
\r
1117 mtCOVERAGE_TEST_MARKER();
\r
1120 /*-----------------------------------------------------------*/
\r
1122 #if ( INCLUDE_vTaskDelete == 1 )
\r
1124 void vTaskDelete( TaskHandle_t xTaskToDelete )
\r
1128 taskENTER_CRITICAL();
\r
1130 /* If null is passed in here then it is the calling task that is
\r
1132 pxTCB = prvGetTCBFromHandle( xTaskToDelete );
\r
1134 /* Remove task from the ready list. */
\r
1135 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
1137 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
1141 mtCOVERAGE_TEST_MARKER();
\r
1144 /* Is the task waiting on an event also? */
\r
1145 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
1147 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1151 mtCOVERAGE_TEST_MARKER();
\r
1154 /* Increment the uxTaskNumber also so kernel aware debuggers can
\r
1155 detect that the task lists need re-generating. This is done before
\r
1156 portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will
\r
1160 if( pxTCB == pxCurrentTCB )
\r
1162 /* A task is deleting itself. This cannot complete within the
\r
1163 task itself, as a context switch to another task is required.
\r
1164 Place the task in the termination list. The idle task will
\r
1165 check the termination list and free up any memory allocated by
\r
1166 the scheduler for the TCB and stack of the deleted task. */
\r
1167 vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );
\r
1169 /* Increment the ucTasksDeleted variable so the idle task knows
\r
1170 there is a task that has been deleted and that it should therefore
\r
1171 check the xTasksWaitingTermination list. */
\r
1172 ++uxDeletedTasksWaitingCleanUp;
\r
1174 /* The pre-delete hook is primarily for the Windows simulator,
\r
1175 in which Windows specific clean up operations are performed,
\r
1176 after which it is not possible to yield away from this task -
\r
1177 hence xYieldPending is used to latch that a context switch is
\r
1179 portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
\r
1183 --uxCurrentNumberOfTasks;
\r
1184 prvDeleteTCB( pxTCB );
\r
1186 /* Reset the next expected unblock time in case it referred to
\r
1187 the task that has just been deleted. */
\r
1188 prvResetNextTaskUnblockTime();
\r
1191 traceTASK_DELETE( pxTCB );
\r
1193 taskEXIT_CRITICAL();
\r
1195 /* Force a reschedule if it is the currently running task that has just
\r
1197 if( xSchedulerRunning != pdFALSE )
\r
1199 if( pxTCB == pxCurrentTCB )
\r
1201 configASSERT( uxSchedulerSuspended == 0 );
\r
1202 portYIELD_WITHIN_API();
\r
1206 mtCOVERAGE_TEST_MARKER();
\r
1211 #endif /* INCLUDE_vTaskDelete */
\r
1212 /*-----------------------------------------------------------*/
\r
1214 #if ( INCLUDE_vTaskDelayUntil == 1 )
\r
1216 void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
\r
1218 TickType_t xTimeToWake;
\r
1219 BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
\r
1221 configASSERT( pxPreviousWakeTime );
\r
1222 configASSERT( ( xTimeIncrement > 0U ) );
\r
1223 configASSERT( uxSchedulerSuspended == 0 );
\r
1225 vTaskSuspendAll();
\r
1227 /* Minor optimisation. The tick count cannot change in this
\r
1229 const TickType_t xConstTickCount = xTickCount;
\r
1231 /* Generate the tick time at which the task wants to wake. */
\r
1232 xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
\r
1234 if( xConstTickCount < *pxPreviousWakeTime )
\r
1236 /* The tick count has overflowed since this function was
\r
1237 lasted called. In this case the only time we should ever
\r
1238 actually delay is if the wake time has also overflowed,
\r
1239 and the wake time is greater than the tick time. When this
\r
1240 is the case it is as if neither time had overflowed. */
\r
1241 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
\r
1243 xShouldDelay = pdTRUE;
\r
1247 mtCOVERAGE_TEST_MARKER();
\r
1252 /* The tick time has not overflowed. In this case we will
\r
1253 delay if either the wake time has overflowed, and/or the
\r
1254 tick time is less than the wake time. */
\r
1255 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
\r
1257 xShouldDelay = pdTRUE;
\r
1261 mtCOVERAGE_TEST_MARKER();
\r
1265 /* Update the wake time ready for the next call. */
\r
1266 *pxPreviousWakeTime = xTimeToWake;
\r
1268 if( xShouldDelay != pdFALSE )
\r
1270 traceTASK_DELAY_UNTIL( xTimeToWake );
\r
1272 /* prvAddCurrentTaskToDelayedList() needs the block time, not
\r
1273 the time to wake, so subtract the current tick count. */
\r
1274 prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE );
\r
1278 mtCOVERAGE_TEST_MARKER();
\r
1281 xAlreadyYielded = xTaskResumeAll();
\r
1283 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
1284 have put ourselves to sleep. */
\r
1285 if( xAlreadyYielded == pdFALSE )
\r
1287 portYIELD_WITHIN_API();
\r
1291 mtCOVERAGE_TEST_MARKER();
\r
1295 #endif /* INCLUDE_vTaskDelayUntil */
\r
1296 /*-----------------------------------------------------------*/
\r
1298 #if ( INCLUDE_vTaskDelay == 1 )
\r
1300 void vTaskDelay( const TickType_t xTicksToDelay )
\r
1302 BaseType_t xAlreadyYielded = pdFALSE;
\r
1304 /* A delay time of zero just forces a reschedule. */
\r
1305 if( xTicksToDelay > ( TickType_t ) 0U )
\r
1307 configASSERT( uxSchedulerSuspended == 0 );
\r
1308 vTaskSuspendAll();
\r
1310 traceTASK_DELAY();
\r
1312 /* A task that is removed from the event list while the
\r
1313 scheduler is suspended will not get placed in the ready
\r
1314 list or removed from the blocked list until the scheduler
\r
1317 This task cannot be in an event list as it is the currently
\r
1318 executing task. */
\r
1319 prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
\r
1321 xAlreadyYielded = xTaskResumeAll();
\r
1325 mtCOVERAGE_TEST_MARKER();
\r
1328 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
1329 have put ourselves to sleep. */
\r
1330 if( xAlreadyYielded == pdFALSE )
\r
1332 portYIELD_WITHIN_API();
\r
1336 mtCOVERAGE_TEST_MARKER();
\r
1340 #endif /* INCLUDE_vTaskDelay */
\r
1341 /*-----------------------------------------------------------*/
\r
1343 #if( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) )
\r
1345 eTaskState eTaskGetState( TaskHandle_t xTask )
\r
1347 eTaskState eReturn;
\r
1348 List_t const * pxStateList, *pxDelayedList, *pxOverflowedDelayedList;
\r
1349 const TCB_t * const pxTCB = xTask;
\r
1351 configASSERT( pxTCB );
\r
1353 if( pxTCB == pxCurrentTCB )
\r
1355 /* The task calling this function is querying its own state. */
\r
1356 eReturn = eRunning;
\r
1360 taskENTER_CRITICAL();
\r
1362 pxStateList = listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) );
\r
1363 pxDelayedList = pxDelayedTaskList;
\r
1364 pxOverflowedDelayedList = pxOverflowDelayedTaskList;
\r
1366 taskEXIT_CRITICAL();
\r
1368 if( ( pxStateList == pxDelayedList ) || ( pxStateList == pxOverflowedDelayedList ) )
\r
1370 /* The task being queried is referenced from one of the Blocked
\r
1372 eReturn = eBlocked;
\r
1375 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1376 else if( pxStateList == &xSuspendedTaskList )
\r
1378 /* The task being queried is referenced from the suspended
\r
1379 list. Is it genuinely suspended or is it blocked
\r
1381 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
\r
1383 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
1385 /* The task does not appear on the event list item of
\r
1386 and of the RTOS objects, but could still be in the
\r
1387 blocked state if it is waiting on its notification
\r
1388 rather than waiting on an object. */
\r
1389 if( pxTCB->ucNotifyState == taskWAITING_NOTIFICATION )
\r
1391 eReturn = eBlocked;
\r
1395 eReturn = eSuspended;
\r
1400 eReturn = eSuspended;
\r
1406 eReturn = eBlocked;
\r
1411 #if ( INCLUDE_vTaskDelete == 1 )
\r
1412 else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) )
\r
1414 /* The task being queried is referenced from the deleted
\r
1415 tasks list, or it is not referenced from any lists at
\r
1417 eReturn = eDeleted;
\r
1421 else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */
\r
1423 /* If the task is not in any other state, it must be in the
\r
1424 Ready (including pending ready) state. */
\r
1430 } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
\r
1432 #endif /* INCLUDE_eTaskGetState */
\r
1433 /*-----------------------------------------------------------*/
\r
1435 #if ( INCLUDE_uxTaskPriorityGet == 1 )
\r
1437 UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask )
\r
1439 TCB_t const *pxTCB;
\r
1440 UBaseType_t uxReturn;
\r
1442 taskENTER_CRITICAL();
\r
1444 /* If null is passed in here then it is the priority of the task
\r
1445 that called uxTaskPriorityGet() that is being queried. */
\r
1446 pxTCB = prvGetTCBFromHandle( xTask );
\r
1447 uxReturn = pxTCB->uxPriority;
\r
1449 taskEXIT_CRITICAL();
\r
1454 #endif /* INCLUDE_uxTaskPriorityGet */
\r
1455 /*-----------------------------------------------------------*/
\r
1457 #if ( INCLUDE_uxTaskPriorityGet == 1 )
\r
1459 UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask )
\r
1461 TCB_t const *pxTCB;
\r
1462 UBaseType_t uxReturn, uxSavedInterruptState;
\r
1464 /* RTOS ports that support interrupt nesting have the concept of a
\r
1465 maximum system call (or maximum API call) interrupt priority.
\r
1466 Interrupts that are above the maximum system call priority are keep
\r
1467 permanently enabled, even when the RTOS kernel is in a critical section,
\r
1468 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
1469 is defined in FreeRTOSConfig.h then
\r
1470 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1471 failure if a FreeRTOS API function is called from an interrupt that has
\r
1472 been assigned a priority above the configured maximum system call
\r
1473 priority. Only FreeRTOS functions that end in FromISR can be called
\r
1474 from interrupts that have been assigned a priority at or (logically)
\r
1475 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
1476 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
1477 simple as possible. More information (albeit Cortex-M specific) is
\r
1478 provided on the following link:
\r
1479 https://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1480 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1482 uxSavedInterruptState = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1484 /* If null is passed in here then it is the priority of the calling
\r
1485 task that is being queried. */
\r
1486 pxTCB = prvGetTCBFromHandle( xTask );
\r
1487 uxReturn = pxTCB->uxPriority;
\r
1489 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState );
\r
1494 #endif /* INCLUDE_uxTaskPriorityGet */
\r
1495 /*-----------------------------------------------------------*/
\r
1497 #if ( INCLUDE_vTaskPrioritySet == 1 )
\r
1499 void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )
\r
1502 UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;
\r
1503 BaseType_t xYieldRequired = pdFALSE;
\r
1505 configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
\r
1507 /* Ensure the new priority is valid. */
\r
1508 if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
\r
1510 uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
\r
1514 mtCOVERAGE_TEST_MARKER();
\r
1517 taskENTER_CRITICAL();
\r
1519 /* If null is passed in here then it is the priority of the calling
\r
1520 task that is being changed. */
\r
1521 pxTCB = prvGetTCBFromHandle( xTask );
\r
1523 traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
\r
1525 #if ( configUSE_MUTEXES == 1 )
\r
1527 uxCurrentBasePriority = pxTCB->uxBasePriority;
\r
1531 uxCurrentBasePriority = pxTCB->uxPriority;
\r
1535 if( uxCurrentBasePriority != uxNewPriority )
\r
1537 /* The priority change may have readied a task of higher
\r
1538 priority than the calling task. */
\r
1539 if( uxNewPriority > uxCurrentBasePriority )
\r
1541 if( pxTCB != pxCurrentTCB )
\r
1543 /* The priority of a task other than the currently
\r
1544 running task is being raised. Is the priority being
\r
1545 raised above that of the running task? */
\r
1546 if( uxNewPriority >= pxCurrentTCB->uxPriority )
\r
1548 xYieldRequired = pdTRUE;
\r
1552 mtCOVERAGE_TEST_MARKER();
\r
1557 /* The priority of the running task is being raised,
\r
1558 but the running task must already be the highest
\r
1559 priority task able to run so no yield is required. */
\r
1562 else if( pxTCB == pxCurrentTCB )
\r
1564 /* Setting the priority of the running task down means
\r
1565 there may now be another task of higher priority that
\r
1566 is ready to execute. */
\r
1567 xYieldRequired = pdTRUE;
\r
1571 /* Setting the priority of any other task down does not
\r
1572 require a yield as the running task must be above the
\r
1573 new priority of the task being modified. */
\r
1576 /* Remember the ready list the task might be referenced from
\r
1577 before its uxPriority member is changed so the
\r
1578 taskRESET_READY_PRIORITY() macro can function correctly. */
\r
1579 uxPriorityUsedOnEntry = pxTCB->uxPriority;
\r
1581 #if ( configUSE_MUTEXES == 1 )
\r
1583 /* Only change the priority being used if the task is not
\r
1584 currently using an inherited priority. */
\r
1585 if( pxTCB->uxBasePriority == pxTCB->uxPriority )
\r
1587 pxTCB->uxPriority = uxNewPriority;
\r
1591 mtCOVERAGE_TEST_MARKER();
\r
1594 /* The base priority gets set whatever. */
\r
1595 pxTCB->uxBasePriority = uxNewPriority;
\r
1599 pxTCB->uxPriority = uxNewPriority;
\r
1603 /* Only reset the event list item value if the value is not
\r
1604 being used for anything else. */
\r
1605 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
\r
1607 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
1611 mtCOVERAGE_TEST_MARKER();
\r
1614 /* If the task is in the blocked or suspended list we need do
\r
1615 nothing more than change its priority variable. However, if
\r
1616 the task is in a ready list it needs to be removed and placed
\r
1617 in the list appropriate to its new priority. */
\r
1618 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
\r
1620 /* The task is currently in its ready list - remove before
\r
1621 adding it to it's new ready list. As we are in a critical
\r
1622 section we can do this even if the scheduler is suspended. */
\r
1623 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
1625 /* It is known that the task is in its ready list so
\r
1626 there is no need to check again and the port level
\r
1627 reset macro can be called directly. */
\r
1628 portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
\r
1632 mtCOVERAGE_TEST_MARKER();
\r
1634 prvAddTaskToReadyList( pxTCB );
\r
1638 mtCOVERAGE_TEST_MARKER();
\r
1641 if( xYieldRequired != pdFALSE )
\r
1643 taskYIELD_IF_USING_PREEMPTION();
\r
1647 mtCOVERAGE_TEST_MARKER();
\r
1650 /* Remove compiler warning about unused variables when the port
\r
1651 optimised task selection is not being used. */
\r
1652 ( void ) uxPriorityUsedOnEntry;
\r
1655 taskEXIT_CRITICAL();
\r
1658 #endif /* INCLUDE_vTaskPrioritySet */
\r
1659 /*-----------------------------------------------------------*/
\r
1661 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1663 void vTaskSuspend( TaskHandle_t xTaskToSuspend )
\r
1667 taskENTER_CRITICAL();
\r
1669 /* If null is passed in here then it is the running task that is
\r
1670 being suspended. */
\r
1671 pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
\r
1673 traceTASK_SUSPEND( pxTCB );
\r
1675 /* Remove task from the ready/delayed list and place in the
\r
1676 suspended list. */
\r
1677 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
1679 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
1683 mtCOVERAGE_TEST_MARKER();
\r
1686 /* Is the task waiting on an event also? */
\r
1687 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
1689 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1693 mtCOVERAGE_TEST_MARKER();
\r
1696 vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
\r
1698 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
1700 if( pxTCB->ucNotifyState == taskWAITING_NOTIFICATION )
\r
1702 /* The task was blocked to wait for a notification, but is
\r
1703 now suspended, so no notification was received. */
\r
1704 pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
\r
1709 taskEXIT_CRITICAL();
\r
1711 if( xSchedulerRunning != pdFALSE )
\r
1713 /* Reset the next expected unblock time in case it referred to the
\r
1714 task that is now in the Suspended state. */
\r
1715 taskENTER_CRITICAL();
\r
1717 prvResetNextTaskUnblockTime();
\r
1719 taskEXIT_CRITICAL();
\r
1723 mtCOVERAGE_TEST_MARKER();
\r
1726 if( pxTCB == pxCurrentTCB )
\r
1728 if( xSchedulerRunning != pdFALSE )
\r
1730 /* The current task has just been suspended. */
\r
1731 configASSERT( uxSchedulerSuspended == 0 );
\r
1732 portYIELD_WITHIN_API();
\r
1736 /* The scheduler is not running, but the task that was pointed
\r
1737 to by pxCurrentTCB has just been suspended and pxCurrentTCB
\r
1738 must be adjusted to point to a different task. */
\r
1739 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks ) /*lint !e931 Right has no side effect, just volatile. */
\r
1741 /* No other tasks are ready, so set pxCurrentTCB back to
\r
1742 NULL so when the next task is created pxCurrentTCB will
\r
1743 be set to point to it no matter what its relative priority
\r
1745 pxCurrentTCB = NULL;
\r
1749 vTaskSwitchContext();
\r
1755 mtCOVERAGE_TEST_MARKER();
\r
1759 #endif /* INCLUDE_vTaskSuspend */
\r
1760 /*-----------------------------------------------------------*/
\r
1762 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1764 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
\r
1766 BaseType_t xReturn = pdFALSE;
\r
1767 const TCB_t * const pxTCB = xTask;
\r
1769 /* Accesses xPendingReadyList so must be called from a critical
\r
1772 /* It does not make sense to check if the calling task is suspended. */
\r
1773 configASSERT( xTask );
\r
1775 /* Is the task being resumed actually in the suspended list? */
\r
1776 if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE )
\r
1778 /* Has the task already been resumed from within an ISR? */
\r
1779 if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
\r
1781 /* Is it in the suspended list because it is in the Suspended
\r
1782 state, or because is is blocked with no timeout? */
\r
1783 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) /*lint !e961. The cast is only redundant when NULL is used. */
\r
1789 mtCOVERAGE_TEST_MARKER();
\r
1794 mtCOVERAGE_TEST_MARKER();
\r
1799 mtCOVERAGE_TEST_MARKER();
\r
1803 } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
\r
1805 #endif /* INCLUDE_vTaskSuspend */
\r
1806 /*-----------------------------------------------------------*/
\r
1808 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1810 void vTaskResume( TaskHandle_t xTaskToResume )
\r
1812 TCB_t * const pxTCB = xTaskToResume;
\r
1814 /* It does not make sense to resume the calling task. */
\r
1815 configASSERT( xTaskToResume );
\r
1817 /* The parameter cannot be NULL as it is impossible to resume the
\r
1818 currently executing task. */
\r
1819 if( ( pxTCB != pxCurrentTCB ) && ( pxTCB != NULL ) )
\r
1821 taskENTER_CRITICAL();
\r
1823 if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
\r
1825 traceTASK_RESUME( pxTCB );
\r
1827 /* The ready list can be accessed even if the scheduler is
\r
1828 suspended because this is inside a critical section. */
\r
1829 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
1830 prvAddTaskToReadyList( pxTCB );
\r
1832 /* A higher priority task may have just been resumed. */
\r
1833 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1835 /* This yield may not cause the task just resumed to run,
\r
1836 but will leave the lists in the correct state for the
\r
1838 taskYIELD_IF_USING_PREEMPTION();
\r
1842 mtCOVERAGE_TEST_MARKER();
\r
1847 mtCOVERAGE_TEST_MARKER();
\r
1850 taskEXIT_CRITICAL();
\r
1854 mtCOVERAGE_TEST_MARKER();
\r
1858 #endif /* INCLUDE_vTaskSuspend */
\r
1860 /*-----------------------------------------------------------*/
\r
1862 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
\r
1864 BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
\r
1866 BaseType_t xYieldRequired = pdFALSE;
\r
1867 TCB_t * const pxTCB = xTaskToResume;
\r
1868 UBaseType_t uxSavedInterruptStatus;
\r
1870 configASSERT( xTaskToResume );
\r
1872 /* RTOS ports that support interrupt nesting have the concept of a
\r
1873 maximum system call (or maximum API call) interrupt priority.
\r
1874 Interrupts that are above the maximum system call priority are keep
\r
1875 permanently enabled, even when the RTOS kernel is in a critical section,
\r
1876 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
1877 is defined in FreeRTOSConfig.h then
\r
1878 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1879 failure if a FreeRTOS API function is called from an interrupt that has
\r
1880 been assigned a priority above the configured maximum system call
\r
1881 priority. Only FreeRTOS functions that end in FromISR can be called
\r
1882 from interrupts that have been assigned a priority at or (logically)
\r
1883 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
1884 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
1885 simple as possible. More information (albeit Cortex-M specific) is
\r
1886 provided on the following link:
\r
1887 https://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1888 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1890 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1892 if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
\r
1894 traceTASK_RESUME_FROM_ISR( pxTCB );
\r
1896 /* Check the ready lists can be accessed. */
\r
1897 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
1899 /* Ready lists can be accessed so move the task from the
\r
1900 suspended list to the ready list directly. */
\r
1901 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1903 xYieldRequired = pdTRUE;
\r
1907 mtCOVERAGE_TEST_MARKER();
\r
1910 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
1911 prvAddTaskToReadyList( pxTCB );
\r
1915 /* The delayed or ready lists cannot be accessed so the task
\r
1916 is held in the pending ready list until the scheduler is
\r
1918 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
1923 mtCOVERAGE_TEST_MARKER();
\r
1926 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1928 return xYieldRequired;
\r
1931 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
\r
1932 /*-----------------------------------------------------------*/
\r
1934 void vTaskStartScheduler( void )
\r
1936 BaseType_t xReturn;
\r
1938 /* Add the idle task at the lowest priority. */
\r
1939 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
1941 StaticTask_t *pxIdleTaskTCBBuffer = NULL;
\r
1942 StackType_t *pxIdleTaskStackBuffer = NULL;
\r
1943 uint32_t ulIdleTaskStackSize;
\r
1945 /* The Idle task is created using user provided RAM - obtain the
\r
1946 address of the RAM then create the idle task. */
\r
1947 vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );
\r
1948 xIdleTaskHandle = xTaskCreateStatic( prvIdleTask,
\r
1949 configIDLE_TASK_NAME,
\r
1950 ulIdleTaskStackSize,
\r
1951 ( void * ) NULL, /*lint !e961. The cast is not redundant for all compilers. */
\r
1952 portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
\r
1953 pxIdleTaskStackBuffer,
\r
1954 pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
\r
1956 if( xIdleTaskHandle != NULL )
\r
1967 /* The Idle task is being created using dynamically allocated RAM. */
\r
1968 xReturn = xTaskCreate( prvIdleTask,
\r
1969 configIDLE_TASK_NAME,
\r
1970 configMINIMAL_STACK_SIZE,
\r
1972 portPRIVILEGE_BIT, /* In effect ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), but tskIDLE_PRIORITY is zero. */
\r
1973 &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
\r
1975 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
1977 #if ( configUSE_TIMERS == 1 )
\r
1979 if( xReturn == pdPASS )
\r
1981 xReturn = xTimerCreateTimerTask();
\r
1985 mtCOVERAGE_TEST_MARKER();
\r
1988 #endif /* configUSE_TIMERS */
\r
1990 if( xReturn == pdPASS )
\r
1992 /* freertos_tasks_c_additions_init() should only be called if the user
\r
1993 definable macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is
\r
1994 the only macro called by the function. */
\r
1995 #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
\r
1997 freertos_tasks_c_additions_init();
\r
2001 /* Interrupts are turned off here, to ensure a tick does not occur
\r
2002 before or during the call to xPortStartScheduler(). The stacks of
\r
2003 the created tasks contain a status word with interrupts switched on
\r
2004 so interrupts will automatically get re-enabled when the first task
\r
2006 portDISABLE_INTERRUPTS();
\r
2008 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
2010 /* Switch Newlib's _impure_ptr variable to point to the _reent
\r
2011 structure specific to the task that will run first. */
\r
2012 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
\r
2014 #endif /* configUSE_NEWLIB_REENTRANT */
\r
2016 xNextTaskUnblockTime = portMAX_DELAY;
\r
2017 xSchedulerRunning = pdTRUE;
\r
2018 xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;
\r
2020 /* If configGENERATE_RUN_TIME_STATS is defined then the following
\r
2021 macro must be defined to configure the timer/counter used to generate
\r
2022 the run time counter time base. NOTE: If configGENERATE_RUN_TIME_STATS
\r
2023 is set to 0 and the following line fails to build then ensure you do not
\r
2024 have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your
\r
2025 FreeRTOSConfig.h file. */
\r
2026 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
\r
2028 traceTASK_SWITCHED_IN();
\r
2030 /* Setting up the timer tick is hardware specific and thus in the
\r
2031 portable interface. */
\r
2032 if( xPortStartScheduler() != pdFALSE )
\r
2034 /* Should not reach here as if the scheduler is running the
\r
2035 function will not return. */
\r
2039 /* Should only reach here if a task calls xTaskEndScheduler(). */
\r
2044 /* This line will only be reached if the kernel could not be started,
\r
2045 because there was not enough FreeRTOS heap to create the idle task
\r
2046 or the timer task. */
\r
2047 configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );
\r
2050 /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,
\r
2051 meaning xIdleTaskHandle is not used anywhere else. */
\r
2052 ( void ) xIdleTaskHandle;
\r
2054 /*-----------------------------------------------------------*/
\r
2056 void vTaskEndScheduler( void )
\r
2058 /* Stop the scheduler interrupts and call the portable scheduler end
\r
2059 routine so the original ISRs can be restored if necessary. The port
\r
2060 layer must ensure interrupts enable bit is left in the correct state. */
\r
2061 portDISABLE_INTERRUPTS();
\r
2062 xSchedulerRunning = pdFALSE;
\r
2063 vPortEndScheduler();
\r
2065 /*----------------------------------------------------------*/
\r
2067 void vTaskSuspendAll( void )
\r
2069 /* A critical section is not required as the variable is of type
\r
2070 BaseType_t. Please read Richard Barry's reply in the following link to a
\r
2071 post in the FreeRTOS support forum before reporting this as a bug! -
\r
2072 http://goo.gl/wu4acr */
\r
2073 ++uxSchedulerSuspended;
\r
2075 /*----------------------------------------------------------*/
\r
2077 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
2079 static TickType_t prvGetExpectedIdleTime( void )
\r
2081 TickType_t xReturn;
\r
2082 UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;
\r
2084 /* uxHigherPriorityReadyTasks takes care of the case where
\r
2085 configUSE_PREEMPTION is 0, so there may be tasks above the idle priority
\r
2086 task that are in the Ready state, even though the idle task is
\r
2088 #if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
\r
2090 if( uxTopReadyPriority > tskIDLE_PRIORITY )
\r
2092 uxHigherPriorityReadyTasks = pdTRUE;
\r
2097 const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;
\r
2099 /* When port optimised task selection is used the uxTopReadyPriority
\r
2100 variable is used as a bit map. If bits other than the least
\r
2101 significant bit are set then there are tasks that have a priority
\r
2102 above the idle priority that are in the Ready state. This takes
\r
2103 care of the case where the co-operative scheduler is in use. */
\r
2104 if( uxTopReadyPriority > uxLeastSignificantBit )
\r
2106 uxHigherPriorityReadyTasks = pdTRUE;
\r
2111 if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
\r
2115 else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
\r
2117 /* There are other idle priority tasks in the ready state. If
\r
2118 time slicing is used then the very next tick interrupt must be
\r
2122 else if( uxHigherPriorityReadyTasks != pdFALSE )
\r
2124 /* There are tasks in the Ready state that have a priority above the
\r
2125 idle priority. This path can only be reached if
\r
2126 configUSE_PREEMPTION is 0. */
\r
2131 xReturn = xNextTaskUnblockTime - xTickCount;
\r
2137 #endif /* configUSE_TICKLESS_IDLE */
\r
2138 /*----------------------------------------------------------*/
\r
2140 BaseType_t xTaskResumeAll( void )
\r
2142 TCB_t *pxTCB = NULL;
\r
2143 BaseType_t xAlreadyYielded = pdFALSE;
\r
2145 /* If uxSchedulerSuspended is zero then this function does not match a
\r
2146 previous call to vTaskSuspendAll(). */
\r
2147 configASSERT( uxSchedulerSuspended );
\r
2149 /* It is possible that an ISR caused a task to be removed from an event
\r
2150 list while the scheduler was suspended. If this was the case then the
\r
2151 removed task will have been added to the xPendingReadyList. Once the
\r
2152 scheduler has been resumed it is safe to move all the pending ready
\r
2153 tasks from this list into their appropriate ready list. */
\r
2154 taskENTER_CRITICAL();
\r
2156 --uxSchedulerSuspended;
\r
2158 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
2160 if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )
\r
2162 /* Move any readied tasks from the pending list into the
\r
2163 appropriate ready list. */
\r
2164 while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
\r
2166 pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
\r
2167 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
2168 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
2169 prvAddTaskToReadyList( pxTCB );
\r
2171 /* If the moved task has a priority higher than the current
\r
2172 task then a yield must be performed. */
\r
2173 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
2175 xYieldPending = pdTRUE;
\r
2179 mtCOVERAGE_TEST_MARKER();
\r
2183 if( pxTCB != NULL )
\r
2185 /* A task was unblocked while the scheduler was suspended,
\r
2186 which may have prevented the next unblock time from being
\r
2187 re-calculated, in which case re-calculate it now. Mainly
\r
2188 important for low power tickless implementations, where
\r
2189 this can prevent an unnecessary exit from low power
\r
2191 prvResetNextTaskUnblockTime();
\r
2194 /* If any ticks occurred while the scheduler was suspended then
\r
2195 they should be processed now. This ensures the tick count does
\r
2196 not slip, and that any delayed tasks are resumed at the correct
\r
2199 UBaseType_t uxPendedCounts = uxPendedTicks; /* Non-volatile copy. */
\r
2201 if( uxPendedCounts > ( UBaseType_t ) 0U )
\r
2205 if( xTaskIncrementTick() != pdFALSE )
\r
2207 xYieldPending = pdTRUE;
\r
2211 mtCOVERAGE_TEST_MARKER();
\r
2214 } while( uxPendedCounts > ( UBaseType_t ) 0U );
\r
2216 uxPendedTicks = 0;
\r
2220 mtCOVERAGE_TEST_MARKER();
\r
2224 if( xYieldPending != pdFALSE )
\r
2226 #if( configUSE_PREEMPTION != 0 )
\r
2228 xAlreadyYielded = pdTRUE;
\r
2231 taskYIELD_IF_USING_PREEMPTION();
\r
2235 mtCOVERAGE_TEST_MARKER();
\r
2241 mtCOVERAGE_TEST_MARKER();
\r
2244 taskEXIT_CRITICAL();
\r
2246 return xAlreadyYielded;
\r
2248 /*-----------------------------------------------------------*/
\r
2250 TickType_t xTaskGetTickCount( void )
\r
2252 TickType_t xTicks;
\r
2254 /* Critical section required if running on a 16 bit processor. */
\r
2255 portTICK_TYPE_ENTER_CRITICAL();
\r
2257 xTicks = xTickCount;
\r
2259 portTICK_TYPE_EXIT_CRITICAL();
\r
2263 /*-----------------------------------------------------------*/
\r
2265 TickType_t xTaskGetTickCountFromISR( void )
\r
2267 TickType_t xReturn;
\r
2268 UBaseType_t uxSavedInterruptStatus;
\r
2270 /* RTOS ports that support interrupt nesting have the concept of a maximum
\r
2271 system call (or maximum API call) interrupt priority. Interrupts that are
\r
2272 above the maximum system call priority are kept permanently enabled, even
\r
2273 when the RTOS kernel is in a critical section, but cannot make any calls to
\r
2274 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
\r
2275 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
2276 failure if a FreeRTOS API function is called from an interrupt that has been
\r
2277 assigned a priority above the configured maximum system call priority.
\r
2278 Only FreeRTOS functions that end in FromISR can be called from interrupts
\r
2279 that have been assigned a priority at or (logically) below the maximum
\r
2280 system call interrupt priority. FreeRTOS maintains a separate interrupt
\r
2281 safe API to ensure interrupt entry is as fast and as simple as possible.
\r
2282 More information (albeit Cortex-M specific) is provided on the following
\r
2283 link: https://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
2284 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
2286 uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR();
\r
2288 xReturn = xTickCount;
\r
2290 portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
2294 /*-----------------------------------------------------------*/
\r
2296 UBaseType_t uxTaskGetNumberOfTasks( void )
\r
2298 /* A critical section is not required because the variables are of type
\r
2300 return uxCurrentNumberOfTasks;
\r
2302 /*-----------------------------------------------------------*/
\r
2304 char *pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
2308 /* If null is passed in here then the name of the calling task is being
\r
2310 pxTCB = prvGetTCBFromHandle( xTaskToQuery );
\r
2311 configASSERT( pxTCB );
\r
2312 return &( pxTCB->pcTaskName[ 0 ] );
\r
2314 /*-----------------------------------------------------------*/
\r
2316 #if ( INCLUDE_xTaskGetHandle == 1 )
\r
2318 static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] )
\r
2320 TCB_t *pxNextTCB, *pxFirstTCB, *pxReturn = NULL;
\r
2323 BaseType_t xBreakLoop;
\r
2325 /* This function is called with the scheduler suspended. */
\r
2327 if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
\r
2329 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
\r
2333 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
\r
2335 /* Check each character in the name looking for a match or
\r
2337 xBreakLoop = pdFALSE;
\r
2338 for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
\r
2340 cNextChar = pxNextTCB->pcTaskName[ x ];
\r
2342 if( cNextChar != pcNameToQuery[ x ] )
\r
2344 /* Characters didn't match. */
\r
2345 xBreakLoop = pdTRUE;
\r
2347 else if( cNextChar == ( char ) 0x00 )
\r
2349 /* Both strings terminated, a match must have been
\r
2351 pxReturn = pxNextTCB;
\r
2352 xBreakLoop = pdTRUE;
\r
2356 mtCOVERAGE_TEST_MARKER();
\r
2359 if( xBreakLoop != pdFALSE )
\r
2365 if( pxReturn != NULL )
\r
2367 /* The handle has been found. */
\r
2371 } while( pxNextTCB != pxFirstTCB );
\r
2375 mtCOVERAGE_TEST_MARKER();
\r
2381 #endif /* INCLUDE_xTaskGetHandle */
\r
2382 /*-----------------------------------------------------------*/
\r
2384 #if ( INCLUDE_xTaskGetHandle == 1 )
\r
2386 TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
2388 UBaseType_t uxQueue = configMAX_PRIORITIES;
\r
2391 /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */
\r
2392 configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN );
\r
2394 vTaskSuspendAll();
\r
2396 /* Search the ready lists. */
\r
2400 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery );
\r
2402 if( pxTCB != NULL )
\r
2404 /* Found the handle. */
\r
2408 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2410 /* Search the delayed lists. */
\r
2411 if( pxTCB == NULL )
\r
2413 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery );
\r
2416 if( pxTCB == NULL )
\r
2418 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery );
\r
2421 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2423 if( pxTCB == NULL )
\r
2425 /* Search the suspended list. */
\r
2426 pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery );
\r
2431 #if( INCLUDE_vTaskDelete == 1 )
\r
2433 if( pxTCB == NULL )
\r
2435 /* Search the deleted list. */
\r
2436 pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery );
\r
2441 ( void ) xTaskResumeAll();
\r
2446 #endif /* INCLUDE_xTaskGetHandle */
\r
2447 /*-----------------------------------------------------------*/
\r
2449 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2451 UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime )
\r
2453 UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
\r
2455 vTaskSuspendAll();
\r
2457 /* Is there a space in the array for each task in the system? */
\r
2458 if( uxArraySize >= uxCurrentNumberOfTasks )
\r
2460 /* Fill in an TaskStatus_t structure with information on each
\r
2461 task in the Ready state. */
\r
2465 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
\r
2467 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2469 /* Fill in an TaskStatus_t structure with information on each
\r
2470 task in the Blocked state. */
\r
2471 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );
\r
2472 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );
\r
2474 #if( INCLUDE_vTaskDelete == 1 )
\r
2476 /* Fill in an TaskStatus_t structure with information on
\r
2477 each task that has been deleted but not yet cleaned up. */
\r
2478 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
\r
2482 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2484 /* Fill in an TaskStatus_t structure with information on
\r
2485 each task in the Suspended state. */
\r
2486 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
\r
2490 #if ( configGENERATE_RUN_TIME_STATS == 1)
\r
2492 if( pulTotalRunTime != NULL )
\r
2494 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
2495 portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
\r
2497 *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
2503 if( pulTotalRunTime != NULL )
\r
2505 *pulTotalRunTime = 0;
\r
2512 mtCOVERAGE_TEST_MARKER();
\r
2515 ( void ) xTaskResumeAll();
\r
2520 #endif /* configUSE_TRACE_FACILITY */
\r
2521 /*----------------------------------------------------------*/
\r
2523 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
2525 TaskHandle_t xTaskGetIdleTaskHandle( void )
\r
2527 /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
\r
2528 started, then xIdleTaskHandle will be NULL. */
\r
2529 configASSERT( ( xIdleTaskHandle != NULL ) );
\r
2530 return xIdleTaskHandle;
\r
2533 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
\r
2534 /*----------------------------------------------------------*/
\r
2536 /* This conditional compilation should use inequality to 0, not equality to 1.
\r
2537 This is to ensure vTaskStepTick() is available when user defined low power mode
\r
2538 implementations require configUSE_TICKLESS_IDLE to be set to a value other than
\r
2540 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
2542 void vTaskStepTick( const TickType_t xTicksToJump )
\r
2544 /* Correct the tick count value after a period during which the tick
\r
2545 was suppressed. Note this does *not* call the tick hook function for
\r
2546 each stepped tick. */
\r
2547 configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
\r
2548 xTickCount += xTicksToJump;
\r
2549 traceINCREASE_TICK_COUNT( xTicksToJump );
\r
2552 #endif /* configUSE_TICKLESS_IDLE */
\r
2553 /*----------------------------------------------------------*/
\r
2555 #if ( INCLUDE_xTaskAbortDelay == 1 )
\r
2557 BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
\r
2559 TCB_t *pxTCB = xTask;
\r
2560 BaseType_t xReturn;
\r
2562 configASSERT( pxTCB );
\r
2564 vTaskSuspendAll();
\r
2566 /* A task can only be prematurely removed from the Blocked state if
\r
2567 it is actually in the Blocked state. */
\r
2568 if( eTaskGetState( xTask ) == eBlocked )
\r
2572 /* Remove the reference to the task from the blocked list. An
\r
2573 interrupt won't touch the xStateListItem because the
\r
2574 scheduler is suspended. */
\r
2575 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
2577 /* Is the task waiting on an event also? If so remove it from
\r
2578 the event list too. Interrupts can touch the event list item,
\r
2579 even though the scheduler is suspended, so a critical section
\r
2581 taskENTER_CRITICAL();
\r
2583 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
2585 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
2586 pxTCB->ucDelayAborted = pdTRUE;
\r
2590 mtCOVERAGE_TEST_MARKER();
\r
2593 taskEXIT_CRITICAL();
\r
2595 /* Place the unblocked task into the appropriate ready list. */
\r
2596 prvAddTaskToReadyList( pxTCB );
\r
2598 /* A task being unblocked cannot cause an immediate context
\r
2599 switch if preemption is turned off. */
\r
2600 #if ( configUSE_PREEMPTION == 1 )
\r
2602 /* Preemption is on, but a context switch should only be
\r
2603 performed if the unblocked task has a priority that is
\r
2604 equal to or higher than the currently executing task. */
\r
2605 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
2607 /* Pend the yield to be performed when the scheduler
\r
2608 is unsuspended. */
\r
2609 xYieldPending = pdTRUE;
\r
2613 mtCOVERAGE_TEST_MARKER();
\r
2616 #endif /* configUSE_PREEMPTION */
\r
2623 ( void ) xTaskResumeAll();
\r
2628 #endif /* INCLUDE_xTaskAbortDelay */
\r
2629 /*----------------------------------------------------------*/
\r
2631 BaseType_t xTaskIncrementTick( void )
\r
2634 TickType_t xItemValue;
\r
2635 BaseType_t xSwitchRequired = pdFALSE;
\r
2637 /* Called by the portable layer each time a tick interrupt occurs.
\r
2638 Increments the tick then checks to see if the new tick value will cause any
\r
2639 tasks to be unblocked. */
\r
2640 traceTASK_INCREMENT_TICK( xTickCount );
\r
2641 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
2643 /* Minor optimisation. The tick count cannot change in this
\r
2645 const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
\r
2647 /* Increment the RTOS tick, switching the delayed and overflowed
\r
2648 delayed lists if it wraps to 0. */
\r
2649 xTickCount = xConstTickCount;
\r
2651 if( xConstTickCount == ( TickType_t ) 0U ) /*lint !e774 'if' does not always evaluate to false as it is looking for an overflow. */
\r
2653 taskSWITCH_DELAYED_LISTS();
\r
2657 mtCOVERAGE_TEST_MARKER();
\r
2660 /* See if this tick has made a timeout expire. Tasks are stored in
\r
2661 the queue in the order of their wake time - meaning once one task
\r
2662 has been found whose block time has not expired there is no need to
\r
2663 look any further down the list. */
\r
2664 if( xConstTickCount >= xNextTaskUnblockTime )
\r
2668 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
\r
2670 /* The delayed list is empty. Set xNextTaskUnblockTime
\r
2671 to the maximum possible value so it is extremely
\r
2673 if( xTickCount >= xNextTaskUnblockTime ) test will pass
\r
2674 next time through. */
\r
2675 xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2680 /* The delayed list is not empty, get the value of the
\r
2681 item at the head of the delayed list. This is the time
\r
2682 at which the task at the head of the delayed list must
\r
2683 be removed from the Blocked state. */
\r
2684 pxTCB = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
\r
2685 xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );
\r
2687 if( xConstTickCount < xItemValue )
\r
2689 /* It is not time to unblock this item yet, but the
\r
2690 item value is the time at which the task at the head
\r
2691 of the blocked list must be removed from the Blocked
\r
2692 state - so record the item value in
\r
2693 xNextTaskUnblockTime. */
\r
2694 xNextTaskUnblockTime = xItemValue;
\r
2695 break; /*lint !e9011 Code structure here is deedmed easier to understand with multiple breaks. */
\r
2699 mtCOVERAGE_TEST_MARKER();
\r
2702 /* It is time to remove the item from the Blocked state. */
\r
2703 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
2705 /* Is the task waiting on an event also? If so remove
\r
2706 it from the event list. */
\r
2707 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
2709 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
2713 mtCOVERAGE_TEST_MARKER();
\r
2716 /* Place the unblocked task into the appropriate ready
\r
2718 prvAddTaskToReadyList( pxTCB );
\r
2720 /* A task being unblocked cannot cause an immediate
\r
2721 context switch if preemption is turned off. */
\r
2722 #if ( configUSE_PREEMPTION == 1 )
\r
2724 /* Preemption is on, but a context switch should
\r
2725 only be performed if the unblocked task has a
\r
2726 priority that is equal to or higher than the
\r
2727 currently executing task. */
\r
2728 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
2730 xSwitchRequired = pdTRUE;
\r
2734 mtCOVERAGE_TEST_MARKER();
\r
2737 #endif /* configUSE_PREEMPTION */
\r
2742 /* Tasks of equal priority to the currently running task will share
\r
2743 processing time (time slice) if preemption is on, and the application
\r
2744 writer has not explicitly turned time slicing off. */
\r
2745 #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
\r
2747 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )
\r
2749 xSwitchRequired = pdTRUE;
\r
2753 mtCOVERAGE_TEST_MARKER();
\r
2756 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
\r
2758 #if ( configUSE_TICK_HOOK == 1 )
\r
2760 /* Guard against the tick hook being called when the pended tick
\r
2761 count is being unwound (when the scheduler is being unlocked). */
\r
2762 if( uxPendedTicks == ( UBaseType_t ) 0U )
\r
2764 vApplicationTickHook();
\r
2768 mtCOVERAGE_TEST_MARKER();
\r
2771 #endif /* configUSE_TICK_HOOK */
\r
2777 /* The tick hook gets called at regular intervals, even if the
\r
2778 scheduler is locked. */
\r
2779 #if ( configUSE_TICK_HOOK == 1 )
\r
2781 vApplicationTickHook();
\r
2786 #if ( configUSE_PREEMPTION == 1 )
\r
2788 if( xYieldPending != pdFALSE )
\r
2790 xSwitchRequired = pdTRUE;
\r
2794 mtCOVERAGE_TEST_MARKER();
\r
2797 #endif /* configUSE_PREEMPTION */
\r
2799 return xSwitchRequired;
\r
2801 /*-----------------------------------------------------------*/
\r
2803 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2805 void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction )
\r
2809 /* If xTask is NULL then it is the task hook of the calling task that is
\r
2811 if( xTask == NULL )
\r
2813 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2820 /* Save the hook function in the TCB. A critical section is required as
\r
2821 the value can be accessed from an interrupt. */
\r
2822 taskENTER_CRITICAL();
\r
2824 xTCB->pxTaskTag = pxHookFunction;
\r
2826 taskEXIT_CRITICAL();
\r
2829 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2830 /*-----------------------------------------------------------*/
\r
2832 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2834 TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
\r
2837 TaskHookFunction_t xReturn;
\r
2839 /* If xTask is NULL then we are setting our own task hook. */
\r
2840 if( xTask == NULL )
\r
2842 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2849 /* Save the hook function in the TCB. A critical section is required as
\r
2850 the value can be accessed from an interrupt. */
\r
2851 taskENTER_CRITICAL();
\r
2853 xReturn = xTCB->pxTaskTag;
\r
2855 taskEXIT_CRITICAL();
\r
2860 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2861 /*-----------------------------------------------------------*/
\r
2863 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2865 BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter )
\r
2868 BaseType_t xReturn;
\r
2870 /* If xTask is NULL then we are calling our own task hook. */
\r
2871 if( xTask == NULL )
\r
2873 xTCB = pxCurrentTCB;
\r
2880 if( xTCB->pxTaskTag != NULL )
\r
2882 xReturn = xTCB->pxTaskTag( pvParameter );
\r
2892 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2893 /*-----------------------------------------------------------*/
\r
2895 void vTaskSwitchContext( void )
\r
2897 if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )
\r
2899 /* The scheduler is currently suspended - do not allow a context
\r
2901 xYieldPending = pdTRUE;
\r
2905 xYieldPending = pdFALSE;
\r
2906 traceTASK_SWITCHED_OUT();
\r
2908 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
2910 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
2911 portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
\r
2913 ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
2916 /* Add the amount of time the task has been running to the
\r
2917 accumulated time so far. The time the task started running was
\r
2918 stored in ulTaskSwitchedInTime. Note that there is no overflow
\r
2919 protection here so count values are only valid until the timer
\r
2920 overflows. The guard against negative values is to protect
\r
2921 against suspect run time stat counter implementations - which
\r
2922 are provided by the application, not the kernel. */
\r
2923 if( ulTotalRunTime > ulTaskSwitchedInTime )
\r
2925 pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
\r
2929 mtCOVERAGE_TEST_MARKER();
\r
2931 ulTaskSwitchedInTime = ulTotalRunTime;
\r
2933 #endif /* configGENERATE_RUN_TIME_STATS */
\r
2935 /* Check for stack overflow, if configured. */
\r
2936 taskCHECK_FOR_STACK_OVERFLOW();
\r
2938 /* Before the currently running task is switched out, save its errno. */
\r
2939 #if( configUSE_POSIX_ERRNO == 1 )
\r
2941 pxCurrentTCB->iTaskErrno = FreeRTOS_errno;
\r
2945 /* Select a new task to run using either the generic C or port
\r
2946 optimised asm code. */
\r
2947 taskSELECT_HIGHEST_PRIORITY_TASK(); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
\r
2948 traceTASK_SWITCHED_IN();
\r
2950 /* After the new task is switched in, update the global errno. */
\r
2951 #if( configUSE_POSIX_ERRNO == 1 )
\r
2953 FreeRTOS_errno = pxCurrentTCB->iTaskErrno;
\r
2957 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
2959 /* Switch Newlib's _impure_ptr variable to point to the _reent
\r
2960 structure specific to this task. */
\r
2961 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
\r
2963 #endif /* configUSE_NEWLIB_REENTRANT */
\r
2966 /*-----------------------------------------------------------*/
\r
2968 void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )
\r
2970 configASSERT( pxEventList );
\r
2972 /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
\r
2973 SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
\r
2975 /* Place the event list item of the TCB in the appropriate event list.
\r
2976 This is placed in the list in priority order so the highest priority task
\r
2977 is the first to be woken by the event. The queue that contains the event
\r
2978 list is locked, preventing simultaneous access from interrupts. */
\r
2979 vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2981 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
\r
2983 /*-----------------------------------------------------------*/
\r
2985 void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait )
\r
2987 configASSERT( pxEventList );
\r
2989 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
\r
2990 the event groups implementation. */
\r
2991 configASSERT( uxSchedulerSuspended != 0 );
\r
2993 /* Store the item value in the event list item. It is safe to access the
\r
2994 event list item here as interrupts won't access the event list item of a
\r
2995 task that is not in the Blocked state. */
\r
2996 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
\r
2998 /* Place the event list item of the TCB at the end of the appropriate event
\r
2999 list. It is safe to access the event list here because it is part of an
\r
3000 event group implementation - and interrupts don't access event groups
\r
3001 directly (instead they access them indirectly by pending function calls to
\r
3002 the task level). */
\r
3003 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
3005 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
\r
3007 /*-----------------------------------------------------------*/
\r
3009 #if( configUSE_TIMERS == 1 )
\r
3011 void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely )
\r
3013 configASSERT( pxEventList );
\r
3015 /* This function should not be called by application code hence the
\r
3016 'Restricted' in its name. It is not part of the public API. It is
\r
3017 designed for use by kernel code, and has special calling requirements -
\r
3018 it should be called with the scheduler suspended. */
\r
3021 /* Place the event list item of the TCB in the appropriate event list.
\r
3022 In this case it is assume that this is the only task that is going to
\r
3023 be waiting on this event list, so the faster vListInsertEnd() function
\r
3024 can be used in place of vListInsert. */
\r
3025 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
3027 /* If the task should block indefinitely then set the block time to a
\r
3028 value that will be recognised as an indefinite delay inside the
\r
3029 prvAddCurrentTaskToDelayedList() function. */
\r
3030 if( xWaitIndefinitely != pdFALSE )
\r
3032 xTicksToWait = portMAX_DELAY;
\r
3035 traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) );
\r
3036 prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely );
\r
3039 #endif /* configUSE_TIMERS */
\r
3040 /*-----------------------------------------------------------*/
\r
3042 BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
\r
3044 TCB_t *pxUnblockedTCB;
\r
3045 BaseType_t xReturn;
\r
3047 /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be
\r
3048 called from a critical section within an ISR. */
\r
3050 /* The event list is sorted in priority order, so the first in the list can
\r
3051 be removed as it is known to be the highest priority. Remove the TCB from
\r
3052 the delayed list, and add it to the ready list.
\r
3054 If an event is for a queue that is locked then this function will never
\r
3055 get called - the lock count on the queue will get modified instead. This
\r
3056 means exclusive access to the event list is guaranteed here.
\r
3058 This function assumes that a check has already been made to ensure that
\r
3059 pxEventList is not empty. */
\r
3060 pxUnblockedTCB = listGET_OWNER_OF_HEAD_ENTRY( pxEventList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
\r
3061 configASSERT( pxUnblockedTCB );
\r
3062 ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
\r
3064 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
3066 ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
\r
3067 prvAddTaskToReadyList( pxUnblockedTCB );
\r
3071 /* The delayed and ready lists cannot be accessed, so hold this task
\r
3072 pending until the scheduler is resumed. */
\r
3073 vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
\r
3076 if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
3078 /* Return true if the task removed from the event list has a higher
\r
3079 priority than the calling task. This allows the calling task to know if
\r
3080 it should force a context switch now. */
\r
3083 /* Mark that a yield is pending in case the user is not using the
\r
3084 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
\r
3085 xYieldPending = pdTRUE;
\r
3089 xReturn = pdFALSE;
\r
3092 #if( configUSE_TICKLESS_IDLE != 0 )
\r
3094 /* If a task is blocked on a kernel object then xNextTaskUnblockTime
\r
3095 might be set to the blocked task's time out time. If the task is
\r
3096 unblocked for a reason other than a timeout xNextTaskUnblockTime is
\r
3097 normally left unchanged, because it is automatically reset to a new
\r
3098 value when the tick count equals xNextTaskUnblockTime. However if
\r
3099 tickless idling is used it might be more important to enter sleep mode
\r
3100 at the earliest possible time - so reset xNextTaskUnblockTime here to
\r
3101 ensure it is updated at the earliest possible time. */
\r
3102 prvResetNextTaskUnblockTime();
\r
3108 /*-----------------------------------------------------------*/
\r
3110 void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )
\r
3112 TCB_t *pxUnblockedTCB;
\r
3114 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
\r
3115 the event flags implementation. */
\r
3116 configASSERT( uxSchedulerSuspended != pdFALSE );
\r
3118 /* Store the new item value in the event list. */
\r
3119 listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
\r
3121 /* Remove the event list form the event flag. Interrupts do not access
\r
3123 pxUnblockedTCB = listGET_LIST_ITEM_OWNER( pxEventListItem ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
\r
3124 configASSERT( pxUnblockedTCB );
\r
3125 ( void ) uxListRemove( pxEventListItem );
\r
3127 /* Remove the task from the delayed list and add it to the ready list. The
\r
3128 scheduler is suspended so interrupts will not be accessing the ready
\r
3130 ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
\r
3131 prvAddTaskToReadyList( pxUnblockedTCB );
\r
3133 if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
3135 /* The unblocked task has a priority above that of the calling task, so
\r
3136 a context switch is required. This function is called with the
\r
3137 scheduler suspended so xYieldPending is set so the context switch
\r
3138 occurs immediately that the scheduler is resumed (unsuspended). */
\r
3139 xYieldPending = pdTRUE;
\r
3142 /*-----------------------------------------------------------*/
\r
3144 void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
\r
3146 configASSERT( pxTimeOut );
\r
3147 taskENTER_CRITICAL();
\r
3149 pxTimeOut->xOverflowCount = xNumOfOverflows;
\r
3150 pxTimeOut->xTimeOnEntering = xTickCount;
\r
3152 taskEXIT_CRITICAL();
\r
3154 /*-----------------------------------------------------------*/
\r
3156 void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut )
\r
3158 /* For internal use only as it does not use a critical section. */
\r
3159 pxTimeOut->xOverflowCount = xNumOfOverflows;
\r
3160 pxTimeOut->xTimeOnEntering = xTickCount;
\r
3162 /*-----------------------------------------------------------*/
\r
3164 BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait )
\r
3166 BaseType_t xReturn;
\r
3168 configASSERT( pxTimeOut );
\r
3169 configASSERT( pxTicksToWait );
\r
3171 taskENTER_CRITICAL();
\r
3173 /* Minor optimisation. The tick count cannot change in this block. */
\r
3174 const TickType_t xConstTickCount = xTickCount;
\r
3175 const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering;
\r
3177 #if( INCLUDE_xTaskAbortDelay == 1 )
\r
3178 if( pxCurrentTCB->ucDelayAborted != ( uint8_t ) pdFALSE )
\r
3180 /* The delay was aborted, which is not the same as a time out,
\r
3181 but has the same result. */
\r
3182 pxCurrentTCB->ucDelayAborted = pdFALSE;
\r
3188 #if ( INCLUDE_vTaskSuspend == 1 )
\r
3189 if( *pxTicksToWait == portMAX_DELAY )
\r
3191 /* If INCLUDE_vTaskSuspend is set to 1 and the block time
\r
3192 specified is the maximum block time then the task should block
\r
3193 indefinitely, and therefore never time out. */
\r
3194 xReturn = pdFALSE;
\r
3199 if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
\r
3201 /* The tick count is greater than the time at which
\r
3202 vTaskSetTimeout() was called, but has also overflowed since
\r
3203 vTaskSetTimeOut() was called. It must have wrapped all the way
\r
3204 around and gone past again. This passed since vTaskSetTimeout()
\r
3208 else if( xElapsedTime < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */
\r
3210 /* Not a genuine timeout. Adjust parameters for time remaining. */
\r
3211 *pxTicksToWait -= xElapsedTime;
\r
3212 vTaskInternalSetTimeOutState( pxTimeOut );
\r
3213 xReturn = pdFALSE;
\r
3217 *pxTicksToWait = 0;
\r
3221 taskEXIT_CRITICAL();
\r
3225 /*-----------------------------------------------------------*/
\r
3227 void vTaskMissedYield( void )
\r
3229 xYieldPending = pdTRUE;
\r
3231 /*-----------------------------------------------------------*/
\r
3233 #if ( configUSE_TRACE_FACILITY == 1 )
\r
3235 UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )
\r
3237 UBaseType_t uxReturn;
\r
3238 TCB_t const *pxTCB;
\r
3240 if( xTask != NULL )
\r
3243 uxReturn = pxTCB->uxTaskNumber;
\r
3253 #endif /* configUSE_TRACE_FACILITY */
\r
3254 /*-----------------------------------------------------------*/
\r
3256 #if ( configUSE_TRACE_FACILITY == 1 )
\r
3258 void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle )
\r
3262 if( xTask != NULL )
\r
3265 pxTCB->uxTaskNumber = uxHandle;
\r
3269 #endif /* configUSE_TRACE_FACILITY */
\r
3272 * -----------------------------------------------------------
\r
3274 * ----------------------------------------------------------
\r
3276 * The portTASK_FUNCTION() macro is used to allow port/compiler specific
\r
3277 * language extensions. The equivalent prototype for this function is:
\r
3279 * void prvIdleTask( void *pvParameters );
\r
3282 static portTASK_FUNCTION( prvIdleTask, pvParameters )
\r
3284 /* Stop warnings. */
\r
3285 ( void ) pvParameters;
\r
3287 /** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
\r
3288 SCHEDULER IS STARTED. **/
\r
3290 /* In case a task that has a secure context deletes itself, in which case
\r
3291 the idle task is responsible for deleting the task's secure context, if
\r
3293 portTASK_CALLS_SECURE_FUNCTIONS();
\r
3297 /* See if any tasks have deleted themselves - if so then the idle task
\r
3298 is responsible for freeing the deleted task's TCB and stack. */
\r
3299 prvCheckTasksWaitingTermination();
\r
3301 #if ( configUSE_PREEMPTION == 0 )
\r
3303 /* If we are not using preemption we keep forcing a task switch to
\r
3304 see if any other task has become available. If we are using
\r
3305 preemption we don't need to do this as any task becoming available
\r
3306 will automatically get the processor anyway. */
\r
3309 #endif /* configUSE_PREEMPTION */
\r
3311 #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
\r
3313 /* When using preemption tasks of equal priority will be
\r
3314 timesliced. If a task that is sharing the idle priority is ready
\r
3315 to run then the idle task should yield before the end of the
\r
3318 A critical region is not required here as we are just reading from
\r
3319 the list, and an occasional incorrect value will not matter. If
\r
3320 the ready list at the idle priority contains more than one task
\r
3321 then a task other than the idle task is ready to execute. */
\r
3322 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )
\r
3328 mtCOVERAGE_TEST_MARKER();
\r
3331 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
\r
3333 #if ( configUSE_IDLE_HOOK == 1 )
\r
3335 extern void vApplicationIdleHook( void );
\r
3337 /* Call the user defined function from within the idle task. This
\r
3338 allows the application designer to add background functionality
\r
3339 without the overhead of a separate task.
\r
3340 NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
\r
3341 CALL A FUNCTION THAT MIGHT BLOCK. */
\r
3342 vApplicationIdleHook();
\r
3344 #endif /* configUSE_IDLE_HOOK */
\r
3346 /* This conditional compilation should use inequality to 0, not equality
\r
3347 to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
\r
3348 user defined low power mode implementations require
\r
3349 configUSE_TICKLESS_IDLE to be set to a value other than 1. */
\r
3350 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
3352 TickType_t xExpectedIdleTime;
\r
3354 /* It is not desirable to suspend then resume the scheduler on
\r
3355 each iteration of the idle task. Therefore, a preliminary
\r
3356 test of the expected idle time is performed without the
\r
3357 scheduler suspended. The result here is not necessarily
\r
3359 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
3361 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
3363 vTaskSuspendAll();
\r
3365 /* Now the scheduler is suspended, the expected idle
\r
3366 time can be sampled again, and this time its value can
\r
3368 configASSERT( xNextTaskUnblockTime >= xTickCount );
\r
3369 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
3371 /* Define the following macro to set xExpectedIdleTime to 0
\r
3372 if the application does not want
\r
3373 portSUPPRESS_TICKS_AND_SLEEP() to be called. */
\r
3374 configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime );
\r
3376 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
3378 traceLOW_POWER_IDLE_BEGIN();
\r
3379 portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
\r
3380 traceLOW_POWER_IDLE_END();
\r
3384 mtCOVERAGE_TEST_MARKER();
\r
3387 ( void ) xTaskResumeAll();
\r
3391 mtCOVERAGE_TEST_MARKER();
\r
3394 #endif /* configUSE_TICKLESS_IDLE */
\r
3397 /*-----------------------------------------------------------*/
\r
3399 #if( configUSE_TICKLESS_IDLE != 0 )
\r
3401 eSleepModeStatus eTaskConfirmSleepModeStatus( void )
\r
3403 /* The idle task exists in addition to the application tasks. */
\r
3404 const UBaseType_t uxNonApplicationTasks = 1;
\r
3405 eSleepModeStatus eReturn = eStandardSleep;
\r
3407 if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
\r
3409 /* A task was made ready while the scheduler was suspended. */
\r
3410 eReturn = eAbortSleep;
\r
3412 else if( xYieldPending != pdFALSE )
\r
3414 /* A yield was pended while the scheduler was suspended. */
\r
3415 eReturn = eAbortSleep;
\r
3419 /* If all the tasks are in the suspended list (which might mean they
\r
3420 have an infinite block time rather than actually being suspended)
\r
3421 then it is safe to turn all clocks off and just wait for external
\r
3423 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
\r
3425 eReturn = eNoTasksWaitingTimeout;
\r
3429 mtCOVERAGE_TEST_MARKER();
\r
3436 #endif /* configUSE_TICKLESS_IDLE */
\r
3437 /*-----------------------------------------------------------*/
\r
3439 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
\r
3441 void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue )
\r
3445 if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS )
\r
3447 pxTCB = prvGetTCBFromHandle( xTaskToSet );
\r
3448 pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue;
\r
3452 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
\r
3453 /*-----------------------------------------------------------*/
\r
3455 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
\r
3457 void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex )
\r
3459 void *pvReturn = NULL;
\r
3462 if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS )
\r
3464 pxTCB = prvGetTCBFromHandle( xTaskToQuery );
\r
3465 pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ];
\r
3475 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
\r
3476 /*-----------------------------------------------------------*/
\r
3478 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
3480 void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions )
\r
3484 /* If null is passed in here then we are modifying the MPU settings of
\r
3485 the calling task. */
\r
3486 pxTCB = prvGetTCBFromHandle( xTaskToModify );
\r
3488 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
\r
3491 #endif /* portUSING_MPU_WRAPPERS */
\r
3492 /*-----------------------------------------------------------*/
\r
3494 static void prvInitialiseTaskLists( void )
\r
3496 UBaseType_t uxPriority;
\r
3498 for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
\r
3500 vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
\r
3503 vListInitialise( &xDelayedTaskList1 );
\r
3504 vListInitialise( &xDelayedTaskList2 );
\r
3505 vListInitialise( &xPendingReadyList );
\r
3507 #if ( INCLUDE_vTaskDelete == 1 )
\r
3509 vListInitialise( &xTasksWaitingTermination );
\r
3511 #endif /* INCLUDE_vTaskDelete */
\r
3513 #if ( INCLUDE_vTaskSuspend == 1 )
\r
3515 vListInitialise( &xSuspendedTaskList );
\r
3517 #endif /* INCLUDE_vTaskSuspend */
\r
3519 /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
\r
3521 pxDelayedTaskList = &xDelayedTaskList1;
\r
3522 pxOverflowDelayedTaskList = &xDelayedTaskList2;
\r
3524 /*-----------------------------------------------------------*/
\r
3526 static void prvCheckTasksWaitingTermination( void )
\r
3529 /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/
\r
3531 #if ( INCLUDE_vTaskDelete == 1 )
\r
3535 /* uxDeletedTasksWaitingCleanUp is used to prevent taskENTER_CRITICAL()
\r
3536 being called too often in the idle task. */
\r
3537 while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
\r
3539 taskENTER_CRITICAL();
\r
3541 pxTCB = listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
\r
3542 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
3543 --uxCurrentNumberOfTasks;
\r
3544 --uxDeletedTasksWaitingCleanUp;
\r
3546 taskEXIT_CRITICAL();
\r
3548 prvDeleteTCB( pxTCB );
\r
3551 #endif /* INCLUDE_vTaskDelete */
\r
3553 /*-----------------------------------------------------------*/
\r
3555 #if( configUSE_TRACE_FACILITY == 1 )
\r
3557 void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState )
\r
3561 /* xTask is NULL then get the state of the calling task. */
\r
3562 pxTCB = prvGetTCBFromHandle( xTask );
\r
3564 pxTaskStatus->xHandle = ( TaskHandle_t ) pxTCB;
\r
3565 pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName [ 0 ] );
\r
3566 pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority;
\r
3567 pxTaskStatus->pxStackBase = pxTCB->pxStack;
\r
3568 pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber;
\r
3570 #if ( configUSE_MUTEXES == 1 )
\r
3572 pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;
\r
3576 pxTaskStatus->uxBasePriority = 0;
\r
3580 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
3582 pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter;
\r
3586 pxTaskStatus->ulRunTimeCounter = 0;
\r
3590 /* Obtaining the task state is a little fiddly, so is only done if the
\r
3591 value of eState passed into this function is eInvalid - otherwise the
\r
3592 state is just set to whatever is passed in. */
\r
3593 if( eState != eInvalid )
\r
3595 if( pxTCB == pxCurrentTCB )
\r
3597 pxTaskStatus->eCurrentState = eRunning;
\r
3601 pxTaskStatus->eCurrentState = eState;
\r
3603 #if ( INCLUDE_vTaskSuspend == 1 )
\r
3605 /* If the task is in the suspended list then there is a
\r
3606 chance it is actually just blocked indefinitely - so really
\r
3607 it should be reported as being in the Blocked state. */
\r
3608 if( eState == eSuspended )
\r
3610 vTaskSuspendAll();
\r
3612 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
3614 pxTaskStatus->eCurrentState = eBlocked;
\r
3617 ( void ) xTaskResumeAll();
\r
3620 #endif /* INCLUDE_vTaskSuspend */
\r
3625 pxTaskStatus->eCurrentState = eTaskGetState( pxTCB );
\r
3628 /* Obtaining the stack space takes some time, so the xGetFreeStackSpace
\r
3629 parameter is provided to allow it to be skipped. */
\r
3630 if( xGetFreeStackSpace != pdFALSE )
\r
3632 #if ( portSTACK_GROWTH > 0 )
\r
3634 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack );
\r
3638 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack );
\r
3644 pxTaskStatus->usStackHighWaterMark = 0;
\r
3648 #endif /* configUSE_TRACE_FACILITY */
\r
3649 /*-----------------------------------------------------------*/
\r
3651 #if ( configUSE_TRACE_FACILITY == 1 )
\r
3653 static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )
\r
3655 configLIST_VOLATILE TCB_t *pxNextTCB, *pxFirstTCB;
\r
3656 UBaseType_t uxTask = 0;
\r
3658 if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
\r
3660 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
\r
3662 /* Populate an TaskStatus_t structure within the
\r
3663 pxTaskStatusArray array for each task that is referenced from
\r
3664 pxList. See the definition of TaskStatus_t in task.h for the
\r
3665 meaning of each TaskStatus_t structure member. */
\r
3668 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
\r
3669 vTaskGetInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState );
\r
3671 } while( pxNextTCB != pxFirstTCB );
\r
3675 mtCOVERAGE_TEST_MARKER();
\r
3681 #endif /* configUSE_TRACE_FACILITY */
\r
3682 /*-----------------------------------------------------------*/
\r
3684 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
3686 static configSTACK_DEPTH_TYPE prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
\r
3688 uint32_t ulCount = 0U;
\r
3690 while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE )
\r
3692 pucStackByte -= portSTACK_GROWTH;
\r
3696 ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */
\r
3698 return ( configSTACK_DEPTH_TYPE ) ulCount;
\r
3701 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */
\r
3702 /*-----------------------------------------------------------*/
\r
3704 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
\r
3706 UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
\r
3709 uint8_t *pucEndOfStack;
\r
3710 UBaseType_t uxReturn;
\r
3712 pxTCB = prvGetTCBFromHandle( xTask );
\r
3714 #if portSTACK_GROWTH < 0
\r
3716 pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
\r
3720 pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
\r
3724 uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );
\r
3729 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
\r
3730 /*-----------------------------------------------------------*/
\r
3732 #if ( INCLUDE_vTaskDelete == 1 )
\r
3734 static void prvDeleteTCB( TCB_t *pxTCB )
\r
3736 /* This call is required specifically for the TriCore port. It must be
\r
3737 above the vPortFree() calls. The call is also used by ports/demos that
\r
3738 want to allocate and clean RAM statically. */
\r
3739 portCLEAN_UP_TCB( pxTCB );
\r
3741 /* Free up the memory allocated by the scheduler for the task. It is up
\r
3742 to the task to free any memory allocated at the application level. */
\r
3743 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
3745 _reclaim_reent( &( pxTCB->xNewLib_reent ) );
\r
3747 #endif /* configUSE_NEWLIB_REENTRANT */
\r
3749 #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
\r
3751 /* The task can only have been allocated dynamically - free both
\r
3752 the stack and TCB. */
\r
3753 vPortFree( pxTCB->pxStack );
\r
3754 vPortFree( pxTCB );
\r
3756 #elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
\r
3758 /* The task could have been allocated statically or dynamically, so
\r
3759 check what was statically allocated before trying to free the
\r
3761 if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB )
\r
3763 /* Both the stack and TCB were allocated dynamically, so both
\r
3765 vPortFree( pxTCB->pxStack );
\r
3766 vPortFree( pxTCB );
\r
3768 else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY )
\r
3770 /* Only the stack was statically allocated, so the TCB is the
\r
3771 only memory that must be freed. */
\r
3772 vPortFree( pxTCB );
\r
3776 /* Neither the stack nor the TCB were allocated dynamically, so
\r
3777 nothing needs to be freed. */
\r
3778 configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB );
\r
3779 mtCOVERAGE_TEST_MARKER();
\r
3782 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
3785 #endif /* INCLUDE_vTaskDelete */
\r
3786 /*-----------------------------------------------------------*/
\r
3788 static void prvResetNextTaskUnblockTime( void )
\r
3792 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
\r
3794 /* The new current delayed list is empty. Set xNextTaskUnblockTime to
\r
3795 the maximum possible value so it is extremely unlikely that the
\r
3796 if( xTickCount >= xNextTaskUnblockTime ) test will pass until
\r
3797 there is an item in the delayed list. */
\r
3798 xNextTaskUnblockTime = portMAX_DELAY;
\r
3802 /* The new current delayed list is not empty, get the value of
\r
3803 the item at the head of the delayed list. This is the time at
\r
3804 which the task at the head of the delayed list should be removed
\r
3805 from the Blocked state. */
\r
3806 ( pxTCB ) = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
\r
3807 xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xStateListItem ) );
\r
3810 /*-----------------------------------------------------------*/
\r
3812 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
\r
3814 TaskHandle_t xTaskGetCurrentTaskHandle( void )
\r
3816 TaskHandle_t xReturn;
\r
3818 /* A critical section is not required as this is not called from
\r
3819 an interrupt and the current TCB will always be the same for any
\r
3820 individual execution thread. */
\r
3821 xReturn = pxCurrentTCB;
\r
3826 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
\r
3827 /*-----------------------------------------------------------*/
\r
3829 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
3831 BaseType_t xTaskGetSchedulerState( void )
\r
3833 BaseType_t xReturn;
\r
3835 if( xSchedulerRunning == pdFALSE )
\r
3837 xReturn = taskSCHEDULER_NOT_STARTED;
\r
3841 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
3843 xReturn = taskSCHEDULER_RUNNING;
\r
3847 xReturn = taskSCHEDULER_SUSPENDED;
\r
3854 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
\r
3855 /*-----------------------------------------------------------*/
\r
3857 #if ( configUSE_MUTEXES == 1 )
\r
3859 BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
\r
3861 TCB_t * const pxMutexHolderTCB = pxMutexHolder;
\r
3862 BaseType_t xReturn = pdFALSE;
\r
3864 /* If the mutex was given back by an interrupt while the queue was
\r
3865 locked then the mutex holder might now be NULL. _RB_ Is this still
\r
3866 needed as interrupts can no longer use mutexes? */
\r
3867 if( pxMutexHolder != NULL )
\r
3869 /* If the holder of the mutex has a priority below the priority of
\r
3870 the task attempting to obtain the mutex then it will temporarily
\r
3871 inherit the priority of the task attempting to obtain the mutex. */
\r
3872 if( pxMutexHolderTCB->uxPriority < pxCurrentTCB->uxPriority )
\r
3874 /* Adjust the mutex holder state to account for its new
\r
3875 priority. Only reset the event list item value if the value is
\r
3876 not being used for anything else. */
\r
3877 if( ( listGET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
\r
3879 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. */
\r
3883 mtCOVERAGE_TEST_MARKER();
\r
3886 /* If the task being modified is in the ready state it will need
\r
3887 to be moved into a new list. */
\r
3888 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxMutexHolderTCB->uxPriority ] ), &( pxMutexHolderTCB->xStateListItem ) ) != pdFALSE )
\r
3890 if( uxListRemove( &( pxMutexHolderTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
3892 taskRESET_READY_PRIORITY( pxMutexHolderTCB->uxPriority );
\r
3896 mtCOVERAGE_TEST_MARKER();
\r
3899 /* Inherit the priority before being moved into the new list. */
\r
3900 pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
3901 prvAddTaskToReadyList( pxMutexHolderTCB );
\r
3905 /* Just inherit the priority. */
\r
3906 pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
3909 traceTASK_PRIORITY_INHERIT( pxMutexHolderTCB, pxCurrentTCB->uxPriority );
\r
3911 /* Inheritance occurred. */
\r
3916 if( pxMutexHolderTCB->uxBasePriority < pxCurrentTCB->uxPriority )
\r
3918 /* The base priority of the mutex holder is lower than the
\r
3919 priority of the task attempting to take the mutex, but the
\r
3920 current priority of the mutex holder is not lower than the
\r
3921 priority of the task attempting to take the mutex.
\r
3922 Therefore the mutex holder must have already inherited a
\r
3923 priority, but inheritance would have occurred if that had
\r
3924 not been the case. */
\r
3929 mtCOVERAGE_TEST_MARKER();
\r
3935 mtCOVERAGE_TEST_MARKER();
\r
3941 #endif /* configUSE_MUTEXES */
\r
3942 /*-----------------------------------------------------------*/
\r
3944 #if ( configUSE_MUTEXES == 1 )
\r
3946 BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )
\r
3948 TCB_t * const pxTCB = pxMutexHolder;
\r
3949 BaseType_t xReturn = pdFALSE;
\r
3951 if( pxMutexHolder != NULL )
\r
3953 /* A task can only have an inherited priority if it holds the mutex.
\r
3954 If the mutex is held by a task then it cannot be given from an
\r
3955 interrupt, and if a mutex is given by the holding task then it must
\r
3956 be the running state task. */
\r
3957 configASSERT( pxTCB == pxCurrentTCB );
\r
3958 configASSERT( pxTCB->uxMutexesHeld );
\r
3959 ( pxTCB->uxMutexesHeld )--;
\r
3961 /* Has the holder of the mutex inherited the priority of another
\r
3963 if( pxTCB->uxPriority != pxTCB->uxBasePriority )
\r
3965 /* Only disinherit if no other mutexes are held. */
\r
3966 if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
\r
3968 /* A task can only have an inherited priority if it holds
\r
3969 the mutex. If the mutex is held by a task then it cannot be
\r
3970 given from an interrupt, and if a mutex is given by the
\r
3971 holding task then it must be the running state task. Remove
\r
3972 the holding task from the ready list. */
\r
3973 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
3975 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
3979 mtCOVERAGE_TEST_MARKER();
\r
3982 /* Disinherit the priority before adding the task into the
\r
3983 new ready list. */
\r
3984 traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
\r
3985 pxTCB->uxPriority = pxTCB->uxBasePriority;
\r
3987 /* Reset the event list item value. It cannot be in use for
\r
3988 any other purpose if this task is running, and it must be
\r
3989 running to give back the mutex. */
\r
3990 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
3991 prvAddTaskToReadyList( pxTCB );
\r
3993 /* Return true to indicate that a context switch is required.
\r
3994 This is only actually required in the corner case whereby
\r
3995 multiple mutexes were held and the mutexes were given back
\r
3996 in an order different to that in which they were taken.
\r
3997 If a context switch did not occur when the first mutex was
\r
3998 returned, even if a task was waiting on it, then a context
\r
3999 switch should occur when the last mutex is returned whether
\r
4000 a task is waiting on it or not. */
\r
4005 mtCOVERAGE_TEST_MARKER();
\r
4010 mtCOVERAGE_TEST_MARKER();
\r
4015 mtCOVERAGE_TEST_MARKER();
\r
4021 #endif /* configUSE_MUTEXES */
\r
4022 /*-----------------------------------------------------------*/
\r
4024 #if ( configUSE_MUTEXES == 1 )
\r
4026 void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder, UBaseType_t uxHighestPriorityWaitingTask )
\r
4028 TCB_t * const pxTCB = pxMutexHolder;
\r
4029 UBaseType_t uxPriorityUsedOnEntry, uxPriorityToUse;
\r
4030 const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1;
\r
4032 if( pxMutexHolder != NULL )
\r
4034 /* If pxMutexHolder is not NULL then the holder must hold at least
\r
4036 configASSERT( pxTCB->uxMutexesHeld );
\r
4038 /* Determine the priority to which the priority of the task that
\r
4039 holds the mutex should be set. This will be the greater of the
\r
4040 holding task's base priority and the priority of the highest
\r
4041 priority task that is waiting to obtain the mutex. */
\r
4042 if( pxTCB->uxBasePriority < uxHighestPriorityWaitingTask )
\r
4044 uxPriorityToUse = uxHighestPriorityWaitingTask;
\r
4048 uxPriorityToUse = pxTCB->uxBasePriority;
\r
4051 /* Does the priority need to change? */
\r
4052 if( pxTCB->uxPriority != uxPriorityToUse )
\r
4054 /* Only disinherit if no other mutexes are held. This is a
\r
4055 simplification in the priority inheritance implementation. If
\r
4056 the task that holds the mutex is also holding other mutexes then
\r
4057 the other mutexes may have caused the priority inheritance. */
\r
4058 if( pxTCB->uxMutexesHeld == uxOnlyOneMutexHeld )
\r
4060 /* If a task has timed out because it already holds the
\r
4061 mutex it was trying to obtain then it cannot of inherited
\r
4062 its own priority. */
\r
4063 configASSERT( pxTCB != pxCurrentTCB );
\r
4065 /* Disinherit the priority, remembering the previous
\r
4066 priority to facilitate determining the subject task's
\r
4068 traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
\r
4069 uxPriorityUsedOnEntry = pxTCB->uxPriority;
\r
4070 pxTCB->uxPriority = uxPriorityToUse;
\r
4072 /* Only reset the event list item value if the value is not
\r
4073 being used for anything else. */
\r
4074 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
\r
4076 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. */
\r
4080 mtCOVERAGE_TEST_MARKER();
\r
4083 /* If the running task is not the task that holds the mutex
\r
4084 then the task that holds the mutex could be in either the
\r
4085 Ready, Blocked or Suspended states. Only remove the task
\r
4086 from its current state list if it is in the Ready state as
\r
4087 the task's priority is going to change and there is one
\r
4088 Ready list per priority. */
\r
4089 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
\r
4091 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
4093 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
4097 mtCOVERAGE_TEST_MARKER();
\r
4100 prvAddTaskToReadyList( pxTCB );
\r
4104 mtCOVERAGE_TEST_MARKER();
\r
4109 mtCOVERAGE_TEST_MARKER();
\r
4114 mtCOVERAGE_TEST_MARKER();
\r
4119 mtCOVERAGE_TEST_MARKER();
\r
4123 #endif /* configUSE_MUTEXES */
\r
4124 /*-----------------------------------------------------------*/
\r
4126 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
4128 void vTaskEnterCritical( void )
\r
4130 portDISABLE_INTERRUPTS();
\r
4132 if( xSchedulerRunning != pdFALSE )
\r
4134 ( pxCurrentTCB->uxCriticalNesting )++;
\r
4136 /* This is not the interrupt safe version of the enter critical
\r
4137 function so assert() if it is being called from an interrupt
\r
4138 context. Only API functions that end in "FromISR" can be used in an
\r
4139 interrupt. Only assert if the critical nesting count is 1 to
\r
4140 protect against recursive calls if the assert function also uses a
\r
4141 critical section. */
\r
4142 if( pxCurrentTCB->uxCriticalNesting == 1 )
\r
4144 portASSERT_IF_IN_ISR();
\r
4149 mtCOVERAGE_TEST_MARKER();
\r
4153 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
4154 /*-----------------------------------------------------------*/
\r
4156 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
4158 void vTaskExitCritical( void )
\r
4160 if( xSchedulerRunning != pdFALSE )
\r
4162 if( pxCurrentTCB->uxCriticalNesting > 0U )
\r
4164 ( pxCurrentTCB->uxCriticalNesting )--;
\r
4166 if( pxCurrentTCB->uxCriticalNesting == 0U )
\r
4168 portENABLE_INTERRUPTS();
\r
4172 mtCOVERAGE_TEST_MARKER();
\r
4177 mtCOVERAGE_TEST_MARKER();
\r
4182 mtCOVERAGE_TEST_MARKER();
\r
4186 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
4187 /*-----------------------------------------------------------*/
\r
4189 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
4191 static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName )
\r
4195 /* Start by copying the entire string. */
\r
4196 strcpy( pcBuffer, pcTaskName );
\r
4198 /* Pad the end of the string with spaces to ensure columns line up when
\r
4200 for( x = strlen( pcBuffer ); x < ( size_t ) ( configMAX_TASK_NAME_LEN - 1 ); x++ )
\r
4202 pcBuffer[ x ] = ' ';
\r
4206 pcBuffer[ x ] = ( char ) 0x00;
\r
4208 /* Return the new end of string. */
\r
4209 return &( pcBuffer[ x ] );
\r
4212 #endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
\r
4213 /*-----------------------------------------------------------*/
\r
4215 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
\r
4217 void vTaskList( char * pcWriteBuffer )
\r
4219 TaskStatus_t *pxTaskStatusArray;
\r
4220 UBaseType_t uxArraySize, x;
\r
4226 * This function is provided for convenience only, and is used by many
\r
4227 * of the demo applications. Do not consider it to be part of the
\r
4230 * vTaskList() calls uxTaskGetSystemState(), then formats part of the
\r
4231 * uxTaskGetSystemState() output into a human readable table that
\r
4232 * displays task names, states and stack usage.
\r
4234 * vTaskList() has a dependency on the sprintf() C library function that
\r
4235 * might bloat the code size, use a lot of stack, and provide different
\r
4236 * results on different platforms. An alternative, tiny, third party,
\r
4237 * and limited functionality implementation of sprintf() is provided in
\r
4238 * many of the FreeRTOS/Demo sub-directories in a file called
\r
4239 * printf-stdarg.c (note printf-stdarg.c does not provide a full
\r
4240 * snprintf() implementation!).
\r
4242 * It is recommended that production systems call uxTaskGetSystemState()
\r
4243 * directly to get access to raw stats data, rather than indirectly
\r
4244 * through a call to vTaskList().
\r
4248 /* Make sure the write buffer does not contain a string. */
\r
4249 *pcWriteBuffer = ( char ) 0x00;
\r
4251 /* Take a snapshot of the number of tasks in case it changes while this
\r
4252 function is executing. */
\r
4253 uxArraySize = uxCurrentNumberOfTasks;
\r
4255 /* Allocate an array index for each task. NOTE! if
\r
4256 configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
\r
4257 equate to NULL. */
\r
4258 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation allocates a struct that has the alignment requirements of a pointer. */
\r
4260 if( pxTaskStatusArray != NULL )
\r
4262 /* Generate the (binary) data. */
\r
4263 uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
\r
4265 /* Create a human readable table from the binary data. */
\r
4266 for( x = 0; x < uxArraySize; x++ )
\r
4268 switch( pxTaskStatusArray[ x ].eCurrentState )
\r
4270 case eRunning: cStatus = tskRUNNING_CHAR;
\r
4273 case eReady: cStatus = tskREADY_CHAR;
\r
4276 case eBlocked: cStatus = tskBLOCKED_CHAR;
\r
4279 case eSuspended: cStatus = tskSUSPENDED_CHAR;
\r
4282 case eDeleted: cStatus = tskDELETED_CHAR;
\r
4285 case eInvalid: /* Fall through. */
\r
4286 default: /* Should not get here, but it is included
\r
4287 to prevent static checking errors. */
\r
4288 cStatus = ( char ) 0x00;
\r
4292 /* Write the task name to the string, padding with spaces so it
\r
4293 can be printed in tabular form more easily. */
\r
4294 pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
\r
4296 /* Write the rest of the string. */
\r
4297 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 ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */
\r
4298 pcWriteBuffer += strlen( pcWriteBuffer ); /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */
\r
4301 /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
\r
4302 is 0 then vPortFree() will be #defined to nothing. */
\r
4303 vPortFree( pxTaskStatusArray );
\r
4307 mtCOVERAGE_TEST_MARKER();
\r
4311 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
\r
4312 /*----------------------------------------------------------*/
\r
4314 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
\r
4316 void vTaskGetRunTimeStats( char *pcWriteBuffer )
\r
4318 TaskStatus_t *pxTaskStatusArray;
\r
4319 UBaseType_t uxArraySize, x;
\r
4320 uint32_t ulTotalTime, ulStatsAsPercentage;
\r
4322 #if( configUSE_TRACE_FACILITY != 1 )
\r
4324 #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats().
\r
4331 * This function is provided for convenience only, and is used by many
\r
4332 * of the demo applications. Do not consider it to be part of the
\r
4335 * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part
\r
4336 * of the uxTaskGetSystemState() output into a human readable table that
\r
4337 * displays the amount of time each task has spent in the Running state
\r
4338 * in both absolute and percentage terms.
\r
4340 * vTaskGetRunTimeStats() has a dependency on the sprintf() C library
\r
4341 * function that might bloat the code size, use a lot of stack, and
\r
4342 * provide different results on different platforms. An alternative,
\r
4343 * tiny, third party, and limited functionality implementation of
\r
4344 * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in
\r
4345 * a file called printf-stdarg.c (note printf-stdarg.c does not provide
\r
4346 * a full snprintf() implementation!).
\r
4348 * It is recommended that production systems call uxTaskGetSystemState()
\r
4349 * directly to get access to raw stats data, rather than indirectly
\r
4350 * through a call to vTaskGetRunTimeStats().
\r
4353 /* Make sure the write buffer does not contain a string. */
\r
4354 *pcWriteBuffer = ( char ) 0x00;
\r
4356 /* Take a snapshot of the number of tasks in case it changes while this
\r
4357 function is executing. */
\r
4358 uxArraySize = uxCurrentNumberOfTasks;
\r
4360 /* Allocate an array index for each task. NOTE! If
\r
4361 configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
\r
4362 equate to NULL. */
\r
4363 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation allocates a struct that has the alignment requirements of a pointer. */
\r
4365 if( pxTaskStatusArray != NULL )
\r
4367 /* Generate the (binary) data. */
\r
4368 uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
\r
4370 /* For percentage calculations. */
\r
4371 ulTotalTime /= 100UL;
\r
4373 /* Avoid divide by zero errors. */
\r
4374 if( ulTotalTime > 0UL )
\r
4376 /* Create a human readable table from the binary data. */
\r
4377 for( x = 0; x < uxArraySize; x++ )
\r
4379 /* What percentage of the total run time has the task used?
\r
4380 This will always be rounded down to the nearest integer.
\r
4381 ulTotalRunTimeDiv100 has already been divided by 100. */
\r
4382 ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
\r
4384 /* Write the task name to the string, padding with
\r
4385 spaces so it can be printed in tabular form more
\r
4387 pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
\r
4389 if( ulStatsAsPercentage > 0UL )
\r
4391 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
4393 sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
\r
4397 /* sizeof( int ) == sizeof( long ) so a smaller
\r
4398 printf() library can be used. */
\r
4399 sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */
\r
4405 /* If the percentage is zero here then the task has
\r
4406 consumed less than 1% of the total run time. */
\r
4407 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
4409 sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter );
\r
4413 /* sizeof( int ) == sizeof( long ) so a smaller
\r
4414 printf() library can be used. */
\r
4415 sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter ); /*lint !e586 sprintf() allowed as this is compiled with many compilers and this is a utility function only - not part of the core kernel implementation. */
\r
4420 pcWriteBuffer += strlen( pcWriteBuffer ); /*lint !e9016 Pointer arithmetic ok on char pointers especially as in this case where it best denotes the intent of the code. */
\r
4425 mtCOVERAGE_TEST_MARKER();
\r
4428 /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
\r
4429 is 0 then vPortFree() will be #defined to nothing. */
\r
4430 vPortFree( pxTaskStatusArray );
\r
4434 mtCOVERAGE_TEST_MARKER();
\r
4438 #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) */
\r
4439 /*-----------------------------------------------------------*/
\r
4441 TickType_t uxTaskResetEventItemValue( void )
\r
4443 TickType_t uxReturn;
\r
4445 uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );
\r
4447 /* Reset the event list item to its normal value - so it can be used with
\r
4448 queues and semaphores. */
\r
4449 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
4453 /*-----------------------------------------------------------*/
\r
4455 #if ( configUSE_MUTEXES == 1 )
\r
4457 TaskHandle_t pvTaskIncrementMutexHeldCount( void )
\r
4459 /* If xSemaphoreCreateMutex() is called before any tasks have been created
\r
4460 then pxCurrentTCB will be NULL. */
\r
4461 if( pxCurrentTCB != NULL )
\r
4463 ( pxCurrentTCB->uxMutexesHeld )++;
\r
4466 return pxCurrentTCB;
\r
4469 #endif /* configUSE_MUTEXES */
\r
4470 /*-----------------------------------------------------------*/
\r
4472 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4474 uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )
\r
4476 uint32_t ulReturn;
\r
4478 taskENTER_CRITICAL();
\r
4480 /* Only block if the notification count is not already non-zero. */
\r
4481 if( pxCurrentTCB->ulNotifiedValue == 0UL )
\r
4483 /* Mark this task as waiting for a notification. */
\r
4484 pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;
\r
4486 if( xTicksToWait > ( TickType_t ) 0 )
\r
4488 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
\r
4489 traceTASK_NOTIFY_TAKE_BLOCK();
\r
4491 /* All ports are written to allow a yield in a critical
\r
4492 section (some will yield immediately, others wait until the
\r
4493 critical section exits) - but it is not something that
\r
4494 application code should ever do. */
\r
4495 portYIELD_WITHIN_API();
\r
4499 mtCOVERAGE_TEST_MARKER();
\r
4504 mtCOVERAGE_TEST_MARKER();
\r
4507 taskEXIT_CRITICAL();
\r
4509 taskENTER_CRITICAL();
\r
4511 traceTASK_NOTIFY_TAKE();
\r
4512 ulReturn = pxCurrentTCB->ulNotifiedValue;
\r
4514 if( ulReturn != 0UL )
\r
4516 if( xClearCountOnExit != pdFALSE )
\r
4518 pxCurrentTCB->ulNotifiedValue = 0UL;
\r
4522 pxCurrentTCB->ulNotifiedValue = ulReturn - ( uint32_t ) 1;
\r
4527 mtCOVERAGE_TEST_MARKER();
\r
4530 pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
\r
4532 taskEXIT_CRITICAL();
\r
4537 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4538 /*-----------------------------------------------------------*/
\r
4540 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4542 BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait )
\r
4544 BaseType_t xReturn;
\r
4546 taskENTER_CRITICAL();
\r
4548 /* Only block if a notification is not already pending. */
\r
4549 if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED )
\r
4551 /* Clear bits in the task's notification value as bits may get
\r
4552 set by the notifying task or interrupt. This can be used to
\r
4553 clear the value to zero. */
\r
4554 pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry;
\r
4556 /* Mark this task as waiting for a notification. */
\r
4557 pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;
\r
4559 if( xTicksToWait > ( TickType_t ) 0 )
\r
4561 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
\r
4562 traceTASK_NOTIFY_WAIT_BLOCK();
\r
4564 /* All ports are written to allow a yield in a critical
\r
4565 section (some will yield immediately, others wait until the
\r
4566 critical section exits) - but it is not something that
\r
4567 application code should ever do. */
\r
4568 portYIELD_WITHIN_API();
\r
4572 mtCOVERAGE_TEST_MARKER();
\r
4577 mtCOVERAGE_TEST_MARKER();
\r
4580 taskEXIT_CRITICAL();
\r
4582 taskENTER_CRITICAL();
\r
4584 traceTASK_NOTIFY_WAIT();
\r
4586 if( pulNotificationValue != NULL )
\r
4588 /* Output the current notification value, which may or may not
\r
4590 *pulNotificationValue = pxCurrentTCB->ulNotifiedValue;
\r
4593 /* If ucNotifyValue is set then either the task never entered the
\r
4594 blocked state (because a notification was already pending) or the
\r
4595 task unblocked because of a notification. Otherwise the task
\r
4596 unblocked because of a timeout. */
\r
4597 if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED )
\r
4599 /* A notification was not received. */
\r
4600 xReturn = pdFALSE;
\r
4604 /* A notification was already pending or a notification was
\r
4605 received while the task was waiting. */
\r
4606 pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnExit;
\r
4610 pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
\r
4612 taskEXIT_CRITICAL();
\r
4617 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4618 /*-----------------------------------------------------------*/
\r
4620 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4622 BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue )
\r
4625 BaseType_t xReturn = pdPASS;
\r
4626 uint8_t ucOriginalNotifyState;
\r
4628 configASSERT( xTaskToNotify );
\r
4629 pxTCB = xTaskToNotify;
\r
4631 taskENTER_CRITICAL();
\r
4633 if( pulPreviousNotificationValue != NULL )
\r
4635 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
\r
4638 ucOriginalNotifyState = pxTCB->ucNotifyState;
\r
4640 pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
\r
4645 pxTCB->ulNotifiedValue |= ulValue;
\r
4649 ( pxTCB->ulNotifiedValue )++;
\r
4652 case eSetValueWithOverwrite :
\r
4653 pxTCB->ulNotifiedValue = ulValue;
\r
4656 case eSetValueWithoutOverwrite :
\r
4657 if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
\r
4659 pxTCB->ulNotifiedValue = ulValue;
\r
4663 /* The value could not be written to the task. */
\r
4669 /* The task is being notified without its notify value being
\r
4674 /* Should not get here if all enums are handled.
\r
4675 Artificially force an assert by testing a value the
\r
4676 compiler can't assume is const. */
\r
4677 configASSERT( pxTCB->ulNotifiedValue == ~0UL );
\r
4682 traceTASK_NOTIFY();
\r
4684 /* If the task is in the blocked state specifically to wait for a
\r
4685 notification then unblock it now. */
\r
4686 if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
\r
4688 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
4689 prvAddTaskToReadyList( pxTCB );
\r
4691 /* The task should not have been on an event list. */
\r
4692 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
\r
4694 #if( configUSE_TICKLESS_IDLE != 0 )
\r
4696 /* If a task is blocked waiting for a notification then
\r
4697 xNextTaskUnblockTime might be set to the blocked task's time
\r
4698 out time. If the task is unblocked for a reason other than
\r
4699 a timeout xNextTaskUnblockTime is normally left unchanged,
\r
4700 because it will automatically get reset to a new value when
\r
4701 the tick count equals xNextTaskUnblockTime. However if
\r
4702 tickless idling is used it might be more important to enter
\r
4703 sleep mode at the earliest possible time - so reset
\r
4704 xNextTaskUnblockTime here to ensure it is updated at the
\r
4705 earliest possible time. */
\r
4706 prvResetNextTaskUnblockTime();
\r
4710 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
4712 /* The notified task has a priority above the currently
\r
4713 executing task so a yield is required. */
\r
4714 taskYIELD_IF_USING_PREEMPTION();
\r
4718 mtCOVERAGE_TEST_MARKER();
\r
4723 mtCOVERAGE_TEST_MARKER();
\r
4726 taskEXIT_CRITICAL();
\r
4731 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4732 /*-----------------------------------------------------------*/
\r
4734 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4736 BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken )
\r
4739 uint8_t ucOriginalNotifyState;
\r
4740 BaseType_t xReturn = pdPASS;
\r
4741 UBaseType_t uxSavedInterruptStatus;
\r
4743 configASSERT( xTaskToNotify );
\r
4745 /* RTOS ports that support interrupt nesting have the concept of a
\r
4746 maximum system call (or maximum API call) interrupt priority.
\r
4747 Interrupts that are above the maximum system call priority are keep
\r
4748 permanently enabled, even when the RTOS kernel is in a critical section,
\r
4749 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
4750 is defined in FreeRTOSConfig.h then
\r
4751 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
4752 failure if a FreeRTOS API function is called from an interrupt that has
\r
4753 been assigned a priority above the configured maximum system call
\r
4754 priority. Only FreeRTOS functions that end in FromISR can be called
\r
4755 from interrupts that have been assigned a priority at or (logically)
\r
4756 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
4757 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
4758 simple as possible. More information (albeit Cortex-M specific) is
\r
4759 provided on the following link:
\r
4760 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
4761 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
4763 pxTCB = xTaskToNotify;
\r
4765 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
4767 if( pulPreviousNotificationValue != NULL )
\r
4769 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
\r
4772 ucOriginalNotifyState = pxTCB->ucNotifyState;
\r
4773 pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
\r
4778 pxTCB->ulNotifiedValue |= ulValue;
\r
4782 ( pxTCB->ulNotifiedValue )++;
\r
4785 case eSetValueWithOverwrite :
\r
4786 pxTCB->ulNotifiedValue = ulValue;
\r
4789 case eSetValueWithoutOverwrite :
\r
4790 if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
\r
4792 pxTCB->ulNotifiedValue = ulValue;
\r
4796 /* The value could not be written to the task. */
\r
4802 /* The task is being notified without its notify value being
\r
4807 /* Should not get here if all enums are handled.
\r
4808 Artificially force an assert by testing a value the
\r
4809 compiler can't assume is const. */
\r
4810 configASSERT( pxTCB->ulNotifiedValue == ~0UL );
\r
4814 traceTASK_NOTIFY_FROM_ISR();
\r
4816 /* If the task is in the blocked state specifically to wait for a
\r
4817 notification then unblock it now. */
\r
4818 if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
\r
4820 /* The task should not have been on an event list. */
\r
4821 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
\r
4823 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
4825 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
4826 prvAddTaskToReadyList( pxTCB );
\r
4830 /* The delayed and ready lists cannot be accessed, so hold
\r
4831 this task pending until the scheduler is resumed. */
\r
4832 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
4835 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
4837 /* The notified task has a priority above the currently
\r
4838 executing task so a yield is required. */
\r
4839 if( pxHigherPriorityTaskWoken != NULL )
\r
4841 *pxHigherPriorityTaskWoken = pdTRUE;
\r
4844 /* Mark that a yield is pending in case the user is not
\r
4845 using the "xHigherPriorityTaskWoken" parameter to an ISR
\r
4846 safe FreeRTOS function. */
\r
4847 xYieldPending = pdTRUE;
\r
4851 mtCOVERAGE_TEST_MARKER();
\r
4855 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
4860 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4861 /*-----------------------------------------------------------*/
\r
4863 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4865 void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken )
\r
4868 uint8_t ucOriginalNotifyState;
\r
4869 UBaseType_t uxSavedInterruptStatus;
\r
4871 configASSERT( xTaskToNotify );
\r
4873 /* RTOS ports that support interrupt nesting have the concept of a
\r
4874 maximum system call (or maximum API call) interrupt priority.
\r
4875 Interrupts that are above the maximum system call priority are keep
\r
4876 permanently enabled, even when the RTOS kernel is in a critical section,
\r
4877 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
4878 is defined in FreeRTOSConfig.h then
\r
4879 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
4880 failure if a FreeRTOS API function is called from an interrupt that has
\r
4881 been assigned a priority above the configured maximum system call
\r
4882 priority. Only FreeRTOS functions that end in FromISR can be called
\r
4883 from interrupts that have been assigned a priority at or (logically)
\r
4884 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
4885 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
4886 simple as possible. More information (albeit Cortex-M specific) is
\r
4887 provided on the following link:
\r
4888 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
4889 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
4891 pxTCB = xTaskToNotify;
\r
4893 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
4895 ucOriginalNotifyState = pxTCB->ucNotifyState;
\r
4896 pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
\r
4898 /* 'Giving' is equivalent to incrementing a count in a counting
\r
4900 ( pxTCB->ulNotifiedValue )++;
\r
4902 traceTASK_NOTIFY_GIVE_FROM_ISR();
\r
4904 /* If the task is in the blocked state specifically to wait for a
\r
4905 notification then unblock it now. */
\r
4906 if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
\r
4908 /* The task should not have been on an event list. */
\r
4909 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
\r
4911 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
4913 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
4914 prvAddTaskToReadyList( pxTCB );
\r
4918 /* The delayed and ready lists cannot be accessed, so hold
\r
4919 this task pending until the scheduler is resumed. */
\r
4920 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
4923 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
4925 /* The notified task has a priority above the currently
\r
4926 executing task so a yield is required. */
\r
4927 if( pxHigherPriorityTaskWoken != NULL )
\r
4929 *pxHigherPriorityTaskWoken = pdTRUE;
\r
4932 /* Mark that a yield is pending in case the user is not
\r
4933 using the "xHigherPriorityTaskWoken" parameter in an ISR
\r
4934 safe FreeRTOS function. */
\r
4935 xYieldPending = pdTRUE;
\r
4939 mtCOVERAGE_TEST_MARKER();
\r
4943 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
4946 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4948 /*-----------------------------------------------------------*/
\r
4950 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4952 BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask )
\r
4955 BaseType_t xReturn;
\r
4957 /* If null is passed in here then it is the calling task that is having
\r
4958 its notification state cleared. */
\r
4959 pxTCB = prvGetTCBFromHandle( xTask );
\r
4961 taskENTER_CRITICAL();
\r
4963 if( pxTCB->ucNotifyState == taskNOTIFICATION_RECEIVED )
\r
4965 pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
\r
4973 taskEXIT_CRITICAL();
\r
4978 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4979 /*-----------------------------------------------------------*/
\r
4982 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely )
\r
4984 TickType_t xTimeToWake;
\r
4985 const TickType_t xConstTickCount = xTickCount;
\r
4987 #if( INCLUDE_xTaskAbortDelay == 1 )
\r
4989 /* About to enter a delayed list, so ensure the ucDelayAborted flag is
\r
4990 reset to pdFALSE so it can be detected as having been set to pdTRUE
\r
4991 when the task leaves the Blocked state. */
\r
4992 pxCurrentTCB->ucDelayAborted = pdFALSE;
\r
4996 /* Remove the task from the ready list before adding it to the blocked list
\r
4997 as the same list item is used for both lists. */
\r
4998 if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
5000 /* The current task must be in a ready list, so there is no need to
\r
5001 check, and the port reset macro can be called directly. */
\r
5002 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority ); /*lint !e931 pxCurrentTCB cannot change as it is the calling task. pxCurrentTCB->uxPriority and uxTopReadyPriority cannot change as called with scheduler suspended or in a critical section. */
\r
5006 mtCOVERAGE_TEST_MARKER();
\r
5009 #if ( INCLUDE_vTaskSuspend == 1 )
\r
5011 if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )
\r
5013 /* Add the task to the suspended task list instead of a delayed task
\r
5014 list to ensure it is not woken by a timing event. It will block
\r
5016 vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
5020 /* Calculate the time at which the task should be woken if the event
\r
5021 does not occur. This may overflow but this doesn't matter, the
\r
5022 kernel will manage it correctly. */
\r
5023 xTimeToWake = xConstTickCount + xTicksToWait;
\r
5025 /* The list item will be inserted in wake time order. */
\r
5026 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
\r
5028 if( xTimeToWake < xConstTickCount )
\r
5030 /* Wake time has overflowed. Place this item in the overflow
\r
5032 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
5036 /* The wake time has not overflowed, so the current block list
\r
5038 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
5040 /* If the task entering the blocked state was placed at the
\r
5041 head of the list of blocked tasks then xNextTaskUnblockTime
\r
5042 needs to be updated too. */
\r
5043 if( xTimeToWake < xNextTaskUnblockTime )
\r
5045 xNextTaskUnblockTime = xTimeToWake;
\r
5049 mtCOVERAGE_TEST_MARKER();
\r
5054 #else /* INCLUDE_vTaskSuspend */
\r
5056 /* Calculate the time at which the task should be woken if the event
\r
5057 does not occur. This may overflow but this doesn't matter, the kernel
\r
5058 will manage it correctly. */
\r
5059 xTimeToWake = xConstTickCount + xTicksToWait;
\r
5061 /* The list item will be inserted in wake time order. */
\r
5062 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
\r
5064 if( xTimeToWake < xConstTickCount )
\r
5066 /* Wake time has overflowed. Place this item in the overflow list. */
\r
5067 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
5071 /* The wake time has not overflowed, so the current block list is used. */
\r
5072 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
5074 /* If the task entering the blocked state was placed at the head of the
\r
5075 list of blocked tasks then xNextTaskUnblockTime needs to be updated
\r
5077 if( xTimeToWake < xNextTaskUnblockTime )
\r
5079 xNextTaskUnblockTime = xTimeToWake;
\r
5083 mtCOVERAGE_TEST_MARKER();
\r
5087 /* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */
\r
5088 ( void ) xCanBlockIndefinitely;
\r
5090 #endif /* INCLUDE_vTaskSuspend */
\r
5093 /* Code below here allows additional code to be inserted into this source file,
\r
5094 especially where access to file scope functions and data is needed (for example
\r
5095 when performing module tests). */
\r
5097 #ifdef FREERTOS_MODULE_TEST
\r
5098 #include "tasks_test_access_functions.h"
\r
5102 #if( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 )
\r
5104 #include "freertos_tasks_c_additions.h"
\r
5106 #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
\r
5107 static void freertos_tasks_c_additions_init( void )
\r
5109 FREERTOS_TASKS_C_ADDITIONS_INIT();
\r