2 FreeRTOS V7.6.0 - Copyright (C) 2013 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 distribute
\r
28 >>! a combined work that includes FreeRTOS without being obliged to provide
\r
29 >>! the source code for proprietary components outside of the FreeRTOS
\r
32 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
33 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
34 FOR A PARTICULAR PURPOSE. Full license text is available from the following
\r
35 link: http://www.freertos.org/a00114.html
\r
39 ***************************************************************************
\r
41 * Having a problem? Start by reading the FAQ "My application does *
\r
42 * not run, what could be wrong?" *
\r
44 * http://www.FreeRTOS.org/FAQHelp.html *
\r
46 ***************************************************************************
\r
48 http://www.FreeRTOS.org - Documentation, books, training, latest versions,
\r
49 license and Real Time Engineers Ltd. contact details.
\r
51 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
52 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
\r
53 compatible FAT file system, and our tiny thread aware UDP/IP stack.
\r
55 http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
\r
56 Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
\r
57 licenses offer ticketed support, indemnification and middleware.
\r
59 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
60 engineered and independently SIL3 certified version for use in safety and
\r
61 mission critical applications that require provable dependability.
\r
66 /* Standard includes. */
\r
70 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
\r
71 all the API functions to use the MPU wrappers. That should only be done when
\r
72 task.h is included from an application file. */
\r
73 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
75 /* FreeRTOS includes. */
\r
76 #include "FreeRTOS.h"
\r
79 #include "StackMacros.h"
\r
81 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the
\r
82 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
\r
83 header files above, but not in this file, in order to generate the correct
\r
84 privileged Vs unprivileged linkage and placement. */
\r
85 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
\r
87 #if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 )
\r
88 /* At the bottom of this file are two optional functions that can be used
\r
89 to generate human readable text from the raw data generated by the
\r
90 uxTaskGetSystemState() function. Note the formatting functions are provided
\r
91 for convenience only, and are NOT considered part of the kernel. */
\r
93 #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
\r
95 /* Sanity check the configuration. */
\r
96 #if configUSE_TICKLESS_IDLE != 0
\r
97 #if INCLUDE_vTaskSuspend != 1
\r
98 #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0
\r
99 #endif /* INCLUDE_vTaskSuspend */
\r
100 #endif /* configUSE_TICKLESS_IDLE */
\r
103 * Defines the size, in words, of the stack allocated to the idle task.
\r
105 #define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE
\r
107 #if( configUSE_PREEMPTION == 0 )
\r
108 /* If the cooperative scheduler is being used then a yield should not be
\r
109 performed just because a higher priority task has been woken. */
\r
110 #define taskYIELD_IF_USING_PREEMPTION()
\r
112 #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
\r
116 * Task control block. A task control block (TCB) is allocated for each task,
\r
117 * and stores task state information, including a pointer to the task's context
\r
118 * (the task's run time environment, including register values)
\r
120 typedef struct tskTaskControlBlock
\r
122 volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
\r
124 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
125 xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
\r
128 xListItem xGenericListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
\r
129 xListItem xEventListItem; /*< Used to reference a task from an event list. */
\r
130 unsigned portBASE_TYPE uxPriority; /*< The priority of the task. 0 is the lowest priority. */
\r
131 portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */
\r
132 signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */
\r
134 #if ( portSTACK_GROWTH > 0 )
\r
135 portSTACK_TYPE *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */
\r
138 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
139 unsigned portBASE_TYPE uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
\r
142 #if ( configUSE_TRACE_FACILITY == 1 )
\r
143 unsigned portBASE_TYPE uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */
\r
144 unsigned portBASE_TYPE uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
\r
147 #if ( configUSE_MUTEXES == 1 )
\r
148 unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
\r
151 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
152 pdTASK_HOOK_CODE pxTaskTag;
\r
155 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
156 unsigned long ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
\r
159 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
160 /* Allocate a Newlib reent structure that is specific to this task.
\r
161 Note Newlib support has been included by popular demand, but is not
\r
162 used by the FreeRTOS maintainers themselves. FreeRTOS is not
\r
163 responsible for resulting newlib operation. User must be familiar with
\r
164 newlib and must provide system-wide implementations of the necessary
\r
165 stubs. Be warned that (at the time of writing) the current newlib design
\r
166 implements a system-wide malloc() that must be provided with locks. */
\r
167 struct _reent xNewLib_reent;
\r
173 * Some kernel aware debuggers require the data the debugger needs access to to
\r
174 * be global, rather than file scope.
\r
176 #ifdef portREMOVE_STATIC_QUALIFIER
\r
180 /*lint -e956 A manual analysis and inspection has been used to determine which
\r
181 static variables must be declared volatile. */
\r
183 PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL;
\r
185 /* Lists for ready and blocked tasks. --------------------*/
\r
186 PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */
\r
187 PRIVILEGED_DATA static xList xDelayedTaskList1; /*< Delayed tasks. */
\r
188 PRIVILEGED_DATA static xList xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
\r
189 PRIVILEGED_DATA static xList * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */
\r
190 PRIVILEGED_DATA static xList * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */
\r
191 PRIVILEGED_DATA static xList xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */
\r
193 #if ( INCLUDE_vTaskDelete == 1 )
\r
195 PRIVILEGED_DATA static xList xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */
\r
196 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTasksDeleted = ( unsigned portBASE_TYPE ) 0U;
\r
200 #if ( INCLUDE_vTaskSuspend == 1 )
\r
202 PRIVILEGED_DATA static xList xSuspendedTaskList; /*< Tasks that are currently suspended. */
\r
206 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
208 PRIVILEGED_DATA static xTaskHandle xIdleTaskHandle = NULL; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */
\r
212 /* Other file private variables. --------------------------------*/
\r
213 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0U;
\r
214 PRIVILEGED_DATA static volatile portTickType xTickCount = ( portTickType ) 0U;
\r
215 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTopReadyPriority = tskIDLE_PRIORITY;
\r
216 PRIVILEGED_DATA static volatile signed portBASE_TYPE xSchedulerRunning = pdFALSE;
\r
217 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended = ( unsigned portBASE_TYPE ) pdFALSE;
\r
218 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxPendedTicks = ( unsigned portBASE_TYPE ) 0U;
\r
219 PRIVILEGED_DATA static volatile portBASE_TYPE xYieldPending = pdFALSE;
\r
220 PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0;
\r
221 PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0U;
\r
222 PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = portMAX_DELAY;
\r
224 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
226 PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
\r
227 PRIVILEGED_DATA static unsigned long ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */
\r
233 /* Debugging and trace facilities private variables and macros. ------------*/
\r
236 * The value used to fill the stack of a task when the task is created. This
\r
237 * is used purely for checking the high water mark for tasks.
\r
239 #define tskSTACK_FILL_BYTE ( 0xa5U )
\r
242 * Macros used by vListTask to indicate which state a task is in.
\r
244 #define tskBLOCKED_CHAR ( ( signed char ) 'B' )
\r
245 #define tskREADY_CHAR ( ( signed char ) 'R' )
\r
246 #define tskDELETED_CHAR ( ( signed char ) 'D' )
\r
247 #define tskSUSPENDED_CHAR ( ( signed char ) 'S' )
\r
249 /*-----------------------------------------------------------*/
\r
251 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
\r
253 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
\r
254 performed in a generic way that is not optimised to any particular
\r
255 microcontroller architecture. */
\r
257 /* uxTopReadyPriority holds the priority of the highest priority ready
\r
259 #define taskRECORD_READY_PRIORITY( uxPriority ) \
\r
261 if( ( uxPriority ) > uxTopReadyPriority ) \
\r
263 uxTopReadyPriority = ( uxPriority ); \
\r
265 } /* taskRECORD_READY_PRIORITY */
\r
267 /*-----------------------------------------------------------*/
\r
269 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
271 /* Find the highest priority queue that contains ready tasks. */ \
\r
272 while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) \
\r
274 configASSERT( uxTopReadyPriority ); \
\r
275 --uxTopReadyPriority; \
\r
278 /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
\r
279 the same priority get an equal share of the processor time. */ \
\r
280 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \
\r
281 } /* taskSELECT_HIGHEST_PRIORITY_TASK */
\r
283 /*-----------------------------------------------------------*/
\r
285 /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
\r
286 they are only required when a port optimised method of task selection is
\r
288 #define taskRESET_READY_PRIORITY( uxPriority )
\r
289 #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
291 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
293 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
\r
294 performed in a way that is tailored to the particular microcontroller
\r
295 architecture being used. */
\r
297 /* A port optimised version is provided. Call the port defined macros. */
\r
298 #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
300 /*-----------------------------------------------------------*/
\r
302 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
304 unsigned portBASE_TYPE uxTopPriority; \
\r
306 /* Find the highest priority queue that contains ready tasks. */ \
\r
307 portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
\r
308 configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
\r
309 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
\r
310 } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
\r
312 /*-----------------------------------------------------------*/
\r
314 /* A port optimised version is provided, call it only if the TCB being reset
\r
315 is being referenced from a ready list. If it is referenced from a delayed
\r
316 or suspended list then it won't be in a ready list. */
\r
317 #define taskRESET_READY_PRIORITY( uxPriority ) \
\r
319 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == 0 ) \
\r
321 portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \
\r
325 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
327 /*-----------------------------------------------------------*/
\r
329 /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
\r
330 count overflows. */
\r
331 #define taskSWITCH_DELAYED_LISTS() \
\r
335 /* The delayed tasks list should be empty when the lists are switched. */ \
\r
336 configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \
\r
338 pxTemp = pxDelayedTaskList; \
\r
339 pxDelayedTaskList = pxOverflowDelayedTaskList; \
\r
340 pxOverflowDelayedTaskList = pxTemp; \
\r
341 xNumOfOverflows++; \
\r
342 prvResetNextTaskUnblockTime(); \
\r
345 /*-----------------------------------------------------------*/
\r
348 * Place the task represented by pxTCB into the appropriate ready list for
\r
349 * the task. It is inserted at the end of the list.
\r
351 #define prvAddTaskToReadyList( pxTCB ) \
\r
352 traceMOVED_TASK_TO_READY_STATE( pxTCB ) \
\r
353 taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
\r
354 vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) )
\r
355 /*-----------------------------------------------------------*/
\r
358 * Several functions take an xTaskHandle parameter that can optionally be NULL,
\r
359 * where NULL is used to indicate that the handle of the currently executing
\r
360 * task should be used in place of the parameter. This macro simply checks to
\r
361 * see if the parameter is NULL and returns a pointer to the appropriate TCB.
\r
363 #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( tskTCB * ) pxCurrentTCB : ( tskTCB * ) ( pxHandle ) )
\r
365 /* The item value of the event list item is normally used to hold the priority
\r
366 of the task to which it belongs (coded to allow it to be held in reverse
\r
367 priority order). However, it is occasionally borrowed for other purposes. It
\r
368 is important its value is not updated due to a task priority change while it is
\r
369 being used for another purpose. The following bit definition is used to inform
\r
370 the scheduler that the value should not be changed - in which case it is the
\r
371 responsibility of whichever module is using the value to ensure it gets set back
\r
372 to its original value when it is released. */
\r
373 #if configUSE_16_BIT_TICKS == 1
\r
374 #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U
\r
376 #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL
\r
379 /* Callback function prototypes. --------------------------*/
\r
380 #if configCHECK_FOR_STACK_OVERFLOW > 0
\r
381 extern void vApplicationStackOverflowHook( xTaskHandle xTask, signed char *pcTaskName );
\r
384 #if configUSE_TICK_HOOK > 0
\r
385 extern void vApplicationTickHook( void );
\r
388 /* File private functions. --------------------------------*/
\r
391 * Utility to ready a TCB for a given task. Mainly just copies the parameters
\r
392 * into the TCB structure.
\r
394 static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) PRIVILEGED_FUNCTION;
\r
397 * Utility to ready all the lists used by the scheduler. This is called
\r
398 * automatically upon the creation of the first task.
\r
400 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
\r
403 * The idle task, which as all tasks is implemented as a never ending loop.
\r
404 * The idle task is automatically created and added to the ready lists upon
\r
405 * creation of the first user task.
\r
407 * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
\r
408 * language extensions. The equivalent prototype for this function is:
\r
410 * void prvIdleTask( void *pvParameters );
\r
413 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
\r
416 * Utility to free all memory allocated by the scheduler to hold a TCB,
\r
417 * including the stack pointed to by the TCB.
\r
419 * This does not free memory allocated by the task itself (i.e. memory
\r
420 * allocated by calls to pvPortMalloc from within the tasks application code).
\r
422 #if ( INCLUDE_vTaskDelete == 1 )
\r
424 static void prvDeleteTCB( tskTCB *pxTCB ) PRIVILEGED_FUNCTION;
\r
429 * Used only by the idle task. This checks to see if anything has been placed
\r
430 * in the list of tasks waiting to be deleted. If so the task is cleaned up
\r
431 * and its TCB deleted.
\r
433 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
\r
436 * The currently executing task is entering the Blocked state. Add the task to
\r
437 * either the current or the overflow delayed task list.
\r
439 static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake ) PRIVILEGED_FUNCTION;
\r
442 * Allocates memory from the heap for a TCB and associated stack. Checks the
\r
443 * allocation was successful.
\r
445 static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) PRIVILEGED_FUNCTION;
\r
448 * Fills an xTaskStatusType structure with information on each task that is
\r
449 * referenced from the pxList list (which may be a ready list, a delayed list,
\r
450 * a suspended list, etc.).
\r
452 * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
\r
453 * NORMAL APPLICATION CODE.
\r
455 #if ( configUSE_TRACE_FACILITY == 1 )
\r
457 static unsigned portBASE_TYPE prvListTaskWithinSingleList( xTaskStatusType *pxTaskStatusArray, xList *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;
\r
462 * When a task is created, the stack of the task is filled with a known value.
\r
463 * This function determines the 'high water mark' of the task stack by
\r
464 * determining how much of the stack remains at the original preset value.
\r
466 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
468 static unsigned short prvTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) PRIVILEGED_FUNCTION;
\r
473 * Return the amount of time, in ticks, that will pass before the kernel will
\r
474 * next move a task from the Blocked state to the Running state.
\r
476 * This conditional compilation should use inequality to 0, not equality to 1.
\r
477 * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
\r
478 * defined low power mode implementations require configUSE_TICKLESS_IDLE to be
\r
479 * set to a value other than 1.
\r
481 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
483 static portTickType prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
\r
488 * Set xNextTaskUnblockTime to the time at which the next Blocked state task
\r
489 * will exit the Blocked state.
\r
491 static void prvResetNextTaskUnblockTime( void );
\r
493 /*-----------------------------------------------------------*/
\r
495 signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions )
\r
497 signed portBASE_TYPE xReturn;
\r
500 configASSERT( pxTaskCode );
\r
501 configASSERT( ( ( uxPriority & ( ~portPRIVILEGE_BIT ) ) < configMAX_PRIORITIES ) );
\r
503 /* Allocate the memory required by the TCB and stack for the new task,
\r
504 checking that the allocation was successful. */
\r
505 pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer );
\r
507 if( pxNewTCB != NULL )
\r
509 portSTACK_TYPE *pxTopOfStack;
\r
511 #if( portUSING_MPU_WRAPPERS == 1 )
\r
512 /* Should the task be created in privileged mode? */
\r
513 portBASE_TYPE xRunPrivileged;
\r
514 if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
\r
516 xRunPrivileged = pdTRUE;
\r
520 xRunPrivileged = pdFALSE;
\r
522 uxPriority &= ~portPRIVILEGE_BIT;
\r
523 #endif /* portUSING_MPU_WRAPPERS == 1 */
\r
525 /* Calculate the top of stack address. This depends on whether the
\r
526 stack grows from high memory to low (as per the 80x86) or vice versa.
\r
527 portSTACK_GROWTH is used to make the result positive or negative as
\r
528 required by the port. */
\r
529 #if( portSTACK_GROWTH < 0 )
\r
531 pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( unsigned short ) 1 );
\r
532 pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); /*lint !e923 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. */
\r
534 /* Check the alignment of the calculated top of stack is correct. */
\r
535 configASSERT( ( ( ( unsigned long ) pxTopOfStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
537 #else /* portSTACK_GROWTH */
\r
539 pxTopOfStack = pxNewTCB->pxStack;
\r
541 /* Check the alignment of the stack buffer is correct. */
\r
542 configASSERT( ( ( ( unsigned long ) pxNewTCB->pxStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
544 /* If we want to use stack checking on architectures that use
\r
545 a positive stack growth direction then we also need to store the
\r
546 other extreme of the stack space. */
\r
547 pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
\r
549 #endif /* portSTACK_GROWTH */
\r
551 /* Setup the newly allocated TCB with the initial state of the task. */
\r
552 prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth );
\r
554 /* Initialize the TCB stack to look as if the task was already running,
\r
555 but had been interrupted by the scheduler. The return address is set
\r
556 to the start of the task function. Once the stack has been initialised
\r
557 the top of stack variable is updated. */
\r
558 #if( portUSING_MPU_WRAPPERS == 1 )
\r
560 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
\r
562 #else /* portUSING_MPU_WRAPPERS */
\r
564 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
\r
566 #endif /* portUSING_MPU_WRAPPERS */
\r
568 if( ( void * ) pxCreatedTask != NULL )
\r
570 /* Pass the TCB out - in an anonymous way. The calling function/
\r
571 task can use this as a handle to delete the task later if
\r
573 *pxCreatedTask = ( xTaskHandle ) pxNewTCB;
\r
576 /* Ensure interrupts don't access the task lists while they are being
\r
578 taskENTER_CRITICAL();
\r
580 uxCurrentNumberOfTasks++;
\r
581 if( pxCurrentTCB == NULL )
\r
583 /* There are no other tasks, or all the other tasks are in
\r
584 the suspended state - make this the current task. */
\r
585 pxCurrentTCB = pxNewTCB;
\r
587 if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 )
\r
589 /* This is the first task to be created so do the preliminary
\r
590 initialisation required. We will not recover if this call
\r
591 fails, but we will report the failure. */
\r
592 prvInitialiseTaskLists();
\r
597 /* If the scheduler is not already running, make this task the
\r
598 current task if it is the highest priority task to be created
\r
600 if( xSchedulerRunning == pdFALSE )
\r
602 if( pxCurrentTCB->uxPriority <= uxPriority )
\r
604 pxCurrentTCB = pxNewTCB;
\r
611 #if ( configUSE_TRACE_FACILITY == 1 )
\r
613 /* Add a counter into the TCB for tracing only. */
\r
614 pxNewTCB->uxTCBNumber = uxTaskNumber;
\r
616 #endif /* configUSE_TRACE_FACILITY */
\r
617 traceTASK_CREATE( pxNewTCB );
\r
619 prvAddTaskToReadyList( pxNewTCB );
\r
622 portSETUP_TCB( pxNewTCB );
\r
624 taskEXIT_CRITICAL();
\r
628 xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
\r
629 traceTASK_CREATE_FAILED();
\r
632 if( xReturn == pdPASS )
\r
634 if( xSchedulerRunning != pdFALSE )
\r
636 /* If the created task is of a higher priority than the current task
\r
637 then it should run now. */
\r
638 if( pxCurrentTCB->uxPriority < uxPriority )
\r
640 taskYIELD_IF_USING_PREEMPTION();
\r
647 /*-----------------------------------------------------------*/
\r
649 #if ( INCLUDE_vTaskDelete == 1 )
\r
651 void vTaskDelete( xTaskHandle xTaskToDelete )
\r
655 taskENTER_CRITICAL();
\r
657 /* If null is passed in here then it is the calling task that is
\r
659 pxTCB = prvGetTCBFromHandle( xTaskToDelete );
\r
661 /* Remove task from the ready list and place in the termination list.
\r
662 This will stop the task from be scheduled. The idle task will check
\r
663 the termination list and free up any memory allocated by the
\r
664 scheduler for the TCB and stack. */
\r
665 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
\r
667 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
670 /* Is the task waiting on an event also? */
\r
671 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
673 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
676 vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );
\r
678 /* Increment the ucTasksDeleted variable so the idle task knows
\r
679 there is a task that has been deleted and that it should therefore
\r
680 check the xTasksWaitingTermination list. */
\r
683 /* Increment the uxTaskNumberVariable also so kernel aware debuggers
\r
684 can detect that the task lists need re-generating. */
\r
687 traceTASK_DELETE( pxTCB );
\r
689 taskEXIT_CRITICAL();
\r
691 /* Force a reschedule if it is the currently running task that has just
\r
693 if( xSchedulerRunning != pdFALSE )
\r
695 if( pxTCB == pxCurrentTCB )
\r
697 configASSERT( uxSchedulerSuspended == 0 );
\r
699 /* The pre-delete hook is primarily for the Windows simulator,
\r
700 in which Windows specific clean up operations are performed,
\r
701 after which it is not possible to yield away from this task -
\r
702 hence xYieldPending is used to latch that a context switch is
\r
704 portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
\r
705 portYIELD_WITHIN_API();
\r
709 /* Reset the next expected unblock time in case it referred to
\r
710 the task that has just been deleted. */
\r
711 prvResetNextTaskUnblockTime();
\r
716 #endif /* INCLUDE_vTaskDelete */
\r
717 /*-----------------------------------------------------------*/
\r
719 #if ( INCLUDE_vTaskDelayUntil == 1 )
\r
721 void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, const portTickType xTimeIncrement )
\r
723 portTickType xTimeToWake;
\r
724 portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE;
\r
726 configASSERT( pxPreviousWakeTime );
\r
727 configASSERT( ( xTimeIncrement > 0U ) );
\r
728 configASSERT( uxSchedulerSuspended == 0 );
\r
732 /* Minor optimisation. The tick count cannot change in this
\r
734 const portTickType xConstTickCount = xTickCount;
\r
736 /* Generate the tick time at which the task wants to wake. */
\r
737 xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
\r
739 if( xConstTickCount < *pxPreviousWakeTime )
\r
741 /* The tick count has overflowed since this function was
\r
742 lasted called. In this case the only time we should ever
\r
743 actually delay is if the wake time has also overflowed,
\r
744 and the wake time is greater than the tick time. When this
\r
745 is the case it is as if neither time had overflowed. */
\r
746 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
\r
748 xShouldDelay = pdTRUE;
\r
753 /* The tick time has not overflowed. In this case we will
\r
754 delay if either the wake time has overflowed, and/or the
\r
755 tick time is less than the wake time. */
\r
756 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
\r
758 xShouldDelay = pdTRUE;
\r
762 /* Update the wake time ready for the next call. */
\r
763 *pxPreviousWakeTime = xTimeToWake;
\r
765 if( xShouldDelay != pdFALSE )
\r
767 traceTASK_DELAY_UNTIL();
\r
769 /* We must remove ourselves from the ready list before adding
\r
770 ourselves to the blocked list as the same list item is used for
\r
772 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
\r
774 /* The current task must be in a ready list, so there is
\r
775 no need to check, and the port reset macro can be called
\r
777 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
780 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
783 xAlreadyYielded = xTaskResumeAll();
\r
785 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
786 have put ourselves to sleep. */
\r
787 if( xAlreadyYielded == pdFALSE )
\r
789 portYIELD_WITHIN_API();
\r
793 #endif /* INCLUDE_vTaskDelayUntil */
\r
794 /*-----------------------------------------------------------*/
\r
796 #if ( INCLUDE_vTaskDelay == 1 )
\r
798 void vTaskDelay( const portTickType xTicksToDelay )
\r
800 portTickType xTimeToWake;
\r
801 signed portBASE_TYPE xAlreadyYielded = pdFALSE;
\r
804 /* A delay time of zero just forces a reschedule. */
\r
805 if( xTicksToDelay > ( portTickType ) 0U )
\r
807 configASSERT( uxSchedulerSuspended == 0 );
\r
812 /* A task that is removed from the event list while the
\r
813 scheduler is suspended will not get placed in the ready
\r
814 list or removed from the blocked list until the scheduler
\r
817 This task cannot be in an event list as it is the currently
\r
820 /* Calculate the time to wake - this may overflow but this is
\r
822 xTimeToWake = xTickCount + xTicksToDelay;
\r
824 /* We must remove ourselves from the ready list before adding
\r
825 ourselves to the blocked list as the same list item is used for
\r
827 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
\r
829 /* The current task must be in a ready list, so there is
\r
830 no need to check, and the port reset macro can be called
\r
832 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
834 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
836 xAlreadyYielded = xTaskResumeAll();
\r
839 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
840 have put ourselves to sleep. */
\r
841 if( xAlreadyYielded == pdFALSE )
\r
843 portYIELD_WITHIN_API();
\r
847 #endif /* INCLUDE_vTaskDelay */
\r
848 /*-----------------------------------------------------------*/
\r
850 #if ( INCLUDE_eTaskGetState == 1 )
\r
852 eTaskState eTaskGetState( xTaskHandle xTask )
\r
854 eTaskState eReturn;
\r
855 xList *pxStateList;
\r
856 const tskTCB * const pxTCB = ( tskTCB * ) xTask;
\r
858 configASSERT( pxTCB );
\r
860 if( pxTCB == pxCurrentTCB )
\r
862 /* The task calling this function is querying its own state. */
\r
863 eReturn = eRunning;
\r
867 taskENTER_CRITICAL();
\r
869 pxStateList = ( xList * ) listLIST_ITEM_CONTAINER( &( pxTCB->xGenericListItem ) );
\r
871 taskEXIT_CRITICAL();
\r
873 if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) )
\r
875 /* The task being queried is referenced from one of the Blocked
\r
877 eReturn = eBlocked;
\r
880 #if ( INCLUDE_vTaskSuspend == 1 )
\r
881 else if( pxStateList == &xSuspendedTaskList )
\r
883 /* The task being queried is referenced from the suspended
\r
884 list. Is it genuinely suspended or is it block
\r
886 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
\r
888 eReturn = eSuspended;
\r
892 eReturn = eBlocked;
\r
897 #if ( INCLUDE_vTaskDelete == 1 )
\r
898 else if( pxStateList == &xTasksWaitingTermination )
\r
900 /* The task being queried is referenced from the deleted
\r
902 eReturn = eDeleted;
\r
908 /* If the task is not in any other state, it must be in the
\r
909 Ready (including pending ready) state. */
\r
917 #endif /* INCLUDE_eTaskGetState */
\r
918 /*-----------------------------------------------------------*/
\r
920 #if ( INCLUDE_uxTaskPriorityGet == 1 )
\r
922 unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle xTask )
\r
925 unsigned portBASE_TYPE uxReturn;
\r
927 taskENTER_CRITICAL();
\r
929 /* If null is passed in here then we are changing the
\r
930 priority of the calling function. */
\r
931 pxTCB = prvGetTCBFromHandle( xTask );
\r
932 uxReturn = pxTCB->uxPriority;
\r
934 taskEXIT_CRITICAL();
\r
939 #endif /* INCLUDE_uxTaskPriorityGet */
\r
940 /*-----------------------------------------------------------*/
\r
942 #if ( INCLUDE_vTaskPrioritySet == 1 )
\r
944 void vTaskPrioritySet( xTaskHandle xTask, unsigned portBASE_TYPE uxNewPriority )
\r
947 unsigned portBASE_TYPE uxCurrentBasePriority, uxPriorityUsedOnEntry;
\r
948 portBASE_TYPE xYieldRequired = pdFALSE;
\r
950 configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
\r
952 /* Ensure the new priority is valid. */
\r
953 if( uxNewPriority >= ( unsigned portBASE_TYPE ) configMAX_PRIORITIES )
\r
955 uxNewPriority = ( unsigned portBASE_TYPE ) configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U;
\r
958 taskENTER_CRITICAL();
\r
960 /* If null is passed in here then it is the priority of the calling
\r
961 task that is being changed. */
\r
962 pxTCB = prvGetTCBFromHandle( xTask );
\r
964 traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
\r
966 #if ( configUSE_MUTEXES == 1 )
\r
968 uxCurrentBasePriority = pxTCB->uxBasePriority;
\r
972 uxCurrentBasePriority = pxTCB->uxPriority;
\r
976 if( uxCurrentBasePriority != uxNewPriority )
\r
978 /* The priority change may have readied a task of higher
\r
979 priority than the calling task. */
\r
980 if( uxNewPriority > uxCurrentBasePriority )
\r
982 if( pxTCB != pxCurrentTCB )
\r
984 /* The priority of a task other than the currently
\r
985 running task is being raised. Is the priority being
\r
986 raised above that of the running task? */
\r
987 if( uxNewPriority >= pxCurrentTCB->uxPriority )
\r
989 xYieldRequired = pdTRUE;
\r
994 /* The priority of the running task is being raised,
\r
995 but the running task must already be the highest
\r
996 priority task able to run so no yield is required. */
\r
999 else if( pxTCB == pxCurrentTCB )
\r
1001 /* Setting the priority of the running task down means
\r
1002 there may now be another task of higher priority that
\r
1003 is ready to execute. */
\r
1004 xYieldRequired = pdTRUE;
\r
1008 /* Setting the priority of any other task down does not
\r
1009 require a yield as the running task must be above the
\r
1010 new priority of the task being modified. */
\r
1013 /* Remember the ready list the task might be referenced from
\r
1014 before its uxPriority member is changed so the
\r
1015 taskRESET_READY_PRIORITY() macro can function correctly. */
\r
1016 uxPriorityUsedOnEntry = pxTCB->uxPriority;
\r
1018 #if ( configUSE_MUTEXES == 1 )
\r
1020 /* Only change the priority being used if the task is not
\r
1021 currently using an inherited priority. */
\r
1022 if( pxTCB->uxBasePriority == pxTCB->uxPriority )
\r
1024 pxTCB->uxPriority = uxNewPriority;
\r
1027 /* The base priority gets set whatever. */
\r
1028 pxTCB->uxBasePriority = uxNewPriority;
\r
1032 pxTCB->uxPriority = uxNewPriority;
\r
1036 /* Only reset the event list item value if the value is not
\r
1037 being used for anything else. */
\r
1038 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0 )
\r
1040 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( portTickType ) configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
1043 /* If the task is in the blocked or suspended list we need do
\r
1044 nothing more than change it's priority variable. However, if
\r
1045 the task is in a ready list it needs to be removed and placed
\r
1046 in the list appropriate to its new priority. */
\r
1047 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
\r
1049 /* The task is currently in its ready list - remove before adding
\r
1050 it to it's new ready list. As we are in a critical section we
\r
1051 can do this even if the scheduler is suspended. */
\r
1052 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
\r
1054 /* It is known that the task is in its ready list so
\r
1055 there is no need to check again and the port level
\r
1056 reset macro can be called directly. */
\r
1057 portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
\r
1059 prvAddTaskToReadyList( pxTCB );
\r
1062 if( xYieldRequired == pdTRUE )
\r
1064 taskYIELD_IF_USING_PREEMPTION();
\r
1067 /* Remove compiler warning about unused variables when the port
\r
1068 optimised task selection is not being used. */
\r
1069 ( void ) uxPriorityUsedOnEntry;
\r
1072 taskEXIT_CRITICAL();
\r
1075 #endif /* INCLUDE_vTaskPrioritySet */
\r
1076 /*-----------------------------------------------------------*/
\r
1078 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1080 void vTaskSuspend( xTaskHandle xTaskToSuspend )
\r
1084 taskENTER_CRITICAL();
\r
1086 /* If null is passed in here then it is the running task that is
\r
1087 being suspended. */
\r
1088 pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
\r
1090 traceTASK_SUSPEND( pxTCB );
\r
1092 /* Remove task from the ready/delayed list and place in the
\r
1093 suspended list. */
\r
1094 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
\r
1096 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
1099 /* Is the task waiting on an event also? */
\r
1100 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
1102 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1105 vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) );
\r
1107 taskEXIT_CRITICAL();
\r
1109 if( pxTCB == pxCurrentTCB )
\r
1111 if( xSchedulerRunning != pdFALSE )
\r
1113 /* The current task has just been suspended. */
\r
1114 configASSERT( uxSchedulerSuspended == 0 );
\r
1115 portYIELD_WITHIN_API();
\r
1119 /* The scheduler is not running, but the task that was pointed
\r
1120 to by pxCurrentTCB has just been suspended and pxCurrentTCB
\r
1121 must be adjusted to point to a different task. */
\r
1122 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )
\r
1124 /* No other tasks are ready, so set pxCurrentTCB back to
\r
1125 NULL so when the next task is created pxCurrentTCB will
\r
1126 be set to point to it no matter what its relative priority
\r
1128 pxCurrentTCB = NULL;
\r
1132 vTaskSwitchContext();
\r
1138 if( xSchedulerRunning != pdFALSE )
\r
1140 /* A task other than the currently running task was suspended,
\r
1141 reset the next expected unblock time in case it referred to the
\r
1142 task that is now in the Suspended state. */
\r
1143 prvResetNextTaskUnblockTime();
\r
1148 #endif /* INCLUDE_vTaskSuspend */
\r
1149 /*-----------------------------------------------------------*/
\r
1151 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1153 signed portBASE_TYPE xTaskIsTaskSuspended( const xTaskHandle xTask )
\r
1155 signed portBASE_TYPE xReturn = pdFALSE;
\r
1156 const tskTCB * const pxTCB = ( tskTCB * ) xTask;
\r
1158 /* It does not make sense to check if the calling task is suspended. */
\r
1159 configASSERT( xTask );
\r
1161 /* Is the task we are attempting to resume actually in the
\r
1162 suspended list? */
\r
1163 if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
\r
1165 /* Has the task already been resumed from within an ISR? */
\r
1166 if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
\r
1168 /* Is it in the suspended list because it is in the
\r
1169 Suspended state? It is possible to be in the suspended
\r
1170 list because it is blocked on a task with no timeout
\r
1172 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )
\r
1180 } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
\r
1182 #endif /* INCLUDE_vTaskSuspend */
\r
1183 /*-----------------------------------------------------------*/
\r
1185 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1187 void vTaskResume( xTaskHandle xTaskToResume )
\r
1189 tskTCB * const pxTCB = ( tskTCB * ) xTaskToResume;
\r
1191 /* It does not make sense to resume the calling task. */
\r
1192 configASSERT( xTaskToResume );
\r
1194 /* The parameter cannot be NULL as it is impossible to resume the
\r
1195 currently executing task. */
\r
1196 if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
\r
1198 taskENTER_CRITICAL();
\r
1200 if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
\r
1202 traceTASK_RESUME( pxTCB );
\r
1204 /* As we are in a critical section we can access the ready
\r
1205 lists even if the scheduler is suspended. */
\r
1206 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1207 prvAddTaskToReadyList( pxTCB );
\r
1209 /* We may have just resumed a higher priority task. */
\r
1210 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1212 /* This yield may not cause the task just resumed to run,
\r
1213 but will leave the lists in the correct state for the
\r
1215 taskYIELD_IF_USING_PREEMPTION();
\r
1219 taskEXIT_CRITICAL();
\r
1223 #endif /* INCLUDE_vTaskSuspend */
\r
1225 /*-----------------------------------------------------------*/
\r
1227 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
\r
1229 portBASE_TYPE xTaskResumeFromISR( xTaskHandle xTaskToResume )
\r
1231 portBASE_TYPE xYieldRequired = pdFALSE;
\r
1232 tskTCB * const pxTCB = ( tskTCB * ) xTaskToResume;
\r
1233 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
1235 configASSERT( xTaskToResume );
\r
1237 /* RTOS ports that support interrupt nesting have the concept of a
\r
1238 maximum system call (or maximum API call) interrupt priority.
\r
1239 Interrupts that are above the maximum system call priority are keep
\r
1240 permanently enabled, even when the RTOS kernel is in a critical section,
\r
1241 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
1242 is defined in FreeRTOSConfig.h then
\r
1243 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1244 failure if a FreeRTOS API function is called from an interrupt that has
\r
1245 been assigned a priority above the configured maximum system call
\r
1246 priority. Only FreeRTOS functions that end in FromISR can be called
\r
1247 from interrupts that have been assigned a priority at or (logically)
\r
1248 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
1249 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
1250 simple as possible. More information (albeit Cortex-M specific) is
\r
1251 provided on the following link:
\r
1252 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1253 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1255 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1257 if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
\r
1259 traceTASK_RESUME_FROM_ISR( pxTCB );
\r
1261 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
\r
1263 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1265 xYieldRequired = pdTRUE;
\r
1268 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1269 prvAddTaskToReadyList( pxTCB );
\r
1273 /* We cannot access the delayed or ready lists, so will hold this
\r
1274 task pending until the scheduler is resumed, at which point a
\r
1275 yield will be performed if necessary. */
\r
1276 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
1280 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1282 return xYieldRequired;
\r
1285 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
\r
1286 /*-----------------------------------------------------------*/
\r
1288 void vTaskStartScheduler( void )
\r
1290 portBASE_TYPE xReturn;
\r
1292 /* Add the idle task at the lowest priority. */
\r
1293 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
1295 /* Create the idle task, storing its handle in xIdleTaskHandle so it can
\r
1296 be returned by the xTaskGetIdleTaskHandle() function. */
\r
1297 xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
\r
1301 /* Create the idle task without storing its handle. */
\r
1302 xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), NULL ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
\r
1304 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
\r
1306 #if ( configUSE_TIMERS == 1 )
\r
1308 if( xReturn == pdPASS )
\r
1310 xReturn = xTimerCreateTimerTask();
\r
1313 #endif /* configUSE_TIMERS */
\r
1315 if( xReturn == pdPASS )
\r
1317 /* Interrupts are turned off here, to ensure a tick does not occur
\r
1318 before or during the call to xPortStartScheduler(). The stacks of
\r
1319 the created tasks contain a status word with interrupts switched on
\r
1320 so interrupts will automatically get re-enabled when the first task
\r
1322 portDISABLE_INTERRUPTS();
\r
1324 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
1326 /* Switch Newlib's _impure_ptr variable to point to the _reent
\r
1327 structure specific to the task that will run first. */
\r
1328 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
\r
1330 #endif /* configUSE_NEWLIB_REENTRANT */
\r
1332 xSchedulerRunning = pdTRUE;
\r
1333 xTickCount = ( portTickType ) 0U;
\r
1335 /* If configGENERATE_RUN_TIME_STATS is defined then the following
\r
1336 macro must be defined to configure the timer/counter used to generate
\r
1337 the run time counter time base. */
\r
1338 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
\r
1340 /* Setting up the timer tick is hardware specific and thus in the
\r
1341 portable interface. */
\r
1342 if( xPortStartScheduler() != pdFALSE )
\r
1344 /* Should not reach here as if the scheduler is running the
\r
1345 function will not return. */
\r
1349 /* Should only reach here if a task calls xTaskEndScheduler(). */
\r
1354 /* This line will only be reached if the kernel could not be started,
\r
1355 because there was not enough FreeRTOS heap to create the idle task
\r
1356 or the timer task. */
\r
1357 configASSERT( xReturn );
\r
1360 /*-----------------------------------------------------------*/
\r
1362 void vTaskEndScheduler( void )
\r
1364 /* Stop the scheduler interrupts and call the portable scheduler end
\r
1365 routine so the original ISRs can be restored if necessary. The port
\r
1366 layer must ensure interrupts enable bit is left in the correct state. */
\r
1367 portDISABLE_INTERRUPTS();
\r
1368 xSchedulerRunning = pdFALSE;
\r
1369 vPortEndScheduler();
\r
1371 /*----------------------------------------------------------*/
\r
1373 void vTaskSuspendAll( void )
\r
1375 /* A critical section is not required as the variable is of type
\r
1376 portBASE_TYPE. Please read Richard Barry's reply in the following link to a
\r
1377 post in the FreeRTOS support forum before reporting this as a bug! -
\r
1378 http://goo.gl/wu4acr */
\r
1379 ++uxSchedulerSuspended;
\r
1381 /*----------------------------------------------------------*/
\r
1383 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
1385 static portTickType prvGetExpectedIdleTime( void )
\r
1387 portTickType xReturn;
\r
1389 if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
\r
1393 else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
\r
1395 /* There are other idle priority tasks in the ready state. If
\r
1396 time slicing is used then the very next tick interrupt must be
\r
1402 xReturn = xNextTaskUnblockTime - xTickCount;
\r
1408 #endif /* configUSE_TICKLESS_IDLE */
\r
1409 /*----------------------------------------------------------*/
\r
1411 signed portBASE_TYPE xTaskResumeAll( void )
\r
1414 portBASE_TYPE xAlreadyYielded = pdFALSE;
\r
1416 /* If uxSchedulerSuspended is zero then this function does not match a
\r
1417 previous call to vTaskSuspendAll(). */
\r
1418 configASSERT( uxSchedulerSuspended );
\r
1420 /* It is possible that an ISR caused a task to be removed from an event
\r
1421 list while the scheduler was suspended. If this was the case then the
\r
1422 removed task will have been added to the xPendingReadyList. Once the
\r
1423 scheduler has been resumed it is safe to move all the pending ready
\r
1424 tasks from this list into their appropriate ready list. */
\r
1425 taskENTER_CRITICAL();
\r
1427 --uxSchedulerSuspended;
\r
1429 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
\r
1431 if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0U )
\r
1433 /* Move any readied tasks from the pending list into the
\r
1434 appropriate ready list. */
\r
1435 while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
\r
1437 pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );
\r
1438 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1439 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1440 prvAddTaskToReadyList( pxTCB );
\r
1442 /* If we have moved a task that has a priority higher than
\r
1443 the current task then we should yield. */
\r
1444 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1446 xYieldPending = pdTRUE;
\r
1450 /* If any ticks occurred while the scheduler was suspended then
\r
1451 they should be processed now. This ensures the tick count does
\r
1452 not slip, and that any delayed tasks are resumed at the correct
\r
1454 if( uxPendedTicks > ( unsigned portBASE_TYPE ) 0U )
\r
1456 while( uxPendedTicks > ( unsigned portBASE_TYPE ) 0U )
\r
1458 if( xTaskIncrementTick() != pdFALSE )
\r
1460 xYieldPending = pdTRUE;
\r
1466 if( xYieldPending == pdTRUE )
\r
1468 #if( configUSE_PREEMPTION != 0 )
\r
1470 xAlreadyYielded = pdTRUE;
\r
1473 taskYIELD_IF_USING_PREEMPTION();
\r
1478 taskEXIT_CRITICAL();
\r
1480 return xAlreadyYielded;
\r
1482 /*-----------------------------------------------------------*/
\r
1484 portTickType xTaskGetTickCount( void )
\r
1486 portTickType xTicks;
\r
1488 /* Critical section required if running on a 16 bit processor. */
\r
1489 taskENTER_CRITICAL();
\r
1491 xTicks = xTickCount;
\r
1493 taskEXIT_CRITICAL();
\r
1497 /*-----------------------------------------------------------*/
\r
1499 portTickType xTaskGetTickCountFromISR( void )
\r
1501 portTickType xReturn;
\r
1502 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
1504 /* RTOS ports that support interrupt nesting have the concept of a maximum
\r
1505 system call (or maximum API call) interrupt priority. Interrupts that are
\r
1506 above the maximum system call priority are kept permanently enabled, even
\r
1507 when the RTOS kernel is in a critical section, but cannot make any calls to
\r
1508 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
\r
1509 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1510 failure if a FreeRTOS API function is called from an interrupt that has been
\r
1511 assigned a priority above the configured maximum system call priority.
\r
1512 Only FreeRTOS functions that end in FromISR can be called from interrupts
\r
1513 that have been assigned a priority at or (logically) below the maximum
\r
1514 system call interrupt priority. FreeRTOS maintains a separate interrupt
\r
1515 safe API to ensure interrupt entry is as fast and as simple as possible.
\r
1516 More information (albeit Cortex-M specific) is provided on the following
\r
1517 link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1518 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1520 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1521 xReturn = xTickCount;
\r
1522 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1526 /*-----------------------------------------------------------*/
\r
1528 unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
\r
1530 /* A critical section is not required because the variables are of type
\r
1532 return uxCurrentNumberOfTasks;
\r
1534 /*-----------------------------------------------------------*/
\r
1536 #if ( INCLUDE_pcTaskGetTaskName == 1 )
\r
1538 signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery )
\r
1542 /* If null is passed in here then the name of the calling task is being queried. */
\r
1543 pxTCB = prvGetTCBFromHandle( xTaskToQuery );
\r
1544 configASSERT( pxTCB );
\r
1545 return &( pxTCB->pcTaskName[ 0 ] );
\r
1548 #endif /* INCLUDE_pcTaskGetTaskName */
\r
1549 /*-----------------------------------------------------------*/
\r
1551 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1553 unsigned portBASE_TYPE uxTaskGetSystemState( xTaskStatusType *pxTaskStatusArray, unsigned portBASE_TYPE uxArraySize, unsigned long *pulTotalRunTime )
\r
1555 unsigned portBASE_TYPE uxTask = 0, uxQueue = configMAX_PRIORITIES;
\r
1557 vTaskSuspendAll();
\r
1559 /* Is there a space in the array for each task in the system? */
\r
1560 if( uxArraySize >= uxCurrentNumberOfTasks )
\r
1562 /* Fill in an xTaskStatusType structure with information on each
\r
1563 task in the Ready state. */
\r
1567 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
\r
1569 } while( uxQueue > ( unsigned portBASE_TYPE ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
1571 /* Fill in an xTaskStatusType structure with information on each
\r
1572 task in the Blocked state. */
\r
1573 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( xList * ) pxDelayedTaskList, eBlocked );
\r
1574 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( xList * ) pxOverflowDelayedTaskList, eBlocked );
\r
1576 #if( INCLUDE_vTaskDelete == 1 )
\r
1578 /* Fill in an xTaskStatusType structure with information on
\r
1579 each task that has been deleted but not yet cleaned up. */
\r
1580 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
\r
1584 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1586 /* Fill in an xTaskStatusType structure with information on
\r
1587 each task in the Suspended state. */
\r
1588 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
\r
1592 #if ( configGENERATE_RUN_TIME_STATS == 1)
\r
1594 if( pulTotalRunTime != NULL )
\r
1596 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
1597 portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
\r
1599 *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
1605 if( pulTotalRunTime != NULL )
\r
1607 *pulTotalRunTime = 0;
\r
1613 ( void ) xTaskResumeAll();
\r
1618 #endif /* configUSE_TRACE_FACILITY */
\r
1619 /*----------------------------------------------------------*/
\r
1621 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
1623 xTaskHandle xTaskGetIdleTaskHandle( void )
\r
1625 /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
\r
1626 started, then xIdleTaskHandle will be NULL. */
\r
1627 configASSERT( ( xIdleTaskHandle != NULL ) );
\r
1628 return xIdleTaskHandle;
\r
1631 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
\r
1632 /*----------------------------------------------------------*/
\r
1634 /* This conditional compilation should use inequality to 0, not equality to 1.
\r
1635 This is to ensure vTaskStepTick() is available when user defined low power mode
\r
1636 implementations require configUSE_TICKLESS_IDLE to be set to a value other than
\r
1638 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
1640 void vTaskStepTick( portTickType xTicksToJump )
\r
1642 /* Correct the tick count value after a period during which the tick
\r
1643 was suppressed. Note this does *not* call the tick hook function for
\r
1644 each stepped tick. */
\r
1645 configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
\r
1646 xTickCount += xTicksToJump;
\r
1647 traceINCREASE_TICK_COUNT( xTicksToJump );
\r
1650 #endif /* configUSE_TICKLESS_IDLE */
\r
1651 /*----------------------------------------------------------*/
\r
1653 portBASE_TYPE xTaskIncrementTick( void )
\r
1656 portTickType xItemValue;
\r
1657 portBASE_TYPE xSwitchRequired = pdFALSE;
\r
1659 /* Called by the portable layer each time a tick interrupt occurs.
\r
1660 Increments the tick then checks to see if the new tick value will cause any
\r
1661 tasks to be unblocked. */
\r
1662 traceTASK_INCREMENT_TICK( xTickCount );
\r
1663 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
\r
1665 /* Increment the RTOS tick, switching the delayed and overflowed
\r
1666 delayed lists if it wraps to 0. */
\r
1670 /* Minor optimisation. The tick count cannot change in this
\r
1672 const portTickType xConstTickCount = xTickCount;
\r
1674 if( xConstTickCount == ( portTickType ) 0U )
\r
1676 taskSWITCH_DELAYED_LISTS();
\r
1679 /* See if this tick has made a timeout expire. Tasks are stored in
\r
1680 the queue in the order of their wake time - meaning once one task
\r
1681 has been found whose block time has not expired there is no need to
\r
1682 look any further down the list. */
\r
1683 if( xConstTickCount >= xNextTaskUnblockTime )
\r
1687 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
\r
1689 /* The delayed list is empty. Set xNextTaskUnblockTime
\r
1690 to the maximum possible value so it is extremely
\r
1692 if( xTickCount >= xNextTaskUnblockTime ) test will pass
\r
1693 next time through. */
\r
1694 xNextTaskUnblockTime = portMAX_DELAY;
\r
1699 /* The delayed list is not empty, get the value of the
\r
1700 item at the head of the delayed list. This is the time
\r
1701 at which the task at the head of the delayed list must
\r
1702 be removed from the Blocked state. */
\r
1703 pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
\r
1704 xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
\r
1706 if( xConstTickCount < xItemValue )
\r
1708 /* It is not time to unblock this item yet, but the
\r
1709 item value is the time at which the task at the head
\r
1710 of the blocked list must be removed from the Blocked
\r
1711 state - so record the item value in
\r
1712 xNextTaskUnblockTime. */
\r
1713 xNextTaskUnblockTime = xItemValue;
\r
1717 /* It is time to remove the item from the Blocked state. */
\r
1718 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1720 /* Is the task waiting on an event also? If so remove
\r
1721 it from the event list. */
\r
1722 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
1724 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1727 /* Place the unblocked task into the appropriate ready
\r
1729 prvAddTaskToReadyList( pxTCB );
\r
1731 /* A task being unblocked cannot cause an immediate
\r
1732 context switch if preemption is turned off. */
\r
1733 #if ( configUSE_PREEMPTION == 1 )
\r
1735 /* Preemption is on, but a context switch should
\r
1736 only be performed if the unblocked task has a
\r
1737 priority that is equal to or higher than the
\r
1738 currently executing task. */
\r
1739 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1741 xSwitchRequired = pdTRUE;
\r
1744 #endif /* configUSE_PREEMPTION */
\r
1750 /* Tasks of equal priority to the currently running task will share
\r
1751 processing time (time slice) if preemption is on, and the application
\r
1752 writer has not explicitly turned time slicing off. */
\r
1753 #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
\r
1755 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( unsigned portBASE_TYPE ) 1 )
\r
1757 xSwitchRequired = pdTRUE;
\r
1760 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
\r
1762 #if ( configUSE_TICK_HOOK == 1 )
\r
1764 /* Guard against the tick hook being called when the pended tick
\r
1765 count is being unwound (when the scheduler is being unlocked). */
\r
1766 if( uxPendedTicks == ( unsigned portBASE_TYPE ) 0U )
\r
1768 vApplicationTickHook();
\r
1771 #endif /* configUSE_TICK_HOOK */
\r
1777 /* The tick hook gets called at regular intervals, even if the
\r
1778 scheduler is locked. */
\r
1779 #if ( configUSE_TICK_HOOK == 1 )
\r
1781 vApplicationTickHook();
\r
1786 #if ( configUSE_PREEMPTION == 1 )
\r
1788 if( xYieldPending != pdFALSE )
\r
1790 xSwitchRequired = pdTRUE;
\r
1793 #endif /* configUSE_PREEMPTION */
\r
1795 return xSwitchRequired;
\r
1797 /*-----------------------------------------------------------*/
\r
1799 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
1801 void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction )
\r
1805 /* If xTask is NULL then it is the task hook of the calling task that is
\r
1807 if( xTask == NULL )
\r
1809 xTCB = ( tskTCB * ) pxCurrentTCB;
\r
1813 xTCB = ( tskTCB * ) xTask;
\r
1816 /* Save the hook function in the TCB. A critical section is required as
\r
1817 the value can be accessed from an interrupt. */
\r
1818 taskENTER_CRITICAL();
\r
1819 xTCB->pxTaskTag = pxHookFunction;
\r
1820 taskEXIT_CRITICAL();
\r
1823 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
1824 /*-----------------------------------------------------------*/
\r
1826 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
1828 pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask )
\r
1831 pdTASK_HOOK_CODE xReturn;
\r
1833 /* If xTask is NULL then we are setting our own task hook. */
\r
1834 if( xTask == NULL )
\r
1836 xTCB = ( tskTCB * ) pxCurrentTCB;
\r
1840 xTCB = ( tskTCB * ) xTask;
\r
1843 /* Save the hook function in the TCB. A critical section is required as
\r
1844 the value can be accessed from an interrupt. */
\r
1845 taskENTER_CRITICAL();
\r
1846 xReturn = xTCB->pxTaskTag;
\r
1847 taskEXIT_CRITICAL();
\r
1852 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
1853 /*-----------------------------------------------------------*/
\r
1855 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
1857 portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter )
\r
1860 portBASE_TYPE xReturn;
\r
1862 /* If xTask is NULL then we are calling our own task hook. */
\r
1863 if( xTask == NULL )
\r
1865 xTCB = ( tskTCB * ) pxCurrentTCB;
\r
1869 xTCB = ( tskTCB * ) xTask;
\r
1872 if( xTCB->pxTaskTag != NULL )
\r
1874 xReturn = xTCB->pxTaskTag( pvParameter );
\r
1884 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
1885 /*-----------------------------------------------------------*/
\r
1887 void vTaskSwitchContext( void )
\r
1889 if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE )
\r
1891 /* The scheduler is currently suspended - do not allow a context
\r
1893 xYieldPending = pdTRUE;
\r
1897 xYieldPending = pdFALSE;
\r
1898 traceTASK_SWITCHED_OUT();
\r
1900 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
1902 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
1903 portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
\r
1905 ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
1908 /* Add the amount of time the task has been running to the
\r
1909 accumulated time so far. The time the task started running was
\r
1910 stored in ulTaskSwitchedInTime. Note that there is no overflow
\r
1911 protection here so count values are only valid until the timer
\r
1912 overflows. The guard against negative values is to protect
\r
1913 against suspect run time stat counter implementations - which
\r
1914 are provided by the application, not the kernel. */
\r
1915 if( ulTotalRunTime > ulTaskSwitchedInTime )
\r
1917 pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
\r
1919 ulTaskSwitchedInTime = ulTotalRunTime;
\r
1921 #endif /* configGENERATE_RUN_TIME_STATS */
\r
1923 taskFIRST_CHECK_FOR_STACK_OVERFLOW();
\r
1924 taskSECOND_CHECK_FOR_STACK_OVERFLOW();
\r
1926 taskSELECT_HIGHEST_PRIORITY_TASK();
\r
1928 traceTASK_SWITCHED_IN();
\r
1930 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
1932 /* Switch Newlib's _impure_ptr variable to point to the _reent
\r
1933 structure specific to this task. */
\r
1934 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
\r
1936 #endif /* configUSE_NEWLIB_REENTRANT */
\r
1939 /*-----------------------------------------------------------*/
\r
1941 void vTaskPlaceOnEventList( xList * const pxEventList, const portTickType xTicksToWait )
\r
1943 portTickType xTimeToWake;
\r
1945 configASSERT( pxEventList );
\r
1947 /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
\r
1948 SCHEDULER SUSPENDED. */
\r
1950 /* Place the event list item of the TCB in the appropriate event list.
\r
1951 This is placed in the list in priority order so the highest priority task
\r
1952 is the first to be woken by the event. */
\r
1953 vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
1955 /* We must remove ourselves from the ready list before adding ourselves
\r
1956 to the blocked list as the same list item is used for both lists. We have
\r
1957 exclusive access to the ready lists as the scheduler is locked. */
\r
1958 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
\r
1960 /* The current task must be in a ready list, so there is no need to
\r
1961 check, and the port reset macro can be called directly. */
\r
1962 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
1965 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1967 if( xTicksToWait == portMAX_DELAY )
\r
1969 /* Add ourselves to the suspended task list instead of a delayed task
\r
1970 list to ensure we are not woken by a timing event. We will block
\r
1972 vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
\r
1976 /* Calculate the time at which the task should be woken if the event does
\r
1977 not occur. This may overflow but this doesn't matter. */
\r
1978 xTimeToWake = xTickCount + xTicksToWait;
\r
1979 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
1982 #else /* INCLUDE_vTaskSuspend */
\r
1984 /* Calculate the time at which the task should be woken if the event does
\r
1985 not occur. This may overflow but this doesn't matter. */
\r
1986 xTimeToWake = xTickCount + xTicksToWait;
\r
1987 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
1989 #endif /* INCLUDE_vTaskSuspend */
\r
1991 /*-----------------------------------------------------------*/
\r
1993 void vTaskPlaceOnUnorderedEventList( xList * pxEventList, portTickType xItemValue, const portTickType xTicksToWait )
\r
1995 portTickType xTimeToWake;
\r
1997 configASSERT( pxEventList );
\r
1999 /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
\r
2000 SCHEDULER SUSPENDED. */
\r
2002 /* Store the item value in the event list item. */
\r
2003 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
\r
2005 /* Place the event list item of the TCB at the end of the appropriate event
\r
2007 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2009 /* The task must be removed from the ready list before it is added to the
\r
2010 blocked list. Exclusive access can be assured to the ready list as the
\r
2011 scheduler is locked. */
\r
2012 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
\r
2014 /* The current task must be in a ready list, so there is no need to
\r
2015 check, and the port reset macro can be called directly. */
\r
2016 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
2019 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2021 if( xTicksToWait == portMAX_DELAY )
\r
2023 /* Add the task to the suspended task list instead of a delayed task
\r
2024 list to ensure it is not woken by a timing event. It will block
\r
2026 vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
\r
2030 /* Calculate the time at which the task should be woken if the event does
\r
2031 not occur. This may overflow but this doesn't matter. */
\r
2032 xTimeToWake = xTickCount + xTicksToWait;
\r
2033 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
2036 #else /* INCLUDE_vTaskSuspend */
\r
2038 /* Calculate the time at which the task should be woken if the event does
\r
2039 not occur. This may overflow but this doesn't matter. */
\r
2040 xTimeToWake = xTickCount + xTicksToWait;
\r
2041 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
2043 #endif /* INCLUDE_vTaskSuspend */
\r
2045 /*-----------------------------------------------------------*/
\r
2047 #if configUSE_TIMERS == 1
\r
2049 void vTaskPlaceOnEventListRestricted( xList * const pxEventList, portTickType xTicksToWait )
\r
2051 portTickType xTimeToWake;
\r
2053 configASSERT( pxEventList );
\r
2055 /* This function should not be called by application code hence the
\r
2056 'Restricted' in its name. It is not part of the public API. It is
\r
2057 designed for use by kernel code, and has special calling requirements -
\r
2058 it should be called from a critical section. */
\r
2061 /* Place the event list item of the TCB in the appropriate event list.
\r
2062 In this case it is assume that this is the only task that is going to
\r
2063 be waiting on this event list, so the faster vListInsertEnd() function
\r
2064 can be used in place of vListInsert. */
\r
2065 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2067 /* We must remove this task from the ready list before adding it to the
\r
2068 blocked list as the same list item is used for both lists. This
\r
2069 function is called form a critical section. */
\r
2070 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
\r
2072 /* The current task must be in a ready list, so there is no need to
\r
2073 check, and the port reset macro can be called directly. */
\r
2074 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
2077 /* Calculate the time at which the task should be woken if the event does
\r
2078 not occur. This may overflow but this doesn't matter. */
\r
2079 xTimeToWake = xTickCount + xTicksToWait;
\r
2081 traceTASK_DELAY_UNTIL();
\r
2082 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
2085 #endif /* configUSE_TIMERS */
\r
2086 /*-----------------------------------------------------------*/
\r
2088 signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList )
\r
2090 tskTCB *pxUnblockedTCB;
\r
2091 portBASE_TYPE xReturn;
\r
2093 /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
\r
2094 SCHEDULER SUSPENDED. It can also be called from within an ISR. */
\r
2096 /* The event list is sorted in priority order, so we can remove the
\r
2097 first in the list, remove the TCB from the delayed list, and add
\r
2098 it to the ready list.
\r
2100 If an event is for a queue that is locked then this function will never
\r
2101 get called - the lock count on the queue will get modified instead. This
\r
2102 means we can always expect exclusive access to the event list here.
\r
2104 This function assumes that a check has already been made to ensure that
\r
2105 pxEventList is not empty. */
\r
2106 pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
\r
2107 configASSERT( pxUnblockedTCB );
\r
2108 ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
\r
2110 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
\r
2112 ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
\r
2113 prvAddTaskToReadyList( pxUnblockedTCB );
\r
2117 /* We cannot access the delayed or ready lists, so will hold this
\r
2118 task pending until the scheduler is resumed. */
\r
2119 vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
\r
2122 if( pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
2124 /* Return true if the task removed from the event list has
\r
2125 a higher priority than the calling task. This allows
\r
2126 the calling task to know if it should force a context
\r
2130 /* Mark that a yield is pending in case the user is not using the
\r
2131 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
\r
2132 xYieldPending = pdTRUE;
\r
2136 xReturn = pdFALSE;
\r
2141 /*-----------------------------------------------------------*/
\r
2143 signed portBASE_TYPE xTaskRemoveFromUnorderedEventList( xListItem * pxEventListItem, portTickType xItemValue )
\r
2145 tskTCB *pxUnblockedTCB;
\r
2146 portBASE_TYPE xReturn;
\r
2148 /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
\r
2149 SCHEDULER SUSPENDED. It can also be called from within an ISR. */
\r
2151 /* Store the new item value in the event list. */
\r
2152 listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
\r
2154 /* Remove the TCB from the delayed list, and add it to the ready list. */
\r
2156 pxUnblockedTCB = ( tskTCB * ) listGET_LIST_ITEM_OWNER( pxEventListItem );
\r
2157 configASSERT( pxUnblockedTCB );
\r
2158 ( void ) uxListRemove( pxEventListItem );
\r
2160 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
\r
2162 ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
\r
2163 prvAddTaskToReadyList( pxUnblockedTCB );
\r
2167 /* Cannot access the delayed or ready lists, so will hold this task
\r
2168 pending until the scheduler is resumed. */
\r
2169 vListInsertEnd( &( xPendingReadyList ), pxEventListItem );
\r
2172 if( pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
2174 /* Return true if the task removed from the event list has
\r
2175 a higher priority than the calling task. This allows
\r
2176 the calling task to know if it should force a context
\r
2180 /* Mark that a yield is pending in case the user is not using the
\r
2181 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
\r
2182 xYieldPending = pdTRUE;
\r
2186 xReturn = pdFALSE;
\r
2191 /*-----------------------------------------------------------*/
\r
2193 void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut )
\r
2195 configASSERT( pxTimeOut );
\r
2196 pxTimeOut->xOverflowCount = xNumOfOverflows;
\r
2197 pxTimeOut->xTimeOnEntering = xTickCount;
\r
2199 /*-----------------------------------------------------------*/
\r
2201 portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait )
\r
2203 portBASE_TYPE xReturn;
\r
2205 configASSERT( pxTimeOut );
\r
2206 configASSERT( pxTicksToWait );
\r
2208 taskENTER_CRITICAL();
\r
2210 /* Minor optimisation. The tick count cannot change in this block. */
\r
2211 const portTickType xConstTickCount = xTickCount;
\r
2213 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2214 /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is
\r
2215 the maximum block time then the task should block indefinitely, and
\r
2216 therefore never time out. */
\r
2217 if( *pxTicksToWait == portMAX_DELAY )
\r
2219 xReturn = pdFALSE;
\r
2221 else /* We are not blocking indefinitely, perform the checks below. */
\r
2224 if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
\r
2226 /* The tick count is greater than the time at which vTaskSetTimeout()
\r
2227 was called, but has also overflowed since vTaskSetTimeOut() was called.
\r
2228 It must have wrapped all the way around and gone past us again. This
\r
2229 passed since vTaskSetTimeout() was called. */
\r
2232 else if( ( xConstTickCount - pxTimeOut->xTimeOnEntering ) < *pxTicksToWait )
\r
2234 /* Not a genuine timeout. Adjust parameters for time remaining. */
\r
2235 *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );
\r
2236 vTaskSetTimeOutState( pxTimeOut );
\r
2237 xReturn = pdFALSE;
\r
2244 taskEXIT_CRITICAL();
\r
2248 /*-----------------------------------------------------------*/
\r
2250 void vTaskMissedYield( void )
\r
2252 xYieldPending = pdTRUE;
\r
2254 /*-----------------------------------------------------------*/
\r
2256 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2258 unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask )
\r
2260 unsigned portBASE_TYPE uxReturn;
\r
2263 if( xTask != NULL )
\r
2265 pxTCB = ( tskTCB * ) xTask;
\r
2266 uxReturn = pxTCB->uxTaskNumber;
\r
2276 #endif /* configUSE_TRACE_FACILITY */
\r
2277 /*-----------------------------------------------------------*/
\r
2279 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2281 void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle )
\r
2285 if( xTask != NULL )
\r
2287 pxTCB = ( tskTCB * ) xTask;
\r
2288 pxTCB->uxTaskNumber = uxHandle;
\r
2292 #endif /* configUSE_TRACE_FACILITY */
\r
2295 * -----------------------------------------------------------
\r
2297 * ----------------------------------------------------------
\r
2299 * The portTASK_FUNCTION() macro is used to allow port/compiler specific
\r
2300 * language extensions. The equivalent prototype for this function is:
\r
2302 * void prvIdleTask( void *pvParameters );
\r
2305 static portTASK_FUNCTION( prvIdleTask, pvParameters )
\r
2307 /* Stop warnings. */
\r
2308 ( void ) pvParameters;
\r
2312 /* See if any tasks have been deleted. */
\r
2313 prvCheckTasksWaitingTermination();
\r
2315 #if ( configUSE_PREEMPTION == 0 )
\r
2317 /* If we are not using preemption we keep forcing a task switch to
\r
2318 see if any other task has become available. If we are using
\r
2319 preemption we don't need to do this as any task becoming available
\r
2320 will automatically get the processor anyway. */
\r
2323 #endif /* configUSE_PREEMPTION */
\r
2325 #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
\r
2327 /* When using preemption tasks of equal priority will be
\r
2328 timesliced. If a task that is sharing the idle priority is ready
\r
2329 to run then the idle task should yield before the end of the
\r
2332 A critical region is not required here as we are just reading from
\r
2333 the list, and an occasional incorrect value will not matter. If
\r
2334 the ready list at the idle priority contains more than one task
\r
2335 then a task other than the idle task is ready to execute. */
\r
2336 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( unsigned portBASE_TYPE ) 1 )
\r
2341 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
\r
2343 #if ( configUSE_IDLE_HOOK == 1 )
\r
2345 extern void vApplicationIdleHook( void );
\r
2347 /* Call the user defined function from within the idle task. This
\r
2348 allows the application designer to add background functionality
\r
2349 without the overhead of a separate task.
\r
2350 NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
\r
2351 CALL A FUNCTION THAT MIGHT BLOCK. */
\r
2352 vApplicationIdleHook();
\r
2354 #endif /* configUSE_IDLE_HOOK */
\r
2356 /* This conditional compilation should use inequality to 0, not equality
\r
2357 to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
\r
2358 user defined low power mode implementations require
\r
2359 configUSE_TICKLESS_IDLE to be set to a value other than 1. */
\r
2360 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
2362 portTickType xExpectedIdleTime;
\r
2364 /* It is not desirable to suspend then resume the scheduler on
\r
2365 each iteration of the idle task. Therefore, a preliminary
\r
2366 test of the expected idle time is performed without the
\r
2367 scheduler suspended. The result here is not necessarily
\r
2369 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
2371 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
2373 vTaskSuspendAll();
\r
2375 /* Now the scheduler is suspended, the expected idle
\r
2376 time can be sampled again, and this time its value can
\r
2378 configASSERT( xNextTaskUnblockTime >= xTickCount );
\r
2379 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
2381 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
2383 traceLOW_POWER_IDLE_BEGIN();
\r
2384 portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
\r
2385 traceLOW_POWER_IDLE_END();
\r
2388 ( void ) xTaskResumeAll();
\r
2391 #endif /* configUSE_TICKLESS_IDLE */
\r
2394 /*-----------------------------------------------------------*/
\r
2396 #if configUSE_TICKLESS_IDLE != 0
\r
2398 eSleepModeStatus eTaskConfirmSleepModeStatus( void )
\r
2400 eSleepModeStatus eReturn = eStandardSleep;
\r
2402 if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
\r
2404 /* A task was made ready while the scheduler was suspended. */
\r
2405 eReturn = eAbortSleep;
\r
2407 else if( xYieldPending != pdFALSE )
\r
2409 /* A yield was pended while the scheduler was suspended. */
\r
2410 eReturn = eAbortSleep;
\r
2414 #if configUSE_TIMERS == 0
\r
2416 /* The idle task exists in addition to the application tasks. */
\r
2417 const unsigned portBASE_TYPE uxNonApplicationTasks = 1;
\r
2419 /* If timers are not being used and all the tasks are in the
\r
2420 suspended list (which might mean they have an infinite block
\r
2421 time rather than actually being suspended) then it is safe to
\r
2422 turn all clocks off and just wait for external interrupts. */
\r
2423 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
\r
2425 eReturn = eNoTasksWaitingTimeout;
\r
2428 #endif /* configUSE_TIMERS */
\r
2433 #endif /* configUSE_TICKLESS_IDLE */
\r
2434 /*-----------------------------------------------------------*/
\r
2436 static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth )
\r
2438 unsigned portBASE_TYPE x;
\r
2440 /* Store the task name in the TCB. */
\r
2441 for( x = ( unsigned portBASE_TYPE ) 0; x < ( unsigned portBASE_TYPE ) configMAX_TASK_NAME_LEN; x++ )
\r
2443 pxTCB->pcTaskName[ x ] = pcName[ x ];
\r
2445 /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
\r
2446 configMAX_TASK_NAME_LEN characters just in case the memory after the
\r
2447 string is not accessible (extremely unlikely). */
\r
2448 if( pcName[ x ] == 0x00 )
\r
2454 /* Ensure the name string is terminated in the case that the string length
\r
2455 was greater or equal to configMAX_TASK_NAME_LEN. */
\r
2456 pxTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = ( signed char ) '\0';
\r
2458 /* This is used as an array index so must ensure it's not too large. First
\r
2459 remove the privilege bit if one is present. */
\r
2460 if( uxPriority >= ( unsigned portBASE_TYPE ) configMAX_PRIORITIES )
\r
2462 uxPriority = ( unsigned portBASE_TYPE ) configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U;
\r
2465 pxTCB->uxPriority = uxPriority;
\r
2466 #if ( configUSE_MUTEXES == 1 )
\r
2468 pxTCB->uxBasePriority = uxPriority;
\r
2470 #endif /* configUSE_MUTEXES */
\r
2472 vListInitialiseItem( &( pxTCB->xGenericListItem ) );
\r
2473 vListInitialiseItem( &( pxTCB->xEventListItem ) );
\r
2475 /* Set the pxTCB as a link back from the xListItem. This is so we can get
\r
2476 back to the containing TCB from a generic item in a list. */
\r
2477 listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB );
\r
2479 /* Event lists are always in priority order. */
\r
2480 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( portTickType ) configMAX_PRIORITIES - ( portTickType ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2481 listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB );
\r
2483 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
2485 pxTCB->uxCriticalNesting = ( unsigned portBASE_TYPE ) 0U;
\r
2487 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
2489 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2491 pxTCB->pxTaskTag = NULL;
\r
2493 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2495 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
2497 pxTCB->ulRunTimeCounter = 0UL;
\r
2499 #endif /* configGENERATE_RUN_TIME_STATS */
\r
2501 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
2503 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth );
\r
2505 #else /* portUSING_MPU_WRAPPERS */
\r
2507 ( void ) xRegions;
\r
2508 ( void ) usStackDepth;
\r
2510 #endif /* portUSING_MPU_WRAPPERS */
\r
2512 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
2514 /* Initialise this task's Newlib reent structure. */
\r
2515 _REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) );
\r
2517 #endif /* configUSE_NEWLIB_REENTRANT */
\r
2519 /*-----------------------------------------------------------*/
\r
2521 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
2523 void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions )
\r
2527 /* If null is passed in here then we are deleting ourselves. */
\r
2528 pxTCB = prvGetTCBFromHandle( xTaskToModify );
\r
2530 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
\r
2533 #endif /* portUSING_MPU_WRAPPERS */
\r
2534 /*-----------------------------------------------------------*/
\r
2536 static void prvInitialiseTaskLists( void )
\r
2538 unsigned portBASE_TYPE uxPriority;
\r
2540 for( uxPriority = ( unsigned portBASE_TYPE ) 0U; uxPriority < ( unsigned portBASE_TYPE ) configMAX_PRIORITIES; uxPriority++ )
\r
2542 vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
\r
2545 vListInitialise( &xDelayedTaskList1 );
\r
2546 vListInitialise( &xDelayedTaskList2 );
\r
2547 vListInitialise( &xPendingReadyList );
\r
2549 #if ( INCLUDE_vTaskDelete == 1 )
\r
2551 vListInitialise( &xTasksWaitingTermination );
\r
2553 #endif /* INCLUDE_vTaskDelete */
\r
2555 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2557 vListInitialise( &xSuspendedTaskList );
\r
2559 #endif /* INCLUDE_vTaskSuspend */
\r
2561 /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
\r
2563 pxDelayedTaskList = &xDelayedTaskList1;
\r
2564 pxOverflowDelayedTaskList = &xDelayedTaskList2;
\r
2566 /*-----------------------------------------------------------*/
\r
2568 static void prvCheckTasksWaitingTermination( void )
\r
2570 #if ( INCLUDE_vTaskDelete == 1 )
\r
2572 portBASE_TYPE xListIsEmpty;
\r
2574 /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
\r
2575 too often in the idle task. */
\r
2576 while( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0U )
\r
2578 vTaskSuspendAll();
\r
2579 xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
\r
2580 ( void ) xTaskResumeAll();
\r
2582 if( xListIsEmpty == pdFALSE )
\r
2586 taskENTER_CRITICAL();
\r
2588 pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
\r
2589 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
2590 --uxCurrentNumberOfTasks;
\r
2593 taskEXIT_CRITICAL();
\r
2595 prvDeleteTCB( pxTCB );
\r
2599 #endif /* vTaskDelete */
\r
2601 /*-----------------------------------------------------------*/
\r
2603 static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake )
\r
2605 /* The list item will be inserted in wake time order. */
\r
2606 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
\r
2608 if( xTimeToWake < xTickCount )
\r
2610 /* Wake time has overflowed. Place this item in the overflow list. */
\r
2611 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
\r
2615 /* The wake time has not overflowed, so the current block list is used. */
\r
2616 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
\r
2618 /* If the task entering the blocked state was placed at the head of the
\r
2619 list of blocked tasks then xNextTaskUnblockTime needs to be updated
\r
2621 if( xTimeToWake < xNextTaskUnblockTime )
\r
2623 xNextTaskUnblockTime = xTimeToWake;
\r
2627 /*-----------------------------------------------------------*/
\r
2629 static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer )
\r
2633 /* Allocate space for the TCB. Where the memory comes from depends on
\r
2634 the implementation of the port malloc function. */
\r
2635 pxNewTCB = ( tskTCB * ) pvPortMalloc( sizeof( tskTCB ) );
\r
2637 if( pxNewTCB != NULL )
\r
2639 /* Allocate space for the stack used by the task being created.
\r
2640 The base of the stack memory stored in the TCB so the task can
\r
2641 be deleted later if required. */
\r
2642 pxNewTCB->pxStack = ( portSTACK_TYPE * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( portSTACK_TYPE ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2644 if( pxNewTCB->pxStack == NULL )
\r
2646 /* Could not allocate the stack. Delete the allocated TCB. */
\r
2647 vPortFree( pxNewTCB );
\r
2652 /* Avoid dependency on memset() if it is not required. */
\r
2653 #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
2655 /* Just to help debugging. */
\r
2656 ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( portSTACK_TYPE ) );
\r
2658 #endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */
\r
2664 /*-----------------------------------------------------------*/
\r
2666 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2668 static unsigned portBASE_TYPE prvListTaskWithinSingleList( xTaskStatusType *pxTaskStatusArray, xList *pxList, eTaskState eState )
\r
2670 volatile tskTCB *pxNextTCB, *pxFirstTCB;
\r
2671 unsigned portBASE_TYPE uxTask = 0;
\r
2673 if( listCURRENT_LIST_LENGTH( pxList ) > ( unsigned portBASE_TYPE ) 0 )
\r
2675 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
\r
2677 /* Populate an xTaskStatusType structure within the
\r
2678 pxTaskStatusArray array for each task that is referenced from
\r
2679 pxList. See the definition of xTaskStatusType in task.h for the
\r
2680 meaning of each xTaskStatusType structure member. */
\r
2683 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
\r
2685 pxTaskStatusArray[ uxTask ].xHandle = ( xTaskHandle ) pxNextTCB;
\r
2686 pxTaskStatusArray[ uxTask ].pcTaskName = ( const signed char * ) &( pxNextTCB->pcTaskName [ 0 ] );
\r
2687 pxTaskStatusArray[ uxTask ].xTaskNumber = pxNextTCB->uxTCBNumber;
\r
2688 pxTaskStatusArray[ uxTask ].eCurrentState = eState;
\r
2689 pxTaskStatusArray[ uxTask ].uxCurrentPriority = pxNextTCB->uxPriority;
\r
2691 #if ( configUSE_MUTEXES == 1 )
\r
2693 pxTaskStatusArray[ uxTask ].uxBasePriority = pxNextTCB->uxBasePriority;
\r
2697 pxTaskStatusArray[ uxTask ].uxBasePriority = 0;
\r
2701 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
2703 pxTaskStatusArray[ uxTask ].ulRunTimeCounter = pxNextTCB->ulRunTimeCounter;
\r
2707 pxTaskStatusArray[ uxTask ].ulRunTimeCounter = 0;
\r
2711 #if ( portSTACK_GROWTH > 0 )
\r
2713 pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxEndOfStack );
\r
2717 pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack );
\r
2723 } while( pxNextTCB != pxFirstTCB );
\r
2729 #endif /* configUSE_TRACE_FACILITY */
\r
2730 /*-----------------------------------------------------------*/
\r
2732 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
2734 static unsigned short prvTaskCheckFreeStackSpace( const unsigned char * pucStackByte )
\r
2736 unsigned long ulCount = 0U;
\r
2738 while( *pucStackByte == tskSTACK_FILL_BYTE )
\r
2740 pucStackByte -= portSTACK_GROWTH;
\r
2744 ulCount /= ( unsigned long ) sizeof( portSTACK_TYPE );
\r
2746 return ( unsigned short ) ulCount;
\r
2749 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */
\r
2750 /*-----------------------------------------------------------*/
\r
2752 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
\r
2754 unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask )
\r
2757 unsigned char *pcEndOfStack;
\r
2758 unsigned portBASE_TYPE uxReturn;
\r
2760 pxTCB = prvGetTCBFromHandle( xTask );
\r
2762 #if portSTACK_GROWTH < 0
\r
2764 pcEndOfStack = ( unsigned char * ) pxTCB->pxStack;
\r
2768 pcEndOfStack = ( unsigned char * ) pxTCB->pxEndOfStack;
\r
2772 uxReturn = ( unsigned portBASE_TYPE ) prvTaskCheckFreeStackSpace( pcEndOfStack );
\r
2777 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
\r
2778 /*-----------------------------------------------------------*/
\r
2780 #if ( INCLUDE_vTaskDelete == 1 )
\r
2782 static void prvDeleteTCB( tskTCB *pxTCB )
\r
2784 /* This call is required specifically for the TriCore port. It must be
\r
2785 above the vPortFree() calls. The call is also used by ports/demos that
\r
2786 want to allocate and clean RAM statically. */
\r
2787 portCLEAN_UP_TCB( pxTCB );
\r
2789 /* Free up the memory allocated by the scheduler for the task. It is up to
\r
2790 the task to free any memory allocated at the application level. */
\r
2791 vPortFreeAligned( pxTCB->pxStack );
\r
2792 vPortFree( pxTCB );
\r
2795 #endif /* INCLUDE_vTaskDelete */
\r
2796 /*-----------------------------------------------------------*/
\r
2798 static void prvResetNextTaskUnblockTime( void )
\r
2802 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
\r
2804 /* The new current delayed list is empty. Set
\r
2805 xNextTaskUnblockTime to the maximum possible value so it is
\r
2806 extremely unlikely that the
\r
2807 if( xTickCount >= xNextTaskUnblockTime ) test will pass until
\r
2808 there is an item in the delayed list. */
\r
2809 xNextTaskUnblockTime = portMAX_DELAY;
\r
2813 /* The new current delayed list is not empty, get the value of
\r
2814 the item at the head of the delayed list. This is the time at
\r
2815 which the task at the head of the delayed list should be removed
\r
2816 from the Blocked state. */
\r
2817 ( pxTCB ) = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
\r
2818 xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xGenericListItem ) );
\r
2821 /*-----------------------------------------------------------*/
\r
2823 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
\r
2825 xTaskHandle xTaskGetCurrentTaskHandle( void )
\r
2827 xTaskHandle xReturn;
\r
2829 /* A critical section is not required as this is not called from
\r
2830 an interrupt and the current TCB will always be the same for any
\r
2831 individual execution thread. */
\r
2832 xReturn = pxCurrentTCB;
\r
2837 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
\r
2838 /*-----------------------------------------------------------*/
\r
2840 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
2842 portBASE_TYPE xTaskGetSchedulerState( void )
\r
2844 portBASE_TYPE xReturn;
\r
2846 if( xSchedulerRunning == pdFALSE )
\r
2848 xReturn = taskSCHEDULER_NOT_STARTED;
\r
2852 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
\r
2854 xReturn = taskSCHEDULER_RUNNING;
\r
2858 xReturn = taskSCHEDULER_SUSPENDED;
\r
2865 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
\r
2866 /*-----------------------------------------------------------*/
\r
2868 #if ( configUSE_MUTEXES == 1 )
\r
2870 void vTaskPriorityInherit( xTaskHandle const pxMutexHolder )
\r
2872 tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;
\r
2874 /* If the mutex was given back by an interrupt while the queue was
\r
2875 locked then the mutex holder might now be NULL. */
\r
2876 if( pxMutexHolder != NULL )
\r
2878 if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
\r
2880 /* Adjust the mutex holder state to account for its new
\r
2881 priority. Only reset the event list item value if the value is
\r
2882 not being used for anything else. */
\r
2883 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0 )
\r
2885 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( portTickType ) configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2888 /* If the task being modified is in the ready state it will need to
\r
2889 be moved into a new list. */
\r
2890 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
\r
2892 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
\r
2894 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
2897 /* Inherit the priority before being moved into the new list. */
\r
2898 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
2899 prvAddTaskToReadyList( pxTCB );
\r
2903 /* Just inherit the priority. */
\r
2904 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
2907 traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );
\r
2912 #endif /* configUSE_MUTEXES */
\r
2913 /*-----------------------------------------------------------*/
\r
2915 #if ( configUSE_MUTEXES == 1 )
\r
2917 void vTaskPriorityDisinherit( xTaskHandle const pxMutexHolder )
\r
2919 tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;
\r
2921 if( pxMutexHolder != NULL )
\r
2923 if( pxTCB->uxPriority != pxTCB->uxBasePriority )
\r
2925 /* We must be the running task to be able to give the mutex back.
\r
2926 Remove ourselves from the ready list we currently appear in. */
\r
2927 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( unsigned portBASE_TYPE ) 0 )
\r
2929 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
2932 /* Disinherit the priority before adding the task into the new
\r
2934 traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
\r
2935 pxTCB->uxPriority = pxTCB->uxBasePriority;
\r
2937 /* Only reset the event list item value if the value is not
\r
2938 being used for anything else. */
\r
2939 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0 )
\r
2941 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( portTickType ) configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2943 prvAddTaskToReadyList( pxTCB );
\r
2948 #endif /* configUSE_MUTEXES */
\r
2949 /*-----------------------------------------------------------*/
\r
2951 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
2953 void vTaskEnterCritical( void )
\r
2955 portDISABLE_INTERRUPTS();
\r
2957 if( xSchedulerRunning != pdFALSE )
\r
2959 ( pxCurrentTCB->uxCriticalNesting )++;
\r
2963 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
2964 /*-----------------------------------------------------------*/
\r
2966 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
2968 void vTaskExitCritical( void )
\r
2970 if( xSchedulerRunning != pdFALSE )
\r
2972 if( pxCurrentTCB->uxCriticalNesting > 0U )
\r
2974 ( pxCurrentTCB->uxCriticalNesting )--;
\r
2976 if( pxCurrentTCB->uxCriticalNesting == 0U )
\r
2978 portENABLE_INTERRUPTS();
\r
2984 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
2985 /*-----------------------------------------------------------*/
\r
2987 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) )
\r
2989 void vTaskList( signed char *pcWriteBuffer )
\r
2991 xTaskStatusType *pxTaskStatusArray;
\r
2992 volatile unsigned portBASE_TYPE uxArraySize, x;
\r
2993 signed char cStatus;
\r
2998 * This function is provided for convenience only, and is used by many
\r
2999 * of the demo applications. Do not consider it to be part of the
\r
3002 * vTaskList() calls uxTaskGetSystemState(), then formats part of the
\r
3003 * uxTaskGetSystemState() output into a human readable table that
\r
3004 * displays task names, states and stack usage.
\r
3006 * vTaskList() has a dependency on the sprintf() C library function that
\r
3007 * might bloat the code size, use a lot of stack, and provide different
\r
3008 * results on different platforms. An alternative, tiny, third party,
\r
3009 * and limited functionality implementation of sprintf() is provided in
\r
3010 * many of the FreeRTOS/Demo sub-directories in a file called
\r
3011 * printf-stdarg.c (note printf-stdarg.c does not provide a full
\r
3012 * snprintf() implementation!).
\r
3014 * It is recommended that production systems call uxTaskGetSystemState()
\r
3015 * directly to get access to raw stats data, rather than indirectly
\r
3016 * through a call to vTaskList().
\r
3020 /* Make sure the write buffer does not contain a string. */
\r
3021 *pcWriteBuffer = 0x00;
\r
3023 /* Take a snapshot of the number of tasks in case it changes while this
\r
3024 function is executing. */
\r
3025 uxArraySize = uxCurrentNumberOfTasks;
\r
3027 /* Allocate an array index for each task. */
\r
3028 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( xTaskStatusType ) );
\r
3030 if( pxTaskStatusArray != NULL )
\r
3032 /* Generate the (binary) data. */
\r
3033 uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
\r
3035 /* Create a human readable table from the binary data. */
\r
3036 for( x = 0; x < uxArraySize; x++ )
\r
3038 switch( pxTaskStatusArray[ x ].eCurrentState )
\r
3040 case eReady: cStatus = tskREADY_CHAR;
\r
3043 case eBlocked: cStatus = tskBLOCKED_CHAR;
\r
3046 case eSuspended: cStatus = tskSUSPENDED_CHAR;
\r
3049 case eDeleted: cStatus = tskDELETED_CHAR;
\r
3052 default: /* Should not get here, but it is included
\r
3053 to prevent static checking errors. */
\r
3058 sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxTaskStatusArray[ x ].pcTaskName, ( char ) cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber );
\r
3059 pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
\r
3062 /* Free the array again. */
\r
3063 vPortFree( pxTaskStatusArray );
\r
3067 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) */
\r
3068 /*----------------------------------------------------------*/
\r
3070 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) )
\r
3072 void vTaskGetRunTimeStats( signed char *pcWriteBuffer )
\r
3074 xTaskStatusType *pxTaskStatusArray;
\r
3075 volatile unsigned portBASE_TYPE uxArraySize, x;
\r
3076 unsigned long ulTotalTime, ulStatsAsPercentage;
\r
3081 * This function is provided for convenience only, and is used by many
\r
3082 * of the demo applications. Do not consider it to be part of the
\r
3085 * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part
\r
3086 * of the uxTaskGetSystemState() output into a human readable table that
\r
3087 * displays the amount of time each task has spent in the Running state
\r
3088 * in both absolute and percentage terms.
\r
3090 * vTaskGetRunTimeStats() has a dependency on the sprintf() C library
\r
3091 * function that might bloat the code size, use a lot of stack, and
\r
3092 * provide different results on different platforms. An alternative,
\r
3093 * tiny, third party, and limited functionality implementation of
\r
3094 * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in
\r
3095 * a file called printf-stdarg.c (note printf-stdarg.c does not provide
\r
3096 * a full snprintf() implementation!).
\r
3098 * It is recommended that production systems call uxTaskGetSystemState()
\r
3099 * directly to get access to raw stats data, rather than indirectly
\r
3100 * through a call to vTaskGetRunTimeStats().
\r
3103 /* Make sure the write buffer does not contain a string. */
\r
3104 *pcWriteBuffer = 0x00;
\r
3106 /* Take a snapshot of the number of tasks in case it changes while this
\r
3107 function is executing. */
\r
3108 uxArraySize = uxCurrentNumberOfTasks;
\r
3110 /* Allocate an array index for each task. */
\r
3111 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( xTaskStatusType ) );
\r
3113 if( pxTaskStatusArray != NULL )
\r
3115 /* Generate the (binary) data. */
\r
3116 uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
\r
3118 /* For percentage calculations. */
\r
3119 ulTotalTime /= 100UL;
\r
3121 /* Avoid divide by zero errors. */
\r
3122 if( ulTotalTime > 0 )
\r
3124 /* Create a human readable table from the binary data. */
\r
3125 for( x = 0; x < uxArraySize; x++ )
\r
3127 /* What percentage of the total run time has the task used?
\r
3128 This will always be rounded down to the nearest integer.
\r
3129 ulTotalRunTimeDiv100 has already been divided by 100. */
\r
3130 ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
\r
3132 if( ulStatsAsPercentage > 0UL )
\r
3134 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
3136 sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
\r
3140 /* sizeof( int ) == sizeof( long ) so a smaller
\r
3141 printf() library can be used. */
\r
3142 sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%u\t\t%u%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );
\r
3148 /* If the percentage is zero here then the task has
\r
3149 consumed less than 1% of the total run time. */
\r
3150 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
3152 sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );
\r
3156 /* sizeof( int ) == sizeof( long ) so a smaller
\r
3157 printf() library can be used. */
\r
3158 sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%u\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter );
\r
3163 pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
\r
3167 /* Free the array again. */
\r
3168 vPortFree( pxTaskStatusArray );
\r
3172 #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) ) */
\r
3173 /*-----------------------------------------------------------*/
\r
3175 portTickType uxTaskResetEventItemValue( void )
\r
3177 portTickType uxReturn;
\r
3179 uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );
\r
3181 /* Reset the event list item to its normal value - so it can be used with
\r
3182 queues and semaphores. */
\r
3183 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), ( ( portTickType ) configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
3187 /*-----------------------------------------------------------*/
\r
3189 #ifdef FREERTOS_MODULE_TEST
\r
3190 #include "tasks_test_access_functions.h"
\r