2 FreeRTOS V7.4.2 - Copyright (C) 2013 Real Time Engineers Ltd.
\r
4 FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT
\r
5 http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
7 ***************************************************************************
\r
9 * FreeRTOS tutorial books are available in pdf and paperback. *
\r
10 * Complete, revised, and edited pdf reference manuals are also *
\r
13 * Purchasing FreeRTOS documentation will not only help you, by *
\r
14 * ensuring you get running as quickly as possible and with an *
\r
15 * in-depth knowledge of how to use FreeRTOS, it will also help *
\r
16 * the FreeRTOS project to continue with its mission of providing *
\r
17 * professional grade, cross platform, de facto standard solutions *
\r
18 * for microcontrollers - completely free of charge! *
\r
20 * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
\r
22 * Thank you for using FreeRTOS, and thank you for your support! *
\r
24 ***************************************************************************
\r
27 This file is part of the FreeRTOS distribution.
\r
29 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
30 the terms of the GNU General Public License (version 2) as published by the
\r
31 Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
\r
33 >>>>>>NOTE<<<<<< The modification to the GPL is included to allow you to
\r
34 distribute a combined work that includes FreeRTOS without being obliged to
\r
35 provide the source code for proprietary components outside of the FreeRTOS
\r
38 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
39 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
40 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
\r
41 details. You should have received a copy of the GNU General Public License
\r
42 and the FreeRTOS license exception along with FreeRTOS; if not it can be
\r
43 viewed here: http://www.freertos.org/a00114.html and also obtained by
\r
44 writing to Real Time Engineers Ltd., contact details for whom are available
\r
45 on the FreeRTOS WEB site.
\r
49 ***************************************************************************
\r
51 * Having a problem? Start by reading the FAQ "My application does *
\r
52 * not run, what could be wrong?" *
\r
54 * http://www.FreeRTOS.org/FAQHelp.html *
\r
56 ***************************************************************************
\r
59 http://www.FreeRTOS.org - Documentation, books, training, latest versions,
\r
60 license and Real Time Engineers Ltd. contact details.
\r
62 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
63 including FreeRTOS+Trace - an indispensable productivity tool, and our new
\r
64 fully thread aware and reentrant UDP/IP stack.
\r
66 http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
\r
67 Integrity Systems, who sell the code with commercial support,
\r
68 indemnification and middleware, under the OpenRTOS brand.
\r
70 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
71 engineered and independently SIL3 certified version for use in safety and
\r
72 mission critical applications that require provable dependability.
\r
75 /* Standard includes. */
\r
80 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
\r
81 all the API functions to use the MPU wrappers. That should only be done when
\r
82 task.h is included from an application file. */
\r
83 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
85 /* FreeRTOS includes. */
\r
86 #include "FreeRTOS.h"
\r
89 #include "StackMacros.h"
\r
91 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
93 /* Sanity check the configuration. */
\r
94 #if configUSE_TICKLESS_IDLE != 0
\r
95 #if INCLUDE_vTaskSuspend != 1
\r
96 #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0
\r
97 #endif /* INCLUDE_vTaskSuspend */
\r
98 #endif /* configUSE_TICKLESS_IDLE */
\r
101 * Defines the size, in words, of the stack allocated to the idle task.
\r
103 #define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE
\r
106 * Task control block. A task control block (TCB) is allocated for each task,
\r
107 * and stores task state information, including a pointer to the task's context
\r
108 * (the task's run time environment, including register values)
\r
110 typedef struct tskTaskControlBlock
\r
112 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
114 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
115 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
118 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
119 xListItem xEventListItem; /*< Used to reference a task from an event list. */
\r
120 unsigned portBASE_TYPE uxPriority; /*< The priority of the task. 0 is the lowest priority. */
\r
121 portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */
\r
122 signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */
\r
124 #if ( portSTACK_GROWTH > 0 )
\r
125 portSTACK_TYPE *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */
\r
128 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
129 unsigned portBASE_TYPE uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
\r
132 #if ( configUSE_TRACE_FACILITY == 1 )
\r
133 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
134 unsigned portBASE_TYPE uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
\r
137 #if ( configUSE_MUTEXES == 1 )
\r
138 unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
\r
141 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
142 pdTASK_HOOK_CODE pxTaskTag;
\r
145 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
146 unsigned long ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
\r
149 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
150 /* Allocate a Newlib reent structure that is specific to this task.
\r
151 Note Newlib support has been included by popular demand, but is not
\r
152 used by the FreeRTOS maintainers themselves. FreeRTOS is not
\r
153 responsible for resulting newlib operation. User must be familiar with
\r
154 newlib and must provide system-wide implementations of the necessary
\r
155 stubs. Be warned that (at the time of writing) the current newlib design
\r
156 implements a system-wide malloc() that must be provided with locks. */
\r
157 struct _reent xNewLib_reent;
\r
164 * Some kernel aware debuggers require the data the debugger needs access to to
\r
165 * be global, rather than file scope.
\r
167 #ifdef portREMOVE_STATIC_QUALIFIER
\r
172 PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL;
\r
174 /* Lists for ready and blocked tasks. --------------------*/
\r
175 PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */
\r
176 PRIVILEGED_DATA static xList xDelayedTaskList1; /*< Delayed tasks. */
\r
177 PRIVILEGED_DATA static xList xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
\r
178 PRIVILEGED_DATA static xList * volatile pxDelayedTaskList ; /*< Points to the delayed task list currently being used. */
\r
179 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
180 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
182 #if ( INCLUDE_vTaskDelete == 1 )
\r
184 PRIVILEGED_DATA static xList xTasksWaitingTermination; /*< Tasks that have been deleted - but the their memory not yet freed. */
\r
185 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTasksDeleted = ( unsigned portBASE_TYPE ) 0U;
\r
189 #if ( INCLUDE_vTaskSuspend == 1 )
\r
191 PRIVILEGED_DATA static xList xSuspendedTaskList; /*< Tasks that are currently suspended. */
\r
195 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
197 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
201 /* File private variables. --------------------------------*/
\r
202 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0U;
\r
203 PRIVILEGED_DATA static volatile portTickType xTickCount = ( portTickType ) 0U;
\r
204 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTopReadyPriority = tskIDLE_PRIORITY;
\r
205 PRIVILEGED_DATA static volatile signed portBASE_TYPE xSchedulerRunning = pdFALSE;
\r
206 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended = ( unsigned portBASE_TYPE ) pdFALSE;
\r
207 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxPendedTicks = ( unsigned portBASE_TYPE ) 0U;
\r
208 PRIVILEGED_DATA static volatile portBASE_TYPE xYieldPending = ( portBASE_TYPE ) pdFALSE;
\r
209 PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0;
\r
210 PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0U;
\r
211 PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = ( portTickType ) portMAX_DELAY;
\r
213 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
215 PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
\r
216 PRIVILEGED_DATA static unsigned long ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */
\r
220 /* Debugging and trace facilities private variables and macros. ------------*/
\r
223 * The value used to fill the stack of a task when the task is created. This
\r
224 * is used purely for checking the high water mark for tasks.
\r
226 #define tskSTACK_FILL_BYTE ( 0xa5U )
\r
229 * Macros used by vListTask to indicate which state a task is in.
\r
231 #define tskBLOCKED_CHAR ( ( signed char ) 'B' )
\r
232 #define tskREADY_CHAR ( ( signed char ) 'R' )
\r
233 #define tskDELETED_CHAR ( ( signed char ) 'D' )
\r
234 #define tskSUSPENDED_CHAR ( ( signed char ) 'S' )
\r
236 /*-----------------------------------------------------------*/
\r
238 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
\r
240 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
\r
241 performed in a generic way that is not optimised to any particular
\r
242 microcontroller architecture. */
\r
244 /* uxTopReadyPriority holds the priority of the highest priority ready
\r
246 #define taskRECORD_READY_PRIORITY( uxPriority ) \
\r
248 if( ( uxPriority ) > uxTopReadyPriority ) \
\r
250 uxTopReadyPriority = ( uxPriority ); \
\r
252 } /* taskRECORD_READY_PRIORITY */
\r
254 /*-----------------------------------------------------------*/
\r
256 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
258 /* Find the highest priority queue that contains ready tasks. */ \
\r
259 while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) \
\r
261 configASSERT( uxTopReadyPriority ); \
\r
262 --uxTopReadyPriority; \
\r
265 /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
\r
266 the same priority get an equal share of the processor time. */ \
\r
267 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \
\r
268 } /* taskSELECT_HIGHEST_PRIORITY_TASK */
\r
270 /*-----------------------------------------------------------*/
\r
272 /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
\r
273 they are only required when a port optimised method of task selection is
\r
275 #define taskRESET_READY_PRIORITY( uxPriority )
\r
276 #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
278 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
280 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
\r
281 performed in a way that is tailored to the particular microcontroller
\r
282 architecture being used. */
\r
284 /* A port optimised version is provided. Call the port defined macros. */
\r
285 #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
287 /*-----------------------------------------------------------*/
\r
289 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
291 unsigned portBASE_TYPE uxTopPriority; \
\r
293 /* Find the highest priority queue that contains ready tasks. */ \
\r
294 portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
\r
295 configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
\r
296 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
\r
297 } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
\r
299 /*-----------------------------------------------------------*/
\r
301 /* A port optimised version is provided, call it only if the TCB being reset
\r
302 is being referenced from a ready list. If it is referenced from a delayed
\r
303 or suspended list then it won't be in a ready list. */
\r
304 #define taskRESET_READY_PRIORITY( uxPriority ) \
\r
306 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == 0 ) \
\r
308 portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \
\r
312 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
314 /*-----------------------------------------------------------*/
\r
316 /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
\r
317 count overflows. */
\r
318 #define taskSWITCH_DELAYED_LISTS() \
\r
322 /* The delayed tasks list should be empty when the lists are switched. */ \
\r
323 configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \
\r
325 pxTemp = pxDelayedTaskList; \
\r
326 pxDelayedTaskList = pxOverflowDelayedTaskList; \
\r
327 pxOverflowDelayedTaskList = pxTemp; \
\r
328 xNumOfOverflows++; \
\r
330 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) \
\r
332 /* The new current delayed list is empty. Set \
\r
333 xNextTaskUnblockTime to the maximum possible value so it is \
\r
334 extremely unlikely that the \
\r
335 if( xTickCount >= xNextTaskUnblockTime ) test will pass until \
\r
336 there is an item in the delayed list. */ \
\r
337 xNextTaskUnblockTime = portMAX_DELAY; \
\r
341 /* The new current delayed list is not empty, get the value of \
\r
342 the item at the head of the delayed list. This is the time at \
\r
343 which the task at the head of the delayed list should be removed \
\r
344 from the Blocked state. */ \
\r
345 pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); \
\r
346 xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ); \
\r
350 /*-----------------------------------------------------------*/
\r
353 * Place the task represented by pxTCB into the appropriate ready list for
\r
354 * the task. It is inserted at the end of the list.
\r
356 #define prvAddTaskToReadyList( pxTCB ) \
\r
357 traceMOVED_TASK_TO_READY_STATE( pxTCB ) \
\r
358 taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
\r
359 vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) )
\r
360 /*-----------------------------------------------------------*/
\r
363 * Several functions take an xTaskHandle parameter that can optionally be NULL,
\r
364 * where NULL is used to indicate that the handle of the currently executing
\r
365 * task should be used in place of the parameter. This macro simply checks to
\r
366 * see if the parameter is NULL and returns a pointer to the appropriate TCB.
\r
368 #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( tskTCB * ) pxCurrentTCB : ( tskTCB * ) ( pxHandle ) )
\r
370 /* Callback function prototypes. --------------------------*/
\r
371 extern void vApplicationStackOverflowHook( xTaskHandle xTask, signed char *pcTaskName );
\r
372 extern void vApplicationTickHook( void );
\r
374 /* File private functions. --------------------------------*/
\r
377 * Utility to ready a TCB for a given task. Mainly just copies the parameters
\r
378 * into the TCB structure.
\r
380 static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) PRIVILEGED_FUNCTION;
\r
383 * Utility to ready all the lists used by the scheduler. This is called
\r
384 * automatically upon the creation of the first task.
\r
386 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
\r
389 * The idle task, which as all tasks is implemented as a never ending loop.
\r
390 * The idle task is automatically created and added to the ready lists upon
\r
391 * creation of the first user task.
\r
393 * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
\r
394 * language extensions. The equivalent prototype for this function is:
\r
396 * void prvIdleTask( void *pvParameters );
\r
399 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
\r
402 * Utility to free all memory allocated by the scheduler to hold a TCB,
\r
403 * including the stack pointed to by the TCB.
\r
405 * This does not free memory allocated by the task itself (i.e. memory
\r
406 * allocated by calls to pvPortMalloc from within the tasks application code).
\r
408 #if ( INCLUDE_vTaskDelete == 1 )
\r
410 static void prvDeleteTCB( tskTCB *pxTCB ) PRIVILEGED_FUNCTION;
\r
415 * Used only by the idle task. This checks to see if anything has been placed
\r
416 * in the list of tasks waiting to be deleted. If so the task is cleaned up
\r
417 * and its TCB deleted.
\r
419 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
\r
422 * The currently executing task is entering the Blocked state. Add the task to
\r
423 * either the current or the overflow delayed task list.
\r
425 static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake ) PRIVILEGED_FUNCTION;
\r
428 * Allocates memory from the heap for a TCB and associated stack. Checks the
\r
429 * allocation was successful.
\r
431 static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) PRIVILEGED_FUNCTION;
\r
434 * Fills an xTaskStatusType structure with information on each task that is
\r
435 * referenced from the pxList list (which may be a ready list, a delayed list,
\r
436 * a suspended list, etc.).
\r
438 * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
\r
439 * NORMAL APPLICATION CODE.
\r
441 #if ( configUSE_TRACE_FACILITY == 1 )
\r
443 static unsigned portBASE_TYPE prvListTaskWithinSingleList( xTaskStatusType *pxTaskStatusArray, xList *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;
\r
448 * When a task is created, the stack of the task is filled with a known value.
\r
449 * This function determines the 'high water mark' of the task stack by
\r
450 * determining how much of the stack remains at the original preset value.
\r
452 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
454 static unsigned short prvTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) PRIVILEGED_FUNCTION;
\r
459 * Return the amount of time, in ticks, that will pass before the kernel will
\r
460 * next move a task from the Blocked state to the Running state.
\r
462 * This conditional compilation should use inequality to 0, not equality to 1.
\r
463 * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
\r
464 * defined low power mode implementations require configUSE_TICKLESS_IDLE to be
\r
465 * set to a value other than 1.
\r
467 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
469 static portTickType prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
\r
475 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
477 signed portBASE_TYPE xReturn;
\r
480 configASSERT( pxTaskCode );
\r
481 configASSERT( ( ( uxPriority & ( ~portPRIVILEGE_BIT ) ) < configMAX_PRIORITIES ) );
\r
483 /* Allocate the memory required by the TCB and stack for the new task,
\r
484 checking that the allocation was successful. */
\r
485 pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer );
\r
487 if( pxNewTCB != NULL )
\r
489 portSTACK_TYPE *pxTopOfStack;
\r
491 #if( portUSING_MPU_WRAPPERS == 1 )
\r
492 /* Should the task be created in privileged mode? */
\r
493 portBASE_TYPE xRunPrivileged;
\r
494 if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
\r
496 xRunPrivileged = pdTRUE;
\r
500 xRunPrivileged = pdFALSE;
\r
502 uxPriority &= ~portPRIVILEGE_BIT;
\r
503 #endif /* portUSING_MPU_WRAPPERS == 1 */
\r
505 /* Calculate the top of stack address. This depends on whether the
\r
506 stack grows from high memory to low (as per the 80x86) or visa versa.
\r
507 portSTACK_GROWTH is used to make the result positive or negative as
\r
508 required by the port. */
\r
509 #if( portSTACK_GROWTH < 0 )
\r
511 pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( unsigned short ) 1 );
\r
512 pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) );
\r
514 /* Check the alignment of the calculated top of stack is correct. */
\r
515 configASSERT( ( ( ( unsigned long ) pxTopOfStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
517 #else /* portSTACK_GROWTH */
\r
519 pxTopOfStack = pxNewTCB->pxStack;
\r
521 /* Check the alignment of the stack buffer is correct. */
\r
522 configASSERT( ( ( ( unsigned long ) pxNewTCB->pxStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
524 /* If we want to use stack checking on architectures that use
\r
525 a positive stack growth direction then we also need to store the
\r
526 other extreme of the stack space. */
\r
527 pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
\r
529 #endif /* portSTACK_GROWTH */
\r
531 /* Setup the newly allocated TCB with the initial state of the task. */
\r
532 prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth );
\r
534 /* Initialize the TCB stack to look as if the task was already running,
\r
535 but had been interrupted by the scheduler. The return address is set
\r
536 to the start of the task function. Once the stack has been initialised
\r
537 the top of stack variable is updated. */
\r
538 #if( portUSING_MPU_WRAPPERS == 1 )
\r
540 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
\r
542 #else /* portUSING_MPU_WRAPPERS */
\r
544 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
\r
546 #endif /* portUSING_MPU_WRAPPERS */
\r
548 if( ( void * ) pxCreatedTask != NULL )
\r
550 /* Pass the TCB out - in an anonymous way. The calling function/
\r
551 task can use this as a handle to delete the task later if
\r
553 *pxCreatedTask = ( xTaskHandle ) pxNewTCB;
\r
556 /* Ensure interrupts don't access the task lists while they are being
\r
558 taskENTER_CRITICAL();
\r
560 uxCurrentNumberOfTasks++;
\r
561 if( pxCurrentTCB == NULL )
\r
563 /* There are no other tasks, or all the other tasks are in
\r
564 the suspended state - make this the current task. */
\r
565 pxCurrentTCB = pxNewTCB;
\r
567 if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 )
\r
569 /* This is the first task to be created so do the preliminary
\r
570 initialisation required. We will not recover if this call
\r
571 fails, but we will report the failure. */
\r
572 prvInitialiseTaskLists();
\r
577 /* If the scheduler is not already running, make this task the
\r
578 current task if it is the highest priority task to be created
\r
580 if( xSchedulerRunning == pdFALSE )
\r
582 if( pxCurrentTCB->uxPriority <= uxPriority )
\r
584 pxCurrentTCB = pxNewTCB;
\r
591 #if ( configUSE_TRACE_FACILITY == 1 )
\r
593 /* Add a counter into the TCB for tracing only. */
\r
594 pxNewTCB->uxTCBNumber = uxTaskNumber;
\r
596 #endif /* configUSE_TRACE_FACILITY */
\r
597 traceTASK_CREATE( pxNewTCB );
\r
599 prvAddTaskToReadyList( pxNewTCB );
\r
602 portSETUP_TCB( pxNewTCB );
\r
604 taskEXIT_CRITICAL();
\r
608 xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
\r
609 traceTASK_CREATE_FAILED();
\r
612 if( xReturn == pdPASS )
\r
614 if( xSchedulerRunning != pdFALSE )
\r
616 /* If the created task is of a higher priority than the current task
\r
617 then it should run now. */
\r
618 if( pxCurrentTCB->uxPriority < uxPriority )
\r
620 portYIELD_WITHIN_API();
\r
627 /*-----------------------------------------------------------*/
\r
629 #if ( INCLUDE_vTaskDelete == 1 )
\r
631 void vTaskDelete( xTaskHandle xTaskToDelete )
\r
635 taskENTER_CRITICAL();
\r
637 /* Ensure a yield is performed if the current task is being
\r
639 if( xTaskToDelete == pxCurrentTCB )
\r
641 xTaskToDelete = NULL;
\r
644 /* If null is passed in here then we are deleting ourselves. */
\r
645 pxTCB = prvGetTCBFromHandle( xTaskToDelete );
\r
647 /* Remove task from the ready list and place in the termination list.
\r
648 This will stop the task from be scheduled. The idle task will check
\r
649 the termination list and free up any memory allocated by the
\r
650 scheduler for the TCB and stack. */
\r
651 if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
\r
653 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
656 /* Is the task waiting on an event also? */
\r
657 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
659 uxListRemove( &( pxTCB->xEventListItem ) );
\r
662 vListInsertEnd( ( xList * ) &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );
\r
664 /* Increment the ucTasksDeleted variable so the idle task knows
\r
665 there is a task that has been deleted and that it should therefore
\r
666 check the xTasksWaitingTermination list. */
\r
669 /* Increment the uxTaskNumberVariable also so kernel aware debuggers
\r
670 can detect that the task lists need re-generating. */
\r
673 traceTASK_DELETE( pxTCB );
\r
675 taskEXIT_CRITICAL();
\r
677 /* Force a reschedule if we have just deleted the current task. */
\r
678 if( xSchedulerRunning != pdFALSE )
\r
680 if( ( void * ) xTaskToDelete == NULL )
\r
682 portYIELD_WITHIN_API();
\r
687 #endif /* INCLUDE_vTaskDelete */
\r
688 /*-----------------------------------------------------------*/
\r
690 #if ( INCLUDE_vTaskDelayUntil == 1 )
\r
692 void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement )
\r
694 portTickType xTimeToWake;
\r
695 portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE;
\r
697 configASSERT( pxPreviousWakeTime );
\r
698 configASSERT( ( xTimeIncrement > 0U ) );
\r
702 /* Minor optimisation. The tick count cannot change in this
\r
704 const portTickType xConstTickCount = xTickCount;
\r
706 /* Generate the tick time at which the task wants to wake. */
\r
707 xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
\r
709 if( xConstTickCount < *pxPreviousWakeTime )
\r
711 /* The tick count has overflowed since this function was
\r
712 lasted called. In this case the only time we should ever
\r
713 actually delay is if the wake time has also overflowed,
\r
714 and the wake time is greater than the tick time. When this
\r
715 is the case it is as if neither time had overflowed. */
\r
716 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
\r
718 xShouldDelay = pdTRUE;
\r
723 /* The tick time has not overflowed. In this case we will
\r
724 delay if either the wake time has overflowed, and/or the
\r
725 tick time is less than the wake time. */
\r
726 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
\r
728 xShouldDelay = pdTRUE;
\r
732 /* Update the wake time ready for the next call. */
\r
733 *pxPreviousWakeTime = xTimeToWake;
\r
735 if( xShouldDelay != pdFALSE )
\r
737 traceTASK_DELAY_UNTIL();
\r
739 /* We must remove ourselves from the ready list before adding
\r
740 ourselves to the blocked list as the same list item is used for
\r
742 if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 )
\r
744 /* The current task must be in a ready list, so there is
\r
745 no need to check, and the port reset macro can be called
\r
747 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
750 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
753 xAlreadyYielded = xTaskResumeAll();
\r
755 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
756 have put ourselves to sleep. */
\r
757 if( xAlreadyYielded == pdFALSE )
\r
759 portYIELD_WITHIN_API();
\r
763 #endif /* INCLUDE_vTaskDelayUntil */
\r
764 /*-----------------------------------------------------------*/
\r
766 #if ( INCLUDE_vTaskDelay == 1 )
\r
768 void vTaskDelay( portTickType xTicksToDelay )
\r
770 portTickType xTimeToWake;
\r
771 signed portBASE_TYPE xAlreadyYielded = pdFALSE;
\r
773 /* A delay time of zero just forces a reschedule. */
\r
774 if( xTicksToDelay > ( portTickType ) 0U )
\r
780 /* A task that is removed from the event list while the
\r
781 scheduler is suspended will not get placed in the ready
\r
782 list or removed from the blocked list until the scheduler
\r
785 This task cannot be in an event list as it is the currently
\r
788 /* Calculate the time to wake - this may overflow but this is
\r
790 xTimeToWake = xTickCount + xTicksToDelay;
\r
792 /* We must remove ourselves from the ready list before adding
\r
793 ourselves to the blocked list as the same list item is used for
\r
795 if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 )
\r
797 /* The current task must be in a ready list, so there is
\r
798 no need to check, and the port reset macro can be called
\r
800 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
802 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
804 xAlreadyYielded = xTaskResumeAll();
\r
807 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
808 have put ourselves to sleep. */
\r
809 if( xAlreadyYielded == pdFALSE )
\r
811 portYIELD_WITHIN_API();
\r
815 #endif /* INCLUDE_vTaskDelay */
\r
816 /*-----------------------------------------------------------*/
\r
818 #if ( INCLUDE_eTaskGetState == 1 )
\r
820 eTaskState eTaskGetState( xTaskHandle xTask )
\r
822 eTaskState eReturn;
\r
823 xList *pxStateList;
\r
824 const tskTCB * const pxTCB = ( tskTCB * ) xTask;
\r
826 if( pxTCB == pxCurrentTCB )
\r
828 /* The task calling this function is querying its own state. */
\r
829 eReturn = eRunning;
\r
833 taskENTER_CRITICAL();
\r
835 pxStateList = ( xList * ) listLIST_ITEM_CONTAINER( &( pxTCB->xGenericListItem ) );
\r
837 taskEXIT_CRITICAL();
\r
839 if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) )
\r
841 /* The task being queried is referenced from one of the Blocked
\r
843 eReturn = eBlocked;
\r
846 #if ( INCLUDE_vTaskSuspend == 1 )
\r
847 else if( pxStateList == &xSuspendedTaskList )
\r
849 /* The task being queried is referenced from the suspended
\r
851 eReturn = eSuspended;
\r
855 #if ( INCLUDE_vTaskDelete == 1 )
\r
856 else if( pxStateList == &xTasksWaitingTermination )
\r
858 /* The task being queried is referenced from the deleted
\r
860 eReturn = eDeleted;
\r
866 /* If the task is not in any other state, it must be in the
\r
867 Ready (including pending ready) state. */
\r
875 #endif /* INCLUDE_eTaskGetState */
\r
876 /*-----------------------------------------------------------*/
\r
878 #if ( INCLUDE_uxTaskPriorityGet == 1 )
\r
880 unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle xTask )
\r
883 unsigned portBASE_TYPE uxReturn;
\r
885 taskENTER_CRITICAL();
\r
887 /* If null is passed in here then we are changing the
\r
888 priority of the calling function. */
\r
889 pxTCB = prvGetTCBFromHandle( xTask );
\r
890 uxReturn = pxTCB->uxPriority;
\r
892 taskEXIT_CRITICAL();
\r
897 #endif /* INCLUDE_uxTaskPriorityGet */
\r
898 /*-----------------------------------------------------------*/
\r
900 #if ( INCLUDE_vTaskPrioritySet == 1 )
\r
902 void vTaskPrioritySet( xTaskHandle xTask, unsigned portBASE_TYPE uxNewPriority )
\r
905 unsigned portBASE_TYPE uxCurrentPriority, uxPriorityUsedOnEntry;
\r
906 portBASE_TYPE xYieldRequired = pdFALSE;
\r
908 configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
\r
910 /* Ensure the new priority is valid. */
\r
911 if( uxNewPriority >= configMAX_PRIORITIES )
\r
913 uxNewPriority = configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U;
\r
916 taskENTER_CRITICAL();
\r
918 if( xTask == ( xTaskHandle ) pxCurrentTCB )
\r
923 /* If null is passed in here then we are changing the
\r
924 priority of the calling function. */
\r
925 pxTCB = prvGetTCBFromHandle( xTask );
\r
927 traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
\r
929 #if ( configUSE_MUTEXES == 1 )
\r
931 uxCurrentPriority = pxTCB->uxBasePriority;
\r
935 uxCurrentPriority = pxTCB->uxPriority;
\r
939 if( uxCurrentPriority != uxNewPriority )
\r
941 /* The priority change may have readied a task of higher
\r
942 priority than the calling task. */
\r
943 if( uxNewPriority > uxCurrentPriority )
\r
945 if( xTask != NULL )
\r
947 /* The priority of another task is being raised. If we
\r
948 were raising the priority of the currently running task
\r
949 there would be no need to switch as it must have already
\r
950 been the highest priority task. */
\r
951 xYieldRequired = pdTRUE;
\r
954 else if( xTask == NULL )
\r
956 /* Setting our own priority down means there may now be another
\r
957 task of higher priority that is ready to execute. */
\r
958 xYieldRequired = pdTRUE;
\r
961 /* Remember the ready list the task might be referenced from
\r
962 before its uxPriority member is changed so the
\r
963 taskRESET_READY_PRIORITY() macro can function correctly. */
\r
964 uxPriorityUsedOnEntry = pxTCB->uxPriority;
\r
966 #if ( configUSE_MUTEXES == 1 )
\r
968 /* Only change the priority being used if the task is not
\r
969 currently using an inherited priority. */
\r
970 if( pxTCB->uxBasePriority == pxTCB->uxPriority )
\r
972 pxTCB->uxPriority = uxNewPriority;
\r
975 /* The base priority gets set whatever. */
\r
976 pxTCB->uxBasePriority = uxNewPriority;
\r
980 pxTCB->uxPriority = uxNewPriority;
\r
984 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) );
\r
986 /* If the task is in the blocked or suspended list we need do
\r
987 nothing more than change it's priority variable. However, if
\r
988 the task is in a ready list it needs to be removed and placed
\r
989 in the queue appropriate to its new priority. */
\r
990 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxCurrentPriority ] ), &( pxTCB->xGenericListItem ) ) )
\r
992 /* The task is currently in its ready list - remove before adding
\r
993 it to it's new ready list. As we are in a critical section we
\r
994 can do this even if the scheduler is suspended. */
\r
995 if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
\r
997 taskRESET_READY_PRIORITY( uxPriorityUsedOnEntry );
\r
999 prvAddTaskToReadyList( pxTCB );
\r
1002 if( xYieldRequired == pdTRUE )
\r
1004 portYIELD_WITHIN_API();
\r
1007 /* Remove compiler warning about unused variables when the port
\r
1008 optimised task selection is not being used. */
\r
1009 ( void ) uxPriorityUsedOnEntry;
\r
1012 taskEXIT_CRITICAL();
\r
1015 #endif /* INCLUDE_vTaskPrioritySet */
\r
1016 /*-----------------------------------------------------------*/
\r
1018 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1020 void vTaskSuspend( xTaskHandle xTaskToSuspend )
\r
1024 taskENTER_CRITICAL();
\r
1026 /* Ensure a yield is performed if the current task is being
\r
1028 if( xTaskToSuspend == ( xTaskHandle ) pxCurrentTCB )
\r
1030 xTaskToSuspend = NULL;
\r
1033 /* If null is passed in here then we are suspending ourselves. */
\r
1034 pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
\r
1036 traceTASK_SUSPEND( pxTCB );
\r
1038 /* Remove task from the ready/delayed list and place in the suspended list. */
\r
1039 if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
\r
1041 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
1044 /* Is the task waiting on an event also? */
\r
1045 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
1047 uxListRemove( &( pxTCB->xEventListItem ) );
\r
1050 vListInsertEnd( ( xList * ) &xSuspendedTaskList, &( pxTCB->xGenericListItem ) );
\r
1052 taskEXIT_CRITICAL();
\r
1054 if( ( void * ) xTaskToSuspend == NULL )
\r
1056 if( xSchedulerRunning != pdFALSE )
\r
1058 /* We have just suspended the current task. */
\r
1059 portYIELD_WITHIN_API();
\r
1063 /* The scheduler is not running, but the task that was pointed
\r
1064 to by pxCurrentTCB has just been suspended and pxCurrentTCB
\r
1065 must be adjusted to point to a different task. */
\r
1066 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )
\r
1068 /* No other tasks are ready, so set pxCurrentTCB back to
\r
1069 NULL so when the next task is created pxCurrentTCB will
\r
1070 be set to point to it no matter what its relative priority
\r
1072 pxCurrentTCB = NULL;
\r
1076 vTaskSwitchContext();
\r
1082 #endif /* INCLUDE_vTaskSuspend */
\r
1083 /*-----------------------------------------------------------*/
\r
1085 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1087 signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask )
\r
1089 portBASE_TYPE xReturn = pdFALSE;
\r
1090 const tskTCB * const pxTCB = ( tskTCB * ) xTask;
\r
1092 /* It does not make sense to check if the calling task is suspended. */
\r
1093 configASSERT( xTask );
\r
1095 /* Is the task we are attempting to resume actually in the
\r
1096 suspended list? */
\r
1097 if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
\r
1099 /* Has the task already been resumed from within an ISR? */
\r
1100 if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE )
\r
1102 /* Is it in the suspended list because it is in the
\r
1103 Suspended state? It is possible to be in the suspended
\r
1104 list because it is blocked on a task with no timeout
\r
1106 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) == pdTRUE )
\r
1116 #endif /* INCLUDE_vTaskSuspend */
\r
1117 /*-----------------------------------------------------------*/
\r
1119 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1121 void vTaskResume( xTaskHandle xTaskToResume )
\r
1123 tskTCB * const pxTCB = ( tskTCB * ) xTaskToResume;
\r
1125 /* It does not make sense to resume the calling task. */
\r
1126 configASSERT( xTaskToResume );
\r
1128 /* The parameter cannot be NULL as it is impossible to resume the
\r
1129 currently executing task. */
\r
1130 if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
\r
1132 taskENTER_CRITICAL();
\r
1134 if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
\r
1136 traceTASK_RESUME( pxTCB );
\r
1138 /* As we are in a critical section we can access the ready
\r
1139 lists even if the scheduler is suspended. */
\r
1140 uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1141 prvAddTaskToReadyList( pxTCB );
\r
1143 /* We may have just resumed a higher priority task. */
\r
1144 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1146 /* This yield may not cause the task just resumed to run, but
\r
1147 will leave the lists in the correct state for the next yield. */
\r
1148 portYIELD_WITHIN_API();
\r
1152 taskEXIT_CRITICAL();
\r
1156 #endif /* INCLUDE_vTaskSuspend */
\r
1158 /*-----------------------------------------------------------*/
\r
1160 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
\r
1162 portBASE_TYPE xTaskResumeFromISR( xTaskHandle xTaskToResume )
\r
1164 portBASE_TYPE xYieldRequired = pdFALSE;
\r
1165 tskTCB * const pxTCB = ( tskTCB * ) xTaskToResume;
\r
1166 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
1168 configASSERT( xTaskToResume );
\r
1170 /* RTOS ports that support interrupt nesting have the concept of a
\r
1171 maximum system call (or maximum API call) interrupt priority.
\r
1172 Interrupts that are above the maximum system call priority are keep
\r
1173 permanently enabled, even when the RTOS kernel is in a critical section,
\r
1174 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
1175 is defined in FreeRTOSConfig.h then
\r
1176 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1177 failure if a FreeRTOS API function is called from an interrupt that has
\r
1178 been assigned a priority above the configured maximum system call
\r
1179 priority. Only FreeRTOS functions that end in FromISR can be called
\r
1180 from interrupts that have been assigned a priority at or (logically)
\r
1181 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
1182 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
1183 simple as possible. More information (albeit Cortex-M specific) is
\r
1184 provided on the following link:
\r
1185 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1186 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1188 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1190 if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
\r
1192 traceTASK_RESUME_FROM_ISR( pxTCB );
\r
1194 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
\r
1196 xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority );
\r
1197 uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1198 prvAddTaskToReadyList( pxTCB );
\r
1202 /* We cannot access the delayed or ready lists, so will hold this
\r
1203 task pending until the scheduler is resumed, at which point a
\r
1204 yield will be performed if necessary. */
\r
1205 vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
1209 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1211 return xYieldRequired;
\r
1214 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
\r
1215 /*-----------------------------------------------------------*/
\r
1217 void vTaskStartScheduler( void )
\r
1219 portBASE_TYPE xReturn;
\r
1221 /* Add the idle task at the lowest priority. */
\r
1222 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
1224 /* Create the idle task, storing its handle in xIdleTaskHandle so it can
\r
1225 be returned by the xTaskGetIdleTaskHandle() function. */
\r
1226 xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle );
\r
1230 /* Create the idle task without storing its handle. */
\r
1231 xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), NULL );
\r
1233 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
\r
1235 #if ( configUSE_TIMERS == 1 )
\r
1237 if( xReturn == pdPASS )
\r
1239 xReturn = xTimerCreateTimerTask();
\r
1242 #endif /* configUSE_TIMERS */
\r
1244 if( xReturn == pdPASS )
\r
1246 /* Interrupts are turned off here, to ensure a tick does not occur
\r
1247 before or during the call to xPortStartScheduler(). The stacks of
\r
1248 the created tasks contain a status word with interrupts switched on
\r
1249 so interrupts will automatically get re-enabled when the first task
\r
1252 STEPPING THROUGH HERE USING A DEBUGGER CAN CAUSE BIG PROBLEMS IF THE
\r
1253 DEBUGGER ALLOWS INTERRUPTS TO BE PROCESSED. */
\r
1254 portDISABLE_INTERRUPTS();
\r
1256 xSchedulerRunning = pdTRUE;
\r
1257 xTickCount = ( portTickType ) 0U;
\r
1259 /* If configGENERATE_RUN_TIME_STATS is defined then the following
\r
1260 macro must be defined to configure the timer/counter used to generate
\r
1261 the run time counter time base. */
\r
1262 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
\r
1264 /* Setting up the timer tick is hardware specific and thus in the
\r
1265 portable interface. */
\r
1266 if( xPortStartScheduler() != pdFALSE )
\r
1268 /* Should not reach here as if the scheduler is running the
\r
1269 function will not return. */
\r
1273 /* Should only reach here if a task calls xTaskEndScheduler(). */
\r
1278 /* This line will only be reached if the kernel could not be started,
\r
1279 because there was not enough FreeRTOS heap to create the idle task
\r
1280 or the timer task. */
\r
1281 configASSERT( xReturn );
\r
1284 /*-----------------------------------------------------------*/
\r
1286 void vTaskEndScheduler( void )
\r
1288 /* Stop the scheduler interrupts and call the portable scheduler end
\r
1289 routine so the original ISRs can be restored if necessary. The port
\r
1290 layer must ensure interrupts enable bit is left in the correct state. */
\r
1291 portDISABLE_INTERRUPTS();
\r
1292 xSchedulerRunning = pdFALSE;
\r
1293 vPortEndScheduler();
\r
1295 /*----------------------------------------------------------*/
\r
1297 void vTaskSuspendAll( void )
\r
1299 /* A critical section is not required as the variable is of type
\r
1301 ++uxSchedulerSuspended;
\r
1303 /*----------------------------------------------------------*/
\r
1305 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
1307 static portTickType prvGetExpectedIdleTime( void )
\r
1309 portTickType xReturn;
\r
1311 if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
\r
1315 else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
\r
1317 /* There are other idle priority tasks in the ready state. If
\r
1318 time slicing is used then the very next tick interrupt must be
\r
1324 xReturn = xNextTaskUnblockTime - xTickCount;
\r
1330 #endif /* configUSE_TICKLESS_IDLE */
\r
1331 /*----------------------------------------------------------*/
\r
1333 signed portBASE_TYPE xTaskResumeAll( void )
\r
1335 register tskTCB *pxTCB;
\r
1336 signed portBASE_TYPE xAlreadyYielded = pdFALSE;
\r
1337 portBASE_TYPE xYieldRequired = pdFALSE;
\r
1339 /* If uxSchedulerSuspended is zero then this function does not match a
\r
1340 previous call to vTaskSuspendAll(). */
\r
1341 configASSERT( uxSchedulerSuspended );
\r
1343 /* It is possible that an ISR caused a task to be removed from an event
\r
1344 list while the scheduler was suspended. If this was the case then the
\r
1345 removed task will have been added to the xPendingReadyList. Once the
\r
1346 scheduler has been resumed it is safe to move all the pending ready
\r
1347 tasks from this list into their appropriate ready list. */
\r
1348 taskENTER_CRITICAL();
\r
1350 --uxSchedulerSuspended;
\r
1352 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
\r
1354 if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0U )
\r
1356 /* Move any readied tasks from the pending list into the
\r
1357 appropriate ready list. */
\r
1358 while( listLIST_IS_EMPTY( ( xList * ) &xPendingReadyList ) == pdFALSE )
\r
1360 pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xPendingReadyList ) );
\r
1361 uxListRemove( &( pxTCB->xEventListItem ) );
\r
1362 uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1363 prvAddTaskToReadyList( pxTCB );
\r
1365 /* If we have moved a task that has a priority higher than
\r
1366 the current task then we should yield. */
\r
1367 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1369 xYieldRequired = pdTRUE;
\r
1373 /* If any ticks occurred while the scheduler was suspended then
\r
1374 they should be processed now. This ensures the tick count does not
\r
1375 slip, and that any delayed tasks are resumed at the correct time. */
\r
1376 if( uxPendedTicks > ( unsigned portBASE_TYPE ) 0U )
\r
1378 while( uxPendedTicks > ( unsigned portBASE_TYPE ) 0U )
\r
1380 if( xTaskIncrementTick() != pdFALSE )
\r
1382 xYieldRequired = pdTRUE;
\r
1388 if( ( xYieldRequired == pdTRUE ) || ( xYieldPending == pdTRUE ) )
\r
1390 xAlreadyYielded = pdTRUE;
\r
1391 xYieldPending = pdFALSE;
\r
1392 portYIELD_WITHIN_API();
\r
1397 taskEXIT_CRITICAL();
\r
1399 return xAlreadyYielded;
\r
1401 /*-----------------------------------------------------------*/
\r
1403 portTickType xTaskGetTickCount( void )
\r
1405 portTickType xTicks;
\r
1407 /* Critical section required if running on a 16 bit processor. */
\r
1408 taskENTER_CRITICAL();
\r
1410 xTicks = xTickCount;
\r
1412 taskEXIT_CRITICAL();
\r
1416 /*-----------------------------------------------------------*/
\r
1418 portTickType xTaskGetTickCountFromISR( void )
\r
1420 portTickType xReturn;
\r
1421 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
1423 /* RTOS ports that support interrupt nesting have the concept of a maximum
\r
1424 system call (or maximum API call) interrupt priority. Interrupts that are
\r
1425 above the maximum system call priority are keep permanently enabled, even
\r
1426 when the RTOS kernel is in a critical section, but cannot make any calls to
\r
1427 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
\r
1428 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1429 failure if a FreeRTOS API function is called from an interrupt that has been
\r
1430 assigned a priority above the configured maximum system call priority.
\r
1431 Only FreeRTOS functions that end in FromISR can be called from interrupts
\r
1432 that have been assigned a priority at or (logically) below the maximum
\r
1433 system call interrupt priority. FreeRTOS maintains a separate interrupt
\r
1434 safe API to ensure interrupt entry is as fast and as simple as possible.
\r
1435 More information (albeit Cortex-M specific) is provided on the following
\r
1436 link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1437 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1439 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1440 xReturn = xTickCount;
\r
1441 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1445 /*-----------------------------------------------------------*/
\r
1447 unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
\r
1449 /* A critical section is not required because the variables are of type
\r
1451 return uxCurrentNumberOfTasks;
\r
1453 /*-----------------------------------------------------------*/
\r
1455 #if ( INCLUDE_pcTaskGetTaskName == 1 )
\r
1457 signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery )
\r
1461 /* If null is passed in here then the name of the calling task is being queried. */
\r
1462 pxTCB = prvGetTCBFromHandle( xTaskToQuery );
\r
1463 configASSERT( pxTCB );
\r
1464 return &( pxTCB->pcTaskName[ 0 ] );
\r
1467 #endif /* INCLUDE_pcTaskGetTaskName */
\r
1468 /*-----------------------------------------------------------*/
\r
1470 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1472 unsigned portBASE_TYPE xTaskGetSystemState( xTaskStatusType *pxTaskStatusArray, unsigned portBASE_TYPE uxArraySize, unsigned long *pulTotalRunTime )
\r
1474 unsigned portBASE_TYPE uxTask = 0, uxQueue = configMAX_PRIORITIES;
\r
1476 vTaskSuspendAll();
\r
1478 /* Is there a space in the array for each task in the system? */
\r
1479 if( uxArraySize >= uxCurrentNumberOfTasks )
\r
1481 /* Fill in an xTaskStatusType structure with information on each
\r
1482 task in the Ready state. */
\r
1486 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), eReady );
\r
1488 }while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY );
\r
1490 /* Fill in an xTaskStatusType structure with information on each
\r
1491 task in the Blocked state. */
\r
1492 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( xList * ) pxDelayedTaskList, eBlocked );
\r
1493 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( xList * ) pxOverflowDelayedTaskList, eBlocked );
\r
1495 #if( INCLUDE_vTaskDelete == 1 )
\r
1497 /* Fill in an xTaskStatusType structure with information on
\r
1498 each task that has been deleted but not yet cleaned up. */
\r
1499 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
\r
1503 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1505 /* Fill in an xTaskStatusType structure with information on
\r
1506 each task in the Suspended state. */
\r
1507 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
\r
1511 #if ( configGENERATE_RUN_TIME_STATS == 1)
\r
1513 if( pulTotalRunTime != NULL )
\r
1515 *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
1520 if( pulTotalRunTime != NULL )
\r
1522 *pulTotalRunTime = 0;
\r
1533 #endif /* configUSE_TRACE_FACILITY */
\r
1534 /*----------------------------------------------------------*/
\r
1536 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
1538 xTaskHandle xTaskGetIdleTaskHandle( void )
\r
1540 /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
\r
1541 started, then xIdleTaskHandle will be NULL. */
\r
1542 configASSERT( ( xIdleTaskHandle != NULL ) );
\r
1543 return xIdleTaskHandle;
\r
1546 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
\r
1547 /*----------------------------------------------------------*/
\r
1549 /* This conditional compilation should use inequality to 0, not equality to 1.
\r
1550 This is to ensure vTaskStepTick() is available when user defined low power mode
\r
1551 implementations require configUSE_TICKLESS_IDLE to be set to a value other than
\r
1553 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
1555 void vTaskStepTick( portTickType xTicksToJump )
\r
1557 /* Correct the tick count value after a period during which the tick
\r
1558 was suppressed. Note this does *not* call the tick hook function for
\r
1559 each stepped tick. */
\r
1560 configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
\r
1561 xTickCount += xTicksToJump;
\r
1564 #endif /* configUSE_TICKLESS_IDLE */
\r
1565 /*----------------------------------------------------------*/
\r
1567 portBASE_TYPE xTaskIncrementTick( void )
\r
1570 portTickType xItemValue;
\r
1571 portBASE_TYPE xSwitchRequired = pdFALSE;
\r
1573 /* Called by the portable layer each time a tick interrupt occurs.
\r
1574 Increments the tick then checks to see if the new tick value will cause any
\r
1575 tasks to be unblocked. */
\r
1576 traceTASK_INCREMENT_TICK( xTickCount );
\r
1577 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
\r
1579 /* Increment the RTOS tick, switching the delayed and overflowed
\r
1580 delayed lists if it wraps to 0. */
\r
1584 /* Minor optimisation. The tick count cannot change in this
\r
1586 const portTickType xConstTickCount = xTickCount;
\r
1588 if( xConstTickCount == ( portTickType ) 0U )
\r
1590 taskSWITCH_DELAYED_LISTS();
\r
1593 /* See if this tick has made a timeout expire. Tasks are stored in the
\r
1594 queue in the order of their wake time - meaning once one tasks has been
\r
1595 found whose block time has not expired there is no need not look any
\r
1596 further down the list. */
\r
1597 if( xConstTickCount >= xNextTaskUnblockTime )
\r
1601 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
\r
1603 /* The delayed list is empty. Set xNextTaskUnblockTime to
\r
1604 the maximum possible value so it is extremely unlikely that
\r
1605 the if( xTickCount >= xNextTaskUnblockTime ) test will pass
\r
1606 next time through. */
\r
1607 xNextTaskUnblockTime = portMAX_DELAY;
\r
1612 /* The delayed list is not empty, get the value of the item
\r
1613 at the head of the delayed list. This is the time at which
\r
1614 the task at the head of the delayed list must be removed
\r
1615 from the Blocked state. */
\r
1616 pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
\r
1617 xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
\r
1619 if( xConstTickCount < xItemValue )
\r
1621 /* It is not time to unblock this item yet, but the item
\r
1622 value is the time at which the task at the head of the
\r
1623 blocked list must be removed from the Blocked state -
\r
1624 so record the item value in xNextTaskUnblockTime. */
\r
1625 xNextTaskUnblockTime = xItemValue;
\r
1629 /* It is time to remove the item from the Blocked state. */
\r
1630 uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1632 /* Is the task waiting on an event also? If so remove it
\r
1633 from the event list. */
\r
1634 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
1636 uxListRemove( &( pxTCB->xEventListItem ) );
\r
1639 /* Place the unblocked task into the appropriate ready
\r
1641 prvAddTaskToReadyList( pxTCB );
\r
1643 /* A task being unblocked cannot cause an immediate context
\r
1644 switch if preemption is turned off. */
\r
1645 #if ( configUSE_PREEMPTION == 1 )
\r
1647 /* Preemption is on, but a context switch should only
\r
1648 be performed if the unblocked task has a priority that
\r
1649 is equal to or higher than the currently executing
\r
1651 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1653 xSwitchRequired = pdTRUE;
\r
1656 #endif /* configUSE_PREEMPTION */
\r
1662 /* Tasks of equal priority to the currently running task will share
\r
1663 processing time (time slice) if preemption is on, and the application
\r
1664 writer has not explicitly turned time slicing off. */
\r
1665 #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
\r
1667 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > 1 )
\r
1669 xSwitchRequired = pdTRUE;
\r
1672 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
\r
1678 /* The tick hook gets called at regular intervals, even if the
\r
1679 scheduler is locked. */
\r
1680 #if ( configUSE_TICK_HOOK == 1 )
\r
1682 vApplicationTickHook();
\r
1687 #if ( configUSE_TICK_HOOK == 1 )
\r
1689 /* Guard against the tick hook being called when the missed tick
\r
1690 count is being unwound (when the scheduler is being unlocked). */
\r
1691 if( uxPendedTicks == ( unsigned portBASE_TYPE ) 0U )
\r
1693 vApplicationTickHook();
\r
1696 #endif /* configUSE_TICK_HOOK */
\r
1698 return xSwitchRequired;
\r
1700 /*-----------------------------------------------------------*/
\r
1702 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
1704 void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction )
\r
1708 /* If xTask is NULL then we are setting our own task hook. */
\r
1709 if( xTask == NULL )
\r
1711 xTCB = ( tskTCB * ) pxCurrentTCB;
\r
1715 xTCB = ( tskTCB * ) xTask;
\r
1718 /* Save the hook function in the TCB. A critical section is required as
\r
1719 the value can be accessed from an interrupt. */
\r
1720 taskENTER_CRITICAL();
\r
1721 xTCB->pxTaskTag = pxHookFunction;
\r
1722 taskEXIT_CRITICAL();
\r
1725 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
1726 /*-----------------------------------------------------------*/
\r
1728 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
1730 pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask )
\r
1733 pdTASK_HOOK_CODE xReturn;
\r
1735 /* If xTask is NULL then we are setting our own task hook. */
\r
1736 if( xTask == NULL )
\r
1738 xTCB = ( tskTCB * ) pxCurrentTCB;
\r
1742 xTCB = ( tskTCB * ) xTask;
\r
1745 /* Save the hook function in the TCB. A critical section is required as
\r
1746 the value can be accessed from an interrupt. */
\r
1747 taskENTER_CRITICAL();
\r
1748 xReturn = xTCB->pxTaskTag;
\r
1749 taskEXIT_CRITICAL();
\r
1754 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
1755 /*-----------------------------------------------------------*/
\r
1757 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
1759 portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter )
\r
1762 portBASE_TYPE xReturn;
\r
1764 /* If xTask is NULL then we are calling our own task hook. */
\r
1765 if( xTask == NULL )
\r
1767 xTCB = ( tskTCB * ) pxCurrentTCB;
\r
1771 xTCB = ( tskTCB * ) xTask;
\r
1774 if( xTCB->pxTaskTag != NULL )
\r
1776 xReturn = xTCB->pxTaskTag( pvParameter );
\r
1786 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
1787 /*-----------------------------------------------------------*/
\r
1789 void vTaskSwitchContext( void )
\r
1791 if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE )
\r
1793 /* The scheduler is currently suspended - do not allow a context
\r
1795 xYieldPending = pdTRUE;
\r
1799 traceTASK_SWITCHED_OUT();
\r
1801 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
1803 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
1804 portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
\r
1806 ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
1809 /* Add the amount of time the task has been running to the
\r
1810 accumulated time so far. The time the task started running was
\r
1811 stored in ulTaskSwitchedInTime. Note that there is no overflow
\r
1812 protection here so count values are only valid until the timer
\r
1813 overflows. The guard against negative values is to protect
\r
1814 against suspect run time stat counter implementations - which
\r
1815 are provided by the application, not the kernel. */
\r
1816 if( ulTotalRunTime > ulTaskSwitchedInTime )
\r
1818 pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
\r
1820 ulTaskSwitchedInTime = ulTotalRunTime;
\r
1822 #endif /* configGENERATE_RUN_TIME_STATS */
\r
1824 taskFIRST_CHECK_FOR_STACK_OVERFLOW();
\r
1825 taskSECOND_CHECK_FOR_STACK_OVERFLOW();
\r
1827 taskSELECT_HIGHEST_PRIORITY_TASK();
\r
1829 traceTASK_SWITCHED_IN();
\r
1831 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
1833 /* Switch Newlib's _impure_ptr variable to point to the _reent
\r
1834 structure specific to this task. */
\r
1835 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
\r
1837 #endif /* configUSE_NEWLIB_REENTRANT */
\r
1840 /*-----------------------------------------------------------*/
\r
1842 void vTaskPlaceOnEventList( const xList * const pxEventList, portTickType xTicksToWait )
\r
1844 portTickType xTimeToWake;
\r
1846 configASSERT( pxEventList );
\r
1848 /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
\r
1849 SCHEDULER SUSPENDED. */
\r
1851 /* Place the event list item of the TCB in the appropriate event list.
\r
1852 This is placed in the list in priority order so the highest priority task
\r
1853 is the first to be woken by the event. */
\r
1854 vListInsert( ( xList * ) pxEventList, ( xListItem * ) &( pxCurrentTCB->xEventListItem ) );
\r
1856 /* We must remove ourselves from the ready list before adding ourselves
\r
1857 to the blocked list as the same list item is used for both lists. We have
\r
1858 exclusive access to the ready lists as the scheduler is locked. */
\r
1859 if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 )
\r
1861 /* The current task must be in a ready list, so there is no need to
\r
1862 check, and the port reset macro can be called directly. */
\r
1863 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
1866 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1868 if( xTicksToWait == portMAX_DELAY )
\r
1870 /* Add ourselves to the suspended task list instead of a delayed task
\r
1871 list to ensure we are not woken by a timing event. We will block
\r
1873 vListInsertEnd( ( xList * ) &xSuspendedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
\r
1877 /* Calculate the time at which the task should be woken if the event does
\r
1878 not occur. This may overflow but this doesn't matter. */
\r
1879 xTimeToWake = xTickCount + xTicksToWait;
\r
1880 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
1883 #else /* INCLUDE_vTaskSuspend */
\r
1885 /* Calculate the time at which the task should be woken if the event does
\r
1886 not occur. This may overflow but this doesn't matter. */
\r
1887 xTimeToWake = xTickCount + xTicksToWait;
\r
1888 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
1890 #endif /* INCLUDE_vTaskSuspend */
\r
1892 /*-----------------------------------------------------------*/
\r
1894 #if configUSE_TIMERS == 1
\r
1896 void vTaskPlaceOnEventListRestricted( const xList * const pxEventList, portTickType xTicksToWait )
\r
1898 portTickType xTimeToWake;
\r
1900 configASSERT( pxEventList );
\r
1902 /* This function should not be called by application code hence the
\r
1903 'Restricted' in its name. It is not part of the public API. It is
\r
1904 designed for use by kernel code, and has special calling requirements -
\r
1905 it should be called from a critical section. */
\r
1908 /* Place the event list item of the TCB in the appropriate event list.
\r
1909 In this case it is assume that this is the only task that is going to
\r
1910 be waiting on this event list, so the faster vListInsertEnd() function
\r
1911 can be used in place of vListInsert. */
\r
1912 vListInsertEnd( ( xList * ) pxEventList, ( xListItem * ) &( pxCurrentTCB->xEventListItem ) );
\r
1914 /* We must remove this task from the ready list before adding it to the
\r
1915 blocked list as the same list item is used for both lists. This
\r
1916 function is called form a critical section. */
\r
1917 if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 )
\r
1919 /* The current task must be in a ready list, so there is no need to
\r
1920 check, and the port reset macro can be called directly. */
\r
1921 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
1924 /* Calculate the time at which the task should be woken if the event does
\r
1925 not occur. This may overflow but this doesn't matter. */
\r
1926 xTimeToWake = xTickCount + xTicksToWait;
\r
1928 traceTASK_DELAY_UNTIL();
\r
1929 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
1932 #endif /* configUSE_TIMERS */
\r
1933 /*-----------------------------------------------------------*/
\r
1935 signed portBASE_TYPE xTaskRemoveFromEventList( const xList * const pxEventList )
\r
1937 tskTCB *pxUnblockedTCB;
\r
1938 portBASE_TYPE xReturn;
\r
1940 /* THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED OR THE
\r
1941 SCHEDULER SUSPENDED. It can also be called from within an ISR. */
\r
1943 /* The event list is sorted in priority order, so we can remove the
\r
1944 first in the list, remove the TCB from the delayed list, and add
\r
1945 it to the ready list.
\r
1947 If an event is for a queue that is locked then this function will never
\r
1948 get called - the lock count on the queue will get modified instead. This
\r
1949 means we can always expect exclusive access to the event list here.
\r
1951 This function assumes that a check has already been made to ensure that
\r
1952 pxEventList is not empty. */
\r
1953 pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
\r
1954 configASSERT( pxUnblockedTCB );
\r
1955 uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
\r
1957 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
\r
1959 uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
\r
1960 prvAddTaskToReadyList( pxUnblockedTCB );
\r
1964 /* We cannot access the delayed or ready lists, so will hold this
\r
1965 task pending until the scheduler is resumed. */
\r
1966 vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
\r
1969 if( pxUnblockedTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1971 /* Return true if the task removed from the event list has
\r
1972 a higher priority than the calling task. This allows
\r
1973 the calling task to know if it should force a context
\r
1979 xReturn = pdFALSE;
\r
1984 /*-----------------------------------------------------------*/
\r
1986 void vTaskSetTimeOutState( xTimeOutType * const pxTimeOut )
\r
1988 configASSERT( pxTimeOut );
\r
1989 pxTimeOut->xOverflowCount = xNumOfOverflows;
\r
1990 pxTimeOut->xTimeOnEntering = xTickCount;
\r
1992 /*-----------------------------------------------------------*/
\r
1994 portBASE_TYPE xTaskCheckForTimeOut( xTimeOutType * const pxTimeOut, portTickType * const pxTicksToWait )
\r
1996 portBASE_TYPE xReturn;
\r
1998 configASSERT( pxTimeOut );
\r
1999 configASSERT( pxTicksToWait );
\r
2001 taskENTER_CRITICAL();
\r
2003 /* Minor optimisation. The tick count cannot change in this block. */
\r
2004 const portTickType xConstTickCount = xTickCount;
\r
2006 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2007 /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is
\r
2008 the maximum block time then the task should block indefinitely, and
\r
2009 therefore never time out. */
\r
2010 if( *pxTicksToWait == portMAX_DELAY )
\r
2012 xReturn = pdFALSE;
\r
2014 else /* We are not blocking indefinitely, perform the checks below. */
\r
2017 if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( ( portTickType ) xConstTickCount >= ( portTickType ) pxTimeOut->xTimeOnEntering ) )
\r
2019 /* The tick count is greater than the time at which vTaskSetTimeout()
\r
2020 was called, but has also overflowed since vTaskSetTimeOut() was called.
\r
2021 It must have wrapped all the way around and gone past us again. This
\r
2022 passed since vTaskSetTimeout() was called. */
\r
2025 else if( ( ( portTickType ) ( ( portTickType ) xConstTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ) ) < ( portTickType ) *pxTicksToWait )
\r
2027 /* Not a genuine timeout. Adjust parameters for time remaining. */
\r
2028 *pxTicksToWait -= ( ( portTickType ) xConstTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering );
\r
2029 vTaskSetTimeOutState( pxTimeOut );
\r
2030 xReturn = pdFALSE;
\r
2037 taskEXIT_CRITICAL();
\r
2041 /*-----------------------------------------------------------*/
\r
2043 void vTaskMissedYield( void )
\r
2045 xYieldPending = pdTRUE;
\r
2047 /*-----------------------------------------------------------*/
\r
2049 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2051 unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask )
\r
2053 unsigned portBASE_TYPE uxReturn;
\r
2056 if( xTask != NULL )
\r
2058 pxTCB = ( tskTCB * ) xTask;
\r
2059 uxReturn = pxTCB->uxTaskNumber;
\r
2069 #endif /* configUSE_TRACE_FACILITY */
\r
2070 /*-----------------------------------------------------------*/
\r
2072 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2074 void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle )
\r
2078 if( xTask != NULL )
\r
2080 pxTCB = ( tskTCB * ) xTask;
\r
2081 pxTCB->uxTaskNumber = uxHandle;
\r
2085 #endif /* configUSE_TRACE_FACILITY */
\r
2088 * -----------------------------------------------------------
\r
2090 * ----------------------------------------------------------
\r
2092 * The portTASK_FUNCTION() macro is used to allow port/compiler specific
\r
2093 * language extensions. The equivalent prototype for this function is:
\r
2095 * void prvIdleTask( void *pvParameters );
\r
2098 static portTASK_FUNCTION( prvIdleTask, pvParameters )
\r
2100 /* Stop warnings. */
\r
2101 ( void ) pvParameters;
\r
2105 /* See if any tasks have been deleted. */
\r
2106 prvCheckTasksWaitingTermination();
\r
2108 #if ( configUSE_PREEMPTION == 0 )
\r
2110 /* If we are not using preemption we keep forcing a task switch to
\r
2111 see if any other task has become available. If we are using
\r
2112 preemption we don't need to do this as any task becoming available
\r
2113 will automatically get the processor anyway. */
\r
2116 #endif /* configUSE_PREEMPTION */
\r
2118 #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
\r
2120 /* When using preemption tasks of equal priority will be
\r
2121 timesliced. If a task that is sharing the idle priority is ready
\r
2122 to run then the idle task should yield before the end of the
\r
2125 A critical region is not required here as we are just reading from
\r
2126 the list, and an occasional incorrect value will not matter. If
\r
2127 the ready list at the idle priority contains more than one task
\r
2128 then a task other than the idle task is ready to execute. */
\r
2129 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( unsigned portBASE_TYPE ) 1 )
\r
2134 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
\r
2136 #if ( configUSE_IDLE_HOOK == 1 )
\r
2138 extern void vApplicationIdleHook( void );
\r
2140 /* Call the user defined function from within the idle task. This
\r
2141 allows the application designer to add background functionality
\r
2142 without the overhead of a separate task.
\r
2143 NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
\r
2144 CALL A FUNCTION THAT MIGHT BLOCK. */
\r
2145 vApplicationIdleHook();
\r
2147 #endif /* configUSE_IDLE_HOOK */
\r
2149 /* This conditional compilation should use inequality to 0, not equality
\r
2150 to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
\r
2151 user defined low power mode implementations require
\r
2152 configUSE_TICKLESS_IDLE to be set to a value other than 1. */
\r
2153 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
2155 portTickType xExpectedIdleTime;
\r
2157 /* It is not desirable to suspend then resume the scheduler on
\r
2158 each iteration of the idle task. Therefore, a preliminary
\r
2159 test of the expected idle time is performed without the
\r
2160 scheduler suspended. The result here is not necessarily
\r
2162 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
2164 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
2166 vTaskSuspendAll();
\r
2168 /* Now the scheduler is suspended, the expected idle
\r
2169 time can be sampled again, and this time its value can
\r
2171 configASSERT( xNextTaskUnblockTime >= xTickCount );
\r
2172 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
2174 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
2176 portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
\r
2182 #endif /* configUSE_TICKLESS_IDLE */
\r
2184 } /*lint !e715 pvParameters is not accessed but all task functions require the same prototype. */
\r
2185 /*-----------------------------------------------------------*/
\r
2187 #if configUSE_TICKLESS_IDLE != 0
\r
2189 eSleepModeStatus eTaskConfirmSleepModeStatus( void )
\r
2191 eSleepModeStatus eReturn = eStandardSleep;
\r
2193 if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
\r
2195 /* A task was made ready while the scheduler was suspended. */
\r
2196 eReturn = eAbortSleep;
\r
2198 else if( xYieldPending != pdFALSE )
\r
2200 /* A yield was pended while the scheduler was suspended. */
\r
2201 eReturn = eAbortSleep;
\r
2205 #if configUSE_TIMERS == 0
\r
2207 /* The idle task exists in addition to the application tasks. */
\r
2208 const unsigned portBASE_TYPE uxNonApplicationTasks = 1;
\r
2210 /* If timers are not being used and all the tasks are in the
\r
2211 suspended list (which might mean they have an infinite block
\r
2212 time rather than actually being suspended) then it is safe to
\r
2213 turn all clocks off and just wait for external interrupts. */
\r
2214 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
\r
2216 eReturn = eNoTasksWaitingTimeout;
\r
2219 #endif /* configUSE_TIMERS */
\r
2224 #endif /* configUSE_TICKLESS_IDLE */
\r
2225 /*-----------------------------------------------------------*/
\r
2227 static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth )
\r
2231 /* Store the task name in the TCB. */
\r
2232 for( x = 0; x < configMAX_TASK_NAME_LEN; x++ )
\r
2234 pxTCB->pcTaskName[ x ] = pcName[ x ];
\r
2236 /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
\r
2237 configMAX_TASK_NAME_LEN characters just in case the memory after the
\r
2238 string is not accessible (extremely unlikely). */
\r
2239 if( pcName[ x ] == 0x00 )
\r
2245 /* Ensure the name string is terminated in the case that the string length
\r
2246 was greater or equal to configMAX_TASK_NAME_LEN. */
\r
2247 pxTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = ( signed char ) '\0';
\r
2249 /* This is used as an array index so must ensure it's not too large. First
\r
2250 remove the privilege bit if one is present. */
\r
2251 if( uxPriority >= configMAX_PRIORITIES )
\r
2253 uxPriority = configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U;
\r
2256 pxTCB->uxPriority = uxPriority;
\r
2257 #if ( configUSE_MUTEXES == 1 )
\r
2259 pxTCB->uxBasePriority = uxPriority;
\r
2261 #endif /* configUSE_MUTEXES */
\r
2263 vListInitialiseItem( &( pxTCB->xGenericListItem ) );
\r
2264 vListInitialiseItem( &( pxTCB->xEventListItem ) );
\r
2266 /* Set the pxTCB as a link back from the xListItem. This is so we can get
\r
2267 back to the containing TCB from a generic item in a list. */
\r
2268 listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB );
\r
2270 /* Event lists are always in priority order. */
\r
2271 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxPriority );
\r
2272 listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB );
\r
2274 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
2276 pxTCB->uxCriticalNesting = ( unsigned portBASE_TYPE ) 0U;
\r
2278 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
2280 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2282 pxTCB->pxTaskTag = NULL;
\r
2284 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2286 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
2288 pxTCB->ulRunTimeCounter = 0UL;
\r
2290 #endif /* configGENERATE_RUN_TIME_STATS */
\r
2292 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
2294 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth );
\r
2296 #else /* portUSING_MPU_WRAPPERS */
\r
2298 ( void ) xRegions;
\r
2299 ( void ) usStackDepth;
\r
2301 #endif /* portUSING_MPU_WRAPPERS */
\r
2303 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
2305 /* Initialise this task's Newlib reent structure. */
\r
2306 _REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) );
\r
2308 #endif /* configUSE_NEWLIB_REENTRANT */
\r
2310 /*-----------------------------------------------------------*/
\r
2312 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
2314 void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions )
\r
2318 if( xTaskToModify == pxCurrentTCB )
\r
2320 xTaskToModify = NULL;
\r
2323 /* If null is passed in here then we are deleting ourselves. */
\r
2324 pxTCB = prvGetTCBFromHandle( xTaskToModify );
\r
2326 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
\r
2329 #endif /* portUSING_MPU_WRAPPERS */
\r
2330 /*-----------------------------------------------------------*/
\r
2332 static void prvInitialiseTaskLists( void )
\r
2334 unsigned portBASE_TYPE uxPriority;
\r
2336 for( uxPriority = ( unsigned portBASE_TYPE ) 0U; uxPriority < configMAX_PRIORITIES; uxPriority++ )
\r
2338 vListInitialise( ( xList * ) &( pxReadyTasksLists[ uxPriority ] ) );
\r
2341 vListInitialise( ( xList * ) &xDelayedTaskList1 );
\r
2342 vListInitialise( ( xList * ) &xDelayedTaskList2 );
\r
2343 vListInitialise( ( xList * ) &xPendingReadyList );
\r
2345 #if ( INCLUDE_vTaskDelete == 1 )
\r
2347 vListInitialise( ( xList * ) &xTasksWaitingTermination );
\r
2349 #endif /* INCLUDE_vTaskDelete */
\r
2351 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2353 vListInitialise( ( xList * ) &xSuspendedTaskList );
\r
2355 #endif /* INCLUDE_vTaskSuspend */
\r
2357 /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
\r
2359 pxDelayedTaskList = &xDelayedTaskList1;
\r
2360 pxOverflowDelayedTaskList = &xDelayedTaskList2;
\r
2362 /*-----------------------------------------------------------*/
\r
2364 static void prvCheckTasksWaitingTermination( void )
\r
2366 #if ( INCLUDE_vTaskDelete == 1 )
\r
2368 portBASE_TYPE xListIsEmpty;
\r
2370 /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
\r
2371 too often in the idle task. */
\r
2372 while( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0U )
\r
2374 vTaskSuspendAll();
\r
2375 xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
\r
2378 if( xListIsEmpty == pdFALSE )
\r
2382 taskENTER_CRITICAL();
\r
2384 pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xTasksWaitingTermination ) );
\r
2385 uxListRemove( &( pxTCB->xGenericListItem ) );
\r
2386 --uxCurrentNumberOfTasks;
\r
2389 taskEXIT_CRITICAL();
\r
2391 prvDeleteTCB( pxTCB );
\r
2395 #endif /* vTaskDelete */
\r
2397 /*-----------------------------------------------------------*/
\r
2399 static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake )
\r
2401 /* The list item will be inserted in wake time order. */
\r
2402 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
\r
2404 if( xTimeToWake < xTickCount )
\r
2406 /* Wake time has overflowed. Place this item in the overflow list. */
\r
2407 vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
\r
2411 /* The wake time has not overflowed, so we can use the current block list. */
\r
2412 vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
\r
2414 /* If the task entering the blocked state was placed at the head of the
\r
2415 list of blocked tasks then xNextTaskUnblockTime needs to be updated
\r
2417 if( xTimeToWake < xNextTaskUnblockTime )
\r
2419 xNextTaskUnblockTime = xTimeToWake;
\r
2423 /*-----------------------------------------------------------*/
\r
2425 static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer )
\r
2429 /* Allocate space for the TCB. Where the memory comes from depends on
\r
2430 the implementation of the port malloc function. */
\r
2431 pxNewTCB = ( tskTCB * ) pvPortMalloc( sizeof( tskTCB ) );
\r
2433 if( pxNewTCB != NULL )
\r
2435 /* Allocate space for the stack used by the task being created.
\r
2436 The base of the stack memory stored in the TCB so the task can
\r
2437 be deleted later if required. */
\r
2438 pxNewTCB->pxStack = ( portSTACK_TYPE * ) pvPortMallocAligned( ( ( ( size_t )usStackDepth ) * sizeof( portSTACK_TYPE ) ), puxStackBuffer );
\r
2440 if( pxNewTCB->pxStack == NULL )
\r
2442 /* Could not allocate the stack. Delete the allocated TCB. */
\r
2443 vPortFree( pxNewTCB );
\r
2448 /* Just to help debugging. */
\r
2449 memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( portSTACK_TYPE ) );
\r
2455 /*-----------------------------------------------------------*/
\r
2457 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2459 static unsigned portBASE_TYPE prvListTaskWithinSingleList( xTaskStatusType *pxTaskStatusArray, xList *pxList, eTaskState eState )
\r
2461 volatile tskTCB *pxNextTCB, *pxFirstTCB;
\r
2462 unsigned portBASE_TYPE uxTask = 0;
\r
2464 if( listCURRENT_LIST_LENGTH( pxList ) > 0 )
\r
2466 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
\r
2468 /* Populate an xTaskStatusType structure within the
\r
2469 pxTaskStatusArray array for each task that is referenced from
\r
2470 pxList. See the definition of xTaskStatusType in task.h for the
\r
2471 meaning of each xTaskStatusType structure member. */
\r
2474 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
\r
2476 pxTaskStatusArray[ uxTask ].xHandle = ( xTaskHandle ) pxNextTCB;
\r
2477 pxTaskStatusArray[ uxTask ].pcTaskName = ( const signed char * ) &( pxNextTCB->pcTaskName [ 0 ] );
\r
2478 pxTaskStatusArray[ uxTask ].xTaskNumber = pxNextTCB->uxTCBNumber;
\r
2479 pxTaskStatusArray[ uxTask ].eCurrentState = eState;
\r
2480 pxTaskStatusArray[ uxTask ].uxCurrentPriority = pxNextTCB->uxPriority;
\r
2482 #if ( configUSE_MUTEXES == 1 )
\r
2484 pxTaskStatusArray[ uxTask ].uxBasePriority = pxNextTCB->uxBasePriority;
\r
2488 pxTaskStatusArray[ uxTask ].uxBasePriority = 0;
\r
2492 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
2494 pxTaskStatusArray[ uxTask ].ulRunTimeCounter = pxNextTCB->ulRunTimeCounter;
\r
2498 pxTaskStatusArray[ uxTask ].ulRunTimeCounter = 0;
\r
2502 #if ( portSTACK_GROWTH > 0 )
\r
2504 ppxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxEndOfStack );
\r
2508 pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack );
\r
2514 } while( pxNextTCB != pxFirstTCB );
\r
2520 #endif /* configUSE_TRACE_FACILITY */
\r
2521 /*-----------------------------------------------------------*/
\r
2523 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
2525 static unsigned short prvTaskCheckFreeStackSpace( const unsigned char * pucStackByte )
\r
2527 register unsigned short usCount = 0U;
\r
2529 while( *pucStackByte == tskSTACK_FILL_BYTE )
\r
2531 pucStackByte -= portSTACK_GROWTH;
\r
2535 usCount /= sizeof( portSTACK_TYPE );
\r
2540 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */
\r
2541 /*-----------------------------------------------------------*/
\r
2543 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
\r
2545 unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask )
\r
2548 unsigned char *pcEndOfStack;
\r
2549 unsigned portBASE_TYPE uxReturn;
\r
2551 pxTCB = prvGetTCBFromHandle( xTask );
\r
2553 #if portSTACK_GROWTH < 0
\r
2555 pcEndOfStack = ( unsigned char * ) pxTCB->pxStack;
\r
2559 pcEndOfStack = ( unsigned char * ) pxTCB->pxEndOfStack;
\r
2563 uxReturn = ( unsigned portBASE_TYPE ) prvTaskCheckFreeStackSpace( pcEndOfStack );
\r
2568 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
\r
2569 /*-----------------------------------------------------------*/
\r
2571 #if ( INCLUDE_vTaskDelete == 1 )
\r
2573 static void prvDeleteTCB( tskTCB *pxTCB )
\r
2575 /* This call is required specifically for the TriCore port. It must be
\r
2576 above the vPortFree() calls. The call is also used by ports/demos that
\r
2577 want to allocate and clean RAM statically. */
\r
2578 portCLEAN_UP_TCB( pxTCB );
\r
2580 /* Free up the memory allocated by the scheduler for the task. It is up to
\r
2581 the task to free any memory allocated at the application level. */
\r
2582 vPortFreeAligned( pxTCB->pxStack );
\r
2583 vPortFree( pxTCB );
\r
2586 #endif /* INCLUDE_vTaskDelete */
\r
2587 /*-----------------------------------------------------------*/
\r
2589 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
\r
2591 xTaskHandle xTaskGetCurrentTaskHandle( void )
\r
2593 xTaskHandle xReturn;
\r
2595 /* A critical section is not required as this is not called from
\r
2596 an interrupt and the current TCB will always be the same for any
\r
2597 individual execution thread. */
\r
2598 xReturn = pxCurrentTCB;
\r
2603 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
\r
2604 /*-----------------------------------------------------------*/
\r
2606 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
2608 portBASE_TYPE xTaskGetSchedulerState( void )
\r
2610 portBASE_TYPE xReturn;
\r
2612 if( xSchedulerRunning == pdFALSE )
\r
2614 xReturn = taskSCHEDULER_NOT_STARTED;
\r
2618 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
\r
2620 xReturn = taskSCHEDULER_RUNNING;
\r
2624 xReturn = taskSCHEDULER_SUSPENDED;
\r
2631 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
\r
2632 /*-----------------------------------------------------------*/
\r
2634 #if ( configUSE_MUTEXES == 1 )
\r
2636 void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder )
\r
2638 tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;
\r
2640 /* If the mutex was given back by an interrupt while the queue was
\r
2641 locked then the mutex holder might now be NULL. */
\r
2642 if( pxMutexHolder != NULL )
\r
2644 if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
\r
2646 /* Adjust the mutex holder state to account for its new priority. */
\r
2647 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority );
\r
2649 /* If the task being modified is in the ready state it will need to
\r
2650 be moved into a new list. */
\r
2651 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
\r
2653 if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
\r
2655 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
2658 /* Inherit the priority before being moved into the new list. */
\r
2659 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
2660 prvAddTaskToReadyList( pxTCB );
\r
2664 /* Just inherit the priority. */
\r
2665 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
2668 traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );
\r
2673 #endif /* configUSE_MUTEXES */
\r
2674 /*-----------------------------------------------------------*/
\r
2676 #if ( configUSE_MUTEXES == 1 )
\r
2678 void vTaskPriorityDisinherit( xTaskHandle * const pxMutexHolder )
\r
2680 tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;
\r
2682 if( pxMutexHolder != NULL )
\r
2684 if( pxTCB->uxPriority != pxTCB->uxBasePriority )
\r
2686 /* We must be the running task to be able to give the mutex back.
\r
2687 Remove ourselves from the ready list we currently appear in. */
\r
2688 if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
\r
2690 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
2693 /* Disinherit the priority before adding the task into the new
\r
2695 traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
\r
2696 pxTCB->uxPriority = pxTCB->uxBasePriority;
\r
2697 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority );
\r
2698 prvAddTaskToReadyList( pxTCB );
\r
2703 #endif /* configUSE_MUTEXES */
\r
2704 /*-----------------------------------------------------------*/
\r
2706 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
2708 void vTaskEnterCritical( void )
\r
2710 portDISABLE_INTERRUPTS();
\r
2712 if( xSchedulerRunning != pdFALSE )
\r
2714 ( pxCurrentTCB->uxCriticalNesting )++;
\r
2718 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
2719 /*-----------------------------------------------------------*/
\r
2721 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
2723 void vTaskExitCritical( void )
\r
2725 if( xSchedulerRunning != pdFALSE )
\r
2727 if( pxCurrentTCB->uxCriticalNesting > 0U )
\r
2729 ( pxCurrentTCB->uxCriticalNesting )--;
\r
2731 if( pxCurrentTCB->uxCriticalNesting == 0U )
\r
2733 portENABLE_INTERRUPTS();
\r
2739 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
2740 /*-----------------------------------------------------------*/
\r
2742 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configINCLUDE_STATS_FORMATTING_FUNCTIONS == 1 ) )
\r
2744 void vTaskList( signed char *pcWriteBuffer )
\r
2746 xTaskStatusType *pxTaskStatusArray;
\r
2747 volatile unsigned portBASE_TYPE uxArraySize, x;
\r
2753 * This function is provided for convenience only, and is used by many
\r
2754 * of the demo applications. Do not consider it to be part of the
\r
2757 * vTaskList() calls xTaskGetSystemState(), then formats part of the
\r
2758 * xTaskGetSystemState() output into a human readable table that
\r
2759 * displays task names, states and stack usage.
\r
2761 * vTaskList() has a dependency on the sprintf() C library function that
\r
2762 * might bloat the code size, use a lot of stack, and provide different
\r
2763 * results on different platforms. An alternative, tiny, third party,
\r
2764 * and limited functionality implementation of sprintf() is provided in
\r
2765 * many of the FreeRTOS/Demo sub-directories in a file called
\r
2766 * printf-stdarg.c (note printf-stdarg.c does not provide a full
\r
2767 * snprintf() implementation!).
\r
2769 * It is recommended that production systems call xTaskGetSystemState()
\r
2770 * directly to get access to raw stats data, rather than indirectly
\r
2771 * through a call to vTaskList().
\r
2775 /* Make sure the write buffer does not contain a string. */
\r
2776 *pcWriteBuffer = 0x00;
\r
2778 /* Take a snapshot of the number of tasks in case it changes while this
\r
2779 function is executing. */
\r
2780 uxArraySize = uxCurrentNumberOfTasks;
\r
2782 /* Allocate an array index for each task. */
\r
2783 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( xTaskStatusType ) );
\r
2785 if( pxTaskStatusArray != NULL )
\r
2787 /* Generate the (binary) data. */
\r
2788 uxArraySize = xTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
\r
2790 /* Create a human readable table from the binary data. */
\r
2791 for( x = 0; x < uxArraySize; x++ )
\r
2793 switch( pxTaskStatusArray[ x ].eCurrentState )
\r
2795 case eReady: cStatus = tskREADY_CHAR;
\r
2798 case eBlocked: cStatus = tskBLOCKED_CHAR;
\r
2801 case eSuspended: cStatus = tskSUSPENDED_CHAR;
\r
2804 case eDeleted: cStatus = tskDELETED_CHAR;
\r
2807 default: /* Should not get here, but it is included
\r
2808 to prevent static checking errors. */
\r
2813 sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxTaskStatusArray[ x ].pcTaskName, cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber );
\r
2814 pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
\r
2817 /* Free the array again. */
\r
2818 vPortFree( pxTaskStatusArray );
\r
2822 #endif /* configUSE_TRACE_FACILITY */
\r
2823 /*----------------------------------------------------------*/
\r
2825 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configINCLUDE_STATS_FORMATTING_FUNCTIONS == 1 ) )
\r
2827 void vTaskGetRunTimeStats( signed char *pcWriteBuffer )
\r
2829 xTaskStatusType *pxTaskStatusArray;
\r
2830 volatile unsigned portBASE_TYPE uxArraySize, x;
\r
2831 unsigned long ulTotalTime, ulStatsAsPercentage;
\r
2836 * This function is provided for convenience only, and is used by many
\r
2837 * of the demo applications. Do not consider it to be part of the
\r
2840 * vTaskGetRunTimeStats() calls xTaskGetSystemState(), then formats part
\r
2841 * of the xTaskGetSystemState() output into a human readable table that
\r
2842 * displays the amount of time each task has spent in the Running state
\r
2843 * in both absolute and percentage terms.
\r
2845 * vTaskGetRunTimeStats() has a dependency on the sprintf() C library
\r
2846 * function that might bloat the code size, use a lot of stack, and
\r
2847 * provide different results on different platforms. An alternative,
\r
2848 * tiny, third party, and limited functionality implementation of
\r
2849 * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in
\r
2850 * a file called printf-stdarg.c (note printf-stdarg.c does not provide
\r
2851 * a full snprintf() implementation!).
\r
2853 * It is recommended that production systems call xTaskGetSystemState()
\r
2854 * directly to get access to raw stats data, rather than indirectly
\r
2855 * through a call to vTaskGetRunTimeStats().
\r
2858 /* Make sure the write buffer does not contain a string. */
\r
2859 *pcWriteBuffer = 0x00;
\r
2861 /* Take a snapshot of the number of tasks in case it changes while this
\r
2862 function is executing. */
\r
2863 uxArraySize = uxCurrentNumberOfTasks;
\r
2865 /* Allocate an array index for each task. */
\r
2866 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( xTaskStatusType ) );
\r
2868 if( pxTaskStatusArray != NULL )
\r
2870 /* Generate the (binary) data. */
\r
2871 uxArraySize = xTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
\r
2873 /* For percentage calculations. */
\r
2874 ulTotalTime /= 100UL;
\r
2876 /* Avoid divide by zero errors. */
\r
2877 if( ulTotalTime > 0 )
\r
2879 /* Create a human readable table from the binary data. */
\r
2880 for( x = 0; x < uxArraySize; x++ )
\r
2882 /* What percentage of the total run time has the task used?
\r
2883 This will always be rounded down to the nearest integer.
\r
2884 ulTotalRunTimeDiv100 has already been divided by 100. */
\r
2885 ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
\r
2887 if( ulStatsAsPercentage > 0UL )
\r
2889 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
2891 sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
\r
2895 /* sizeof( int ) == sizeof( long ) so a smaller
\r
2896 printf() library can be used. */
\r
2897 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
2903 /* If the percentage is zero here then the task has
\r
2904 consumed less than 1% of the total run time. */
\r
2905 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
2907 sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );
\r
2911 /* sizeof( int ) == sizeof( long ) so a smaller
\r
2912 printf() library can be used. */
\r
2913 sprintf( ( char * ) pcWriteBuffer, ( char * ) "%s\t\t%u\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter );
\r
2918 pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
\r
2922 /* Free the array again. */
\r
2923 vPortFree( pxTaskStatusArray );
\r
2927 #endif /* configGENERATE_RUN_TIME_STATS */
\r