2 FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
\r
5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
7 ***************************************************************************
\r
9 * FreeRTOS provides completely free yet professionally developed, *
\r
10 * robust, strictly quality controlled, supported, and cross *
\r
11 * platform software that has become a de facto standard. *
\r
13 * Help yourself get started quickly and support the FreeRTOS *
\r
14 * project by purchasing a FreeRTOS tutorial book, reference *
\r
15 * manual, or both from: http://www.FreeRTOS.org/Documentation *
\r
19 ***************************************************************************
\r
21 This file is part of the FreeRTOS distribution.
\r
23 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
24 the terms of the GNU General Public License (version 2) as published by the
\r
25 Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
\r
27 >>! NOTE: The modification to the GPL is included to allow you to !<<
\r
28 >>! distribute a combined work that includes FreeRTOS without being !<<
\r
29 >>! obliged to provide the source code for proprietary components !<<
\r
30 >>! outside of the FreeRTOS kernel. !<<
\r
32 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
33 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
34 FOR A PARTICULAR PURPOSE. Full license text is available from the following
\r
35 link: http://www.freertos.org/a00114.html
\r
39 ***************************************************************************
\r
41 * Having a problem? Start by reading the FAQ "My application does *
\r
42 * not run, what could be wrong?" *
\r
44 * http://www.FreeRTOS.org/FAQHelp.html *
\r
46 ***************************************************************************
\r
48 http://www.FreeRTOS.org - Documentation, books, training, latest versions,
\r
49 license and Real Time Engineers Ltd. contact details.
\r
51 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
52 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
\r
53 compatible FAT file system, and our tiny thread aware UDP/IP stack.
\r
55 http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
\r
56 Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
\r
57 licenses offer ticketed support, indemnification and middleware.
\r
59 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
60 engineered and independently SIL3 certified version for use in safety and
\r
61 mission critical applications that require provable dependability.
\r
66 /* Standard includes. */
\r
70 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
\r
71 all the API functions to use the MPU wrappers. That should only be done when
\r
72 task.h is included from an application file. */
\r
73 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
75 /* FreeRTOS includes. */
\r
76 #include "FreeRTOS.h"
\r
79 #include "StackMacros.h"
\r
81 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the
\r
82 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
\r
83 header files above, but not in this file, in order to generate the correct
\r
84 privileged Vs unprivileged linkage and placement. */
\r
85 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
\r
87 #if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 )
\r
88 /* At the bottom of this file are two optional functions that can be used
\r
89 to generate human readable text from the raw data generated by the
\r
90 uxTaskGetSystemState() function. Note the formatting functions are provided
\r
91 for convenience only, and are NOT considered part of the kernel. */
\r
93 #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
\r
95 /* Sanity check the configuration. */
\r
96 #if configUSE_TICKLESS_IDLE != 0
\r
97 #if INCLUDE_vTaskSuspend != 1
\r
98 #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0
\r
99 #endif /* INCLUDE_vTaskSuspend */
\r
100 #endif /* configUSE_TICKLESS_IDLE */
\r
103 * Defines the size, in words, of the stack allocated to the idle task.
\r
105 #define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE
\r
107 #if( configUSE_PREEMPTION == 0 )
\r
108 /* If the cooperative scheduler is being used then a yield should not be
\r
109 performed just because a higher priority task has been woken. */
\r
110 #define taskYIELD_IF_USING_PREEMPTION()
\r
112 #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
\r
116 * Task control block. A task control block (TCB) is allocated for each task,
\r
117 * and stores task state information, including a pointer to the task's context
\r
118 * (the task's run time environment, including register values)
\r
120 typedef struct tskTaskControlBlock
\r
122 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
124 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
125 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
128 ListItem_t xGenericListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
\r
129 ListItem_t xEventListItem; /*< Used to reference a task from an event list. */
\r
130 UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */
\r
131 StackType_t *pxStack; /*< Points to the start of the stack. */
\r
132 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
134 #if ( portSTACK_GROWTH > 0 )
\r
135 StackType_t *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */
\r
138 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
139 UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
\r
142 #if ( configUSE_TRACE_FACILITY == 1 )
\r
143 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
144 UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
\r
147 #if ( configUSE_MUTEXES == 1 )
\r
148 UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
\r
149 UBaseType_t uxMutexesHeld;
\r
152 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
153 TaskHookFunction_t pxTaskTag;
\r
156 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
157 uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
\r
160 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
161 /* Allocate a Newlib reent structure that is specific to this task.
\r
162 Note Newlib support has been included by popular demand, but is not
\r
163 used by the FreeRTOS maintainers themselves. FreeRTOS is not
\r
164 responsible for resulting newlib operation. User must be familiar with
\r
165 newlib and must provide system-wide implementations of the necessary
\r
166 stubs. Be warned that (at the time of writing) the current newlib design
\r
167 implements a system-wide malloc() that must be provided with locks. */
\r
168 struct _reent xNewLib_reent;
\r
173 /* The old tskTCB name is maintained above then typedefed to the new TCB_t name
\r
174 below to enable the use of older kernel aware debuggers. */
\r
175 typedef tskTCB TCB_t;
\r
178 * Some kernel aware debuggers require the data the debugger needs access to to
\r
179 * be global, rather than file scope.
\r
181 #ifdef portREMOVE_STATIC_QUALIFIER
\r
185 /*lint -e956 A manual analysis and inspection has been used to determine which
\r
186 static variables must be declared volatile. */
\r
188 PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
\r
190 /* Lists for ready and blocked tasks. --------------------*/
\r
191 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */
\r
192 PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */
\r
193 PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
\r
194 PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */
\r
195 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
196 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
198 #if ( INCLUDE_vTaskDelete == 1 )
\r
200 PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */
\r
201 PRIVILEGED_DATA static volatile UBaseType_t uxTasksDeleted = ( UBaseType_t ) 0U;
\r
205 #if ( INCLUDE_vTaskSuspend == 1 )
\r
207 PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */
\r
211 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
213 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
217 /* Other file private variables. --------------------------------*/
\r
218 PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
\r
219 PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U;
\r
220 PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
\r
221 PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
\r
222 PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U;
\r
223 PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE;
\r
224 PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
\r
225 PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
\r
226 PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = portMAX_DELAY;
\r
228 /* Context switches are held pending while the scheduler is suspended. Also,
\r
229 interrupts must not manipulate the xStateListItem of a TCB, or any of the
\r
230 lists the xStateListItem can be referenced from, if the scheduler is suspended.
\r
231 If an interrupt needs to unblock a task while the scheduler is suspended then it
\r
232 moves the task's event list item into the xPendingReadyList, ready for the
\r
233 kernel to move the task from the pending ready list into the real ready list
\r
234 when the scheduler is unsuspended. The pending ready list itself can only be
\r
235 accessed from a critical section. */
\r
236 PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE;
\r
238 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
240 PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
\r
241 PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */
\r
247 /* Debugging and trace facilities private variables and macros. ------------*/
\r
250 * The value used to fill the stack of a task when the task is created. This
\r
251 * is used purely for checking the high water mark for tasks.
\r
253 #define tskSTACK_FILL_BYTE ( 0xa5U )
\r
256 * Macros used by vListTask to indicate which state a task is in.
\r
258 #define tskBLOCKED_CHAR ( 'B' )
\r
259 #define tskREADY_CHAR ( 'R' )
\r
260 #define tskDELETED_CHAR ( 'D' )
\r
261 #define tskSUSPENDED_CHAR ( 'S' )
\r
263 /*-----------------------------------------------------------*/
\r
265 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
\r
267 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
\r
268 performed in a generic way that is not optimised to any particular
\r
269 microcontroller architecture. */
\r
271 /* uxTopReadyPriority holds the priority of the highest priority ready
\r
273 #define taskRECORD_READY_PRIORITY( uxPriority ) \
\r
275 if( ( uxPriority ) > uxTopReadyPriority ) \
\r
277 uxTopReadyPriority = ( uxPriority ); \
\r
279 } /* taskRECORD_READY_PRIORITY */
\r
281 /*-----------------------------------------------------------*/
\r
283 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
285 /* Find the highest priority queue that contains ready tasks. */ \
\r
286 while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) \
\r
288 configASSERT( uxTopReadyPriority ); \
\r
289 --uxTopReadyPriority; \
\r
292 /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
\r
293 the same priority get an equal share of the processor time. */ \
\r
294 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \
\r
295 } /* taskSELECT_HIGHEST_PRIORITY_TASK */
\r
297 /*-----------------------------------------------------------*/
\r
299 /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
\r
300 they are only required when a port optimised method of task selection is
\r
302 #define taskRESET_READY_PRIORITY( uxPriority )
\r
303 #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
305 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
307 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
\r
308 performed in a way that is tailored to the particular microcontroller
\r
309 architecture being used. */
\r
311 /* A port optimised version is provided. Call the port defined macros. */
\r
312 #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
314 /*-----------------------------------------------------------*/
\r
316 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
318 UBaseType_t uxTopPriority; \
\r
320 /* Find the highest priority queue that contains ready tasks. */ \
\r
321 portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
\r
322 configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
\r
323 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
\r
324 } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
\r
326 /*-----------------------------------------------------------*/
\r
328 /* A port optimised version is provided, call it only if the TCB being reset
\r
329 is being referenced from a ready list. If it is referenced from a delayed
\r
330 or suspended list then it won't be in a ready list. */
\r
331 #define taskRESET_READY_PRIORITY( uxPriority ) \
\r
333 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \
\r
335 portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \
\r
339 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
341 /*-----------------------------------------------------------*/
\r
343 /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
\r
344 count overflows. */
\r
345 #define taskSWITCH_DELAYED_LISTS() \
\r
349 /* The delayed tasks list should be empty when the lists are switched. */ \
\r
350 configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \
\r
352 pxTemp = pxDelayedTaskList; \
\r
353 pxDelayedTaskList = pxOverflowDelayedTaskList; \
\r
354 pxOverflowDelayedTaskList = pxTemp; \
\r
355 xNumOfOverflows++; \
\r
356 prvResetNextTaskUnblockTime(); \
\r
359 /*-----------------------------------------------------------*/
\r
362 * Place the task represented by pxTCB into the appropriate ready list for
\r
363 * the task. It is inserted at the end of the list.
\r
365 #define prvAddTaskToReadyList( pxTCB ) \
\r
366 traceMOVED_TASK_TO_READY_STATE( pxTCB ) \
\r
367 taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
\r
368 vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) )
\r
369 /*-----------------------------------------------------------*/
\r
372 * Several functions take an TaskHandle_t parameter that can optionally be NULL,
\r
373 * where NULL is used to indicate that the handle of the currently executing
\r
374 * task should be used in place of the parameter. This macro simply checks to
\r
375 * see if the parameter is NULL and returns a pointer to the appropriate TCB.
\r
377 #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TCB_t * ) pxCurrentTCB : ( TCB_t * ) ( pxHandle ) )
\r
379 /* The item value of the event list item is normally used to hold the priority
\r
380 of the task to which it belongs (coded to allow it to be held in reverse
\r
381 priority order). However, it is occasionally borrowed for other purposes. It
\r
382 is important its value is not updated due to a task priority change while it is
\r
383 being used for another purpose. The following bit definition is used to inform
\r
384 the scheduler that the value should not be changed - in which case it is the
\r
385 responsibility of whichever module is using the value to ensure it gets set back
\r
386 to its original value when it is released. */
\r
387 #if configUSE_16_BIT_TICKS == 1
\r
388 #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U
\r
390 #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL
\r
393 /* Callback function prototypes. --------------------------*/
\r
394 #if configCHECK_FOR_STACK_OVERFLOW > 0
\r
395 extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName );
\r
398 #if configUSE_TICK_HOOK > 0
\r
399 extern void vApplicationTickHook( void );
\r
402 /* File private functions. --------------------------------*/
\r
405 * Utility to ready a TCB for a given task. Mainly just copies the parameters
\r
406 * into the TCB structure.
\r
408 static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
411 * Utility task that simply returns pdTRUE if the task referenced by xTask is
\r
412 * currently in the Suspended state, or pdFALSE if the task referenced by xTask
\r
413 * is in any other state.
\r
415 #if ( INCLUDE_vTaskSuspend == 1 )
\r
416 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
\r
417 #endif /* INCLUDE_vTaskSuspend */
\r
420 * Utility to ready all the lists used by the scheduler. This is called
\r
421 * automatically upon the creation of the first task.
\r
423 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
\r
426 * The idle task, which as all tasks is implemented as a never ending loop.
\r
427 * The idle task is automatically created and added to the ready lists upon
\r
428 * creation of the first user task.
\r
430 * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
\r
431 * language extensions. The equivalent prototype for this function is:
\r
433 * void prvIdleTask( void *pvParameters );
\r
436 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
\r
439 * Utility to free all memory allocated by the scheduler to hold a TCB,
\r
440 * including the stack pointed to by the TCB.
\r
442 * This does not free memory allocated by the task itself (i.e. memory
\r
443 * allocated by calls to pvPortMalloc from within the tasks application code).
\r
445 #if ( INCLUDE_vTaskDelete == 1 )
\r
447 static void prvDeleteTCB( TCB_t *pxTCB ) PRIVILEGED_FUNCTION;
\r
452 * Used only by the idle task. This checks to see if anything has been placed
\r
453 * in the list of tasks waiting to be deleted. If so the task is cleaned up
\r
454 * and its TCB deleted.
\r
456 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
\r
459 * The currently executing task is entering the Blocked state. Add the task to
\r
460 * either the current or the overflow delayed task list.
\r
462 static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake ) PRIVILEGED_FUNCTION;
\r
465 * Allocates memory from the heap for a TCB and associated stack. Checks the
\r
466 * allocation was successful.
\r
468 static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer ) PRIVILEGED_FUNCTION;
\r
471 * Fills an TaskStatus_t structure with information on each task that is
\r
472 * referenced from the pxList list (which may be a ready list, a delayed list,
\r
473 * a suspended list, etc.).
\r
475 * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
\r
476 * NORMAL APPLICATION CODE.
\r
478 #if ( configUSE_TRACE_FACILITY == 1 )
\r
480 static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;
\r
485 * When a task is created, the stack of the task is filled with a known value.
\r
486 * This function determines the 'high water mark' of the task stack by
\r
487 * determining how much of the stack remains at the original preset value.
\r
489 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
491 static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
\r
496 * Return the amount of time, in ticks, that will pass before the kernel will
\r
497 * next move a task from the Blocked state to the Running state.
\r
499 * This conditional compilation should use inequality to 0, not equality to 1.
\r
500 * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
\r
501 * defined low power mode implementations require configUSE_TICKLESS_IDLE to be
\r
502 * set to a value other than 1.
\r
504 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
506 static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
\r
511 * Set xNextTaskUnblockTime to the time at which the next Blocked state task
\r
512 * will exit the Blocked state.
\r
514 static void prvResetNextTaskUnblockTime( void );
\r
516 /*-----------------------------------------------------------*/
\r
518 BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
520 BaseType_t xReturn;
\r
523 configASSERT( pxTaskCode );
\r
524 configASSERT( ( ( uxPriority & ( ~portPRIVILEGE_BIT ) ) < configMAX_PRIORITIES ) );
\r
526 /* Allocate the memory required by the TCB and stack for the new task,
\r
527 checking that the allocation was successful. */
\r
528 pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer );
\r
530 if( pxNewTCB != NULL )
\r
532 StackType_t *pxTopOfStack;
\r
534 #if( portUSING_MPU_WRAPPERS == 1 )
\r
535 /* Should the task be created in privileged mode? */
\r
536 BaseType_t xRunPrivileged;
\r
537 if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
\r
539 xRunPrivileged = pdTRUE;
\r
543 xRunPrivileged = pdFALSE;
\r
545 uxPriority &= ~portPRIVILEGE_BIT;
\r
546 #endif /* portUSING_MPU_WRAPPERS == 1 */
\r
548 /* Calculate the top of stack address. This depends on whether the
\r
549 stack grows from high memory to low (as per the 80x86) or vice versa.
\r
550 portSTACK_GROWTH is used to make the result positive or negative as
\r
551 required by the port. */
\r
552 #if( portSTACK_GROWTH < 0 )
\r
554 pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( uint16_t ) 1 );
\r
555 pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); /*lint !e923 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. */
\r
557 /* Check the alignment of the calculated top of stack is correct. */
\r
558 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
560 #else /* portSTACK_GROWTH */
\r
562 pxTopOfStack = pxNewTCB->pxStack;
\r
564 /* Check the alignment of the stack buffer is correct. */
\r
565 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
567 /* If we want to use stack checking on architectures that use
\r
568 a positive stack growth direction then we also need to store the
\r
569 other extreme of the stack space. */
\r
570 pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
\r
572 #endif /* portSTACK_GROWTH */
\r
574 /* Setup the newly allocated TCB with the initial state of the task. */
\r
575 prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth );
\r
577 /* Initialize the TCB stack to look as if the task was already running,
\r
578 but had been interrupted by the scheduler. The return address is set
\r
579 to the start of the task function. Once the stack has been initialised
\r
580 the top of stack variable is updated. */
\r
581 #if( portUSING_MPU_WRAPPERS == 1 )
\r
583 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
\r
585 #else /* portUSING_MPU_WRAPPERS */
\r
587 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
\r
589 #endif /* portUSING_MPU_WRAPPERS */
\r
591 if( ( void * ) pxCreatedTask != NULL )
\r
593 /* Pass the TCB out - in an anonymous way. The calling function/
\r
594 task can use this as a handle to delete the task later if
\r
596 *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
\r
600 mtCOVERAGE_TEST_MARKER();
\r
603 /* Ensure interrupts don't access the task lists while they are being
\r
605 taskENTER_CRITICAL();
\r
607 uxCurrentNumberOfTasks++;
\r
608 if( pxCurrentTCB == NULL )
\r
610 /* There are no other tasks, or all the other tasks are in
\r
611 the suspended state - make this the current task. */
\r
612 pxCurrentTCB = pxNewTCB;
\r
614 if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
\r
616 /* This is the first task to be created so do the preliminary
\r
617 initialisation required. We will not recover if this call
\r
618 fails, but we will report the failure. */
\r
619 prvInitialiseTaskLists();
\r
623 mtCOVERAGE_TEST_MARKER();
\r
628 /* If the scheduler is not already running, make this task the
\r
629 current task if it is the highest priority task to be created
\r
631 if( xSchedulerRunning == pdFALSE )
\r
633 if( pxCurrentTCB->uxPriority <= uxPriority )
\r
635 pxCurrentTCB = pxNewTCB;
\r
639 mtCOVERAGE_TEST_MARKER();
\r
644 mtCOVERAGE_TEST_MARKER();
\r
650 #if ( configUSE_TRACE_FACILITY == 1 )
\r
652 /* Add a counter into the TCB for tracing only. */
\r
653 pxNewTCB->uxTCBNumber = uxTaskNumber;
\r
655 #endif /* configUSE_TRACE_FACILITY */
\r
656 traceTASK_CREATE( pxNewTCB );
\r
658 prvAddTaskToReadyList( pxNewTCB );
\r
661 portSETUP_TCB( pxNewTCB );
\r
663 taskEXIT_CRITICAL();
\r
667 xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
\r
668 traceTASK_CREATE_FAILED();
\r
671 if( xReturn == pdPASS )
\r
673 if( xSchedulerRunning != pdFALSE )
\r
675 /* If the created task is of a higher priority than the current task
\r
676 then it should run now. */
\r
677 if( pxCurrentTCB->uxPriority < uxPriority )
\r
679 taskYIELD_IF_USING_PREEMPTION();
\r
683 mtCOVERAGE_TEST_MARKER();
\r
688 mtCOVERAGE_TEST_MARKER();
\r
694 /*-----------------------------------------------------------*/
\r
696 #if ( INCLUDE_vTaskDelete == 1 )
\r
698 void vTaskDelete( TaskHandle_t xTaskToDelete )
\r
702 taskENTER_CRITICAL();
\r
704 /* If null is passed in here then it is the calling task that is
\r
706 pxTCB = prvGetTCBFromHandle( xTaskToDelete );
\r
708 /* Remove task from the ready list and place in the termination list.
\r
709 This will stop the task from be scheduled. The idle task will check
\r
710 the termination list and free up any memory allocated by the
\r
711 scheduler for the TCB and stack. */
\r
712 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
714 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
718 mtCOVERAGE_TEST_MARKER();
\r
721 /* Is the task waiting on an event also? */
\r
722 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
724 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
728 mtCOVERAGE_TEST_MARKER();
\r
731 vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );
\r
733 /* Increment the ucTasksDeleted variable so the idle task knows
\r
734 there is a task that has been deleted and that it should therefore
\r
735 check the xTasksWaitingTermination list. */
\r
738 /* Increment the uxTaskNumberVariable also so kernel aware debuggers
\r
739 can detect that the task lists need re-generating. */
\r
742 traceTASK_DELETE( pxTCB );
\r
744 taskEXIT_CRITICAL();
\r
746 /* Force a reschedule if it is the currently running task that has just
\r
748 if( xSchedulerRunning != pdFALSE )
\r
750 if( pxTCB == pxCurrentTCB )
\r
752 configASSERT( uxSchedulerSuspended == 0 );
\r
754 /* The pre-delete hook is primarily for the Windows simulator,
\r
755 in which Windows specific clean up operations are performed,
\r
756 after which it is not possible to yield away from this task -
\r
757 hence xYieldPending is used to latch that a context switch is
\r
759 portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
\r
760 portYIELD_WITHIN_API();
\r
764 /* Reset the next expected unblock time in case it referred to
\r
765 the task that has just been deleted. */
\r
766 taskENTER_CRITICAL();
\r
768 prvResetNextTaskUnblockTime();
\r
770 taskEXIT_CRITICAL();
\r
775 #endif /* INCLUDE_vTaskDelete */
\r
776 /*-----------------------------------------------------------*/
\r
778 #if ( INCLUDE_vTaskDelayUntil == 1 )
\r
780 void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
\r
782 TickType_t xTimeToWake;
\r
783 BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
\r
785 configASSERT( pxPreviousWakeTime );
\r
786 configASSERT( ( xTimeIncrement > 0U ) );
\r
787 configASSERT( uxSchedulerSuspended == 0 );
\r
791 /* Minor optimisation. The tick count cannot change in this
\r
793 const TickType_t xConstTickCount = xTickCount;
\r
795 /* Generate the tick time at which the task wants to wake. */
\r
796 xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
\r
798 if( xConstTickCount < *pxPreviousWakeTime )
\r
800 /* The tick count has overflowed since this function was
\r
801 lasted called. In this case the only time we should ever
\r
802 actually delay is if the wake time has also overflowed,
\r
803 and the wake time is greater than the tick time. When this
\r
804 is the case it is as if neither time had overflowed. */
\r
805 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
\r
807 xShouldDelay = pdTRUE;
\r
811 mtCOVERAGE_TEST_MARKER();
\r
816 /* The tick time has not overflowed. In this case we will
\r
817 delay if either the wake time has overflowed, and/or the
\r
818 tick time is less than the wake time. */
\r
819 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
\r
821 xShouldDelay = pdTRUE;
\r
825 mtCOVERAGE_TEST_MARKER();
\r
829 /* Update the wake time ready for the next call. */
\r
830 *pxPreviousWakeTime = xTimeToWake;
\r
832 if( xShouldDelay != pdFALSE )
\r
834 traceTASK_DELAY_UNTIL();
\r
836 /* Remove the task from the ready list before adding it to the
\r
837 blocked list as the same list item is used for both lists. */
\r
838 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
840 /* The current task must be in a ready list, so there is
\r
841 no need to check, and the port reset macro can be called
\r
843 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
847 mtCOVERAGE_TEST_MARKER();
\r
850 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
854 mtCOVERAGE_TEST_MARKER();
\r
857 xAlreadyYielded = xTaskResumeAll();
\r
859 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
860 have put ourselves to sleep. */
\r
861 if( xAlreadyYielded == pdFALSE )
\r
863 portYIELD_WITHIN_API();
\r
867 mtCOVERAGE_TEST_MARKER();
\r
871 #endif /* INCLUDE_vTaskDelayUntil */
\r
872 /*-----------------------------------------------------------*/
\r
874 #if ( INCLUDE_vTaskDelay == 1 )
\r
876 void vTaskDelay( const TickType_t xTicksToDelay )
\r
878 TickType_t xTimeToWake;
\r
879 BaseType_t xAlreadyYielded = pdFALSE;
\r
882 /* A delay time of zero just forces a reschedule. */
\r
883 if( xTicksToDelay > ( TickType_t ) 0U )
\r
885 configASSERT( uxSchedulerSuspended == 0 );
\r
890 /* A task that is removed from the event list while the
\r
891 scheduler is suspended will not get placed in the ready
\r
892 list or removed from the blocked list until the scheduler
\r
895 This task cannot be in an event list as it is the currently
\r
898 /* Calculate the time to wake - this may overflow but this is
\r
900 xTimeToWake = xTickCount + xTicksToDelay;
\r
902 /* We must remove ourselves from the ready list before adding
\r
903 ourselves to the blocked list as the same list item is used for
\r
905 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
907 /* The current task must be in a ready list, so there is
\r
908 no need to check, and the port reset macro can be called
\r
910 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
914 mtCOVERAGE_TEST_MARKER();
\r
916 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
918 xAlreadyYielded = xTaskResumeAll();
\r
922 mtCOVERAGE_TEST_MARKER();
\r
925 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
926 have put ourselves to sleep. */
\r
927 if( xAlreadyYielded == pdFALSE )
\r
929 portYIELD_WITHIN_API();
\r
933 mtCOVERAGE_TEST_MARKER();
\r
937 #endif /* INCLUDE_vTaskDelay */
\r
938 /*-----------------------------------------------------------*/
\r
940 #if ( INCLUDE_eTaskGetState == 1 )
\r
942 eTaskState eTaskGetState( TaskHandle_t xTask )
\r
944 eTaskState eReturn;
\r
945 List_t *pxStateList;
\r
946 const TCB_t * const pxTCB = ( TCB_t * ) xTask;
\r
948 configASSERT( pxTCB );
\r
950 if( pxTCB == pxCurrentTCB )
\r
952 /* The task calling this function is querying its own state. */
\r
953 eReturn = eRunning;
\r
957 taskENTER_CRITICAL();
\r
959 pxStateList = ( List_t * ) listLIST_ITEM_CONTAINER( &( pxTCB->xGenericListItem ) );
\r
961 taskEXIT_CRITICAL();
\r
963 if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) )
\r
965 /* The task being queried is referenced from one of the Blocked
\r
967 eReturn = eBlocked;
\r
970 #if ( INCLUDE_vTaskSuspend == 1 )
\r
971 else if( pxStateList == &xSuspendedTaskList )
\r
973 /* The task being queried is referenced from the suspended
\r
974 list. Is it genuinely suspended or is it block
\r
976 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
\r
978 eReturn = eSuspended;
\r
982 eReturn = eBlocked;
\r
987 #if ( INCLUDE_vTaskDelete == 1 )
\r
988 else if( pxStateList == &xTasksWaitingTermination )
\r
990 /* The task being queried is referenced from the deleted
\r
992 eReturn = eDeleted;
\r
998 /* If the task is not in any other state, it must be in the
\r
999 Ready (including pending ready) state. */
\r
1005 } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
\r
1007 #endif /* INCLUDE_eTaskGetState */
\r
1008 /*-----------------------------------------------------------*/
\r
1010 #if ( INCLUDE_uxTaskPriorityGet == 1 )
\r
1012 UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask )
\r
1015 UBaseType_t uxReturn;
\r
1017 taskENTER_CRITICAL();
\r
1019 /* If null is passed in here then we are changing the
\r
1020 priority of the calling function. */
\r
1021 pxTCB = prvGetTCBFromHandle( xTask );
\r
1022 uxReturn = pxTCB->uxPriority;
\r
1024 taskEXIT_CRITICAL();
\r
1029 #endif /* INCLUDE_uxTaskPriorityGet */
\r
1030 /*-----------------------------------------------------------*/
\r
1032 #if ( INCLUDE_vTaskPrioritySet == 1 )
\r
1034 void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )
\r
1037 UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;
\r
1038 BaseType_t xYieldRequired = pdFALSE;
\r
1040 configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
\r
1042 /* Ensure the new priority is valid. */
\r
1043 if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
\r
1045 uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
\r
1049 mtCOVERAGE_TEST_MARKER();
\r
1052 taskENTER_CRITICAL();
\r
1054 /* If null is passed in here then it is the priority of the calling
\r
1055 task that is being changed. */
\r
1056 pxTCB = prvGetTCBFromHandle( xTask );
\r
1058 traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
\r
1060 #if ( configUSE_MUTEXES == 1 )
\r
1062 uxCurrentBasePriority = pxTCB->uxBasePriority;
\r
1066 uxCurrentBasePriority = pxTCB->uxPriority;
\r
1070 if( uxCurrentBasePriority != uxNewPriority )
\r
1072 /* The priority change may have readied a task of higher
\r
1073 priority than the calling task. */
\r
1074 if( uxNewPriority > uxCurrentBasePriority )
\r
1076 if( pxTCB != pxCurrentTCB )
\r
1078 /* The priority of a task other than the currently
\r
1079 running task is being raised. Is the priority being
\r
1080 raised above that of the running task? */
\r
1081 if( uxNewPriority >= pxCurrentTCB->uxPriority )
\r
1083 xYieldRequired = pdTRUE;
\r
1087 mtCOVERAGE_TEST_MARKER();
\r
1092 /* The priority of the running task is being raised,
\r
1093 but the running task must already be the highest
\r
1094 priority task able to run so no yield is required. */
\r
1097 else if( pxTCB == pxCurrentTCB )
\r
1099 /* Setting the priority of the running task down means
\r
1100 there may now be another task of higher priority that
\r
1101 is ready to execute. */
\r
1102 xYieldRequired = pdTRUE;
\r
1106 /* Setting the priority of any other task down does not
\r
1107 require a yield as the running task must be above the
\r
1108 new priority of the task being modified. */
\r
1111 /* Remember the ready list the task might be referenced from
\r
1112 before its uxPriority member is changed so the
\r
1113 taskRESET_READY_PRIORITY() macro can function correctly. */
\r
1114 uxPriorityUsedOnEntry = pxTCB->uxPriority;
\r
1116 #if ( configUSE_MUTEXES == 1 )
\r
1118 /* Only change the priority being used if the task is not
\r
1119 currently using an inherited priority. */
\r
1120 if( pxTCB->uxBasePriority == pxTCB->uxPriority )
\r
1122 pxTCB->uxPriority = uxNewPriority;
\r
1126 mtCOVERAGE_TEST_MARKER();
\r
1129 /* The base priority gets set whatever. */
\r
1130 pxTCB->uxBasePriority = uxNewPriority;
\r
1134 pxTCB->uxPriority = uxNewPriority;
\r
1138 /* Only reset the event list item value if the value is not
\r
1139 being used for anything else. */
\r
1140 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
\r
1142 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
1146 mtCOVERAGE_TEST_MARKER();
\r
1149 /* If the task is in the blocked or suspended list we need do
\r
1150 nothing more than change it's priority variable. However, if
\r
1151 the task is in a ready list it needs to be removed and placed
\r
1152 in the list appropriate to its new priority. */
\r
1153 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
\r
1155 /* The task is currently in its ready list - remove before adding
\r
1156 it to it's new ready list. As we are in a critical section we
\r
1157 can do this even if the scheduler is suspended. */
\r
1158 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
1160 /* It is known that the task is in its ready list so
\r
1161 there is no need to check again and the port level
\r
1162 reset macro can be called directly. */
\r
1163 portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
\r
1167 mtCOVERAGE_TEST_MARKER();
\r
1169 prvAddTaskToReadyList( pxTCB );
\r
1173 mtCOVERAGE_TEST_MARKER();
\r
1176 if( xYieldRequired == pdTRUE )
\r
1178 taskYIELD_IF_USING_PREEMPTION();
\r
1182 mtCOVERAGE_TEST_MARKER();
\r
1185 /* Remove compiler warning about unused variables when the port
\r
1186 optimised task selection is not being used. */
\r
1187 ( void ) uxPriorityUsedOnEntry;
\r
1190 taskEXIT_CRITICAL();
\r
1193 #endif /* INCLUDE_vTaskPrioritySet */
\r
1194 /*-----------------------------------------------------------*/
\r
1196 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1198 void vTaskSuspend( TaskHandle_t xTaskToSuspend )
\r
1202 taskENTER_CRITICAL();
\r
1204 /* If null is passed in here then it is the running task that is
\r
1205 being suspended. */
\r
1206 pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
\r
1208 traceTASK_SUSPEND( pxTCB );
\r
1210 /* Remove task from the ready/delayed list and place in the
\r
1211 suspended list. */
\r
1212 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
1214 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
1218 mtCOVERAGE_TEST_MARKER();
\r
1221 /* Is the task waiting on an event also? */
\r
1222 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
1224 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1228 mtCOVERAGE_TEST_MARKER();
\r
1231 vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) );
\r
1233 taskEXIT_CRITICAL();
\r
1235 if( pxTCB == pxCurrentTCB )
\r
1237 if( xSchedulerRunning != pdFALSE )
\r
1239 /* The current task has just been suspended. */
\r
1240 configASSERT( uxSchedulerSuspended == 0 );
\r
1241 portYIELD_WITHIN_API();
\r
1245 /* The scheduler is not running, but the task that was pointed
\r
1246 to by pxCurrentTCB has just been suspended and pxCurrentTCB
\r
1247 must be adjusted to point to a different task. */
\r
1248 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )
\r
1250 /* No other tasks are ready, so set pxCurrentTCB back to
\r
1251 NULL so when the next task is created pxCurrentTCB will
\r
1252 be set to point to it no matter what its relative priority
\r
1254 pxCurrentTCB = NULL;
\r
1258 vTaskSwitchContext();
\r
1264 if( xSchedulerRunning != pdFALSE )
\r
1266 /* A task other than the currently running task was suspended,
\r
1267 reset the next expected unblock time in case it referred to the
\r
1268 task that is now in the Suspended state. */
\r
1269 taskENTER_CRITICAL();
\r
1271 prvResetNextTaskUnblockTime();
\r
1273 taskEXIT_CRITICAL();
\r
1277 mtCOVERAGE_TEST_MARKER();
\r
1282 #endif /* INCLUDE_vTaskSuspend */
\r
1283 /*-----------------------------------------------------------*/
\r
1285 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1287 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
\r
1289 BaseType_t xReturn = pdFALSE;
\r
1290 const TCB_t * const pxTCB = ( TCB_t * ) xTask;
\r
1292 /* Accesses xPendingReadyList so must be called from a critical
\r
1295 /* It does not make sense to check if the calling task is suspended. */
\r
1296 configASSERT( xTask );
\r
1298 /* Is the task being resumed actually in the suspended list? */
\r
1299 if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
\r
1301 /* Has the task already been resumed from within an ISR? */
\r
1302 if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
\r
1304 /* Is it in the suspended list because it is in the Suspended
\r
1305 state, or because is is blocked with no timeout? */
\r
1306 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )
\r
1312 mtCOVERAGE_TEST_MARKER();
\r
1317 mtCOVERAGE_TEST_MARKER();
\r
1322 mtCOVERAGE_TEST_MARKER();
\r
1326 } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
\r
1328 #endif /* INCLUDE_vTaskSuspend */
\r
1329 /*-----------------------------------------------------------*/
\r
1331 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1333 void vTaskResume( TaskHandle_t xTaskToResume )
\r
1335 TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
\r
1337 /* It does not make sense to resume the calling task. */
\r
1338 configASSERT( xTaskToResume );
\r
1340 /* The parameter cannot be NULL as it is impossible to resume the
\r
1341 currently executing task. */
\r
1342 if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
\r
1344 taskENTER_CRITICAL();
\r
1346 if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE )
\r
1348 traceTASK_RESUME( pxTCB );
\r
1350 /* As we are in a critical section we can access the ready
\r
1351 lists even if the scheduler is suspended. */
\r
1352 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1353 prvAddTaskToReadyList( pxTCB );
\r
1355 /* We may have just resumed a higher priority task. */
\r
1356 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1358 /* This yield may not cause the task just resumed to run,
\r
1359 but will leave the lists in the correct state for the
\r
1361 taskYIELD_IF_USING_PREEMPTION();
\r
1365 mtCOVERAGE_TEST_MARKER();
\r
1370 mtCOVERAGE_TEST_MARKER();
\r
1373 taskEXIT_CRITICAL();
\r
1377 mtCOVERAGE_TEST_MARKER();
\r
1381 #endif /* INCLUDE_vTaskSuspend */
\r
1383 /*-----------------------------------------------------------*/
\r
1385 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
\r
1387 BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
\r
1389 BaseType_t xYieldRequired = pdFALSE;
\r
1390 TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
\r
1391 UBaseType_t uxSavedInterruptStatus;
\r
1393 configASSERT( xTaskToResume );
\r
1395 /* RTOS ports that support interrupt nesting have the concept of a
\r
1396 maximum system call (or maximum API call) interrupt priority.
\r
1397 Interrupts that are above the maximum system call priority are keep
\r
1398 permanently enabled, even when the RTOS kernel is in a critical section,
\r
1399 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
1400 is defined in FreeRTOSConfig.h then
\r
1401 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1402 failure if a FreeRTOS API function is called from an interrupt that has
\r
1403 been assigned a priority above the configured maximum system call
\r
1404 priority. Only FreeRTOS functions that end in FromISR can be called
\r
1405 from interrupts that have been assigned a priority at or (logically)
\r
1406 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
1407 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
1408 simple as possible. More information (albeit Cortex-M specific) is
\r
1409 provided on the following link:
\r
1410 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1411 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1413 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1415 if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE )
\r
1417 traceTASK_RESUME_FROM_ISR( pxTCB );
\r
1419 /* Check the ready lists can be accessed. */
\r
1420 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
1422 /* Ready lists can be accessed so move the task from the
\r
1423 suspended list to the ready list directly. */
\r
1424 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1426 xYieldRequired = pdTRUE;
\r
1430 mtCOVERAGE_TEST_MARKER();
\r
1433 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1434 prvAddTaskToReadyList( pxTCB );
\r
1438 /* The delayed or ready lists cannot be accessed so the task
\r
1439 is held in the pending ready list until the scheduler is
\r
1441 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
1446 mtCOVERAGE_TEST_MARKER();
\r
1449 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1451 return xYieldRequired;
\r
1454 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
\r
1455 /*-----------------------------------------------------------*/
\r
1457 void vTaskStartScheduler( void )
\r
1459 BaseType_t xReturn;
\r
1461 /* Add the idle task at the lowest priority. */
\r
1462 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
1464 /* Create the idle task, storing its handle in xIdleTaskHandle so it can
\r
1465 be returned by the xTaskGetIdleTaskHandle() function. */
\r
1466 xReturn = xTaskCreate( prvIdleTask, "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
\r
1470 /* Create the idle task without storing its handle. */
\r
1471 xReturn = xTaskCreate( prvIdleTask, "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), NULL ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
\r
1473 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
\r
1475 #if ( configUSE_TIMERS == 1 )
\r
1477 if( xReturn == pdPASS )
\r
1479 xReturn = xTimerCreateTimerTask();
\r
1483 mtCOVERAGE_TEST_MARKER();
\r
1486 #endif /* configUSE_TIMERS */
\r
1488 if( xReturn == pdPASS )
\r
1490 /* Interrupts are turned off here, to ensure a tick does not occur
\r
1491 before or during the call to xPortStartScheduler(). The stacks of
\r
1492 the created tasks contain a status word with interrupts switched on
\r
1493 so interrupts will automatically get re-enabled when the first task
\r
1495 portDISABLE_INTERRUPTS();
\r
1497 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
1499 /* Switch Newlib's _impure_ptr variable to point to the _reent
\r
1500 structure specific to the task that will run first. */
\r
1501 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
\r
1503 #endif /* configUSE_NEWLIB_REENTRANT */
\r
1505 xSchedulerRunning = pdTRUE;
\r
1506 xTickCount = ( TickType_t ) 0U;
\r
1508 /* If configGENERATE_RUN_TIME_STATS is defined then the following
\r
1509 macro must be defined to configure the timer/counter used to generate
\r
1510 the run time counter time base. */
\r
1511 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
\r
1513 /* Setting up the timer tick is hardware specific and thus in the
\r
1514 portable interface. */
\r
1515 if( xPortStartScheduler() != pdFALSE )
\r
1517 /* Should not reach here as if the scheduler is running the
\r
1518 function will not return. */
\r
1522 /* Should only reach here if a task calls xTaskEndScheduler(). */
\r
1527 /* This line will only be reached if the kernel could not be started,
\r
1528 because there was not enough FreeRTOS heap to create the idle task
\r
1529 or the timer task. */
\r
1530 configASSERT( xReturn );
\r
1533 /*-----------------------------------------------------------*/
\r
1535 void vTaskEndScheduler( void )
\r
1537 /* Stop the scheduler interrupts and call the portable scheduler end
\r
1538 routine so the original ISRs can be restored if necessary. The port
\r
1539 layer must ensure interrupts enable bit is left in the correct state. */
\r
1540 portDISABLE_INTERRUPTS();
\r
1541 xSchedulerRunning = pdFALSE;
\r
1542 vPortEndScheduler();
\r
1544 /*----------------------------------------------------------*/
\r
1546 void vTaskSuspendAll( void )
\r
1548 /* A critical section is not required as the variable is of type
\r
1549 BaseType_t. Please read Richard Barry's reply in the following link to a
\r
1550 post in the FreeRTOS support forum before reporting this as a bug! -
\r
1551 http://goo.gl/wu4acr */
\r
1552 ++uxSchedulerSuspended;
\r
1554 /*----------------------------------------------------------*/
\r
1556 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
1558 static TickType_t prvGetExpectedIdleTime( void )
\r
1560 TickType_t xReturn;
\r
1562 if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
\r
1566 else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
\r
1568 /* There are other idle priority tasks in the ready state. If
\r
1569 time slicing is used then the very next tick interrupt must be
\r
1575 xReturn = xNextTaskUnblockTime - xTickCount;
\r
1581 #endif /* configUSE_TICKLESS_IDLE */
\r
1582 /*----------------------------------------------------------*/
\r
1584 BaseType_t xTaskResumeAll( void )
\r
1587 BaseType_t xAlreadyYielded = pdFALSE;
\r
1589 /* If uxSchedulerSuspended is zero then this function does not match a
\r
1590 previous call to vTaskSuspendAll(). */
\r
1591 configASSERT( uxSchedulerSuspended );
\r
1593 /* It is possible that an ISR caused a task to be removed from an event
\r
1594 list while the scheduler was suspended. If this was the case then the
\r
1595 removed task will have been added to the xPendingReadyList. Once the
\r
1596 scheduler has been resumed it is safe to move all the pending ready
\r
1597 tasks from this list into their appropriate ready list. */
\r
1598 taskENTER_CRITICAL();
\r
1600 --uxSchedulerSuspended;
\r
1602 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
1604 if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )
\r
1606 /* Move any readied tasks from the pending list into the
\r
1607 appropriate ready list. */
\r
1608 while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
\r
1610 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );
\r
1611 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1612 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1613 prvAddTaskToReadyList( pxTCB );
\r
1615 /* If we have moved a task that has a priority higher than
\r
1616 the current task then we should yield. */
\r
1617 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1619 xYieldPending = pdTRUE;
\r
1623 mtCOVERAGE_TEST_MARKER();
\r
1627 /* If any ticks occurred while the scheduler was suspended then
\r
1628 they should be processed now. This ensures the tick count does
\r
1629 not slip, and that any delayed tasks are resumed at the correct
\r
1631 if( uxPendedTicks > ( UBaseType_t ) 0U )
\r
1633 while( uxPendedTicks > ( UBaseType_t ) 0U )
\r
1635 if( xTaskIncrementTick() != pdFALSE )
\r
1637 xYieldPending = pdTRUE;
\r
1641 mtCOVERAGE_TEST_MARKER();
\r
1648 mtCOVERAGE_TEST_MARKER();
\r
1651 if( xYieldPending == pdTRUE )
\r
1653 #if( configUSE_PREEMPTION != 0 )
\r
1655 xAlreadyYielded = pdTRUE;
\r
1658 taskYIELD_IF_USING_PREEMPTION();
\r
1662 mtCOVERAGE_TEST_MARKER();
\r
1668 mtCOVERAGE_TEST_MARKER();
\r
1671 taskEXIT_CRITICAL();
\r
1673 return xAlreadyYielded;
\r
1675 /*-----------------------------------------------------------*/
\r
1677 TickType_t xTaskGetTickCount( void )
\r
1679 TickType_t xTicks;
\r
1681 /* Critical section required if running on a 16 bit processor. */
\r
1682 taskENTER_CRITICAL();
\r
1684 xTicks = xTickCount;
\r
1686 taskEXIT_CRITICAL();
\r
1690 /*-----------------------------------------------------------*/
\r
1692 TickType_t xTaskGetTickCountFromISR( void )
\r
1694 TickType_t xReturn;
\r
1695 UBaseType_t uxSavedInterruptStatus;
\r
1697 /* RTOS ports that support interrupt nesting have the concept of a maximum
\r
1698 system call (or maximum API call) interrupt priority. Interrupts that are
\r
1699 above the maximum system call priority are kept permanently enabled, even
\r
1700 when the RTOS kernel is in a critical section, but cannot make any calls to
\r
1701 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
\r
1702 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1703 failure if a FreeRTOS API function is called from an interrupt that has been
\r
1704 assigned a priority above the configured maximum system call priority.
\r
1705 Only FreeRTOS functions that end in FromISR can be called from interrupts
\r
1706 that have been assigned a priority at or (logically) below the maximum
\r
1707 system call interrupt priority. FreeRTOS maintains a separate interrupt
\r
1708 safe API to ensure interrupt entry is as fast and as simple as possible.
\r
1709 More information (albeit Cortex-M specific) is provided on the following
\r
1710 link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1711 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1713 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1715 xReturn = xTickCount;
\r
1717 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1721 /*-----------------------------------------------------------*/
\r
1723 UBaseType_t uxTaskGetNumberOfTasks( void )
\r
1725 /* A critical section is not required because the variables are of type
\r
1727 return uxCurrentNumberOfTasks;
\r
1729 /*-----------------------------------------------------------*/
\r
1731 #if ( INCLUDE_pcTaskGetTaskName == 1 )
\r
1733 char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
1737 /* If null is passed in here then the name of the calling task is being queried. */
\r
1738 pxTCB = prvGetTCBFromHandle( xTaskToQuery );
\r
1739 configASSERT( pxTCB );
\r
1740 return &( pxTCB->pcTaskName[ 0 ] );
\r
1743 #endif /* INCLUDE_pcTaskGetTaskName */
\r
1744 /*-----------------------------------------------------------*/
\r
1746 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1748 UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime )
\r
1750 UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
\r
1752 vTaskSuspendAll();
\r
1754 /* Is there a space in the array for each task in the system? */
\r
1755 if( uxArraySize >= uxCurrentNumberOfTasks )
\r
1757 /* Fill in an TaskStatus_t structure with information on each
\r
1758 task in the Ready state. */
\r
1762 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
\r
1764 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
1766 /* Fill in an TaskStatus_t structure with information on each
\r
1767 task in the Blocked state. */
\r
1768 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );
\r
1769 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );
\r
1771 #if( INCLUDE_vTaskDelete == 1 )
\r
1773 /* Fill in an TaskStatus_t structure with information on
\r
1774 each task that has been deleted but not yet cleaned up. */
\r
1775 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
\r
1779 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1781 /* Fill in an TaskStatus_t structure with information on
\r
1782 each task in the Suspended state. */
\r
1783 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
\r
1787 #if ( configGENERATE_RUN_TIME_STATS == 1)
\r
1789 if( pulTotalRunTime != NULL )
\r
1791 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
1792 portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
\r
1794 *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
1800 if( pulTotalRunTime != NULL )
\r
1802 *pulTotalRunTime = 0;
\r
1809 mtCOVERAGE_TEST_MARKER();
\r
1812 ( void ) xTaskResumeAll();
\r
1817 #endif /* configUSE_TRACE_FACILITY */
\r
1818 /*----------------------------------------------------------*/
\r
1820 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
1822 TaskHandle_t xTaskGetIdleTaskHandle( void )
\r
1824 /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
\r
1825 started, then xIdleTaskHandle will be NULL. */
\r
1826 configASSERT( ( xIdleTaskHandle != NULL ) );
\r
1827 return xIdleTaskHandle;
\r
1830 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
\r
1831 /*----------------------------------------------------------*/
\r
1833 /* This conditional compilation should use inequality to 0, not equality to 1.
\r
1834 This is to ensure vTaskStepTick() is available when user defined low power mode
\r
1835 implementations require configUSE_TICKLESS_IDLE to be set to a value other than
\r
1837 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
1839 void vTaskStepTick( const TickType_t xTicksToJump )
\r
1841 /* Correct the tick count value after a period during which the tick
\r
1842 was suppressed. Note this does *not* call the tick hook function for
\r
1843 each stepped tick. */
\r
1844 configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
\r
1845 xTickCount += xTicksToJump;
\r
1846 traceINCREASE_TICK_COUNT( xTicksToJump );
\r
1849 #endif /* configUSE_TICKLESS_IDLE */
\r
1850 /*----------------------------------------------------------*/
\r
1852 BaseType_t xTaskIncrementTick( void )
\r
1855 TickType_t xItemValue;
\r
1856 BaseType_t xSwitchRequired = pdFALSE;
\r
1858 /* Called by the portable layer each time a tick interrupt occurs.
\r
1859 Increments the tick then checks to see if the new tick value will cause any
\r
1860 tasks to be unblocked. */
\r
1861 traceTASK_INCREMENT_TICK( xTickCount );
\r
1862 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
1864 /* Increment the RTOS tick, switching the delayed and overflowed
\r
1865 delayed lists if it wraps to 0. */
\r
1869 /* Minor optimisation. The tick count cannot change in this
\r
1871 const TickType_t xConstTickCount = xTickCount;
\r
1873 if( xConstTickCount == ( TickType_t ) 0U )
\r
1875 taskSWITCH_DELAYED_LISTS();
\r
1879 mtCOVERAGE_TEST_MARKER();
\r
1882 /* See if this tick has made a timeout expire. Tasks are stored in
\r
1883 the queue in the order of their wake time - meaning once one task
\r
1884 has been found whose block time has not expired there is no need to
\r
1885 look any further down the list. */
\r
1886 if( xConstTickCount >= xNextTaskUnblockTime )
\r
1890 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
\r
1892 /* The delayed list is empty. Set xNextTaskUnblockTime
\r
1893 to the maximum possible value so it is extremely
\r
1895 if( xTickCount >= xNextTaskUnblockTime ) test will pass
\r
1896 next time through. */
\r
1897 xNextTaskUnblockTime = portMAX_DELAY;
\r
1902 /* The delayed list is not empty, get the value of the
\r
1903 item at the head of the delayed list. This is the time
\r
1904 at which the task at the head of the delayed list must
\r
1905 be removed from the Blocked state. */
\r
1906 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
\r
1907 xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
\r
1909 if( xConstTickCount < xItemValue )
\r
1911 /* It is not time to unblock this item yet, but the
\r
1912 item value is the time at which the task at the head
\r
1913 of the blocked list must be removed from the Blocked
\r
1914 state - so record the item value in
\r
1915 xNextTaskUnblockTime. */
\r
1916 xNextTaskUnblockTime = xItemValue;
\r
1921 mtCOVERAGE_TEST_MARKER();
\r
1924 /* It is time to remove the item from the Blocked state. */
\r
1925 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1927 /* Is the task waiting on an event also? If so remove
\r
1928 it from the event list. */
\r
1929 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
1931 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1935 mtCOVERAGE_TEST_MARKER();
\r
1938 /* Place the unblocked task into the appropriate ready
\r
1940 prvAddTaskToReadyList( pxTCB );
\r
1942 /* A task being unblocked cannot cause an immediate
\r
1943 context switch if preemption is turned off. */
\r
1944 #if ( configUSE_PREEMPTION == 1 )
\r
1946 /* Preemption is on, but a context switch should
\r
1947 only be performed if the unblocked task has a
\r
1948 priority that is equal to or higher than the
\r
1949 currently executing task. */
\r
1950 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1952 xSwitchRequired = pdTRUE;
\r
1956 mtCOVERAGE_TEST_MARKER();
\r
1959 #endif /* configUSE_PREEMPTION */
\r
1965 /* Tasks of equal priority to the currently running task will share
\r
1966 processing time (time slice) if preemption is on, and the application
\r
1967 writer has not explicitly turned time slicing off. */
\r
1968 #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
\r
1970 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )
\r
1972 xSwitchRequired = pdTRUE;
\r
1976 mtCOVERAGE_TEST_MARKER();
\r
1979 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
\r
1981 #if ( configUSE_TICK_HOOK == 1 )
\r
1983 /* Guard against the tick hook being called when the pended tick
\r
1984 count is being unwound (when the scheduler is being unlocked). */
\r
1985 if( uxPendedTicks == ( UBaseType_t ) 0U )
\r
1987 vApplicationTickHook();
\r
1991 mtCOVERAGE_TEST_MARKER();
\r
1994 #endif /* configUSE_TICK_HOOK */
\r
2000 /* The tick hook gets called at regular intervals, even if the
\r
2001 scheduler is locked. */
\r
2002 #if ( configUSE_TICK_HOOK == 1 )
\r
2004 vApplicationTickHook();
\r
2009 #if ( configUSE_PREEMPTION == 1 )
\r
2011 if( xYieldPending != pdFALSE )
\r
2013 xSwitchRequired = pdTRUE;
\r
2017 mtCOVERAGE_TEST_MARKER();
\r
2020 #endif /* configUSE_PREEMPTION */
\r
2022 return xSwitchRequired;
\r
2024 /*-----------------------------------------------------------*/
\r
2026 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2028 void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction )
\r
2032 /* If xTask is NULL then it is the task hook of the calling task that is
\r
2034 if( xTask == NULL )
\r
2036 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2040 xTCB = ( TCB_t * ) xTask;
\r
2043 /* Save the hook function in the TCB. A critical section is required as
\r
2044 the value can be accessed from an interrupt. */
\r
2045 taskENTER_CRITICAL();
\r
2046 xTCB->pxTaskTag = pxHookFunction;
\r
2047 taskEXIT_CRITICAL();
\r
2050 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2051 /*-----------------------------------------------------------*/
\r
2053 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2055 TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
\r
2058 TaskHookFunction_t xReturn;
\r
2060 /* If xTask is NULL then we are setting our own task hook. */
\r
2061 if( xTask == NULL )
\r
2063 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2067 xTCB = ( TCB_t * ) xTask;
\r
2070 /* Save the hook function in the TCB. A critical section is required as
\r
2071 the value can be accessed from an interrupt. */
\r
2072 taskENTER_CRITICAL();
\r
2074 xReturn = xTCB->pxTaskTag;
\r
2076 taskEXIT_CRITICAL();
\r
2081 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2082 /*-----------------------------------------------------------*/
\r
2084 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2086 BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter )
\r
2089 BaseType_t xReturn;
\r
2091 /* If xTask is NULL then we are calling our own task hook. */
\r
2092 if( xTask == NULL )
\r
2094 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2098 xTCB = ( TCB_t * ) xTask;
\r
2101 if( xTCB->pxTaskTag != NULL )
\r
2103 xReturn = xTCB->pxTaskTag( pvParameter );
\r
2113 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2114 /*-----------------------------------------------------------*/
\r
2116 void vTaskSwitchContext( void )
\r
2118 if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )
\r
2120 /* The scheduler is currently suspended - do not allow a context
\r
2122 xYieldPending = pdTRUE;
\r
2126 xYieldPending = pdFALSE;
\r
2127 traceTASK_SWITCHED_OUT();
\r
2129 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
2131 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
2132 portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
\r
2134 ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
2137 /* Add the amount of time the task has been running to the
\r
2138 accumulated time so far. The time the task started running was
\r
2139 stored in ulTaskSwitchedInTime. Note that there is no overflow
\r
2140 protection here so count values are only valid until the timer
\r
2141 overflows. The guard against negative values is to protect
\r
2142 against suspect run time stat counter implementations - which
\r
2143 are provided by the application, not the kernel. */
\r
2144 if( ulTotalRunTime > ulTaskSwitchedInTime )
\r
2146 pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
\r
2150 mtCOVERAGE_TEST_MARKER();
\r
2152 ulTaskSwitchedInTime = ulTotalRunTime;
\r
2154 #endif /* configGENERATE_RUN_TIME_STATS */
\r
2156 /* Check for stack overflow, if configured. */
\r
2157 taskFIRST_CHECK_FOR_STACK_OVERFLOW();
\r
2158 taskSECOND_CHECK_FOR_STACK_OVERFLOW();
\r
2160 /* Select a new task to run using either the generic C or port
\r
2161 optimised asm code. */
\r
2162 taskSELECT_HIGHEST_PRIORITY_TASK();
\r
2163 traceTASK_SWITCHED_IN();
\r
2165 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
2167 /* Switch Newlib's _impure_ptr variable to point to the _reent
\r
2168 structure specific to this task. */
\r
2169 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
\r
2171 #endif /* configUSE_NEWLIB_REENTRANT */
\r
2174 /*-----------------------------------------------------------*/
\r
2176 void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )
\r
2178 TickType_t xTimeToWake;
\r
2180 configASSERT( pxEventList );
\r
2182 /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
\r
2183 SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
\r
2185 /* Place the event list item of the TCB in the appropriate event list.
\r
2186 This is placed in the list in priority order so the highest priority task
\r
2187 is the first to be woken by the event. The queue that contains the event
\r
2188 list is locked, preventing simultaneous access from interrupts. */
\r
2189 vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2191 /* The task must be removed from from the ready list before it is added to
\r
2192 the blocked list as the same list item is used for both lists. Exclusive
\r
2193 access to the ready lists guaranteed because the scheduler is locked. */
\r
2194 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
2196 /* The current task must be in a ready list, so there is no need to
\r
2197 check, and the port reset macro can be called directly. */
\r
2198 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
2202 mtCOVERAGE_TEST_MARKER();
\r
2205 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2207 if( xTicksToWait == portMAX_DELAY )
\r
2209 /* Add the task to the suspended task list instead of a delayed task
\r
2210 list to ensure the task is not woken by a timing event. It will
\r
2211 block indefinitely. */
\r
2212 vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
\r
2216 /* Calculate the time at which the task should be woken if the event
\r
2217 does not occur. This may overflow but this doesn't matter, the
\r
2218 scheduler will handle it. */
\r
2219 xTimeToWake = xTickCount + xTicksToWait;
\r
2220 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
2223 #else /* INCLUDE_vTaskSuspend */
\r
2225 /* Calculate the time at which the task should be woken if the event does
\r
2226 not occur. This may overflow but this doesn't matter, the scheduler
\r
2227 will handle it. */
\r
2228 xTimeToWake = xTickCount + xTicksToWait;
\r
2229 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
2231 #endif /* INCLUDE_vTaskSuspend */
\r
2233 /*-----------------------------------------------------------*/
\r
2235 void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait )
\r
2237 TickType_t xTimeToWake;
\r
2239 configASSERT( pxEventList );
\r
2241 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
\r
2242 the event groups implementation. */
\r
2243 configASSERT( uxSchedulerSuspended != 0 );
\r
2245 /* Store the item value in the event list item. It is safe to access the
\r
2246 event list item here as interrupts won't access the event list item of a
\r
2247 task that is not in the Blocked state. */
\r
2248 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
\r
2250 /* Place the event list item of the TCB at the end of the appropriate event
\r
2251 list. It is safe to access the event list here because it is part of an
\r
2252 event group implementation - and interrupts don't access event groups
\r
2253 directly (instead they access them indirectly by pending function calls to
\r
2254 the task level). */
\r
2255 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2257 /* The task must be removed from the ready list before it is added to the
\r
2258 blocked list. Exclusive access can be assured to the ready list as the
\r
2259 scheduler is locked. */
\r
2260 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
2262 /* The current task must be in a ready list, so there is no need to
\r
2263 check, and the port reset macro can be called directly. */
\r
2264 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
2268 mtCOVERAGE_TEST_MARKER();
\r
2271 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2273 if( xTicksToWait == portMAX_DELAY )
\r
2275 /* Add the task to the suspended task list instead of a delayed task
\r
2276 list to ensure it is not woken by a timing event. It will block
\r
2278 vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
\r
2282 /* Calculate the time at which the task should be woken if the event
\r
2283 does not occur. This may overflow but this doesn't matter, the
\r
2284 kernel will manage it correctly. */
\r
2285 xTimeToWake = xTickCount + xTicksToWait;
\r
2286 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
2289 #else /* INCLUDE_vTaskSuspend */
\r
2291 /* Calculate the time at which the task should be woken if the event does
\r
2292 not occur. This may overflow but this doesn't matter, the kernel
\r
2293 will manage it correctly. */
\r
2294 xTimeToWake = xTickCount + xTicksToWait;
\r
2295 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
2297 #endif /* INCLUDE_vTaskSuspend */
\r
2299 /*-----------------------------------------------------------*/
\r
2301 #if configUSE_TIMERS == 1
\r
2303 void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait )
\r
2305 TickType_t xTimeToWake;
\r
2307 configASSERT( pxEventList );
\r
2309 /* This function should not be called by application code hence the
\r
2310 'Restricted' in its name. It is not part of the public API. It is
\r
2311 designed for use by kernel code, and has special calling requirements -
\r
2312 it should be called from a critical section. */
\r
2315 /* Place the event list item of the TCB in the appropriate event list.
\r
2316 In this case it is assume that this is the only task that is going to
\r
2317 be waiting on this event list, so the faster vListInsertEnd() function
\r
2318 can be used in place of vListInsert. */
\r
2319 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2321 /* We must remove this task from the ready list before adding it to the
\r
2322 blocked list as the same list item is used for both lists. This
\r
2323 function is called form a critical section. */
\r
2324 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
2326 /* The current task must be in a ready list, so there is no need to
\r
2327 check, and the port reset macro can be called directly. */
\r
2328 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
2332 mtCOVERAGE_TEST_MARKER();
\r
2335 /* Calculate the time at which the task should be woken if the event does
\r
2336 not occur. This may overflow but this doesn't matter. */
\r
2337 xTimeToWake = xTickCount + xTicksToWait;
\r
2339 traceTASK_DELAY_UNTIL();
\r
2340 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
2343 #endif /* configUSE_TIMERS */
\r
2344 /*-----------------------------------------------------------*/
\r
2346 BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
\r
2348 TCB_t *pxUnblockedTCB;
\r
2349 BaseType_t xReturn;
\r
2351 /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be
\r
2352 called from a critical section within an ISR. */
\r
2354 /* The event list is sorted in priority order, so the first in the list can
\r
2355 be removed as it is known to be the highest priority. Remove the TCB from
\r
2356 the delayed list, and add it to the ready list.
\r
2358 If an event is for a queue that is locked then this function will never
\r
2359 get called - the lock count on the queue will get modified instead. This
\r
2360 means exclusive access to the event list is guaranteed here.
\r
2362 This function assumes that a check has already been made to ensure that
\r
2363 pxEventList is not empty. */
\r
2364 pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
\r
2365 configASSERT( pxUnblockedTCB );
\r
2366 ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
\r
2368 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
2370 ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
\r
2371 prvAddTaskToReadyList( pxUnblockedTCB );
\r
2375 /* The delayed and ready lists cannot be accessed, so hold this task
\r
2376 pending until the scheduler is resumed. */
\r
2377 vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
\r
2380 if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
2382 /* Return true if the task removed from the event list has a higher
\r
2383 priority than the calling task. This allows the calling task to know if
\r
2384 it should force a context switch now. */
\r
2387 /* Mark that a yield is pending in case the user is not using the
\r
2388 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
\r
2389 xYieldPending = pdTRUE;
\r
2393 xReturn = pdFALSE;
\r
2398 /*-----------------------------------------------------------*/
\r
2400 BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )
\r
2402 TCB_t *pxUnblockedTCB;
\r
2403 BaseType_t xReturn;
\r
2405 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
\r
2406 the event flags implementation. */
\r
2407 configASSERT( uxSchedulerSuspended != pdFALSE );
\r
2409 /* Store the new item value in the event list. */
\r
2410 listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
\r
2412 /* Remove the event list form the event flag. Interrupts do not access
\r
2414 pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem );
\r
2415 configASSERT( pxUnblockedTCB );
\r
2416 ( void ) uxListRemove( pxEventListItem );
\r
2418 /* Remove the task from the delayed list and add it to the ready list. The
\r
2419 scheduler is suspended so interrupts will not be accessing the ready
\r
2421 ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
\r
2422 prvAddTaskToReadyList( pxUnblockedTCB );
\r
2424 if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
2426 /* Return true if the task removed from the event list has
\r
2427 a higher priority than the calling task. This allows
\r
2428 the calling task to know if it should force a context
\r
2432 /* Mark that a yield is pending in case the user is not using the
\r
2433 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
\r
2434 xYieldPending = pdTRUE;
\r
2438 xReturn = pdFALSE;
\r
2443 /*-----------------------------------------------------------*/
\r
2445 void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
\r
2447 configASSERT( pxTimeOut );
\r
2448 pxTimeOut->xOverflowCount = xNumOfOverflows;
\r
2449 pxTimeOut->xTimeOnEntering = xTickCount;
\r
2451 /*-----------------------------------------------------------*/
\r
2453 BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait )
\r
2455 BaseType_t xReturn;
\r
2457 configASSERT( pxTimeOut );
\r
2458 configASSERT( pxTicksToWait );
\r
2460 taskENTER_CRITICAL();
\r
2462 /* Minor optimisation. The tick count cannot change in this block. */
\r
2463 const TickType_t xConstTickCount = xTickCount;
\r
2465 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2466 /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is
\r
2467 the maximum block time then the task should block indefinitely, and
\r
2468 therefore never time out. */
\r
2469 if( *pxTicksToWait == portMAX_DELAY )
\r
2471 xReturn = pdFALSE;
\r
2473 else /* We are not blocking indefinitely, perform the checks below. */
\r
2476 if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
\r
2478 /* The tick count is greater than the time at which vTaskSetTimeout()
\r
2479 was called, but has also overflowed since vTaskSetTimeOut() was called.
\r
2480 It must have wrapped all the way around and gone past us again. This
\r
2481 passed since vTaskSetTimeout() was called. */
\r
2484 else if( ( xConstTickCount - pxTimeOut->xTimeOnEntering ) < *pxTicksToWait )
\r
2486 /* Not a genuine timeout. Adjust parameters for time remaining. */
\r
2487 *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );
\r
2488 vTaskSetTimeOutState( pxTimeOut );
\r
2489 xReturn = pdFALSE;
\r
2496 taskEXIT_CRITICAL();
\r
2500 /*-----------------------------------------------------------*/
\r
2502 void vTaskMissedYield( void )
\r
2504 xYieldPending = pdTRUE;
\r
2506 /*-----------------------------------------------------------*/
\r
2508 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2510 UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )
\r
2512 UBaseType_t uxReturn;
\r
2515 if( xTask != NULL )
\r
2517 pxTCB = ( TCB_t * ) xTask;
\r
2518 uxReturn = pxTCB->uxTaskNumber;
\r
2528 #endif /* configUSE_TRACE_FACILITY */
\r
2529 /*-----------------------------------------------------------*/
\r
2531 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2533 void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle )
\r
2537 if( xTask != NULL )
\r
2539 pxTCB = ( TCB_t * ) xTask;
\r
2540 pxTCB->uxTaskNumber = uxHandle;
\r
2544 #endif /* configUSE_TRACE_FACILITY */
\r
2547 * -----------------------------------------------------------
\r
2549 * ----------------------------------------------------------
\r
2551 * The portTASK_FUNCTION() macro is used to allow port/compiler specific
\r
2552 * language extensions. The equivalent prototype for this function is:
\r
2554 * void prvIdleTask( void *pvParameters );
\r
2557 static portTASK_FUNCTION( prvIdleTask, pvParameters )
\r
2559 /* Stop warnings. */
\r
2560 ( void ) pvParameters;
\r
2564 /* See if any tasks have been deleted. */
\r
2565 prvCheckTasksWaitingTermination();
\r
2567 #if ( configUSE_PREEMPTION == 0 )
\r
2569 /* If we are not using preemption we keep forcing a task switch to
\r
2570 see if any other task has become available. If we are using
\r
2571 preemption we don't need to do this as any task becoming available
\r
2572 will automatically get the processor anyway. */
\r
2575 #endif /* configUSE_PREEMPTION */
\r
2577 #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
\r
2579 /* When using preemption tasks of equal priority will be
\r
2580 timesliced. If a task that is sharing the idle priority is ready
\r
2581 to run then the idle task should yield before the end of the
\r
2584 A critical region is not required here as we are just reading from
\r
2585 the list, and an occasional incorrect value will not matter. If
\r
2586 the ready list at the idle priority contains more than one task
\r
2587 then a task other than the idle task is ready to execute. */
\r
2588 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )
\r
2594 mtCOVERAGE_TEST_MARKER();
\r
2597 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
\r
2599 #if ( configUSE_IDLE_HOOK == 1 )
\r
2601 extern void vApplicationIdleHook( void );
\r
2603 /* Call the user defined function from within the idle task. This
\r
2604 allows the application designer to add background functionality
\r
2605 without the overhead of a separate task.
\r
2606 NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
\r
2607 CALL A FUNCTION THAT MIGHT BLOCK. */
\r
2608 vApplicationIdleHook();
\r
2610 #endif /* configUSE_IDLE_HOOK */
\r
2612 /* This conditional compilation should use inequality to 0, not equality
\r
2613 to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
\r
2614 user defined low power mode implementations require
\r
2615 configUSE_TICKLESS_IDLE to be set to a value other than 1. */
\r
2616 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
2618 TickType_t xExpectedIdleTime;
\r
2620 /* It is not desirable to suspend then resume the scheduler on
\r
2621 each iteration of the idle task. Therefore, a preliminary
\r
2622 test of the expected idle time is performed without the
\r
2623 scheduler suspended. The result here is not necessarily
\r
2625 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
2627 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
2629 vTaskSuspendAll();
\r
2631 /* Now the scheduler is suspended, the expected idle
\r
2632 time can be sampled again, and this time its value can
\r
2634 configASSERT( xNextTaskUnblockTime >= xTickCount );
\r
2635 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
2637 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
2639 traceLOW_POWER_IDLE_BEGIN();
\r
2640 portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
\r
2641 traceLOW_POWER_IDLE_END();
\r
2645 mtCOVERAGE_TEST_MARKER();
\r
2648 ( void ) xTaskResumeAll();
\r
2652 mtCOVERAGE_TEST_MARKER();
\r
2655 #endif /* configUSE_TICKLESS_IDLE */
\r
2658 /*-----------------------------------------------------------*/
\r
2660 #if configUSE_TICKLESS_IDLE != 0
\r
2662 eSleepModeStatus eTaskConfirmSleepModeStatus( void )
\r
2664 eSleepModeStatus eReturn = eStandardSleep;
\r
2666 if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
\r
2668 /* A task was made ready while the scheduler was suspended. */
\r
2669 eReturn = eAbortSleep;
\r
2671 else if( xYieldPending != pdFALSE )
\r
2673 /* A yield was pended while the scheduler was suspended. */
\r
2674 eReturn = eAbortSleep;
\r
2678 #if configUSE_TIMERS == 0
\r
2680 /* The idle task exists in addition to the application tasks. */
\r
2681 const UBaseType_t uxNonApplicationTasks = 1;
\r
2683 /* If timers are not being used and all the tasks are in the
\r
2684 suspended list (which might mean they have an infinite block
\r
2685 time rather than actually being suspended) then it is safe to
\r
2686 turn all clocks off and just wait for external interrupts. */
\r
2687 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
\r
2689 eReturn = eNoTasksWaitingTimeout;
\r
2693 mtCOVERAGE_TEST_MARKER();
\r
2696 #endif /* configUSE_TIMERS */
\r
2701 #endif /* configUSE_TICKLESS_IDLE */
\r
2702 /*-----------------------------------------------------------*/
\r
2704 static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
2708 /* Store the task name in the TCB. */
\r
2709 for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
\r
2711 pxTCB->pcTaskName[ x ] = pcName[ x ];
\r
2713 /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
\r
2714 configMAX_TASK_NAME_LEN characters just in case the memory after the
\r
2715 string is not accessible (extremely unlikely). */
\r
2716 if( pcName[ x ] == 0x00 )
\r
2722 mtCOVERAGE_TEST_MARKER();
\r
2726 /* Ensure the name string is terminated in the case that the string length
\r
2727 was greater or equal to configMAX_TASK_NAME_LEN. */
\r
2728 pxTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
\r
2730 /* This is used as an array index so must ensure it's not too large. First
\r
2731 remove the privilege bit if one is present. */
\r
2732 if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
\r
2734 uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
\r
2738 mtCOVERAGE_TEST_MARKER();
\r
2741 pxTCB->uxPriority = uxPriority;
\r
2742 #if ( configUSE_MUTEXES == 1 )
\r
2744 pxTCB->uxBasePriority = uxPriority;
\r
2745 pxTCB->uxMutexesHeld = 0;
\r
2747 #endif /* configUSE_MUTEXES */
\r
2749 vListInitialiseItem( &( pxTCB->xGenericListItem ) );
\r
2750 vListInitialiseItem( &( pxTCB->xEventListItem ) );
\r
2752 /* Set the pxTCB as a link back from the ListItem_t. This is so we can get
\r
2753 back to the containing TCB from a generic item in a list. */
\r
2754 listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB );
\r
2756 /* Event lists are always in priority order. */
\r
2757 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2758 listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB );
\r
2760 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
2762 pxTCB->uxCriticalNesting = ( UBaseType_t ) 0U;
\r
2764 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
2766 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2768 pxTCB->pxTaskTag = NULL;
\r
2770 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2772 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
2774 pxTCB->ulRunTimeCounter = 0UL;
\r
2776 #endif /* configGENERATE_RUN_TIME_STATS */
\r
2778 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
2780 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth );
\r
2782 #else /* portUSING_MPU_WRAPPERS */
\r
2784 ( void ) xRegions;
\r
2785 ( void ) usStackDepth;
\r
2787 #endif /* portUSING_MPU_WRAPPERS */
\r
2789 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
2791 /* Initialise this task's Newlib reent structure. */
\r
2792 _REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) );
\r
2794 #endif /* configUSE_NEWLIB_REENTRANT */
\r
2796 /*-----------------------------------------------------------*/
\r
2798 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
2800 void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions )
\r
2804 /* If null is passed in here then we are deleting ourselves. */
\r
2805 pxTCB = prvGetTCBFromHandle( xTaskToModify );
\r
2807 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
\r
2810 #endif /* portUSING_MPU_WRAPPERS */
\r
2811 /*-----------------------------------------------------------*/
\r
2813 static void prvInitialiseTaskLists( void )
\r
2815 UBaseType_t uxPriority;
\r
2817 for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
\r
2819 vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
\r
2822 vListInitialise( &xDelayedTaskList1 );
\r
2823 vListInitialise( &xDelayedTaskList2 );
\r
2824 vListInitialise( &xPendingReadyList );
\r
2826 #if ( INCLUDE_vTaskDelete == 1 )
\r
2828 vListInitialise( &xTasksWaitingTermination );
\r
2830 #endif /* INCLUDE_vTaskDelete */
\r
2832 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2834 vListInitialise( &xSuspendedTaskList );
\r
2836 #endif /* INCLUDE_vTaskSuspend */
\r
2838 /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
\r
2840 pxDelayedTaskList = &xDelayedTaskList1;
\r
2841 pxOverflowDelayedTaskList = &xDelayedTaskList2;
\r
2843 /*-----------------------------------------------------------*/
\r
2845 static void prvCheckTasksWaitingTermination( void )
\r
2847 #if ( INCLUDE_vTaskDelete == 1 )
\r
2849 BaseType_t xListIsEmpty;
\r
2851 /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
\r
2852 too often in the idle task. */
\r
2853 while( uxTasksDeleted > ( UBaseType_t ) 0U )
\r
2855 vTaskSuspendAll();
\r
2857 xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
\r
2859 ( void ) xTaskResumeAll();
\r
2861 if( xListIsEmpty == pdFALSE )
\r
2865 taskENTER_CRITICAL();
\r
2867 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
\r
2868 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
2869 --uxCurrentNumberOfTasks;
\r
2872 taskEXIT_CRITICAL();
\r
2874 prvDeleteTCB( pxTCB );
\r
2878 mtCOVERAGE_TEST_MARKER();
\r
2882 #endif /* vTaskDelete */
\r
2884 /*-----------------------------------------------------------*/
\r
2886 static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake )
\r
2888 /* The list item will be inserted in wake time order. */
\r
2889 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
\r
2891 if( xTimeToWake < xTickCount )
\r
2893 /* Wake time has overflowed. Place this item in the overflow list. */
\r
2894 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
\r
2898 /* The wake time has not overflowed, so the current block list is used. */
\r
2899 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
\r
2901 /* If the task entering the blocked state was placed at the head of the
\r
2902 list of blocked tasks then xNextTaskUnblockTime needs to be updated
\r
2904 if( xTimeToWake < xNextTaskUnblockTime )
\r
2906 xNextTaskUnblockTime = xTimeToWake;
\r
2910 mtCOVERAGE_TEST_MARKER();
\r
2914 /*-----------------------------------------------------------*/
\r
2916 static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer )
\r
2920 /* If the stack grows down then allocate the stack then the TCB so the stack
\r
2921 does not grow into the TCB. Likewise if the stack grows up then allocate
\r
2922 the TCB then the stack. */
\r
2923 #if( portSTACK_GROWTH > 0 )
\r
2925 /* Allocate space for the TCB. Where the memory comes from depends on
\r
2926 the implementation of the port malloc function. */
\r
2927 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
\r
2929 if( pxNewTCB != NULL )
\r
2931 /* Allocate space for the stack used by the task being created.
\r
2932 The base of the stack memory stored in the TCB so the task can
\r
2933 be deleted later if required. */
\r
2934 pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2936 if( pxNewTCB->pxStack == NULL )
\r
2938 /* Could not allocate the stack. Delete the allocated TCB. */
\r
2939 vPortFree( pxNewTCB );
\r
2944 #else /* portSTACK_GROWTH */
\r
2946 StackType_t *pxStack;
\r
2948 /* Allocate space for the stack used by the task being created. */
\r
2949 pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2951 if( pxStack != NULL )
\r
2953 /* Allocate space for the TCB. Where the memory comes from depends
\r
2954 on the implementation of the port malloc function. */
\r
2955 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
\r
2957 if( pxNewTCB != NULL )
\r
2959 /* Store the stack location in the TCB. */
\r
2960 pxNewTCB->pxStack = pxStack;
\r
2964 /* The stack cannot be used as the TCB was not created. Free it
\r
2966 vPortFree( pxStack );
\r
2974 #endif /* portSTACK_GROWTH */
\r
2976 if( pxNewTCB != NULL )
\r
2978 /* Avoid dependency on memset() if it is not required. */
\r
2979 #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
2981 /* Just to help debugging. */
\r
2982 ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( StackType_t ) );
\r
2984 #endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */
\r
2989 /*-----------------------------------------------------------*/
\r
2991 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2993 static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )
\r
2995 volatile TCB_t *pxNextTCB, *pxFirstTCB;
\r
2996 UBaseType_t uxTask = 0;
\r
2998 if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
\r
3000 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
\r
3002 /* Populate an TaskStatus_t structure within the
\r
3003 pxTaskStatusArray array for each task that is referenced from
\r
3004 pxList. See the definition of TaskStatus_t in task.h for the
\r
3005 meaning of each TaskStatus_t structure member. */
\r
3008 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
\r
3010 pxTaskStatusArray[ uxTask ].xHandle = ( TaskHandle_t ) pxNextTCB;
\r
3011 pxTaskStatusArray[ uxTask ].pcTaskName = ( const char * ) &( pxNextTCB->pcTaskName [ 0 ] );
\r
3012 pxTaskStatusArray[ uxTask ].xTaskNumber = pxNextTCB->uxTCBNumber;
\r
3013 pxTaskStatusArray[ uxTask ].eCurrentState = eState;
\r
3014 pxTaskStatusArray[ uxTask ].uxCurrentPriority = pxNextTCB->uxPriority;
\r
3016 #if ( INCLUDE_vTaskSuspend == 1 )
\r
3018 /* If the task is in the suspended list then there is a chance
\r
3019 it is actually just blocked indefinitely - so really it should
\r
3020 be reported as being in the Blocked state. */
\r
3021 if( eState == eSuspended )
\r
3023 if( listLIST_ITEM_CONTAINER( &( pxNextTCB->xEventListItem ) ) != NULL )
\r
3025 pxTaskStatusArray[ uxTask ].eCurrentState = eBlocked;
\r
3029 #endif /* INCLUDE_vTaskSuspend */
\r
3031 #if ( configUSE_MUTEXES == 1 )
\r
3033 pxTaskStatusArray[ uxTask ].uxBasePriority = pxNextTCB->uxBasePriority;
\r
3037 pxTaskStatusArray[ uxTask ].uxBasePriority = 0;
\r
3041 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
3043 pxTaskStatusArray[ uxTask ].ulRunTimeCounter = pxNextTCB->ulRunTimeCounter;
\r
3047 pxTaskStatusArray[ uxTask ].ulRunTimeCounter = 0;
\r
3051 #if ( portSTACK_GROWTH > 0 )
\r
3053 pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxEndOfStack );
\r
3057 pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxStack );
\r
3063 } while( pxNextTCB != pxFirstTCB );
\r
3067 mtCOVERAGE_TEST_MARKER();
\r
3073 #endif /* configUSE_TRACE_FACILITY */
\r
3074 /*-----------------------------------------------------------*/
\r
3076 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
3078 static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
\r
3080 uint32_t ulCount = 0U;
\r
3082 while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE )
\r
3084 pucStackByte -= portSTACK_GROWTH;
\r
3088 ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */
\r
3090 return ( uint16_t ) ulCount;
\r
3093 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */
\r
3094 /*-----------------------------------------------------------*/
\r
3096 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
\r
3098 UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
\r
3101 uint8_t *pucEndOfStack;
\r
3102 UBaseType_t uxReturn;
\r
3104 pxTCB = prvGetTCBFromHandle( xTask );
\r
3106 #if portSTACK_GROWTH < 0
\r
3108 pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
\r
3112 pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
\r
3116 uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );
\r
3121 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
\r
3122 /*-----------------------------------------------------------*/
\r
3124 #if ( INCLUDE_vTaskDelete == 1 )
\r
3126 static void prvDeleteTCB( TCB_t *pxTCB )
\r
3128 /* This call is required specifically for the TriCore port. It must be
\r
3129 above the vPortFree() calls. The call is also used by ports/demos that
\r
3130 want to allocate and clean RAM statically. */
\r
3131 portCLEAN_UP_TCB( pxTCB );
\r
3133 /* Free up the memory allocated by the scheduler for the task. It is up
\r
3134 to the task to free any memory allocated at the application level. */
\r
3135 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
3137 _reclaim_reent( &( pxTCB->xNewLib_reent ) );
\r
3139 #endif /* configUSE_NEWLIB_REENTRANT */
\r
3140 vPortFreeAligned( pxTCB->pxStack );
\r
3141 vPortFree( pxTCB );
\r
3144 #endif /* INCLUDE_vTaskDelete */
\r
3145 /*-----------------------------------------------------------*/
\r
3147 static void prvResetNextTaskUnblockTime( void )
\r
3151 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
\r
3153 /* The new current delayed list is empty. Set
\r
3154 xNextTaskUnblockTime to the maximum possible value so it is
\r
3155 extremely unlikely that the
\r
3156 if( xTickCount >= xNextTaskUnblockTime ) test will pass until
\r
3157 there is an item in the delayed list. */
\r
3158 xNextTaskUnblockTime = portMAX_DELAY;
\r
3162 /* The new current delayed list is not empty, get the value of
\r
3163 the item at the head of the delayed list. This is the time at
\r
3164 which the task at the head of the delayed list should be removed
\r
3165 from the Blocked state. */
\r
3166 ( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
\r
3167 xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xGenericListItem ) );
\r
3170 /*-----------------------------------------------------------*/
\r
3172 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
\r
3174 TaskHandle_t xTaskGetCurrentTaskHandle( void )
\r
3176 TaskHandle_t xReturn;
\r
3178 /* A critical section is not required as this is not called from
\r
3179 an interrupt and the current TCB will always be the same for any
\r
3180 individual execution thread. */
\r
3181 xReturn = pxCurrentTCB;
\r
3186 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
\r
3187 /*-----------------------------------------------------------*/
\r
3189 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
3191 BaseType_t xTaskGetSchedulerState( void )
\r
3193 BaseType_t xReturn;
\r
3195 if( xSchedulerRunning == pdFALSE )
\r
3197 xReturn = taskSCHEDULER_NOT_STARTED;
\r
3201 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
3203 xReturn = taskSCHEDULER_RUNNING;
\r
3207 xReturn = taskSCHEDULER_SUSPENDED;
\r
3214 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
\r
3215 /*-----------------------------------------------------------*/
\r
3217 #if ( configUSE_MUTEXES == 1 )
\r
3219 void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
\r
3221 TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
\r
3223 /* If the mutex was given back by an interrupt while the queue was
\r
3224 locked then the mutex holder might now be NULL. */
\r
3225 if( pxMutexHolder != NULL )
\r
3227 if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
\r
3229 /* Adjust the mutex holder state to account for its new
\r
3230 priority. Only reset the event list item value if the value is
\r
3231 not being used for anything else. */
\r
3232 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
\r
3234 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
3238 mtCOVERAGE_TEST_MARKER();
\r
3241 /* If the task being modified is in the ready state it will need to
\r
3242 be moved into a new list. */
\r
3243 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
\r
3245 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
3247 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
3251 mtCOVERAGE_TEST_MARKER();
\r
3254 /* Inherit the priority before being moved into the new list. */
\r
3255 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
3256 prvAddTaskToReadyList( pxTCB );
\r
3260 /* Just inherit the priority. */
\r
3261 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
3264 traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );
\r
3268 mtCOVERAGE_TEST_MARKER();
\r
3273 mtCOVERAGE_TEST_MARKER();
\r
3277 #endif /* configUSE_MUTEXES */
\r
3278 /*-----------------------------------------------------------*/
\r
3280 #if ( configUSE_MUTEXES == 1 )
\r
3282 BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )
\r
3284 TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
\r
3285 BaseType_t xReturn = pdFALSE;
\r
3287 if( pxMutexHolder != NULL )
\r
3289 configASSERT( pxTCB->uxMutexesHeld );
\r
3290 ( pxTCB->uxMutexesHeld )--;
\r
3292 if( pxTCB->uxPriority != pxTCB->uxBasePriority )
\r
3294 /* Only disinherit if no other mutexes are held. */
\r
3295 if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
\r
3297 /* A task can only have an inhertied priority if it holds
\r
3298 the mutex. If the mutex is held by a task then it cannot be
\r
3299 given from an interrupt, and if a mutex is given by the
\r
3300 holding task then it must be the running state task. Remove
\r
3301 the holding task from the ready list. */
\r
3302 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
3304 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
3308 mtCOVERAGE_TEST_MARKER();
\r
3311 /* Disinherit the priority before adding the task into the
\r
3312 new ready list. */
\r
3313 traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
\r
3314 pxTCB->uxPriority = pxTCB->uxBasePriority;
\r
3316 /* Reset the event list item value. It cannot be in use for
\r
3317 any other purpose if this task is running, and it must be
\r
3318 running to give back the mutex. */
\r
3319 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
3320 prvAddTaskToReadyList( pxTCB );
\r
3322 /* Return true to indicate that a context switch is required.
\r
3323 This is only actually required in the corner case whereby
\r
3324 multiple mutexes were held and the mutexes were given back
\r
3325 in an order different to that in which they were taken.
\r
3326 If a context switch did not occur when the first mutex was
\r
3327 returned, even if a task was waiting on it, then a context
\r
3328 switch should occur when the last mutex is returned whether
\r
3329 a task is waiting on it or not. */
\r
3334 mtCOVERAGE_TEST_MARKER();
\r
3339 mtCOVERAGE_TEST_MARKER();
\r
3344 mtCOVERAGE_TEST_MARKER();
\r
3350 #endif /* configUSE_MUTEXES */
\r
3351 /*-----------------------------------------------------------*/
\r
3353 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
3355 void vTaskEnterCritical( void )
\r
3357 portDISABLE_INTERRUPTS();
\r
3359 if( xSchedulerRunning != pdFALSE )
\r
3361 ( pxCurrentTCB->uxCriticalNesting )++;
\r
3363 /* This is not the interrupt safe version of the enter critical
\r
3364 function so assert() if it is being called from an interrupt
\r
3365 context. Only API functions that end in "FromISR" can be used in an
\r
3366 interrupt. Only assert if the critical nesting count is 1 to
\r
3367 protect against recursive calls if the assert function also uses a
\r
3368 critical section. */
\r
3369 if( pxCurrentTCB->uxCriticalNesting == 1 )
\r
3371 portASSERT_IF_IN_ISR();
\r
3377 mtCOVERAGE_TEST_MARKER();
\r
3381 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
3382 /*-----------------------------------------------------------*/
\r
3384 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
3386 void vTaskExitCritical( void )
\r
3388 if( xSchedulerRunning != pdFALSE )
\r
3390 if( pxCurrentTCB->uxCriticalNesting > 0U )
\r
3392 ( pxCurrentTCB->uxCriticalNesting )--;
\r
3394 if( pxCurrentTCB->uxCriticalNesting == 0U )
\r
3396 portENABLE_INTERRUPTS();
\r
3400 mtCOVERAGE_TEST_MARKER();
\r
3405 mtCOVERAGE_TEST_MARKER();
\r
3410 mtCOVERAGE_TEST_MARKER();
\r
3414 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
3415 /*-----------------------------------------------------------*/
\r
3417 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) )
\r
3419 void vTaskList( char * pcWriteBuffer )
\r
3421 TaskStatus_t *pxTaskStatusArray;
\r
3422 volatile UBaseType_t uxArraySize, x;
\r
3428 * This function is provided for convenience only, and is used by many
\r
3429 * of the demo applications. Do not consider it to be part of the
\r
3432 * vTaskList() calls uxTaskGetSystemState(), then formats part of the
\r
3433 * uxTaskGetSystemState() output into a human readable table that
\r
3434 * displays task names, states and stack usage.
\r
3436 * vTaskList() has a dependency on the sprintf() C library function that
\r
3437 * might bloat the code size, use a lot of stack, and provide different
\r
3438 * results on different platforms. An alternative, tiny, third party,
\r
3439 * and limited functionality implementation of sprintf() is provided in
\r
3440 * many of the FreeRTOS/Demo sub-directories in a file called
\r
3441 * printf-stdarg.c (note printf-stdarg.c does not provide a full
\r
3442 * snprintf() implementation!).
\r
3444 * It is recommended that production systems call uxTaskGetSystemState()
\r
3445 * directly to get access to raw stats data, rather than indirectly
\r
3446 * through a call to vTaskList().
\r
3450 /* Make sure the write buffer does not contain a string. */
\r
3451 *pcWriteBuffer = 0x00;
\r
3453 /* Take a snapshot of the number of tasks in case it changes while this
\r
3454 function is executing. */
\r
3455 uxArraySize = uxCurrentNumberOfTasks;
\r
3457 /* Allocate an array index for each task. */
\r
3458 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
\r
3460 if( pxTaskStatusArray != NULL )
\r
3462 /* Generate the (binary) data. */
\r
3463 uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
\r
3465 /* Create a human readable table from the binary data. */
\r
3466 for( x = 0; x < uxArraySize; x++ )
\r
3468 switch( pxTaskStatusArray[ x ].eCurrentState )
\r
3470 case eReady: cStatus = tskREADY_CHAR;
\r
3473 case eBlocked: cStatus = tskBLOCKED_CHAR;
\r
3476 case eSuspended: cStatus = tskSUSPENDED_CHAR;
\r
3479 case eDeleted: cStatus = tskDELETED_CHAR;
\r
3482 default: /* Should not get here, but it is included
\r
3483 to prevent static checking errors. */
\r
3488 sprintf( pcWriteBuffer, "%s\t\t%c\t%u\t%u\t%u\r\n", pxTaskStatusArray[ x ].pcTaskName, cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber );
\r
3489 pcWriteBuffer += strlen( pcWriteBuffer );
\r
3492 /* Free the array again. */
\r
3493 vPortFree( pxTaskStatusArray );
\r
3497 mtCOVERAGE_TEST_MARKER();
\r
3501 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) */
\r
3502 /*----------------------------------------------------------*/
\r
3504 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) )
\r
3506 void vTaskGetRunTimeStats( char *pcWriteBuffer )
\r
3508 TaskStatus_t *pxTaskStatusArray;
\r
3509 volatile UBaseType_t uxArraySize, x;
\r
3510 uint32_t ulTotalTime, ulStatsAsPercentage;
\r
3512 #if( configUSE_TRACE_FACILITY != 1 )
\r
3514 #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats().
\r
3521 * This function is provided for convenience only, and is used by many
\r
3522 * of the demo applications. Do not consider it to be part of the
\r
3525 * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part
\r
3526 * of the uxTaskGetSystemState() output into a human readable table that
\r
3527 * displays the amount of time each task has spent in the Running state
\r
3528 * in both absolute and percentage terms.
\r
3530 * vTaskGetRunTimeStats() has a dependency on the sprintf() C library
\r
3531 * function that might bloat the code size, use a lot of stack, and
\r
3532 * provide different results on different platforms. An alternative,
\r
3533 * tiny, third party, and limited functionality implementation of
\r
3534 * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in
\r
3535 * a file called printf-stdarg.c (note printf-stdarg.c does not provide
\r
3536 * a full snprintf() implementation!).
\r
3538 * It is recommended that production systems call uxTaskGetSystemState()
\r
3539 * directly to get access to raw stats data, rather than indirectly
\r
3540 * through a call to vTaskGetRunTimeStats().
\r
3543 /* Make sure the write buffer does not contain a string. */
\r
3544 *pcWriteBuffer = 0x00;
\r
3546 /* Take a snapshot of the number of tasks in case it changes while this
\r
3547 function is executing. */
\r
3548 uxArraySize = uxCurrentNumberOfTasks;
\r
3550 /* Allocate an array index for each task. */
\r
3551 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
\r
3553 if( pxTaskStatusArray != NULL )
\r
3555 /* Generate the (binary) data. */
\r
3556 uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
\r
3558 /* For percentage calculations. */
\r
3559 ulTotalTime /= 100UL;
\r
3561 /* Avoid divide by zero errors. */
\r
3562 if( ulTotalTime > 0 )
\r
3564 /* Create a human readable table from the binary data. */
\r
3565 for( x = 0; x < uxArraySize; x++ )
\r
3567 /* What percentage of the total run time has the task used?
\r
3568 This will always be rounded down to the nearest integer.
\r
3569 ulTotalRunTimeDiv100 has already been divided by 100. */
\r
3570 ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
\r
3572 if( ulStatsAsPercentage > 0UL )
\r
3574 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
3576 sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
\r
3580 /* sizeof( int ) == sizeof( long ) so a smaller
\r
3581 printf() library can be used. */
\r
3582 sprintf( pcWriteBuffer, "%s\t\t%u\t\t%u%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );
\r
3588 /* If the percentage is zero here then the task has
\r
3589 consumed less than 1% of the total run time. */
\r
3590 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
3592 sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );
\r
3596 /* sizeof( int ) == sizeof( long ) so a smaller
\r
3597 printf() library can be used. */
\r
3598 sprintf( pcWriteBuffer, "%s\t\t%u\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter );
\r
3603 pcWriteBuffer += strlen( pcWriteBuffer );
\r
3608 mtCOVERAGE_TEST_MARKER();
\r
3611 /* Free the array again. */
\r
3612 vPortFree( pxTaskStatusArray );
\r
3616 mtCOVERAGE_TEST_MARKER();
\r
3620 #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) */
\r
3621 /*-----------------------------------------------------------*/
\r
3623 TickType_t uxTaskResetEventItemValue( void )
\r
3625 TickType_t uxReturn;
\r
3627 uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );
\r
3629 /* Reset the event list item to its normal value - so it can be used with
\r
3630 queues and semaphores. */
\r
3631 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
3635 /*-----------------------------------------------------------*/
\r
3637 #if ( configUSE_MUTEXES == 1 )
\r
3639 void *pvTaskIncrementMutexHeldCount( void )
\r
3641 /* If xSemaphoreCreateMutex() is called before any tasks have been created
\r
3642 then pxCurrentTCB will be NULL. */
\r
3643 if( pxCurrentTCB != NULL )
\r
3645 ( pxCurrentTCB->uxMutexesHeld )++;
\r
3648 return pxCurrentTCB;
\r
3651 #endif /* configUSE_MUTEXES */
\r
3653 /*-----------------------------------------------------------*/
\r
3655 #ifdef FREERTOS_MODULE_TEST
\r
3656 #include "tasks_test_access_functions.h"
\r