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 /* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting
\r
88 functions but without including stdio.h here. */
\r
89 #if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 )
\r
90 /* At the bottom of this file are two optional functions that can be used
\r
91 to generate human readable text from the raw data generated by the
\r
92 uxTaskGetSystemState() function. Note the formatting functions are provided
\r
93 for convenience only, and are NOT considered part of the kernel. */
\r
95 #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
\r
97 /* Sanity check the configuration. */
\r
98 #if configUSE_TICKLESS_IDLE != 0
\r
99 #if INCLUDE_vTaskSuspend != 1
\r
100 #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0
\r
101 #endif /* INCLUDE_vTaskSuspend */
\r
102 #endif /* configUSE_TICKLESS_IDLE */
\r
105 * Defines the size, in words, of the stack allocated to the idle task.
\r
107 #define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE
\r
109 #if( configUSE_PREEMPTION == 0 )
\r
110 /* If the cooperative scheduler is being used then a yield should not be
\r
111 performed just because a higher priority task has been woken. */
\r
112 #define taskYIELD_IF_USING_PREEMPTION()
\r
114 #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
\r
118 * Task control block. A task control block (TCB) is allocated for each task,
\r
119 * and stores task state information, including a pointer to the task's context
\r
120 * (the task's run time environment, including register values)
\r
122 typedef struct tskTaskControlBlock
\r
124 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
126 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
127 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
130 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
131 ListItem_t xEventListItem; /*< Used to reference a task from an event list. */
\r
132 UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */
\r
133 StackType_t *pxStack; /*< Points to the start of the stack. */
\r
134 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
136 #if ( portSTACK_GROWTH > 0 )
\r
137 StackType_t *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */
\r
140 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
141 UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
\r
144 #if ( configUSE_TRACE_FACILITY == 1 )
\r
145 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
146 UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
\r
149 #if ( configUSE_MUTEXES == 1 )
\r
150 UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
\r
151 UBaseType_t uxMutexesHeld;
\r
154 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
155 TaskHookFunction_t pxTaskTag;
\r
158 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
159 uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
\r
162 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
163 /* Allocate a Newlib reent structure that is specific to this task.
\r
164 Note Newlib support has been included by popular demand, but is not
\r
165 used by the FreeRTOS maintainers themselves. FreeRTOS is not
\r
166 responsible for resulting newlib operation. User must be familiar with
\r
167 newlib and must provide system-wide implementations of the necessary
\r
168 stubs. Be warned that (at the time of writing) the current newlib design
\r
169 implements a system-wide malloc() that must be provided with locks. */
\r
170 struct _reent xNewLib_reent;
\r
175 /* The old tskTCB name is maintained above then typedefed to the new TCB_t name
\r
176 below to enable the use of older kernel aware debuggers. */
\r
177 typedef tskTCB TCB_t;
\r
180 * Some kernel aware debuggers require the data the debugger needs access to to
\r
181 * be global, rather than file scope.
\r
183 #ifdef portREMOVE_STATIC_QUALIFIER
\r
187 /*lint -e956 A manual analysis and inspection has been used to determine which
\r
188 static variables must be declared volatile. */
\r
190 PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
\r
192 /* Lists for ready and blocked tasks. --------------------*/
\r
193 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */
\r
194 PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */
\r
195 PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
\r
196 PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */
\r
197 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
198 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
200 #if ( INCLUDE_vTaskDelete == 1 )
\r
202 PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */
\r
203 PRIVILEGED_DATA static volatile UBaseType_t uxTasksDeleted = ( UBaseType_t ) 0U;
\r
207 #if ( INCLUDE_vTaskSuspend == 1 )
\r
209 PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */
\r
213 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
215 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
219 /* Other file private variables. --------------------------------*/
\r
220 PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
\r
221 PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U;
\r
222 PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
\r
223 PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
\r
224 PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U;
\r
225 PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE;
\r
226 PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
\r
227 PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
\r
228 PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = portMAX_DELAY;
\r
230 /* Context switches are held pending while the scheduler is suspended. Also,
\r
231 interrupts must not manipulate the xStateListItem of a TCB, or any of the
\r
232 lists the xStateListItem can be referenced from, if the scheduler is suspended.
\r
233 If an interrupt needs to unblock a task while the scheduler is suspended then it
\r
234 moves the task's event list item into the xPendingReadyList, ready for the
\r
235 kernel to move the task from the pending ready list into the real ready list
\r
236 when the scheduler is unsuspended. The pending ready list itself can only be
\r
237 accessed from a critical section. */
\r
238 PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE;
\r
240 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
242 PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
\r
243 PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */
\r
249 /* Debugging and trace facilities private variables and macros. ------------*/
\r
252 * The value used to fill the stack of a task when the task is created. This
\r
253 * is used purely for checking the high water mark for tasks.
\r
255 #define tskSTACK_FILL_BYTE ( 0xa5U )
\r
258 * Macros used by vListTask to indicate which state a task is in.
\r
260 #define tskBLOCKED_CHAR ( 'B' )
\r
261 #define tskREADY_CHAR ( 'R' )
\r
262 #define tskDELETED_CHAR ( 'D' )
\r
263 #define tskSUSPENDED_CHAR ( 'S' )
\r
265 /*-----------------------------------------------------------*/
\r
267 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
\r
269 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
\r
270 performed in a generic way that is not optimised to any particular
\r
271 microcontroller architecture. */
\r
273 /* uxTopReadyPriority holds the priority of the highest priority ready
\r
275 #define taskRECORD_READY_PRIORITY( uxPriority ) \
\r
277 if( ( uxPriority ) > uxTopReadyPriority ) \
\r
279 uxTopReadyPriority = ( uxPriority ); \
\r
281 } /* taskRECORD_READY_PRIORITY */
\r
283 /*-----------------------------------------------------------*/
\r
285 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
287 /* Find the highest priority queue that contains ready tasks. */ \
\r
288 while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) \
\r
290 configASSERT( uxTopReadyPriority ); \
\r
291 --uxTopReadyPriority; \
\r
294 /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
\r
295 the same priority get an equal share of the processor time. */ \
\r
296 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \
\r
297 } /* taskSELECT_HIGHEST_PRIORITY_TASK */
\r
299 /*-----------------------------------------------------------*/
\r
301 /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
\r
302 they are only required when a port optimised method of task selection is
\r
304 #define taskRESET_READY_PRIORITY( uxPriority )
\r
305 #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
307 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
309 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
\r
310 performed in a way that is tailored to the particular microcontroller
\r
311 architecture being used. */
\r
313 /* A port optimised version is provided. Call the port defined macros. */
\r
314 #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
316 /*-----------------------------------------------------------*/
\r
318 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
320 UBaseType_t uxTopPriority; \
\r
322 /* Find the highest priority queue that contains ready tasks. */ \
\r
323 portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
\r
324 configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
\r
325 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
\r
326 } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
\r
328 /*-----------------------------------------------------------*/
\r
330 /* A port optimised version is provided, call it only if the TCB being reset
\r
331 is being referenced from a ready list. If it is referenced from a delayed
\r
332 or suspended list then it won't be in a ready list. */
\r
333 #define taskRESET_READY_PRIORITY( uxPriority ) \
\r
335 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \
\r
337 portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \
\r
341 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
343 /*-----------------------------------------------------------*/
\r
345 /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
\r
346 count overflows. */
\r
347 #define taskSWITCH_DELAYED_LISTS() \
\r
351 /* The delayed tasks list should be empty when the lists are switched. */ \
\r
352 configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \
\r
354 pxTemp = pxDelayedTaskList; \
\r
355 pxDelayedTaskList = pxOverflowDelayedTaskList; \
\r
356 pxOverflowDelayedTaskList = pxTemp; \
\r
357 xNumOfOverflows++; \
\r
358 prvResetNextTaskUnblockTime(); \
\r
361 /*-----------------------------------------------------------*/
\r
364 * Place the task represented by pxTCB into the appropriate ready list for
\r
365 * the task. It is inserted at the end of the list.
\r
367 #define prvAddTaskToReadyList( pxTCB ) \
\r
368 traceMOVED_TASK_TO_READY_STATE( pxTCB ) \
\r
369 taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
\r
370 vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) )
\r
371 /*-----------------------------------------------------------*/
\r
374 * Several functions take an TaskHandle_t parameter that can optionally be NULL,
\r
375 * where NULL is used to indicate that the handle of the currently executing
\r
376 * task should be used in place of the parameter. This macro simply checks to
\r
377 * see if the parameter is NULL and returns a pointer to the appropriate TCB.
\r
379 #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TCB_t * ) pxCurrentTCB : ( TCB_t * ) ( pxHandle ) )
\r
381 /* The item value of the event list item is normally used to hold the priority
\r
382 of the task to which it belongs (coded to allow it to be held in reverse
\r
383 priority order). However, it is occasionally borrowed for other purposes. It
\r
384 is important its value is not updated due to a task priority change while it is
\r
385 being used for another purpose. The following bit definition is used to inform
\r
386 the scheduler that the value should not be changed - in which case it is the
\r
387 responsibility of whichever module is using the value to ensure it gets set back
\r
388 to its original value when it is released. */
\r
389 #if configUSE_16_BIT_TICKS == 1
\r
390 #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U
\r
392 #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL
\r
395 /* Callback function prototypes. --------------------------*/
\r
396 #if configCHECK_FOR_STACK_OVERFLOW > 0
\r
397 extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName );
\r
400 #if configUSE_TICK_HOOK > 0
\r
401 extern void vApplicationTickHook( void );
\r
404 /* File private functions. --------------------------------*/
\r
407 * Utility to ready a TCB for a given task. Mainly just copies the parameters
\r
408 * into the TCB structure.
\r
410 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
413 * Utility task that simply returns pdTRUE if the task referenced by xTask is
\r
414 * currently in the Suspended state, or pdFALSE if the task referenced by xTask
\r
415 * is in any other state.
\r
417 #if ( INCLUDE_vTaskSuspend == 1 )
\r
418 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
\r
419 #endif /* INCLUDE_vTaskSuspend */
\r
422 * Utility to ready all the lists used by the scheduler. This is called
\r
423 * automatically upon the creation of the first task.
\r
425 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
\r
428 * The idle task, which as all tasks is implemented as a never ending loop.
\r
429 * The idle task is automatically created and added to the ready lists upon
\r
430 * creation of the first user task.
\r
432 * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
\r
433 * language extensions. The equivalent prototype for this function is:
\r
435 * void prvIdleTask( void *pvParameters );
\r
438 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
\r
441 * Utility to free all memory allocated by the scheduler to hold a TCB,
\r
442 * including the stack pointed to by the TCB.
\r
444 * This does not free memory allocated by the task itself (i.e. memory
\r
445 * allocated by calls to pvPortMalloc from within the tasks application code).
\r
447 #if ( INCLUDE_vTaskDelete == 1 )
\r
449 static void prvDeleteTCB( TCB_t *pxTCB ) PRIVILEGED_FUNCTION;
\r
454 * Used only by the idle task. This checks to see if anything has been placed
\r
455 * in the list of tasks waiting to be deleted. If so the task is cleaned up
\r
456 * and its TCB deleted.
\r
458 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
\r
461 * The currently executing task is entering the Blocked state. Add the task to
\r
462 * either the current or the overflow delayed task list.
\r
464 static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake ) PRIVILEGED_FUNCTION;
\r
467 * Allocates memory from the heap for a TCB and associated stack. Checks the
\r
468 * allocation was successful.
\r
470 static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer ) PRIVILEGED_FUNCTION;
\r
473 * Fills an TaskStatus_t structure with information on each task that is
\r
474 * referenced from the pxList list (which may be a ready list, a delayed list,
\r
475 * a suspended list, etc.).
\r
477 * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
\r
478 * NORMAL APPLICATION CODE.
\r
480 #if ( configUSE_TRACE_FACILITY == 1 )
\r
482 static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;
\r
487 * When a task is created, the stack of the task is filled with a known value.
\r
488 * This function determines the 'high water mark' of the task stack by
\r
489 * determining how much of the stack remains at the original preset value.
\r
491 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
493 static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
\r
498 * Return the amount of time, in ticks, that will pass before the kernel will
\r
499 * next move a task from the Blocked state to the Running state.
\r
501 * This conditional compilation should use inequality to 0, not equality to 1.
\r
502 * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
\r
503 * defined low power mode implementations require configUSE_TICKLESS_IDLE to be
\r
504 * set to a value other than 1.
\r
506 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
508 static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
\r
513 * Set xNextTaskUnblockTime to the time at which the next Blocked state task
\r
514 * will exit the Blocked state.
\r
516 static void prvResetNextTaskUnblockTime( void );
\r
518 /*-----------------------------------------------------------*/
\r
520 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
522 BaseType_t xReturn;
\r
525 configASSERT( pxTaskCode );
\r
526 configASSERT( ( ( uxPriority & ( ~portPRIVILEGE_BIT ) ) < configMAX_PRIORITIES ) );
\r
528 /* Allocate the memory required by the TCB and stack for the new task,
\r
529 checking that the allocation was successful. */
\r
530 pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer );
\r
532 if( pxNewTCB != NULL )
\r
534 StackType_t *pxTopOfStack;
\r
536 #if( portUSING_MPU_WRAPPERS == 1 )
\r
537 /* Should the task be created in privileged mode? */
\r
538 BaseType_t xRunPrivileged;
\r
539 if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
\r
541 xRunPrivileged = pdTRUE;
\r
545 xRunPrivileged = pdFALSE;
\r
547 uxPriority &= ~portPRIVILEGE_BIT;
\r
548 #endif /* portUSING_MPU_WRAPPERS == 1 */
\r
550 /* Calculate the top of stack address. This depends on whether the
\r
551 stack grows from high memory to low (as per the 80x86) or vice versa.
\r
552 portSTACK_GROWTH is used to make the result positive or negative as
\r
553 required by the port. */
\r
554 #if( portSTACK_GROWTH < 0 )
\r
556 pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( uint16_t ) 1 );
\r
557 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
559 /* Check the alignment of the calculated top of stack is correct. */
\r
560 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
562 #else /* portSTACK_GROWTH */
\r
564 pxTopOfStack = pxNewTCB->pxStack;
\r
566 /* Check the alignment of the stack buffer is correct. */
\r
567 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
569 /* If we want to use stack checking on architectures that use
\r
570 a positive stack growth direction then we also need to store the
\r
571 other extreme of the stack space. */
\r
572 pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
\r
574 #endif /* portSTACK_GROWTH */
\r
576 /* Setup the newly allocated TCB with the initial state of the task. */
\r
577 prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth );
\r
579 /* Initialize the TCB stack to look as if the task was already running,
\r
580 but had been interrupted by the scheduler. The return address is set
\r
581 to the start of the task function. Once the stack has been initialised
\r
582 the top of stack variable is updated. */
\r
583 #if( portUSING_MPU_WRAPPERS == 1 )
\r
585 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
\r
587 #else /* portUSING_MPU_WRAPPERS */
\r
589 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
\r
591 #endif /* portUSING_MPU_WRAPPERS */
\r
593 if( ( void * ) pxCreatedTask != NULL )
\r
595 /* Pass the TCB out - in an anonymous way. The calling function/
\r
596 task can use this as a handle to delete the task later if
\r
598 *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
\r
602 mtCOVERAGE_TEST_MARKER();
\r
605 /* Ensure interrupts don't access the task lists while they are being
\r
607 taskENTER_CRITICAL();
\r
609 uxCurrentNumberOfTasks++;
\r
610 if( pxCurrentTCB == NULL )
\r
612 /* There are no other tasks, or all the other tasks are in
\r
613 the suspended state - make this the current task. */
\r
614 pxCurrentTCB = pxNewTCB;
\r
616 if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
\r
618 /* This is the first task to be created so do the preliminary
\r
619 initialisation required. We will not recover if this call
\r
620 fails, but we will report the failure. */
\r
621 prvInitialiseTaskLists();
\r
625 mtCOVERAGE_TEST_MARKER();
\r
630 /* If the scheduler is not already running, make this task the
\r
631 current task if it is the highest priority task to be created
\r
633 if( xSchedulerRunning == pdFALSE )
\r
635 if( pxCurrentTCB->uxPriority <= uxPriority )
\r
637 pxCurrentTCB = pxNewTCB;
\r
641 mtCOVERAGE_TEST_MARKER();
\r
646 mtCOVERAGE_TEST_MARKER();
\r
652 #if ( configUSE_TRACE_FACILITY == 1 )
\r
654 /* Add a counter into the TCB for tracing only. */
\r
655 pxNewTCB->uxTCBNumber = uxTaskNumber;
\r
657 #endif /* configUSE_TRACE_FACILITY */
\r
658 traceTASK_CREATE( pxNewTCB );
\r
660 prvAddTaskToReadyList( pxNewTCB );
\r
663 portSETUP_TCB( pxNewTCB );
\r
665 taskEXIT_CRITICAL();
\r
669 xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
\r
670 traceTASK_CREATE_FAILED();
\r
673 if( xReturn == pdPASS )
\r
675 if( xSchedulerRunning != pdFALSE )
\r
677 /* If the created task is of a higher priority than the current task
\r
678 then it should run now. */
\r
679 if( pxCurrentTCB->uxPriority < uxPriority )
\r
681 taskYIELD_IF_USING_PREEMPTION();
\r
685 mtCOVERAGE_TEST_MARKER();
\r
690 mtCOVERAGE_TEST_MARKER();
\r
696 /*-----------------------------------------------------------*/
\r
698 #if ( INCLUDE_vTaskDelete == 1 )
\r
700 void vTaskDelete( TaskHandle_t xTaskToDelete )
\r
704 taskENTER_CRITICAL();
\r
706 /* If null is passed in here then it is the calling task that is
\r
708 pxTCB = prvGetTCBFromHandle( xTaskToDelete );
\r
710 /* Remove task from the ready list and place in the termination list.
\r
711 This will stop the task from be scheduled. The idle task will check
\r
712 the termination list and free up any memory allocated by the
\r
713 scheduler for the TCB and stack. */
\r
714 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
716 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
720 mtCOVERAGE_TEST_MARKER();
\r
723 /* Is the task waiting on an event also? */
\r
724 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
726 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
730 mtCOVERAGE_TEST_MARKER();
\r
733 vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );
\r
735 /* Increment the ucTasksDeleted variable so the idle task knows
\r
736 there is a task that has been deleted and that it should therefore
\r
737 check the xTasksWaitingTermination list. */
\r
740 /* Increment the uxTaskNumberVariable also so kernel aware debuggers
\r
741 can detect that the task lists need re-generating. */
\r
744 traceTASK_DELETE( pxTCB );
\r
746 taskEXIT_CRITICAL();
\r
748 /* Force a reschedule if it is the currently running task that has just
\r
750 if( xSchedulerRunning != pdFALSE )
\r
752 if( pxTCB == pxCurrentTCB )
\r
754 configASSERT( uxSchedulerSuspended == 0 );
\r
756 /* The pre-delete hook is primarily for the Windows simulator,
\r
757 in which Windows specific clean up operations are performed,
\r
758 after which it is not possible to yield away from this task -
\r
759 hence xYieldPending is used to latch that a context switch is
\r
761 portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
\r
762 portYIELD_WITHIN_API();
\r
766 /* Reset the next expected unblock time in case it referred to
\r
767 the task that has just been deleted. */
\r
768 taskENTER_CRITICAL();
\r
770 prvResetNextTaskUnblockTime();
\r
772 taskEXIT_CRITICAL();
\r
777 #endif /* INCLUDE_vTaskDelete */
\r
778 /*-----------------------------------------------------------*/
\r
780 #if ( INCLUDE_vTaskDelayUntil == 1 )
\r
782 void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
\r
784 TickType_t xTimeToWake;
\r
785 BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
\r
787 configASSERT( pxPreviousWakeTime );
\r
788 configASSERT( ( xTimeIncrement > 0U ) );
\r
789 configASSERT( uxSchedulerSuspended == 0 );
\r
793 /* Minor optimisation. The tick count cannot change in this
\r
795 const TickType_t xConstTickCount = xTickCount;
\r
797 /* Generate the tick time at which the task wants to wake. */
\r
798 xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
\r
800 if( xConstTickCount < *pxPreviousWakeTime )
\r
802 /* The tick count has overflowed since this function was
\r
803 lasted called. In this case the only time we should ever
\r
804 actually delay is if the wake time has also overflowed,
\r
805 and the wake time is greater than the tick time. When this
\r
806 is the case it is as if neither time had overflowed. */
\r
807 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
\r
809 xShouldDelay = pdTRUE;
\r
813 mtCOVERAGE_TEST_MARKER();
\r
818 /* The tick time has not overflowed. In this case we will
\r
819 delay if either the wake time has overflowed, and/or the
\r
820 tick time is less than the wake time. */
\r
821 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
\r
823 xShouldDelay = pdTRUE;
\r
827 mtCOVERAGE_TEST_MARKER();
\r
831 /* Update the wake time ready for the next call. */
\r
832 *pxPreviousWakeTime = xTimeToWake;
\r
834 if( xShouldDelay != pdFALSE )
\r
836 traceTASK_DELAY_UNTIL();
\r
838 /* Remove the task from the ready list before adding it to the
\r
839 blocked list as the same list item is used for both lists. */
\r
840 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
842 /* The current task must be in a ready list, so there is
\r
843 no need to check, and the port reset macro can be called
\r
845 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
849 mtCOVERAGE_TEST_MARKER();
\r
852 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
856 mtCOVERAGE_TEST_MARKER();
\r
859 xAlreadyYielded = xTaskResumeAll();
\r
861 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
862 have put ourselves to sleep. */
\r
863 if( xAlreadyYielded == pdFALSE )
\r
865 portYIELD_WITHIN_API();
\r
869 mtCOVERAGE_TEST_MARKER();
\r
873 #endif /* INCLUDE_vTaskDelayUntil */
\r
874 /*-----------------------------------------------------------*/
\r
876 #if ( INCLUDE_vTaskDelay == 1 )
\r
878 void vTaskDelay( const TickType_t xTicksToDelay )
\r
880 TickType_t xTimeToWake;
\r
881 BaseType_t xAlreadyYielded = pdFALSE;
\r
884 /* A delay time of zero just forces a reschedule. */
\r
885 if( xTicksToDelay > ( TickType_t ) 0U )
\r
887 configASSERT( uxSchedulerSuspended == 0 );
\r
892 /* A task that is removed from the event list while the
\r
893 scheduler is suspended will not get placed in the ready
\r
894 list or removed from the blocked list until the scheduler
\r
897 This task cannot be in an event list as it is the currently
\r
900 /* Calculate the time to wake - this may overflow but this is
\r
902 xTimeToWake = xTickCount + xTicksToDelay;
\r
904 /* We must remove ourselves from the ready list before adding
\r
905 ourselves to the blocked list as the same list item is used for
\r
907 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
909 /* The current task must be in a ready list, so there is
\r
910 no need to check, and the port reset macro can be called
\r
912 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
916 mtCOVERAGE_TEST_MARKER();
\r
918 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
920 xAlreadyYielded = xTaskResumeAll();
\r
924 mtCOVERAGE_TEST_MARKER();
\r
927 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
928 have put ourselves to sleep. */
\r
929 if( xAlreadyYielded == pdFALSE )
\r
931 portYIELD_WITHIN_API();
\r
935 mtCOVERAGE_TEST_MARKER();
\r
939 #endif /* INCLUDE_vTaskDelay */
\r
940 /*-----------------------------------------------------------*/
\r
942 #if ( INCLUDE_eTaskGetState == 1 )
\r
944 eTaskState eTaskGetState( TaskHandle_t xTask )
\r
946 eTaskState eReturn;
\r
947 List_t *pxStateList;
\r
948 const TCB_t * const pxTCB = ( TCB_t * ) xTask;
\r
950 configASSERT( pxTCB );
\r
952 if( pxTCB == pxCurrentTCB )
\r
954 /* The task calling this function is querying its own state. */
\r
955 eReturn = eRunning;
\r
959 taskENTER_CRITICAL();
\r
961 pxStateList = ( List_t * ) listLIST_ITEM_CONTAINER( &( pxTCB->xGenericListItem ) );
\r
963 taskEXIT_CRITICAL();
\r
965 if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) )
\r
967 /* The task being queried is referenced from one of the Blocked
\r
969 eReturn = eBlocked;
\r
972 #if ( INCLUDE_vTaskSuspend == 1 )
\r
973 else if( pxStateList == &xSuspendedTaskList )
\r
975 /* The task being queried is referenced from the suspended
\r
976 list. Is it genuinely suspended or is it block
\r
978 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
\r
980 eReturn = eSuspended;
\r
984 eReturn = eBlocked;
\r
989 #if ( INCLUDE_vTaskDelete == 1 )
\r
990 else if( pxStateList == &xTasksWaitingTermination )
\r
992 /* The task being queried is referenced from the deleted
\r
994 eReturn = eDeleted;
\r
1000 /* If the task is not in any other state, it must be in the
\r
1001 Ready (including pending ready) state. */
\r
1007 } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
\r
1009 #endif /* INCLUDE_eTaskGetState */
\r
1010 /*-----------------------------------------------------------*/
\r
1012 #if ( INCLUDE_uxTaskPriorityGet == 1 )
\r
1014 UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask )
\r
1017 UBaseType_t uxReturn;
\r
1019 taskENTER_CRITICAL();
\r
1021 /* If null is passed in here then we are changing the
\r
1022 priority of the calling function. */
\r
1023 pxTCB = prvGetTCBFromHandle( xTask );
\r
1024 uxReturn = pxTCB->uxPriority;
\r
1026 taskEXIT_CRITICAL();
\r
1031 #endif /* INCLUDE_uxTaskPriorityGet */
\r
1032 /*-----------------------------------------------------------*/
\r
1034 #if ( INCLUDE_vTaskPrioritySet == 1 )
\r
1036 void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )
\r
1039 UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;
\r
1040 BaseType_t xYieldRequired = pdFALSE;
\r
1042 configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
\r
1044 /* Ensure the new priority is valid. */
\r
1045 if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
\r
1047 uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
\r
1051 mtCOVERAGE_TEST_MARKER();
\r
1054 taskENTER_CRITICAL();
\r
1056 /* If null is passed in here then it is the priority of the calling
\r
1057 task that is being changed. */
\r
1058 pxTCB = prvGetTCBFromHandle( xTask );
\r
1060 traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
\r
1062 #if ( configUSE_MUTEXES == 1 )
\r
1064 uxCurrentBasePriority = pxTCB->uxBasePriority;
\r
1068 uxCurrentBasePriority = pxTCB->uxPriority;
\r
1072 if( uxCurrentBasePriority != uxNewPriority )
\r
1074 /* The priority change may have readied a task of higher
\r
1075 priority than the calling task. */
\r
1076 if( uxNewPriority > uxCurrentBasePriority )
\r
1078 if( pxTCB != pxCurrentTCB )
\r
1080 /* The priority of a task other than the currently
\r
1081 running task is being raised. Is the priority being
\r
1082 raised above that of the running task? */
\r
1083 if( uxNewPriority >= pxCurrentTCB->uxPriority )
\r
1085 xYieldRequired = pdTRUE;
\r
1089 mtCOVERAGE_TEST_MARKER();
\r
1094 /* The priority of the running task is being raised,
\r
1095 but the running task must already be the highest
\r
1096 priority task able to run so no yield is required. */
\r
1099 else if( pxTCB == pxCurrentTCB )
\r
1101 /* Setting the priority of the running task down means
\r
1102 there may now be another task of higher priority that
\r
1103 is ready to execute. */
\r
1104 xYieldRequired = pdTRUE;
\r
1108 /* Setting the priority of any other task down does not
\r
1109 require a yield as the running task must be above the
\r
1110 new priority of the task being modified. */
\r
1113 /* Remember the ready list the task might be referenced from
\r
1114 before its uxPriority member is changed so the
\r
1115 taskRESET_READY_PRIORITY() macro can function correctly. */
\r
1116 uxPriorityUsedOnEntry = pxTCB->uxPriority;
\r
1118 #if ( configUSE_MUTEXES == 1 )
\r
1120 /* Only change the priority being used if the task is not
\r
1121 currently using an inherited priority. */
\r
1122 if( pxTCB->uxBasePriority == pxTCB->uxPriority )
\r
1124 pxTCB->uxPriority = uxNewPriority;
\r
1128 mtCOVERAGE_TEST_MARKER();
\r
1131 /* The base priority gets set whatever. */
\r
1132 pxTCB->uxBasePriority = uxNewPriority;
\r
1136 pxTCB->uxPriority = uxNewPriority;
\r
1140 /* Only reset the event list item value if the value is not
\r
1141 being used for anything else. */
\r
1142 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
\r
1144 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
1148 mtCOVERAGE_TEST_MARKER();
\r
1151 /* If the task is in the blocked or suspended list we need do
\r
1152 nothing more than change it's priority variable. However, if
\r
1153 the task is in a ready list it needs to be removed and placed
\r
1154 in the list appropriate to its new priority. */
\r
1155 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
\r
1157 /* The task is currently in its ready list - remove before adding
\r
1158 it to it's new ready list. As we are in a critical section we
\r
1159 can do this even if the scheduler is suspended. */
\r
1160 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
1162 /* It is known that the task is in its ready list so
\r
1163 there is no need to check again and the port level
\r
1164 reset macro can be called directly. */
\r
1165 portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
\r
1169 mtCOVERAGE_TEST_MARKER();
\r
1171 prvAddTaskToReadyList( pxTCB );
\r
1175 mtCOVERAGE_TEST_MARKER();
\r
1178 if( xYieldRequired == pdTRUE )
\r
1180 taskYIELD_IF_USING_PREEMPTION();
\r
1184 mtCOVERAGE_TEST_MARKER();
\r
1187 /* Remove compiler warning about unused variables when the port
\r
1188 optimised task selection is not being used. */
\r
1189 ( void ) uxPriorityUsedOnEntry;
\r
1192 taskEXIT_CRITICAL();
\r
1195 #endif /* INCLUDE_vTaskPrioritySet */
\r
1196 /*-----------------------------------------------------------*/
\r
1198 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1200 void vTaskSuspend( TaskHandle_t xTaskToSuspend )
\r
1204 taskENTER_CRITICAL();
\r
1206 /* If null is passed in here then it is the running task that is
\r
1207 being suspended. */
\r
1208 pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
\r
1210 traceTASK_SUSPEND( pxTCB );
\r
1212 /* Remove task from the ready/delayed list and place in the
\r
1213 suspended list. */
\r
1214 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
1216 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
1220 mtCOVERAGE_TEST_MARKER();
\r
1223 /* Is the task waiting on an event also? */
\r
1224 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
1226 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1230 mtCOVERAGE_TEST_MARKER();
\r
1233 vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) );
\r
1235 taskEXIT_CRITICAL();
\r
1237 if( pxTCB == pxCurrentTCB )
\r
1239 if( xSchedulerRunning != pdFALSE )
\r
1241 /* The current task has just been suspended. */
\r
1242 configASSERT( uxSchedulerSuspended == 0 );
\r
1243 portYIELD_WITHIN_API();
\r
1247 /* The scheduler is not running, but the task that was pointed
\r
1248 to by pxCurrentTCB has just been suspended and pxCurrentTCB
\r
1249 must be adjusted to point to a different task. */
\r
1250 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )
\r
1252 /* No other tasks are ready, so set pxCurrentTCB back to
\r
1253 NULL so when the next task is created pxCurrentTCB will
\r
1254 be set to point to it no matter what its relative priority
\r
1256 pxCurrentTCB = NULL;
\r
1260 vTaskSwitchContext();
\r
1266 if( xSchedulerRunning != pdFALSE )
\r
1268 /* A task other than the currently running task was suspended,
\r
1269 reset the next expected unblock time in case it referred to the
\r
1270 task that is now in the Suspended state. */
\r
1271 taskENTER_CRITICAL();
\r
1273 prvResetNextTaskUnblockTime();
\r
1275 taskEXIT_CRITICAL();
\r
1279 mtCOVERAGE_TEST_MARKER();
\r
1284 #endif /* INCLUDE_vTaskSuspend */
\r
1285 /*-----------------------------------------------------------*/
\r
1287 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1289 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
\r
1291 BaseType_t xReturn = pdFALSE;
\r
1292 const TCB_t * const pxTCB = ( TCB_t * ) xTask;
\r
1294 /* Accesses xPendingReadyList so must be called from a critical
\r
1297 /* It does not make sense to check if the calling task is suspended. */
\r
1298 configASSERT( xTask );
\r
1300 /* Is the task being resumed actually in the suspended list? */
\r
1301 if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
\r
1303 /* Has the task already been resumed from within an ISR? */
\r
1304 if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
\r
1306 /* Is it in the suspended list because it is in the Suspended
\r
1307 state, or because is is blocked with no timeout? */
\r
1308 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )
\r
1314 mtCOVERAGE_TEST_MARKER();
\r
1319 mtCOVERAGE_TEST_MARKER();
\r
1324 mtCOVERAGE_TEST_MARKER();
\r
1328 } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
\r
1330 #endif /* INCLUDE_vTaskSuspend */
\r
1331 /*-----------------------------------------------------------*/
\r
1333 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1335 void vTaskResume( TaskHandle_t xTaskToResume )
\r
1337 TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
\r
1339 /* It does not make sense to resume the calling task. */
\r
1340 configASSERT( xTaskToResume );
\r
1342 /* The parameter cannot be NULL as it is impossible to resume the
\r
1343 currently executing task. */
\r
1344 if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
\r
1346 taskENTER_CRITICAL();
\r
1348 if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE )
\r
1350 traceTASK_RESUME( pxTCB );
\r
1352 /* As we are in a critical section we can access the ready
\r
1353 lists even if the scheduler is suspended. */
\r
1354 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1355 prvAddTaskToReadyList( pxTCB );
\r
1357 /* We may have just resumed a higher priority task. */
\r
1358 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1360 /* This yield may not cause the task just resumed to run,
\r
1361 but will leave the lists in the correct state for the
\r
1363 taskYIELD_IF_USING_PREEMPTION();
\r
1367 mtCOVERAGE_TEST_MARKER();
\r
1372 mtCOVERAGE_TEST_MARKER();
\r
1375 taskEXIT_CRITICAL();
\r
1379 mtCOVERAGE_TEST_MARKER();
\r
1383 #endif /* INCLUDE_vTaskSuspend */
\r
1385 /*-----------------------------------------------------------*/
\r
1387 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
\r
1389 BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
\r
1391 BaseType_t xYieldRequired = pdFALSE;
\r
1392 TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
\r
1393 UBaseType_t uxSavedInterruptStatus;
\r
1395 configASSERT( xTaskToResume );
\r
1397 /* RTOS ports that support interrupt nesting have the concept of a
\r
1398 maximum system call (or maximum API call) interrupt priority.
\r
1399 Interrupts that are above the maximum system call priority are keep
\r
1400 permanently enabled, even when the RTOS kernel is in a critical section,
\r
1401 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
1402 is defined in FreeRTOSConfig.h then
\r
1403 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1404 failure if a FreeRTOS API function is called from an interrupt that has
\r
1405 been assigned a priority above the configured maximum system call
\r
1406 priority. Only FreeRTOS functions that end in FromISR can be called
\r
1407 from interrupts that have been assigned a priority at or (logically)
\r
1408 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
1409 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
1410 simple as possible. More information (albeit Cortex-M specific) is
\r
1411 provided on the following link:
\r
1412 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1413 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1415 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1417 if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE )
\r
1419 traceTASK_RESUME_FROM_ISR( pxTCB );
\r
1421 /* Check the ready lists can be accessed. */
\r
1422 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
1424 /* Ready lists can be accessed so move the task from the
\r
1425 suspended list to the ready list directly. */
\r
1426 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1428 xYieldRequired = pdTRUE;
\r
1432 mtCOVERAGE_TEST_MARKER();
\r
1435 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1436 prvAddTaskToReadyList( pxTCB );
\r
1440 /* The delayed or ready lists cannot be accessed so the task
\r
1441 is held in the pending ready list until the scheduler is
\r
1443 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
1448 mtCOVERAGE_TEST_MARKER();
\r
1451 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1453 return xYieldRequired;
\r
1456 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
\r
1457 /*-----------------------------------------------------------*/
\r
1459 void vTaskStartScheduler( void )
\r
1461 BaseType_t xReturn;
\r
1463 /* Add the idle task at the lowest priority. */
\r
1464 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
1466 /* Create the idle task, storing its handle in xIdleTaskHandle so it can
\r
1467 be returned by the xTaskGetIdleTaskHandle() function. */
\r
1468 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
1472 /* Create the idle task without storing its handle. */
\r
1473 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
1475 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
\r
1477 #if ( configUSE_TIMERS == 1 )
\r
1479 if( xReturn == pdPASS )
\r
1481 xReturn = xTimerCreateTimerTask();
\r
1485 mtCOVERAGE_TEST_MARKER();
\r
1488 #endif /* configUSE_TIMERS */
\r
1490 if( xReturn == pdPASS )
\r
1492 /* Interrupts are turned off here, to ensure a tick does not occur
\r
1493 before or during the call to xPortStartScheduler(). The stacks of
\r
1494 the created tasks contain a status word with interrupts switched on
\r
1495 so interrupts will automatically get re-enabled when the first task
\r
1497 portDISABLE_INTERRUPTS();
\r
1499 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
1501 /* Switch Newlib's _impure_ptr variable to point to the _reent
\r
1502 structure specific to the task that will run first. */
\r
1503 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
\r
1505 #endif /* configUSE_NEWLIB_REENTRANT */
\r
1507 xSchedulerRunning = pdTRUE;
\r
1508 xTickCount = ( TickType_t ) 0U;
\r
1510 /* If configGENERATE_RUN_TIME_STATS is defined then the following
\r
1511 macro must be defined to configure the timer/counter used to generate
\r
1512 the run time counter time base. */
\r
1513 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
\r
1515 /* Setting up the timer tick is hardware specific and thus in the
\r
1516 portable interface. */
\r
1517 if( xPortStartScheduler() != pdFALSE )
\r
1519 /* Should not reach here as if the scheduler is running the
\r
1520 function will not return. */
\r
1524 /* Should only reach here if a task calls xTaskEndScheduler(). */
\r
1529 /* This line will only be reached if the kernel could not be started,
\r
1530 because there was not enough FreeRTOS heap to create the idle task
\r
1531 or the timer task. */
\r
1532 configASSERT( xReturn );
\r
1535 /*-----------------------------------------------------------*/
\r
1537 void vTaskEndScheduler( void )
\r
1539 /* Stop the scheduler interrupts and call the portable scheduler end
\r
1540 routine so the original ISRs can be restored if necessary. The port
\r
1541 layer must ensure interrupts enable bit is left in the correct state. */
\r
1542 portDISABLE_INTERRUPTS();
\r
1543 xSchedulerRunning = pdFALSE;
\r
1544 vPortEndScheduler();
\r
1546 /*----------------------------------------------------------*/
\r
1548 void vTaskSuspendAll( void )
\r
1550 /* A critical section is not required as the variable is of type
\r
1551 BaseType_t. Please read Richard Barry's reply in the following link to a
\r
1552 post in the FreeRTOS support forum before reporting this as a bug! -
\r
1553 http://goo.gl/wu4acr */
\r
1554 ++uxSchedulerSuspended;
\r
1556 /*----------------------------------------------------------*/
\r
1558 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
1560 static TickType_t prvGetExpectedIdleTime( void )
\r
1562 TickType_t xReturn;
\r
1564 if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
\r
1568 else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
\r
1570 /* There are other idle priority tasks in the ready state. If
\r
1571 time slicing is used then the very next tick interrupt must be
\r
1577 xReturn = xNextTaskUnblockTime - xTickCount;
\r
1583 #endif /* configUSE_TICKLESS_IDLE */
\r
1584 /*----------------------------------------------------------*/
\r
1586 BaseType_t xTaskResumeAll( void )
\r
1589 BaseType_t xAlreadyYielded = pdFALSE;
\r
1591 /* If uxSchedulerSuspended is zero then this function does not match a
\r
1592 previous call to vTaskSuspendAll(). */
\r
1593 configASSERT( uxSchedulerSuspended );
\r
1595 /* It is possible that an ISR caused a task to be removed from an event
\r
1596 list while the scheduler was suspended. If this was the case then the
\r
1597 removed task will have been added to the xPendingReadyList. Once the
\r
1598 scheduler has been resumed it is safe to move all the pending ready
\r
1599 tasks from this list into their appropriate ready list. */
\r
1600 taskENTER_CRITICAL();
\r
1602 --uxSchedulerSuspended;
\r
1604 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
1606 if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )
\r
1608 /* Move any readied tasks from the pending list into the
\r
1609 appropriate ready list. */
\r
1610 while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
\r
1612 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );
\r
1613 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1614 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1615 prvAddTaskToReadyList( pxTCB );
\r
1617 /* If we have moved a task that has a priority higher than
\r
1618 the current task then we should yield. */
\r
1619 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1621 xYieldPending = pdTRUE;
\r
1625 mtCOVERAGE_TEST_MARKER();
\r
1629 /* If any ticks occurred while the scheduler was suspended then
\r
1630 they should be processed now. This ensures the tick count does
\r
1631 not slip, and that any delayed tasks are resumed at the correct
\r
1633 if( uxPendedTicks > ( UBaseType_t ) 0U )
\r
1635 while( uxPendedTicks > ( UBaseType_t ) 0U )
\r
1637 if( xTaskIncrementTick() != pdFALSE )
\r
1639 xYieldPending = pdTRUE;
\r
1643 mtCOVERAGE_TEST_MARKER();
\r
1650 mtCOVERAGE_TEST_MARKER();
\r
1653 if( xYieldPending == pdTRUE )
\r
1655 #if( configUSE_PREEMPTION != 0 )
\r
1657 xAlreadyYielded = pdTRUE;
\r
1660 taskYIELD_IF_USING_PREEMPTION();
\r
1664 mtCOVERAGE_TEST_MARKER();
\r
1670 mtCOVERAGE_TEST_MARKER();
\r
1673 taskEXIT_CRITICAL();
\r
1675 return xAlreadyYielded;
\r
1677 /*-----------------------------------------------------------*/
\r
1679 TickType_t xTaskGetTickCount( void )
\r
1681 TickType_t xTicks;
\r
1683 /* Critical section required if running on a 16 bit processor. */
\r
1684 taskENTER_CRITICAL();
\r
1686 xTicks = xTickCount;
\r
1688 taskEXIT_CRITICAL();
\r
1692 /*-----------------------------------------------------------*/
\r
1694 TickType_t xTaskGetTickCountFromISR( void )
\r
1696 TickType_t xReturn;
\r
1697 UBaseType_t uxSavedInterruptStatus;
\r
1699 /* RTOS ports that support interrupt nesting have the concept of a maximum
\r
1700 system call (or maximum API call) interrupt priority. Interrupts that are
\r
1701 above the maximum system call priority are kept permanently enabled, even
\r
1702 when the RTOS kernel is in a critical section, but cannot make any calls to
\r
1703 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
\r
1704 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1705 failure if a FreeRTOS API function is called from an interrupt that has been
\r
1706 assigned a priority above the configured maximum system call priority.
\r
1707 Only FreeRTOS functions that end in FromISR can be called from interrupts
\r
1708 that have been assigned a priority at or (logically) below the maximum
\r
1709 system call interrupt priority. FreeRTOS maintains a separate interrupt
\r
1710 safe API to ensure interrupt entry is as fast and as simple as possible.
\r
1711 More information (albeit Cortex-M specific) is provided on the following
\r
1712 link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1713 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1715 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1717 xReturn = xTickCount;
\r
1719 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1723 /*-----------------------------------------------------------*/
\r
1725 UBaseType_t uxTaskGetNumberOfTasks( void )
\r
1727 /* A critical section is not required because the variables are of type
\r
1729 return uxCurrentNumberOfTasks;
\r
1731 /*-----------------------------------------------------------*/
\r
1733 #if ( INCLUDE_pcTaskGetTaskName == 1 )
\r
1735 char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
1739 /* If null is passed in here then the name of the calling task is being queried. */
\r
1740 pxTCB = prvGetTCBFromHandle( xTaskToQuery );
\r
1741 configASSERT( pxTCB );
\r
1742 return &( pxTCB->pcTaskName[ 0 ] );
\r
1745 #endif /* INCLUDE_pcTaskGetTaskName */
\r
1746 /*-----------------------------------------------------------*/
\r
1748 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1750 UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime )
\r
1752 UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
\r
1754 vTaskSuspendAll();
\r
1756 /* Is there a space in the array for each task in the system? */
\r
1757 if( uxArraySize >= uxCurrentNumberOfTasks )
\r
1759 /* Fill in an TaskStatus_t structure with information on each
\r
1760 task in the Ready state. */
\r
1764 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
\r
1766 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
1768 /* Fill in an TaskStatus_t structure with information on each
\r
1769 task in the Blocked state. */
\r
1770 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );
\r
1771 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );
\r
1773 #if( INCLUDE_vTaskDelete == 1 )
\r
1775 /* Fill in an TaskStatus_t structure with information on
\r
1776 each task that has been deleted but not yet cleaned up. */
\r
1777 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
\r
1781 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1783 /* Fill in an TaskStatus_t structure with information on
\r
1784 each task in the Suspended state. */
\r
1785 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
\r
1789 #if ( configGENERATE_RUN_TIME_STATS == 1)
\r
1791 if( pulTotalRunTime != NULL )
\r
1793 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
1794 portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
\r
1796 *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
1802 if( pulTotalRunTime != NULL )
\r
1804 *pulTotalRunTime = 0;
\r
1811 mtCOVERAGE_TEST_MARKER();
\r
1814 ( void ) xTaskResumeAll();
\r
1819 #endif /* configUSE_TRACE_FACILITY */
\r
1820 /*----------------------------------------------------------*/
\r
1822 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
1824 TaskHandle_t xTaskGetIdleTaskHandle( void )
\r
1826 /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
\r
1827 started, then xIdleTaskHandle will be NULL. */
\r
1828 configASSERT( ( xIdleTaskHandle != NULL ) );
\r
1829 return xIdleTaskHandle;
\r
1832 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
\r
1833 /*----------------------------------------------------------*/
\r
1835 /* This conditional compilation should use inequality to 0, not equality to 1.
\r
1836 This is to ensure vTaskStepTick() is available when user defined low power mode
\r
1837 implementations require configUSE_TICKLESS_IDLE to be set to a value other than
\r
1839 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
1841 void vTaskStepTick( const TickType_t xTicksToJump )
\r
1843 /* Correct the tick count value after a period during which the tick
\r
1844 was suppressed. Note this does *not* call the tick hook function for
\r
1845 each stepped tick. */
\r
1846 configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
\r
1847 xTickCount += xTicksToJump;
\r
1848 traceINCREASE_TICK_COUNT( xTicksToJump );
\r
1851 #endif /* configUSE_TICKLESS_IDLE */
\r
1852 /*----------------------------------------------------------*/
\r
1854 BaseType_t xTaskIncrementTick( void )
\r
1857 TickType_t xItemValue;
\r
1858 BaseType_t xSwitchRequired = pdFALSE;
\r
1860 /* Called by the portable layer each time a tick interrupt occurs.
\r
1861 Increments the tick then checks to see if the new tick value will cause any
\r
1862 tasks to be unblocked. */
\r
1863 traceTASK_INCREMENT_TICK( xTickCount );
\r
1864 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
1866 /* Increment the RTOS tick, switching the delayed and overflowed
\r
1867 delayed lists if it wraps to 0. */
\r
1871 /* Minor optimisation. The tick count cannot change in this
\r
1873 const TickType_t xConstTickCount = xTickCount;
\r
1875 if( xConstTickCount == ( TickType_t ) 0U )
\r
1877 taskSWITCH_DELAYED_LISTS();
\r
1881 mtCOVERAGE_TEST_MARKER();
\r
1884 /* See if this tick has made a timeout expire. Tasks are stored in
\r
1885 the queue in the order of their wake time - meaning once one task
\r
1886 has been found whose block time has not expired there is no need to
\r
1887 look any further down the list. */
\r
1888 if( xConstTickCount >= xNextTaskUnblockTime )
\r
1892 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
\r
1894 /* The delayed list is empty. Set xNextTaskUnblockTime
\r
1895 to the maximum possible value so it is extremely
\r
1897 if( xTickCount >= xNextTaskUnblockTime ) test will pass
\r
1898 next time through. */
\r
1899 xNextTaskUnblockTime = portMAX_DELAY;
\r
1904 /* The delayed list is not empty, get the value of the
\r
1905 item at the head of the delayed list. This is the time
\r
1906 at which the task at the head of the delayed list must
\r
1907 be removed from the Blocked state. */
\r
1908 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
\r
1909 xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
\r
1911 if( xConstTickCount < xItemValue )
\r
1913 /* It is not time to unblock this item yet, but the
\r
1914 item value is the time at which the task at the head
\r
1915 of the blocked list must be removed from the Blocked
\r
1916 state - so record the item value in
\r
1917 xNextTaskUnblockTime. */
\r
1918 xNextTaskUnblockTime = xItemValue;
\r
1923 mtCOVERAGE_TEST_MARKER();
\r
1926 /* It is time to remove the item from the Blocked state. */
\r
1927 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1929 /* Is the task waiting on an event also? If so remove
\r
1930 it from the event list. */
\r
1931 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
1933 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1937 mtCOVERAGE_TEST_MARKER();
\r
1940 /* Place the unblocked task into the appropriate ready
\r
1942 prvAddTaskToReadyList( pxTCB );
\r
1944 /* A task being unblocked cannot cause an immediate
\r
1945 context switch if preemption is turned off. */
\r
1946 #if ( configUSE_PREEMPTION == 1 )
\r
1948 /* Preemption is on, but a context switch should
\r
1949 only be performed if the unblocked task has a
\r
1950 priority that is equal to or higher than the
\r
1951 currently executing task. */
\r
1952 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1954 xSwitchRequired = pdTRUE;
\r
1958 mtCOVERAGE_TEST_MARKER();
\r
1961 #endif /* configUSE_PREEMPTION */
\r
1967 /* Tasks of equal priority to the currently running task will share
\r
1968 processing time (time slice) if preemption is on, and the application
\r
1969 writer has not explicitly turned time slicing off. */
\r
1970 #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
\r
1972 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )
\r
1974 xSwitchRequired = pdTRUE;
\r
1978 mtCOVERAGE_TEST_MARKER();
\r
1981 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
\r
1983 #if ( configUSE_TICK_HOOK == 1 )
\r
1985 /* Guard against the tick hook being called when the pended tick
\r
1986 count is being unwound (when the scheduler is being unlocked). */
\r
1987 if( uxPendedTicks == ( UBaseType_t ) 0U )
\r
1989 vApplicationTickHook();
\r
1993 mtCOVERAGE_TEST_MARKER();
\r
1996 #endif /* configUSE_TICK_HOOK */
\r
2002 /* The tick hook gets called at regular intervals, even if the
\r
2003 scheduler is locked. */
\r
2004 #if ( configUSE_TICK_HOOK == 1 )
\r
2006 vApplicationTickHook();
\r
2011 #if ( configUSE_PREEMPTION == 1 )
\r
2013 if( xYieldPending != pdFALSE )
\r
2015 xSwitchRequired = pdTRUE;
\r
2019 mtCOVERAGE_TEST_MARKER();
\r
2022 #endif /* configUSE_PREEMPTION */
\r
2024 return xSwitchRequired;
\r
2026 /*-----------------------------------------------------------*/
\r
2028 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2030 void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction )
\r
2034 /* If xTask is NULL then it is the task hook of the calling task that is
\r
2036 if( xTask == NULL )
\r
2038 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2042 xTCB = ( TCB_t * ) xTask;
\r
2045 /* Save the hook function in the TCB. A critical section is required as
\r
2046 the value can be accessed from an interrupt. */
\r
2047 taskENTER_CRITICAL();
\r
2048 xTCB->pxTaskTag = pxHookFunction;
\r
2049 taskEXIT_CRITICAL();
\r
2052 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2053 /*-----------------------------------------------------------*/
\r
2055 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2057 TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
\r
2060 TaskHookFunction_t xReturn;
\r
2062 /* If xTask is NULL then we are setting our own task hook. */
\r
2063 if( xTask == NULL )
\r
2065 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2069 xTCB = ( TCB_t * ) xTask;
\r
2072 /* Save the hook function in the TCB. A critical section is required as
\r
2073 the value can be accessed from an interrupt. */
\r
2074 taskENTER_CRITICAL();
\r
2076 xReturn = xTCB->pxTaskTag;
\r
2078 taskEXIT_CRITICAL();
\r
2083 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2084 /*-----------------------------------------------------------*/
\r
2086 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2088 BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter )
\r
2091 BaseType_t xReturn;
\r
2093 /* If xTask is NULL then we are calling our own task hook. */
\r
2094 if( xTask == NULL )
\r
2096 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2100 xTCB = ( TCB_t * ) xTask;
\r
2103 if( xTCB->pxTaskTag != NULL )
\r
2105 xReturn = xTCB->pxTaskTag( pvParameter );
\r
2115 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2116 /*-----------------------------------------------------------*/
\r
2118 void vTaskSwitchContext( void )
\r
2120 if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )
\r
2122 /* The scheduler is currently suspended - do not allow a context
\r
2124 xYieldPending = pdTRUE;
\r
2128 xYieldPending = pdFALSE;
\r
2129 traceTASK_SWITCHED_OUT();
\r
2131 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
2133 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
2134 portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
\r
2136 ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
2139 /* Add the amount of time the task has been running to the
\r
2140 accumulated time so far. The time the task started running was
\r
2141 stored in ulTaskSwitchedInTime. Note that there is no overflow
\r
2142 protection here so count values are only valid until the timer
\r
2143 overflows. The guard against negative values is to protect
\r
2144 against suspect run time stat counter implementations - which
\r
2145 are provided by the application, not the kernel. */
\r
2146 if( ulTotalRunTime > ulTaskSwitchedInTime )
\r
2148 pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
\r
2152 mtCOVERAGE_TEST_MARKER();
\r
2154 ulTaskSwitchedInTime = ulTotalRunTime;
\r
2156 #endif /* configGENERATE_RUN_TIME_STATS */
\r
2158 /* Check for stack overflow, if configured. */
\r
2159 taskFIRST_CHECK_FOR_STACK_OVERFLOW();
\r
2160 taskSECOND_CHECK_FOR_STACK_OVERFLOW();
\r
2162 /* Select a new task to run using either the generic C or port
\r
2163 optimised asm code. */
\r
2164 taskSELECT_HIGHEST_PRIORITY_TASK();
\r
2165 traceTASK_SWITCHED_IN();
\r
2167 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
2169 /* Switch Newlib's _impure_ptr variable to point to the _reent
\r
2170 structure specific to this task. */
\r
2171 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
\r
2173 #endif /* configUSE_NEWLIB_REENTRANT */
\r
2176 /*-----------------------------------------------------------*/
\r
2178 void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )
\r
2180 TickType_t xTimeToWake;
\r
2182 configASSERT( pxEventList );
\r
2184 /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
\r
2185 SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
\r
2187 /* Place the event list item of the TCB in the appropriate event list.
\r
2188 This is placed in the list in priority order so the highest priority task
\r
2189 is the first to be woken by the event. The queue that contains the event
\r
2190 list is locked, preventing simultaneous access from interrupts. */
\r
2191 vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2193 /* The task must be removed from from the ready list before it is added to
\r
2194 the blocked list as the same list item is used for both lists. Exclusive
\r
2195 access to the ready lists guaranteed because the scheduler is locked. */
\r
2196 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
2198 /* The current task must be in a ready list, so there is no need to
\r
2199 check, and the port reset macro can be called directly. */
\r
2200 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
2204 mtCOVERAGE_TEST_MARKER();
\r
2207 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2209 if( xTicksToWait == portMAX_DELAY )
\r
2211 /* Add the task to the suspended task list instead of a delayed task
\r
2212 list to ensure the task is not woken by a timing event. It will
\r
2213 block indefinitely. */
\r
2214 vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
\r
2218 /* Calculate the time at which the task should be woken if the event
\r
2219 does not occur. This may overflow but this doesn't matter, the
\r
2220 scheduler will handle it. */
\r
2221 xTimeToWake = xTickCount + xTicksToWait;
\r
2222 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
2225 #else /* INCLUDE_vTaskSuspend */
\r
2227 /* Calculate the time at which the task should be woken if the event does
\r
2228 not occur. This may overflow but this doesn't matter, the scheduler
\r
2229 will handle it. */
\r
2230 xTimeToWake = xTickCount + xTicksToWait;
\r
2231 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
2233 #endif /* INCLUDE_vTaskSuspend */
\r
2235 /*-----------------------------------------------------------*/
\r
2237 void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait )
\r
2239 TickType_t xTimeToWake;
\r
2241 configASSERT( pxEventList );
\r
2243 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
\r
2244 the event groups implementation. */
\r
2245 configASSERT( uxSchedulerSuspended != 0 );
\r
2247 /* Store the item value in the event list item. It is safe to access the
\r
2248 event list item here as interrupts won't access the event list item of a
\r
2249 task that is not in the Blocked state. */
\r
2250 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
\r
2252 /* Place the event list item of the TCB at the end of the appropriate event
\r
2253 list. It is safe to access the event list here because it is part of an
\r
2254 event group implementation - and interrupts don't access event groups
\r
2255 directly (instead they access them indirectly by pending function calls to
\r
2256 the task level). */
\r
2257 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2259 /* The task must be removed from the ready list before it is added to the
\r
2260 blocked list. Exclusive access can be assured to the ready list as the
\r
2261 scheduler is locked. */
\r
2262 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
2264 /* The current task must be in a ready list, so there is no need to
\r
2265 check, and the port reset macro can be called directly. */
\r
2266 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
2270 mtCOVERAGE_TEST_MARKER();
\r
2273 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2275 if( xTicksToWait == portMAX_DELAY )
\r
2277 /* Add the task to the suspended task list instead of a delayed task
\r
2278 list to ensure it is not woken by a timing event. It will block
\r
2280 vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
\r
2284 /* Calculate the time at which the task should be woken if the event
\r
2285 does not occur. This may overflow but this doesn't matter, the
\r
2286 kernel will manage it correctly. */
\r
2287 xTimeToWake = xTickCount + xTicksToWait;
\r
2288 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
2291 #else /* INCLUDE_vTaskSuspend */
\r
2293 /* Calculate the time at which the task should be woken if the event does
\r
2294 not occur. This may overflow but this doesn't matter, the kernel
\r
2295 will manage it correctly. */
\r
2296 xTimeToWake = xTickCount + xTicksToWait;
\r
2297 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
2299 #endif /* INCLUDE_vTaskSuspend */
\r
2301 /*-----------------------------------------------------------*/
\r
2303 #if configUSE_TIMERS == 1
\r
2305 void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait )
\r
2307 TickType_t xTimeToWake;
\r
2309 configASSERT( pxEventList );
\r
2311 /* This function should not be called by application code hence the
\r
2312 'Restricted' in its name. It is not part of the public API. It is
\r
2313 designed for use by kernel code, and has special calling requirements -
\r
2314 it should be called from a critical section. */
\r
2317 /* Place the event list item of the TCB in the appropriate event list.
\r
2318 In this case it is assume that this is the only task that is going to
\r
2319 be waiting on this event list, so the faster vListInsertEnd() function
\r
2320 can be used in place of vListInsert. */
\r
2321 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2323 /* We must remove this task from the ready list before adding it to the
\r
2324 blocked list as the same list item is used for both lists. This
\r
2325 function is called form a critical section. */
\r
2326 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
2328 /* The current task must be in a ready list, so there is no need to
\r
2329 check, and the port reset macro can be called directly. */
\r
2330 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
2334 mtCOVERAGE_TEST_MARKER();
\r
2337 /* Calculate the time at which the task should be woken if the event does
\r
2338 not occur. This may overflow but this doesn't matter. */
\r
2339 xTimeToWake = xTickCount + xTicksToWait;
\r
2341 traceTASK_DELAY_UNTIL();
\r
2342 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
2345 #endif /* configUSE_TIMERS */
\r
2346 /*-----------------------------------------------------------*/
\r
2348 BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
\r
2350 TCB_t *pxUnblockedTCB;
\r
2351 BaseType_t xReturn;
\r
2353 /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be
\r
2354 called from a critical section within an ISR. */
\r
2356 /* The event list is sorted in priority order, so the first in the list can
\r
2357 be removed as it is known to be the highest priority. Remove the TCB from
\r
2358 the delayed list, and add it to the ready list.
\r
2360 If an event is for a queue that is locked then this function will never
\r
2361 get called - the lock count on the queue will get modified instead. This
\r
2362 means exclusive access to the event list is guaranteed here.
\r
2364 This function assumes that a check has already been made to ensure that
\r
2365 pxEventList is not empty. */
\r
2366 pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
\r
2367 configASSERT( pxUnblockedTCB );
\r
2368 ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
\r
2370 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
2372 ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
\r
2373 prvAddTaskToReadyList( pxUnblockedTCB );
\r
2377 /* The delayed and ready lists cannot be accessed, so hold this task
\r
2378 pending until the scheduler is resumed. */
\r
2379 vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
\r
2382 if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
2384 /* Return true if the task removed from the event list has a higher
\r
2385 priority than the calling task. This allows the calling task to know if
\r
2386 it should force a context switch now. */
\r
2389 /* Mark that a yield is pending in case the user is not using the
\r
2390 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
\r
2391 xYieldPending = pdTRUE;
\r
2395 xReturn = pdFALSE;
\r
2400 /*-----------------------------------------------------------*/
\r
2402 BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )
\r
2404 TCB_t *pxUnblockedTCB;
\r
2405 BaseType_t xReturn;
\r
2407 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
\r
2408 the event flags implementation. */
\r
2409 configASSERT( uxSchedulerSuspended != pdFALSE );
\r
2411 /* Store the new item value in the event list. */
\r
2412 listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
\r
2414 /* Remove the event list form the event flag. Interrupts do not access
\r
2416 pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem );
\r
2417 configASSERT( pxUnblockedTCB );
\r
2418 ( void ) uxListRemove( pxEventListItem );
\r
2420 /* Remove the task from the delayed list and add it to the ready list. The
\r
2421 scheduler is suspended so interrupts will not be accessing the ready
\r
2423 ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
\r
2424 prvAddTaskToReadyList( pxUnblockedTCB );
\r
2426 if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
2428 /* Return true if the task removed from the event list has
\r
2429 a higher priority than the calling task. This allows
\r
2430 the calling task to know if it should force a context
\r
2434 /* Mark that a yield is pending in case the user is not using the
\r
2435 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
\r
2436 xYieldPending = pdTRUE;
\r
2440 xReturn = pdFALSE;
\r
2445 /*-----------------------------------------------------------*/
\r
2447 void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
\r
2449 configASSERT( pxTimeOut );
\r
2450 pxTimeOut->xOverflowCount = xNumOfOverflows;
\r
2451 pxTimeOut->xTimeOnEntering = xTickCount;
\r
2453 /*-----------------------------------------------------------*/
\r
2455 BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait )
\r
2457 BaseType_t xReturn;
\r
2459 configASSERT( pxTimeOut );
\r
2460 configASSERT( pxTicksToWait );
\r
2462 taskENTER_CRITICAL();
\r
2464 /* Minor optimisation. The tick count cannot change in this block. */
\r
2465 const TickType_t xConstTickCount = xTickCount;
\r
2467 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2468 /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is
\r
2469 the maximum block time then the task should block indefinitely, and
\r
2470 therefore never time out. */
\r
2471 if( *pxTicksToWait == portMAX_DELAY )
\r
2473 xReturn = pdFALSE;
\r
2475 else /* We are not blocking indefinitely, perform the checks below. */
\r
2478 if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
\r
2480 /* The tick count is greater than the time at which vTaskSetTimeout()
\r
2481 was called, but has also overflowed since vTaskSetTimeOut() was called.
\r
2482 It must have wrapped all the way around and gone past us again. This
\r
2483 passed since vTaskSetTimeout() was called. */
\r
2486 else if( ( xConstTickCount - pxTimeOut->xTimeOnEntering ) < *pxTicksToWait )
\r
2488 /* Not a genuine timeout. Adjust parameters for time remaining. */
\r
2489 *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );
\r
2490 vTaskSetTimeOutState( pxTimeOut );
\r
2491 xReturn = pdFALSE;
\r
2498 taskEXIT_CRITICAL();
\r
2502 /*-----------------------------------------------------------*/
\r
2504 void vTaskMissedYield( void )
\r
2506 xYieldPending = pdTRUE;
\r
2508 /*-----------------------------------------------------------*/
\r
2510 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2512 UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )
\r
2514 UBaseType_t uxReturn;
\r
2517 if( xTask != NULL )
\r
2519 pxTCB = ( TCB_t * ) xTask;
\r
2520 uxReturn = pxTCB->uxTaskNumber;
\r
2530 #endif /* configUSE_TRACE_FACILITY */
\r
2531 /*-----------------------------------------------------------*/
\r
2533 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2535 void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle )
\r
2539 if( xTask != NULL )
\r
2541 pxTCB = ( TCB_t * ) xTask;
\r
2542 pxTCB->uxTaskNumber = uxHandle;
\r
2546 #endif /* configUSE_TRACE_FACILITY */
\r
2549 * -----------------------------------------------------------
\r
2551 * ----------------------------------------------------------
\r
2553 * The portTASK_FUNCTION() macro is used to allow port/compiler specific
\r
2554 * language extensions. The equivalent prototype for this function is:
\r
2556 * void prvIdleTask( void *pvParameters );
\r
2559 static portTASK_FUNCTION( prvIdleTask, pvParameters )
\r
2561 /* Stop warnings. */
\r
2562 ( void ) pvParameters;
\r
2566 /* See if any tasks have been deleted. */
\r
2567 prvCheckTasksWaitingTermination();
\r
2569 #if ( configUSE_PREEMPTION == 0 )
\r
2571 /* If we are not using preemption we keep forcing a task switch to
\r
2572 see if any other task has become available. If we are using
\r
2573 preemption we don't need to do this as any task becoming available
\r
2574 will automatically get the processor anyway. */
\r
2577 #endif /* configUSE_PREEMPTION */
\r
2579 #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
\r
2581 /* When using preemption tasks of equal priority will be
\r
2582 timesliced. If a task that is sharing the idle priority is ready
\r
2583 to run then the idle task should yield before the end of the
\r
2586 A critical region is not required here as we are just reading from
\r
2587 the list, and an occasional incorrect value will not matter. If
\r
2588 the ready list at the idle priority contains more than one task
\r
2589 then a task other than the idle task is ready to execute. */
\r
2590 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )
\r
2596 mtCOVERAGE_TEST_MARKER();
\r
2599 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
\r
2601 #if ( configUSE_IDLE_HOOK == 1 )
\r
2603 extern void vApplicationIdleHook( void );
\r
2605 /* Call the user defined function from within the idle task. This
\r
2606 allows the application designer to add background functionality
\r
2607 without the overhead of a separate task.
\r
2608 NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
\r
2609 CALL A FUNCTION THAT MIGHT BLOCK. */
\r
2610 vApplicationIdleHook();
\r
2612 #endif /* configUSE_IDLE_HOOK */
\r
2614 /* This conditional compilation should use inequality to 0, not equality
\r
2615 to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
\r
2616 user defined low power mode implementations require
\r
2617 configUSE_TICKLESS_IDLE to be set to a value other than 1. */
\r
2618 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
2620 TickType_t xExpectedIdleTime;
\r
2622 /* It is not desirable to suspend then resume the scheduler on
\r
2623 each iteration of the idle task. Therefore, a preliminary
\r
2624 test of the expected idle time is performed without the
\r
2625 scheduler suspended. The result here is not necessarily
\r
2627 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
2629 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
2631 vTaskSuspendAll();
\r
2633 /* Now the scheduler is suspended, the expected idle
\r
2634 time can be sampled again, and this time its value can
\r
2636 configASSERT( xNextTaskUnblockTime >= xTickCount );
\r
2637 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
2639 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
2641 traceLOW_POWER_IDLE_BEGIN();
\r
2642 portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
\r
2643 traceLOW_POWER_IDLE_END();
\r
2647 mtCOVERAGE_TEST_MARKER();
\r
2650 ( void ) xTaskResumeAll();
\r
2654 mtCOVERAGE_TEST_MARKER();
\r
2657 #endif /* configUSE_TICKLESS_IDLE */
\r
2660 /*-----------------------------------------------------------*/
\r
2662 #if configUSE_TICKLESS_IDLE != 0
\r
2664 eSleepModeStatus eTaskConfirmSleepModeStatus( void )
\r
2666 eSleepModeStatus eReturn = eStandardSleep;
\r
2668 if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
\r
2670 /* A task was made ready while the scheduler was suspended. */
\r
2671 eReturn = eAbortSleep;
\r
2673 else if( xYieldPending != pdFALSE )
\r
2675 /* A yield was pended while the scheduler was suspended. */
\r
2676 eReturn = eAbortSleep;
\r
2680 #if configUSE_TIMERS == 0
\r
2682 /* The idle task exists in addition to the application tasks. */
\r
2683 const UBaseType_t uxNonApplicationTasks = 1;
\r
2685 /* If timers are not being used and all the tasks are in the
\r
2686 suspended list (which might mean they have an infinite block
\r
2687 time rather than actually being suspended) then it is safe to
\r
2688 turn all clocks off and just wait for external interrupts. */
\r
2689 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
\r
2691 eReturn = eNoTasksWaitingTimeout;
\r
2695 mtCOVERAGE_TEST_MARKER();
\r
2698 #endif /* configUSE_TIMERS */
\r
2703 #endif /* configUSE_TICKLESS_IDLE */
\r
2704 /*-----------------------------------------------------------*/
\r
2706 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
2710 /* Store the task name in the TCB. */
\r
2711 for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
\r
2713 pxTCB->pcTaskName[ x ] = pcName[ x ];
\r
2715 /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
\r
2716 configMAX_TASK_NAME_LEN characters just in case the memory after the
\r
2717 string is not accessible (extremely unlikely). */
\r
2718 if( pcName[ x ] == 0x00 )
\r
2724 mtCOVERAGE_TEST_MARKER();
\r
2728 /* Ensure the name string is terminated in the case that the string length
\r
2729 was greater or equal to configMAX_TASK_NAME_LEN. */
\r
2730 pxTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
\r
2732 /* This is used as an array index so must ensure it's not too large. First
\r
2733 remove the privilege bit if one is present. */
\r
2734 if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
\r
2736 uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
\r
2740 mtCOVERAGE_TEST_MARKER();
\r
2743 pxTCB->uxPriority = uxPriority;
\r
2744 #if ( configUSE_MUTEXES == 1 )
\r
2746 pxTCB->uxBasePriority = uxPriority;
\r
2747 pxTCB->uxMutexesHeld = 0;
\r
2749 #endif /* configUSE_MUTEXES */
\r
2751 vListInitialiseItem( &( pxTCB->xGenericListItem ) );
\r
2752 vListInitialiseItem( &( pxTCB->xEventListItem ) );
\r
2754 /* Set the pxTCB as a link back from the ListItem_t. This is so we can get
\r
2755 back to the containing TCB from a generic item in a list. */
\r
2756 listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB );
\r
2758 /* Event lists are always in priority order. */
\r
2759 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
2760 listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB );
\r
2762 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
2764 pxTCB->uxCriticalNesting = ( UBaseType_t ) 0U;
\r
2766 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
2768 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2770 pxTCB->pxTaskTag = NULL;
\r
2772 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2774 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
2776 pxTCB->ulRunTimeCounter = 0UL;
\r
2778 #endif /* configGENERATE_RUN_TIME_STATS */
\r
2780 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
2782 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth );
\r
2784 #else /* portUSING_MPU_WRAPPERS */
\r
2786 ( void ) xRegions;
\r
2787 ( void ) usStackDepth;
\r
2789 #endif /* portUSING_MPU_WRAPPERS */
\r
2791 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
2793 /* Initialise this task's Newlib reent structure. */
\r
2794 _REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) );
\r
2796 #endif /* configUSE_NEWLIB_REENTRANT */
\r
2798 /*-----------------------------------------------------------*/
\r
2800 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
2802 void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions )
\r
2806 /* If null is passed in here then we are deleting ourselves. */
\r
2807 pxTCB = prvGetTCBFromHandle( xTaskToModify );
\r
2809 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
\r
2812 #endif /* portUSING_MPU_WRAPPERS */
\r
2813 /*-----------------------------------------------------------*/
\r
2815 static void prvInitialiseTaskLists( void )
\r
2817 UBaseType_t uxPriority;
\r
2819 for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
\r
2821 vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
\r
2824 vListInitialise( &xDelayedTaskList1 );
\r
2825 vListInitialise( &xDelayedTaskList2 );
\r
2826 vListInitialise( &xPendingReadyList );
\r
2828 #if ( INCLUDE_vTaskDelete == 1 )
\r
2830 vListInitialise( &xTasksWaitingTermination );
\r
2832 #endif /* INCLUDE_vTaskDelete */
\r
2834 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2836 vListInitialise( &xSuspendedTaskList );
\r
2838 #endif /* INCLUDE_vTaskSuspend */
\r
2840 /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
\r
2842 pxDelayedTaskList = &xDelayedTaskList1;
\r
2843 pxOverflowDelayedTaskList = &xDelayedTaskList2;
\r
2845 /*-----------------------------------------------------------*/
\r
2847 static void prvCheckTasksWaitingTermination( void )
\r
2849 #if ( INCLUDE_vTaskDelete == 1 )
\r
2851 BaseType_t xListIsEmpty;
\r
2853 /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
\r
2854 too often in the idle task. */
\r
2855 while( uxTasksDeleted > ( UBaseType_t ) 0U )
\r
2857 vTaskSuspendAll();
\r
2859 xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
\r
2861 ( void ) xTaskResumeAll();
\r
2863 if( xListIsEmpty == pdFALSE )
\r
2867 taskENTER_CRITICAL();
\r
2869 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
\r
2870 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
2871 --uxCurrentNumberOfTasks;
\r
2874 taskEXIT_CRITICAL();
\r
2876 prvDeleteTCB( pxTCB );
\r
2880 mtCOVERAGE_TEST_MARKER();
\r
2884 #endif /* vTaskDelete */
\r
2886 /*-----------------------------------------------------------*/
\r
2888 static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake )
\r
2890 /* The list item will be inserted in wake time order. */
\r
2891 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
\r
2893 if( xTimeToWake < xTickCount )
\r
2895 /* Wake time has overflowed. Place this item in the overflow list. */
\r
2896 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
\r
2900 /* The wake time has not overflowed, so the current block list is used. */
\r
2901 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
\r
2903 /* If the task entering the blocked state was placed at the head of the
\r
2904 list of blocked tasks then xNextTaskUnblockTime needs to be updated
\r
2906 if( xTimeToWake < xNextTaskUnblockTime )
\r
2908 xNextTaskUnblockTime = xTimeToWake;
\r
2912 mtCOVERAGE_TEST_MARKER();
\r
2916 /*-----------------------------------------------------------*/
\r
2918 static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer )
\r
2922 /* If the stack grows down then allocate the stack then the TCB so the stack
\r
2923 does not grow into the TCB. Likewise if the stack grows up then allocate
\r
2924 the TCB then the stack. */
\r
2925 #if( portSTACK_GROWTH > 0 )
\r
2927 /* Allocate space for the TCB. Where the memory comes from depends on
\r
2928 the implementation of the port malloc function. */
\r
2929 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
\r
2931 if( pxNewTCB != NULL )
\r
2933 /* Allocate space for the stack used by the task being created.
\r
2934 The base of the stack memory stored in the TCB so the task can
\r
2935 be deleted later if required. */
\r
2936 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
2938 if( pxNewTCB->pxStack == NULL )
\r
2940 /* Could not allocate the stack. Delete the allocated TCB. */
\r
2941 vPortFree( pxNewTCB );
\r
2946 #else /* portSTACK_GROWTH */
\r
2948 StackType_t *pxStack;
\r
2950 /* Allocate space for the stack used by the task being created. */
\r
2951 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
2953 if( pxStack != NULL )
\r
2955 /* Allocate space for the TCB. Where the memory comes from depends
\r
2956 on the implementation of the port malloc function. */
\r
2957 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
\r
2959 if( pxNewTCB != NULL )
\r
2961 /* Store the stack location in the TCB. */
\r
2962 pxNewTCB->pxStack = pxStack;
\r
2966 /* The stack cannot be used as the TCB was not created. Free it
\r
2968 vPortFree( pxStack );
\r
2976 #endif /* portSTACK_GROWTH */
\r
2978 if( pxNewTCB != NULL )
\r
2980 /* Avoid dependency on memset() if it is not required. */
\r
2981 #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
2983 /* Just to help debugging. */
\r
2984 ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( StackType_t ) );
\r
2986 #endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */
\r
2991 /*-----------------------------------------------------------*/
\r
2993 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2995 static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )
\r
2997 volatile TCB_t *pxNextTCB, *pxFirstTCB;
\r
2998 UBaseType_t uxTask = 0;
\r
3000 if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
\r
3002 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
\r
3004 /* Populate an TaskStatus_t structure within the
\r
3005 pxTaskStatusArray array for each task that is referenced from
\r
3006 pxList. See the definition of TaskStatus_t in task.h for the
\r
3007 meaning of each TaskStatus_t structure member. */
\r
3010 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
\r
3012 pxTaskStatusArray[ uxTask ].xHandle = ( TaskHandle_t ) pxNextTCB;
\r
3013 pxTaskStatusArray[ uxTask ].pcTaskName = ( const char * ) &( pxNextTCB->pcTaskName [ 0 ] );
\r
3014 pxTaskStatusArray[ uxTask ].xTaskNumber = pxNextTCB->uxTCBNumber;
\r
3015 pxTaskStatusArray[ uxTask ].eCurrentState = eState;
\r
3016 pxTaskStatusArray[ uxTask ].uxCurrentPriority = pxNextTCB->uxPriority;
\r
3018 #if ( INCLUDE_vTaskSuspend == 1 )
\r
3020 /* If the task is in the suspended list then there is a chance
\r
3021 it is actually just blocked indefinitely - so really it should
\r
3022 be reported as being in the Blocked state. */
\r
3023 if( eState == eSuspended )
\r
3025 if( listLIST_ITEM_CONTAINER( &( pxNextTCB->xEventListItem ) ) != NULL )
\r
3027 pxTaskStatusArray[ uxTask ].eCurrentState = eBlocked;
\r
3031 #endif /* INCLUDE_vTaskSuspend */
\r
3033 #if ( configUSE_MUTEXES == 1 )
\r
3035 pxTaskStatusArray[ uxTask ].uxBasePriority = pxNextTCB->uxBasePriority;
\r
3039 pxTaskStatusArray[ uxTask ].uxBasePriority = 0;
\r
3043 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
3045 pxTaskStatusArray[ uxTask ].ulRunTimeCounter = pxNextTCB->ulRunTimeCounter;
\r
3049 pxTaskStatusArray[ uxTask ].ulRunTimeCounter = 0;
\r
3053 #if ( portSTACK_GROWTH > 0 )
\r
3055 pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxEndOfStack );
\r
3059 pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxStack );
\r
3065 } while( pxNextTCB != pxFirstTCB );
\r
3069 mtCOVERAGE_TEST_MARKER();
\r
3075 #endif /* configUSE_TRACE_FACILITY */
\r
3076 /*-----------------------------------------------------------*/
\r
3078 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
3080 static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
\r
3082 uint32_t ulCount = 0U;
\r
3084 while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE )
\r
3086 pucStackByte -= portSTACK_GROWTH;
\r
3090 ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */
\r
3092 return ( uint16_t ) ulCount;
\r
3095 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */
\r
3096 /*-----------------------------------------------------------*/
\r
3098 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
\r
3100 UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
\r
3103 uint8_t *pucEndOfStack;
\r
3104 UBaseType_t uxReturn;
\r
3106 pxTCB = prvGetTCBFromHandle( xTask );
\r
3108 #if portSTACK_GROWTH < 0
\r
3110 pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
\r
3114 pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
\r
3118 uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );
\r
3123 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
\r
3124 /*-----------------------------------------------------------*/
\r
3126 #if ( INCLUDE_vTaskDelete == 1 )
\r
3128 static void prvDeleteTCB( TCB_t *pxTCB )
\r
3130 /* This call is required specifically for the TriCore port. It must be
\r
3131 above the vPortFree() calls. The call is also used by ports/demos that
\r
3132 want to allocate and clean RAM statically. */
\r
3133 portCLEAN_UP_TCB( pxTCB );
\r
3135 /* Free up the memory allocated by the scheduler for the task. It is up
\r
3136 to the task to free any memory allocated at the application level. */
\r
3137 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
3139 _reclaim_reent( &( pxTCB->xNewLib_reent ) );
\r
3141 #endif /* configUSE_NEWLIB_REENTRANT */
\r
3142 vPortFreeAligned( pxTCB->pxStack );
\r
3143 vPortFree( pxTCB );
\r
3146 #endif /* INCLUDE_vTaskDelete */
\r
3147 /*-----------------------------------------------------------*/
\r
3149 static void prvResetNextTaskUnblockTime( void )
\r
3153 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
\r
3155 /* The new current delayed list is empty. Set
\r
3156 xNextTaskUnblockTime to the maximum possible value so it is
\r
3157 extremely unlikely that the
\r
3158 if( xTickCount >= xNextTaskUnblockTime ) test will pass until
\r
3159 there is an item in the delayed list. */
\r
3160 xNextTaskUnblockTime = portMAX_DELAY;
\r
3164 /* The new current delayed list is not empty, get the value of
\r
3165 the item at the head of the delayed list. This is the time at
\r
3166 which the task at the head of the delayed list should be removed
\r
3167 from the Blocked state. */
\r
3168 ( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
\r
3169 xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xGenericListItem ) );
\r
3172 /*-----------------------------------------------------------*/
\r
3174 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
\r
3176 TaskHandle_t xTaskGetCurrentTaskHandle( void )
\r
3178 TaskHandle_t xReturn;
\r
3180 /* A critical section is not required as this is not called from
\r
3181 an interrupt and the current TCB will always be the same for any
\r
3182 individual execution thread. */
\r
3183 xReturn = pxCurrentTCB;
\r
3188 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
\r
3189 /*-----------------------------------------------------------*/
\r
3191 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
3193 BaseType_t xTaskGetSchedulerState( void )
\r
3195 BaseType_t xReturn;
\r
3197 if( xSchedulerRunning == pdFALSE )
\r
3199 xReturn = taskSCHEDULER_NOT_STARTED;
\r
3203 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
3205 xReturn = taskSCHEDULER_RUNNING;
\r
3209 xReturn = taskSCHEDULER_SUSPENDED;
\r
3216 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
\r
3217 /*-----------------------------------------------------------*/
\r
3219 #if ( configUSE_MUTEXES == 1 )
\r
3221 void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
\r
3223 TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
\r
3225 /* If the mutex was given back by an interrupt while the queue was
\r
3226 locked then the mutex holder might now be NULL. */
\r
3227 if( pxMutexHolder != NULL )
\r
3229 if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
\r
3231 /* Adjust the mutex holder state to account for its new
\r
3232 priority. Only reset the event list item value if the value is
\r
3233 not being used for anything else. */
\r
3234 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
\r
3236 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
3240 mtCOVERAGE_TEST_MARKER();
\r
3243 /* If the task being modified is in the ready state it will need to
\r
3244 be moved into a new list. */
\r
3245 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
\r
3247 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
3249 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
3253 mtCOVERAGE_TEST_MARKER();
\r
3256 /* Inherit the priority before being moved into the new list. */
\r
3257 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
3258 prvAddTaskToReadyList( pxTCB );
\r
3262 /* Just inherit the priority. */
\r
3263 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
3266 traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );
\r
3270 mtCOVERAGE_TEST_MARKER();
\r
3275 mtCOVERAGE_TEST_MARKER();
\r
3279 #endif /* configUSE_MUTEXES */
\r
3280 /*-----------------------------------------------------------*/
\r
3282 #if ( configUSE_MUTEXES == 1 )
\r
3284 BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )
\r
3286 TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
\r
3287 BaseType_t xReturn = pdFALSE;
\r
3289 if( pxMutexHolder != NULL )
\r
3291 configASSERT( pxTCB->uxMutexesHeld );
\r
3292 ( pxTCB->uxMutexesHeld )--;
\r
3294 if( pxTCB->uxPriority != pxTCB->uxBasePriority )
\r
3296 /* Only disinherit if no other mutexes are held. */
\r
3297 if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
\r
3299 /* A task can only have an inhertied priority if it holds
\r
3300 the mutex. If the mutex is held by a task then it cannot be
\r
3301 given from an interrupt, and if a mutex is given by the
\r
3302 holding task then it must be the running state task. Remove
\r
3303 the holding task from the ready list. */
\r
3304 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
3306 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
3310 mtCOVERAGE_TEST_MARKER();
\r
3313 /* Disinherit the priority before adding the task into the
\r
3314 new ready list. */
\r
3315 traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
\r
3316 pxTCB->uxPriority = pxTCB->uxBasePriority;
\r
3318 /* Reset the event list item value. It cannot be in use for
\r
3319 any other purpose if this task is running, and it must be
\r
3320 running to give back the mutex. */
\r
3321 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
3322 prvAddTaskToReadyList( pxTCB );
\r
3324 /* Return true to indicate that a context switch is required.
\r
3325 This is only actually required in the corner case whereby
\r
3326 multiple mutexes were held and the mutexes were given back
\r
3327 in an order different to that in which they were taken.
\r
3328 If a context switch did not occur when the first mutex was
\r
3329 returned, even if a task was waiting on it, then a context
\r
3330 switch should occur when the last mutex is returned whether
\r
3331 a task is waiting on it or not. */
\r
3336 mtCOVERAGE_TEST_MARKER();
\r
3341 mtCOVERAGE_TEST_MARKER();
\r
3346 mtCOVERAGE_TEST_MARKER();
\r
3352 #endif /* configUSE_MUTEXES */
\r
3353 /*-----------------------------------------------------------*/
\r
3355 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
3357 void vTaskEnterCritical( void )
\r
3359 portDISABLE_INTERRUPTS();
\r
3361 if( xSchedulerRunning != pdFALSE )
\r
3363 ( pxCurrentTCB->uxCriticalNesting )++;
\r
3365 /* This is not the interrupt safe version of the enter critical
\r
3366 function so assert() if it is being called from an interrupt
\r
3367 context. Only API functions that end in "FromISR" can be used in an
\r
3368 interrupt. Only assert if the critical nesting count is 1 to
\r
3369 protect against recursive calls if the assert function also uses a
\r
3370 critical section. */
\r
3371 if( pxCurrentTCB->uxCriticalNesting == 1 )
\r
3373 portASSERT_IF_IN_ISR();
\r
3379 mtCOVERAGE_TEST_MARKER();
\r
3383 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
3384 /*-----------------------------------------------------------*/
\r
3386 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
3388 void vTaskExitCritical( void )
\r
3390 if( xSchedulerRunning != pdFALSE )
\r
3392 if( pxCurrentTCB->uxCriticalNesting > 0U )
\r
3394 ( pxCurrentTCB->uxCriticalNesting )--;
\r
3396 if( pxCurrentTCB->uxCriticalNesting == 0U )
\r
3398 portENABLE_INTERRUPTS();
\r
3402 mtCOVERAGE_TEST_MARKER();
\r
3407 mtCOVERAGE_TEST_MARKER();
\r
3412 mtCOVERAGE_TEST_MARKER();
\r
3416 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
3417 /*-----------------------------------------------------------*/
\r
3419 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
3421 void vTaskList( char * pcWriteBuffer )
\r
3423 TaskStatus_t *pxTaskStatusArray;
\r
3424 volatile UBaseType_t uxArraySize, x;
\r
3430 * This function is provided for convenience only, and is used by many
\r
3431 * of the demo applications. Do not consider it to be part of the
\r
3434 * vTaskList() calls uxTaskGetSystemState(), then formats part of the
\r
3435 * uxTaskGetSystemState() output into a human readable table that
\r
3436 * displays task names, states and stack usage.
\r
3438 * vTaskList() has a dependency on the sprintf() C library function that
\r
3439 * might bloat the code size, use a lot of stack, and provide different
\r
3440 * results on different platforms. An alternative, tiny, third party,
\r
3441 * and limited functionality implementation of sprintf() is provided in
\r
3442 * many of the FreeRTOS/Demo sub-directories in a file called
\r
3443 * printf-stdarg.c (note printf-stdarg.c does not provide a full
\r
3444 * snprintf() implementation!).
\r
3446 * It is recommended that production systems call uxTaskGetSystemState()
\r
3447 * directly to get access to raw stats data, rather than indirectly
\r
3448 * through a call to vTaskList().
\r
3452 /* Make sure the write buffer does not contain a string. */
\r
3453 *pcWriteBuffer = 0x00;
\r
3455 /* Take a snapshot of the number of tasks in case it changes while this
\r
3456 function is executing. */
\r
3457 uxArraySize = uxCurrentNumberOfTasks;
\r
3459 /* Allocate an array index for each task. */
\r
3460 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
\r
3462 if( pxTaskStatusArray != NULL )
\r
3464 /* Generate the (binary) data. */
\r
3465 uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
\r
3467 /* Create a human readable table from the binary data. */
\r
3468 for( x = 0; x < uxArraySize; x++ )
\r
3470 switch( pxTaskStatusArray[ x ].eCurrentState )
\r
3472 case eReady: cStatus = tskREADY_CHAR;
\r
3475 case eBlocked: cStatus = tskBLOCKED_CHAR;
\r
3478 case eSuspended: cStatus = tskSUSPENDED_CHAR;
\r
3481 case eDeleted: cStatus = tskDELETED_CHAR;
\r
3484 default: /* Should not get here, but it is included
\r
3485 to prevent static checking errors. */
\r
3490 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
3491 pcWriteBuffer += strlen( pcWriteBuffer );
\r
3494 /* Free the array again. */
\r
3495 vPortFree( pxTaskStatusArray );
\r
3499 mtCOVERAGE_TEST_MARKER();
\r
3503 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
\r
3504 /*----------------------------------------------------------*/
\r
3506 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
3508 void vTaskGetRunTimeStats( char *pcWriteBuffer )
\r
3510 TaskStatus_t *pxTaskStatusArray;
\r
3511 volatile UBaseType_t uxArraySize, x;
\r
3512 uint32_t ulTotalTime, ulStatsAsPercentage;
\r
3514 #if( configUSE_TRACE_FACILITY != 1 )
\r
3516 #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats().
\r
3523 * This function is provided for convenience only, and is used by many
\r
3524 * of the demo applications. Do not consider it to be part of the
\r
3527 * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part
\r
3528 * of the uxTaskGetSystemState() output into a human readable table that
\r
3529 * displays the amount of time each task has spent in the Running state
\r
3530 * in both absolute and percentage terms.
\r
3532 * vTaskGetRunTimeStats() has a dependency on the sprintf() C library
\r
3533 * function that might bloat the code size, use a lot of stack, and
\r
3534 * provide different results on different platforms. An alternative,
\r
3535 * tiny, third party, and limited functionality implementation of
\r
3536 * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in
\r
3537 * a file called printf-stdarg.c (note printf-stdarg.c does not provide
\r
3538 * a full snprintf() implementation!).
\r
3540 * It is recommended that production systems call uxTaskGetSystemState()
\r
3541 * directly to get access to raw stats data, rather than indirectly
\r
3542 * through a call to vTaskGetRunTimeStats().
\r
3545 /* Make sure the write buffer does not contain a string. */
\r
3546 *pcWriteBuffer = 0x00;
\r
3548 /* Take a snapshot of the number of tasks in case it changes while this
\r
3549 function is executing. */
\r
3550 uxArraySize = uxCurrentNumberOfTasks;
\r
3552 /* Allocate an array index for each task. */
\r
3553 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
\r
3555 if( pxTaskStatusArray != NULL )
\r
3557 /* Generate the (binary) data. */
\r
3558 uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
\r
3560 /* For percentage calculations. */
\r
3561 ulTotalTime /= 100UL;
\r
3563 /* Avoid divide by zero errors. */
\r
3564 if( ulTotalTime > 0 )
\r
3566 /* Create a human readable table from the binary data. */
\r
3567 for( x = 0; x < uxArraySize; x++ )
\r
3569 /* What percentage of the total run time has the task used?
\r
3570 This will always be rounded down to the nearest integer.
\r
3571 ulTotalRunTimeDiv100 has already been divided by 100. */
\r
3572 ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
\r
3574 if( ulStatsAsPercentage > 0UL )
\r
3576 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
3578 sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
\r
3582 /* sizeof( int ) == sizeof( long ) so a smaller
\r
3583 printf() library can be used. */
\r
3584 sprintf( pcWriteBuffer, "%s\t\t%u\t\t%u%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );
\r
3590 /* If the percentage is zero here then the task has
\r
3591 consumed less than 1% of the total run time. */
\r
3592 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
3594 sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );
\r
3598 /* sizeof( int ) == sizeof( long ) so a smaller
\r
3599 printf() library can be used. */
\r
3600 sprintf( pcWriteBuffer, "%s\t\t%u\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter );
\r
3605 pcWriteBuffer += strlen( pcWriteBuffer );
\r
3610 mtCOVERAGE_TEST_MARKER();
\r
3613 /* Free the array again. */
\r
3614 vPortFree( pxTaskStatusArray );
\r
3618 mtCOVERAGE_TEST_MARKER();
\r
3622 #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
\r
3623 /*-----------------------------------------------------------*/
\r
3625 TickType_t uxTaskResetEventItemValue( void )
\r
3627 TickType_t uxReturn;
\r
3629 uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );
\r
3631 /* Reset the event list item to its normal value - so it can be used with
\r
3632 queues and semaphores. */
\r
3633 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
3637 /*-----------------------------------------------------------*/
\r
3639 #if ( configUSE_MUTEXES == 1 )
\r
3641 void *pvTaskIncrementMutexHeldCount( void )
\r
3643 /* If xSemaphoreCreateMutex() is called before any tasks have been created
\r
3644 then pxCurrentTCB will be NULL. */
\r
3645 if( pxCurrentTCB != NULL )
\r
3647 ( pxCurrentTCB->uxMutexesHeld )++;
\r
3650 return pxCurrentTCB;
\r
3653 #endif /* configUSE_MUTEXES */
\r
3655 /*-----------------------------------------------------------*/
\r
3657 #ifdef FREERTOS_MODULE_TEST
\r
3658 #include "tasks_test_access_functions.h"
\r