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
153 * Some kernel aware debuggers require the data the debugger needs access to to
\r
154 * be global, rather than file scope.
\r
156 #ifdef portREMOVE_STATIC_QUALIFIER
\r
161 PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL;
\r
163 /* Lists for ready and blocked tasks. --------------------*/
\r
164 PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */
\r
165 PRIVILEGED_DATA static xList xDelayedTaskList1; /*< Delayed tasks. */
\r
166 PRIVILEGED_DATA static xList xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
\r
167 PRIVILEGED_DATA static xList * volatile pxDelayedTaskList ; /*< Points to the delayed task list currently being used. */
\r
168 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
169 PRIVILEGED_DATA static xList xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready queue when the scheduler is resumed. */
\r
171 #if ( INCLUDE_vTaskDelete == 1 )
\r
173 PRIVILEGED_DATA static xList xTasksWaitingTermination; /*< Tasks that have been deleted - but the their memory not yet freed. */
\r
174 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTasksDeleted = ( unsigned portBASE_TYPE ) 0U;
\r
178 #if ( INCLUDE_vTaskSuspend == 1 )
\r
180 PRIVILEGED_DATA static xList xSuspendedTaskList; /*< Tasks that are currently suspended. */
\r
184 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
186 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
190 /* File private variables. --------------------------------*/
\r
191 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0U;
\r
192 PRIVILEGED_DATA static volatile portTickType xTickCount = ( portTickType ) 0U;
\r
193 PRIVILEGED_DATA static unsigned portBASE_TYPE uxTopUsedPriority = tskIDLE_PRIORITY;
\r
194 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTopReadyPriority = tskIDLE_PRIORITY;
\r
195 PRIVILEGED_DATA static volatile signed portBASE_TYPE xSchedulerRunning = pdFALSE;
\r
196 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended = ( unsigned portBASE_TYPE ) pdFALSE;
\r
197 PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxMissedTicks = ( unsigned portBASE_TYPE ) 0U;
\r
198 PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE;
\r
199 PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0;
\r
200 PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0U;
\r
201 PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime = ( portTickType ) portMAX_DELAY;
\r
203 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
205 PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
\r
206 PRIVILEGED_DATA static unsigned long ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */
\r
207 static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTimeDiv100 ) PRIVILEGED_FUNCTION;
\r
211 /* Debugging and trace facilities private variables and macros. ------------*/
\r
214 * The value used to fill the stack of a task when the task is created. This
\r
215 * is used purely for checking the high water mark for tasks.
\r
217 #define tskSTACK_FILL_BYTE ( 0xa5U )
\r
220 * Macros used by vListTask to indicate which state a task is in.
\r
222 #define tskBLOCKED_CHAR ( ( signed char ) 'B' )
\r
223 #define tskREADY_CHAR ( ( signed char ) 'R' )
\r
224 #define tskDELETED_CHAR ( ( signed char ) 'D' )
\r
225 #define tskSUSPENDED_CHAR ( ( signed char ) 'S' )
\r
227 /*-----------------------------------------------------------*/
\r
229 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
\r
231 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
\r
232 performed in a generic way that is not optimised to any particular
\r
233 microcontroller architecture. */
\r
235 /* uxTopReadyPriority holds the priority of the highest priority ready
\r
237 #define taskRECORD_READY_PRIORITY( uxPriority ) \
\r
239 if( ( uxPriority ) > uxTopReadyPriority ) \
\r
241 uxTopReadyPriority = ( uxPriority ); \
\r
243 } /* taskRECORD_READY_PRIORITY */
\r
245 /*-----------------------------------------------------------*/
\r
247 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
249 /* Find the highest priority queue that contains ready tasks. */ \
\r
250 while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) \
\r
252 configASSERT( uxTopReadyPriority ); \
\r
253 --uxTopReadyPriority; \
\r
256 /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
\r
257 the same priority get an equal share of the processor time. */ \
\r
258 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \
\r
259 } /* taskSELECT_HIGHEST_PRIORITY_TASK */
\r
261 /*-----------------------------------------------------------*/
\r
263 /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
\r
264 they are only required when a port optimised method of task selection is
\r
266 #define taskRESET_READY_PRIORITY( uxPriority )
\r
267 #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
269 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
271 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
\r
272 performed in a way that is tailored to the particular microcontroller
\r
273 architecture being used. */
\r
275 /* A port optimised version is provided. Call the port defined macros. */
\r
276 #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
278 /*-----------------------------------------------------------*/
\r
280 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
282 unsigned portBASE_TYPE uxTopPriority; \
\r
284 /* Find the highest priority queue that contains ready tasks. */ \
\r
285 portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
\r
286 configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
\r
287 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
\r
288 } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
\r
290 /*-----------------------------------------------------------*/
\r
292 /* A port optimised version is provided, call it only if the TCB being reset
\r
293 is being referenced from a ready list. If it is referenced from a delayed
\r
294 or suspended list then it won't be in a ready list. */
\r
295 #define taskRESET_READY_PRIORITY( uxPriority ) \
\r
297 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == 0 ) \
\r
299 portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \
\r
303 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
306 * Place the task represented by pxTCB into the appropriate ready queue for
\r
307 * the task. It is inserted at the end of the list. One quirk of this is
\r
308 * that if the task being inserted is at the same priority as the currently
\r
309 * executing task, then it will only be rescheduled after the currently
\r
310 * executing task has been rescheduled.
\r
312 #define prvAddTaskToReadyQueue( pxTCB ) \
\r
313 traceMOVED_TASK_TO_READY_STATE( pxTCB ) \
\r
314 taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
\r
315 vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) )
\r
316 /*-----------------------------------------------------------*/
\r
319 * Macro that looks at the list of tasks that are currently delayed to see if
\r
320 * any require waking.
\r
322 * Tasks are stored in the queue in the order of their wake time - meaning
\r
323 * once one tasks has been found whose timer has not expired we need not look
\r
324 * any further down the list.
\r
326 #define prvCheckDelayedTasks() \
\r
328 portTickType xItemValue; \
\r
330 /* Is the tick count greater than or equal to the wake time of the first \
\r
331 task referenced from the delayed tasks list? */ \
\r
332 if( xTickCount >= xNextTaskUnblockTime ) \
\r
336 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ) \
\r
338 /* The delayed list is empty. Set xNextTaskUnblockTime to the \
\r
339 maximum possible value so it is extremely unlikely that the \
\r
340 if( xTickCount >= xNextTaskUnblockTime ) test will pass next \
\r
342 xNextTaskUnblockTime = portMAX_DELAY; \
\r
347 /* The delayed list is not empty, get the value of the item at \
\r
348 the head of the delayed list. This is the time at which the \
\r
349 task at the head of the delayed list should be removed from \
\r
350 the Blocked state. */ \
\r
351 pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); \
\r
352 xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ); \
\r
354 if( xTickCount < xItemValue ) \
\r
356 /* It is not time to unblock this item yet, but the item \
\r
357 value is the time at which the task at the head of the \
\r
358 blocked list should be removed from the Blocked state - \
\r
359 so record the item value in xNextTaskUnblockTime. */ \
\r
360 xNextTaskUnblockTime = xItemValue; \
\r
364 /* It is time to remove the item from the Blocked state. */ \
\r
365 uxListRemove( &( pxTCB->xGenericListItem ) ); \
\r
367 /* Is the task waiting on an event also? */ \
\r
368 if( pxTCB->xEventListItem.pvContainer != NULL ) \
\r
370 uxListRemove( &( pxTCB->xEventListItem ) ); \
\r
372 prvAddTaskToReadyQueue( pxTCB ); \
\r
377 /*-----------------------------------------------------------*/
\r
380 * Several functions take an xTaskHandle parameter that can optionally be NULL,
\r
381 * where NULL is used to indicate that the handle of the currently executing
\r
382 * task should be used in place of the parameter. This macro simply checks to
\r
383 * see if the parameter is NULL and returns a pointer to the appropriate TCB.
\r
385 #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( tskTCB * ) pxCurrentTCB : ( tskTCB * ) ( pxHandle ) )
\r
387 /* Callback function prototypes. --------------------------*/
\r
388 extern void vApplicationStackOverflowHook( xTaskHandle xTask, signed char *pcTaskName );
\r
389 extern void vApplicationTickHook( void );
\r
391 /* File private functions. --------------------------------*/
\r
394 * Utility to ready a TCB for a given task. Mainly just copies the parameters
\r
395 * into the TCB structure.
\r
397 static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) PRIVILEGED_FUNCTION;
\r
400 * Utility to ready all the lists used by the scheduler. This is called
\r
401 * automatically upon the creation of the first task.
\r
403 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
\r
406 * The idle task, which as all tasks is implemented as a never ending loop.
\r
407 * The idle task is automatically created and added to the ready lists upon
\r
408 * creation of the first user task.
\r
410 * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
\r
411 * language extensions. The equivalent prototype for this function is:
\r
413 * void prvIdleTask( void *pvParameters );
\r
416 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
\r
419 * Utility to free all memory allocated by the scheduler to hold a TCB,
\r
420 * including the stack pointed to by the TCB.
\r
422 * This does not free memory allocated by the task itself (i.e. memory
\r
423 * allocated by calls to pvPortMalloc from within the tasks application code).
\r
425 #if ( INCLUDE_vTaskDelete == 1 )
\r
427 static void prvDeleteTCB( tskTCB *pxTCB ) PRIVILEGED_FUNCTION;
\r
432 * Used only by the idle task. This checks to see if anything has been placed
\r
433 * in the list of tasks waiting to be deleted. If so the task is cleaned up
\r
434 * and its TCB deleted.
\r
436 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
\r
439 * The currently executing task is entering the Blocked state. Add the task to
\r
440 * either the current or the overflow delayed task list.
\r
442 static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake ) PRIVILEGED_FUNCTION;
\r
445 * Allocates memory from the heap for a TCB and associated stack. Checks the
\r
446 * allocation was successful.
\r
448 static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) PRIVILEGED_FUNCTION;
\r
451 * Called from vTaskList. vListTasks details all the tasks currently under
\r
452 * control of the scheduler. The tasks may be in one of a number of lists.
\r
453 * prvListTaskWithinSingleList accepts a list and details the tasks from
\r
454 * within just that list.
\r
456 * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
\r
457 * NORMAL APPLICATION CODE.
\r
459 #if ( configUSE_TRACE_FACILITY == 1 )
\r
461 static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus ) PRIVILEGED_FUNCTION;
\r
466 * When a task is created, the stack of the task is filled with a known value.
\r
467 * This function determines the 'high water mark' of the task stack by
\r
468 * determining how much of the stack remains at the original preset value.
\r
470 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
472 static unsigned short usTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) PRIVILEGED_FUNCTION;
\r
477 * Return the amount of time, in ticks, that will pass before the kernel will
\r
478 * next move a task from the Blocked state to the Running state.
\r
480 * This conditional compilation should use inequality to 0, not equality to 1.
\r
481 * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
\r
482 * defined low power mode implementations require configUSE_TICKLESS_IDLE to be
\r
483 * set to a value other than 1.
\r
485 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
487 static portTickType prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
\r
493 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
495 signed portBASE_TYPE xReturn;
\r
498 configASSERT( pxTaskCode );
\r
499 configASSERT( ( ( uxPriority & ( ~portPRIVILEGE_BIT ) ) < configMAX_PRIORITIES ) );
\r
501 /* Allocate the memory required by the TCB and stack for the new task,
\r
502 checking that the allocation was successful. */
\r
503 pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer );
\r
505 if( pxNewTCB != NULL )
\r
507 portSTACK_TYPE *pxTopOfStack;
\r
509 #if( portUSING_MPU_WRAPPERS == 1 )
\r
510 /* Should the task be created in privileged mode? */
\r
511 portBASE_TYPE xRunPrivileged;
\r
512 if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
\r
514 xRunPrivileged = pdTRUE;
\r
518 xRunPrivileged = pdFALSE;
\r
520 uxPriority &= ~portPRIVILEGE_BIT;
\r
521 #endif /* portUSING_MPU_WRAPPERS == 1 */
\r
523 /* Calculate the top of stack address. This depends on whether the
\r
524 stack grows from high memory to low (as per the 80x86) or visa versa.
\r
525 portSTACK_GROWTH is used to make the result positive or negative as
\r
526 required by the port. */
\r
527 #if( portSTACK_GROWTH < 0 )
\r
529 pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( unsigned short ) 1 );
\r
530 pxTopOfStack = ( portSTACK_TYPE * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) );
\r
532 /* Check the alignment of the calculated top of stack is correct. */
\r
533 configASSERT( ( ( ( unsigned long ) pxTopOfStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
535 #else /* portSTACK_GROWTH */
\r
537 pxTopOfStack = pxNewTCB->pxStack;
\r
539 /* Check the alignment of the stack buffer is correct. */
\r
540 configASSERT( ( ( ( unsigned long ) pxNewTCB->pxStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
542 /* If we want to use stack checking on architectures that use
\r
543 a positive stack growth direction then we also need to store the
\r
544 other extreme of the stack space. */
\r
545 pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
\r
547 #endif /* portSTACK_GROWTH */
\r
549 /* Setup the newly allocated TCB with the initial state of the task. */
\r
550 prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth );
\r
552 /* Initialize the TCB stack to look as if the task was already running,
\r
553 but had been interrupted by the scheduler. The return address is set
\r
554 to the start of the task function. Once the stack has been initialised
\r
555 the top of stack variable is updated. */
\r
556 #if( portUSING_MPU_WRAPPERS == 1 )
\r
558 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
\r
560 #else /* portUSING_MPU_WRAPPERS */
\r
562 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
\r
564 #endif /* portUSING_MPU_WRAPPERS */
\r
566 /* Check the alignment of the initialised stack. */
\r
567 portALIGNMENT_ASSERT_pxCurrentTCB( ( ( ( unsigned long ) pxNewTCB->pxTopOfStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
569 if( ( void * ) pxCreatedTask != NULL )
\r
571 /* Pass the TCB out - in an anonymous way. The calling function/
\r
572 task can use this as a handle to delete the task later if
\r
574 *pxCreatedTask = ( xTaskHandle ) pxNewTCB;
\r
577 /* We are going to manipulate the task queues to add this task to a
\r
578 ready list, so must make sure no interrupts occur. */
\r
579 taskENTER_CRITICAL();
\r
581 uxCurrentNumberOfTasks++;
\r
582 if( pxCurrentTCB == NULL )
\r
584 /* There are no other tasks, or all the other tasks are in
\r
585 the suspended state - make this the current task. */
\r
586 pxCurrentTCB = pxNewTCB;
\r
588 if( uxCurrentNumberOfTasks == ( unsigned portBASE_TYPE ) 1 )
\r
590 /* This is the first task to be created so do the preliminary
\r
591 initialisation required. We will not recover if this call
\r
592 fails, but we will report the failure. */
\r
593 prvInitialiseTaskLists();
\r
598 /* If the scheduler is not already running, make this task the
\r
599 current task if it is the highest priority task to be created
\r
601 if( xSchedulerRunning == pdFALSE )
\r
603 if( pxCurrentTCB->uxPriority <= uxPriority )
\r
605 pxCurrentTCB = pxNewTCB;
\r
610 /* Remember the top priority to make context switching faster. Use
\r
611 the priority in pxNewTCB as this has been capped to a valid value. */
\r
612 if( pxNewTCB->uxPriority > uxTopUsedPriority )
\r
614 uxTopUsedPriority = pxNewTCB->uxPriority;
\r
619 #if ( configUSE_TRACE_FACILITY == 1 )
\r
621 /* Add a counter into the TCB for tracing only. */
\r
622 pxNewTCB->uxTCBNumber = uxTaskNumber;
\r
624 #endif /* configUSE_TRACE_FACILITY */
\r
625 traceTASK_CREATE( pxNewTCB );
\r
627 prvAddTaskToReadyQueue( pxNewTCB );
\r
630 portSETUP_TCB( pxNewTCB );
\r
632 taskEXIT_CRITICAL();
\r
636 xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
\r
637 traceTASK_CREATE_FAILED();
\r
640 if( xReturn == pdPASS )
\r
642 if( xSchedulerRunning != pdFALSE )
\r
644 /* If the created task is of a higher priority than the current task
\r
645 then it should run now. */
\r
646 if( pxCurrentTCB->uxPriority < uxPriority )
\r
648 portYIELD_WITHIN_API();
\r
655 /*-----------------------------------------------------------*/
\r
657 #if ( INCLUDE_vTaskDelete == 1 )
\r
659 void vTaskDelete( xTaskHandle xTaskToDelete )
\r
663 taskENTER_CRITICAL();
\r
665 /* Ensure a yield is performed if the current task is being
\r
667 if( xTaskToDelete == pxCurrentTCB )
\r
669 xTaskToDelete = NULL;
\r
672 /* If null is passed in here then we are deleting ourselves. */
\r
673 pxTCB = prvGetTCBFromHandle( xTaskToDelete );
\r
675 /* Remove task from the ready list and place in the termination list.
\r
676 This will stop the task from be scheduled. The idle task will check
\r
677 the termination list and free up any memory allocated by the
\r
678 scheduler for the TCB and stack. */
\r
679 if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
\r
681 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
684 /* Is the task waiting on an event also? */
\r
685 if( pxTCB->xEventListItem.pvContainer != NULL )
\r
687 uxListRemove( &( pxTCB->xEventListItem ) );
\r
690 vListInsertEnd( ( xList * ) &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );
\r
692 /* Increment the ucTasksDeleted variable so the idle task knows
\r
693 there is a task that has been deleted and that it should therefore
\r
694 check the xTasksWaitingTermination list. */
\r
697 /* Increment the uxTaskNumberVariable also so kernel aware debuggers
\r
698 can detect that the task lists need re-generating. */
\r
701 traceTASK_DELETE( pxTCB );
\r
703 taskEXIT_CRITICAL();
\r
705 /* Force a reschedule if we have just deleted the current task. */
\r
706 if( xSchedulerRunning != pdFALSE )
\r
708 if( ( void * ) xTaskToDelete == NULL )
\r
710 portYIELD_WITHIN_API();
\r
715 #endif /* INCLUDE_vTaskDelete */
\r
716 /*-----------------------------------------------------------*/
\r
718 #if ( INCLUDE_vTaskDelayUntil == 1 )
\r
720 void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement )
\r
722 portTickType xTimeToWake;
\r
723 portBASE_TYPE xAlreadyYielded, xShouldDelay = pdFALSE;
\r
725 configASSERT( pxPreviousWakeTime );
\r
726 configASSERT( ( xTimeIncrement > 0U ) );
\r
730 /* Generate the tick time at which the task wants to wake. */
\r
731 xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
\r
733 if( xTickCount < *pxPreviousWakeTime )
\r
735 /* The tick count has overflowed since this function was
\r
736 lasted called. In this case the only time we should ever
\r
737 actually delay is if the wake time has also overflowed,
\r
738 and the wake time is greater than the tick time. When this
\r
739 is the case it is as if neither time had overflowed. */
\r
740 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xTickCount ) )
\r
742 xShouldDelay = pdTRUE;
\r
747 /* The tick time has not overflowed. In this case we will
\r
748 delay if either the wake time has overflowed, and/or the
\r
749 tick time is less than the wake time. */
\r
750 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xTickCount ) )
\r
752 xShouldDelay = pdTRUE;
\r
756 /* Update the wake time ready for the next call. */
\r
757 *pxPreviousWakeTime = xTimeToWake;
\r
759 if( xShouldDelay != pdFALSE )
\r
761 traceTASK_DELAY_UNTIL();
\r
763 /* We must remove ourselves from the ready list before adding
\r
764 ourselves to the blocked list as the same list item is used for
\r
766 if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 )
\r
768 /* The current task must be in a ready list, so there is
\r
769 no need to check, and the port reset macro can be called
\r
771 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
774 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
777 xAlreadyYielded = xTaskResumeAll();
\r
779 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
780 have put ourselves to sleep. */
\r
781 if( xAlreadyYielded == pdFALSE )
\r
783 portYIELD_WITHIN_API();
\r
787 #endif /* INCLUDE_vTaskDelayUntil */
\r
788 /*-----------------------------------------------------------*/
\r
790 #if ( INCLUDE_vTaskDelay == 1 )
\r
792 void vTaskDelay( portTickType xTicksToDelay )
\r
794 portTickType xTimeToWake;
\r
795 signed portBASE_TYPE xAlreadyYielded = pdFALSE;
\r
797 /* A delay time of zero just forces a reschedule. */
\r
798 if( xTicksToDelay > ( portTickType ) 0U )
\r
804 /* A task that is removed from the event list while the
\r
805 scheduler is suspended will not get placed in the ready
\r
806 list or removed from the blocked list until the scheduler
\r
809 This task cannot be in an event list as it is the currently
\r
812 /* Calculate the time to wake - this may overflow but this is
\r
814 xTimeToWake = xTickCount + xTicksToDelay;
\r
816 /* We must remove ourselves from the ready list before adding
\r
817 ourselves to the blocked list as the same list item is used for
\r
819 if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 )
\r
821 /* The current task must be in a ready list, so there is
\r
822 no need to check, and the port reset macro can be called
\r
824 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
826 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
828 xAlreadyYielded = xTaskResumeAll();
\r
831 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
832 have put ourselves to sleep. */
\r
833 if( xAlreadyYielded == pdFALSE )
\r
835 portYIELD_WITHIN_API();
\r
839 #endif /* INCLUDE_vTaskDelay */
\r
840 /*-----------------------------------------------------------*/
\r
842 #if ( INCLUDE_eTaskGetState == 1 )
\r
844 eTaskState eTaskGetState( xTaskHandle xTask )
\r
846 eTaskState eReturn;
\r
847 xList *pxStateList;
\r
850 pxTCB = ( tskTCB * ) xTask;
\r
852 if( pxTCB == pxCurrentTCB )
\r
854 /* The task calling this function is querying its own state. */
\r
855 eReturn = eRunning;
\r
859 taskENTER_CRITICAL();
\r
861 pxStateList = ( xList * ) listLIST_ITEM_CONTAINER( &( pxTCB->xGenericListItem ) );
\r
863 taskEXIT_CRITICAL();
\r
865 if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) )
\r
867 /* The task being queried is referenced from one of the Blocked
\r
869 eReturn = eBlocked;
\r
872 #if ( INCLUDE_vTaskSuspend == 1 )
\r
873 else if( pxStateList == &xSuspendedTaskList )
\r
875 /* The task being queried is referenced from the suspended
\r
877 eReturn = eSuspended;
\r
881 #if ( INCLUDE_vTaskDelete == 1 )
\r
882 else if( pxStateList == &xTasksWaitingTermination )
\r
884 /* The task being queried is referenced from the deleted
\r
886 eReturn = eDeleted;
\r
892 /* If the task is not in any other state, it must be in the
\r
893 Ready (including pending ready) state. */
\r
901 #endif /* INCLUDE_eTaskGetState */
\r
902 /*-----------------------------------------------------------*/
\r
904 #if ( INCLUDE_uxTaskPriorityGet == 1 )
\r
906 unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle xTask )
\r
909 unsigned portBASE_TYPE uxReturn;
\r
911 taskENTER_CRITICAL();
\r
913 /* If null is passed in here then we are changing the
\r
914 priority of the calling function. */
\r
915 pxTCB = prvGetTCBFromHandle( xTask );
\r
916 uxReturn = pxTCB->uxPriority;
\r
918 taskEXIT_CRITICAL();
\r
923 #endif /* INCLUDE_uxTaskPriorityGet */
\r
924 /*-----------------------------------------------------------*/
\r
926 #if ( INCLUDE_vTaskPrioritySet == 1 )
\r
928 void vTaskPrioritySet( xTaskHandle xTask, unsigned portBASE_TYPE uxNewPriority )
\r
931 unsigned portBASE_TYPE uxCurrentPriority, uxPriorityUsedOnEntry;
\r
932 portBASE_TYPE xYieldRequired = pdFALSE;
\r
934 configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
\r
936 /* Ensure the new priority is valid. */
\r
937 if( uxNewPriority >= configMAX_PRIORITIES )
\r
939 uxNewPriority = configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U;
\r
942 taskENTER_CRITICAL();
\r
944 if( xTask == ( xTaskHandle ) pxCurrentTCB )
\r
949 /* If null is passed in here then we are changing the
\r
950 priority of the calling function. */
\r
951 pxTCB = prvGetTCBFromHandle( xTask );
\r
953 traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
\r
955 #if ( configUSE_MUTEXES == 1 )
\r
957 uxCurrentPriority = pxTCB->uxBasePriority;
\r
961 uxCurrentPriority = pxTCB->uxPriority;
\r
965 if( uxCurrentPriority != uxNewPriority )
\r
967 /* The priority change may have readied a task of higher
\r
968 priority than the calling task. */
\r
969 if( uxNewPriority > uxCurrentPriority )
\r
971 if( xTask != NULL )
\r
973 /* The priority of another task is being raised. If we
\r
974 were raising the priority of the currently running task
\r
975 there would be no need to switch as it must have already
\r
976 been the highest priority task. */
\r
977 xYieldRequired = pdTRUE;
\r
980 else if( xTask == NULL )
\r
982 /* Setting our own priority down means there may now be another
\r
983 task of higher priority that is ready to execute. */
\r
984 xYieldRequired = pdTRUE;
\r
987 /* Remember the ready list the task might be referenced from
\r
988 before its uxPriority member is changed so the
\r
989 taskRESET_READY_PRIORITY() macro can function correctly. */
\r
990 uxPriorityUsedOnEntry = pxTCB->uxPriority;
\r
992 #if ( configUSE_MUTEXES == 1 )
\r
994 /* Only change the priority being used if the task is not
\r
995 currently using an inherited priority. */
\r
996 if( pxTCB->uxBasePriority == pxTCB->uxPriority )
\r
998 pxTCB->uxPriority = uxNewPriority;
\r
1001 /* The base priority gets set whatever. */
\r
1002 pxTCB->uxBasePriority = uxNewPriority;
\r
1006 pxTCB->uxPriority = uxNewPriority;
\r
1010 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( configMAX_PRIORITIES - ( portTickType ) uxNewPriority ) );
\r
1012 /* If the task is in the blocked or suspended list we need do
\r
1013 nothing more than change it's priority variable. However, if
\r
1014 the task is in a ready list it needs to be removed and placed
\r
1015 in the queue appropriate to its new priority. */
\r
1016 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxCurrentPriority ] ), &( pxTCB->xGenericListItem ) ) )
\r
1018 /* The task is currently in its ready list - remove before adding
\r
1019 it to it's new ready list. As we are in a critical section we
\r
1020 can do this even if the scheduler is suspended. */
\r
1021 if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
\r
1023 taskRESET_READY_PRIORITY( uxPriorityUsedOnEntry );
\r
1025 prvAddTaskToReadyQueue( pxTCB );
\r
1028 if( xYieldRequired == pdTRUE )
\r
1030 portYIELD_WITHIN_API();
\r
1033 /* Remove compiler warning about unused variables when the port
\r
1034 optimised task selection is not being used. */
\r
1035 ( void ) uxPriorityUsedOnEntry;
\r
1038 taskEXIT_CRITICAL();
\r
1041 #endif /* INCLUDE_vTaskPrioritySet */
\r
1042 /*-----------------------------------------------------------*/
\r
1044 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1046 void vTaskSuspend( xTaskHandle xTaskToSuspend )
\r
1050 taskENTER_CRITICAL();
\r
1052 /* Ensure a yield is performed if the current task is being
\r
1054 if( xTaskToSuspend == ( xTaskHandle ) pxCurrentTCB )
\r
1056 xTaskToSuspend = NULL;
\r
1059 /* If null is passed in here then we are suspending ourselves. */
\r
1060 pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
\r
1062 traceTASK_SUSPEND( pxTCB );
\r
1064 /* Remove task from the ready/delayed list and place in the suspended list. */
\r
1065 if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
\r
1067 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
1070 /* Is the task waiting on an event also? */
\r
1071 if( pxTCB->xEventListItem.pvContainer != NULL )
\r
1073 uxListRemove( &( pxTCB->xEventListItem ) );
\r
1076 vListInsertEnd( ( xList * ) &xSuspendedTaskList, &( pxTCB->xGenericListItem ) );
\r
1078 taskEXIT_CRITICAL();
\r
1080 if( ( void * ) xTaskToSuspend == NULL )
\r
1082 if( xSchedulerRunning != pdFALSE )
\r
1084 /* We have just suspended the current task. */
\r
1085 portYIELD_WITHIN_API();
\r
1089 /* The scheduler is not running, but the task that was pointed
\r
1090 to by pxCurrentTCB has just been suspended and pxCurrentTCB
\r
1091 must be adjusted to point to a different task. */
\r
1092 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )
\r
1094 /* No other tasks are ready, so set pxCurrentTCB back to
\r
1095 NULL so when the next task is created pxCurrentTCB will
\r
1096 be set to point to it no matter what its relative priority
\r
1098 pxCurrentTCB = NULL;
\r
1102 vTaskSwitchContext();
\r
1108 #endif /* INCLUDE_vTaskSuspend */
\r
1109 /*-----------------------------------------------------------*/
\r
1111 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1113 signed portBASE_TYPE xTaskIsTaskSuspended( xTaskHandle xTask )
\r
1115 portBASE_TYPE xReturn = pdFALSE;
\r
1116 const tskTCB * const pxTCB = ( tskTCB * ) xTask;
\r
1118 /* It does not make sense to check if the calling task is suspended. */
\r
1119 configASSERT( xTask );
\r
1121 /* Is the task we are attempting to resume actually in the
\r
1122 suspended list? */
\r
1123 if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
\r
1125 /* Has the task already been resumed from within an ISR? */
\r
1126 if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) != pdTRUE )
\r
1128 /* Is it in the suspended list because it is in the
\r
1129 Suspended state? It is possible to be in the suspended
\r
1130 list because it is blocked on a task with no timeout
\r
1132 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) == pdTRUE )
\r
1142 #endif /* INCLUDE_vTaskSuspend */
\r
1143 /*-----------------------------------------------------------*/
\r
1145 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1147 void vTaskResume( xTaskHandle xTaskToResume )
\r
1151 /* It does not make sense to resume the calling task. */
\r
1152 configASSERT( xTaskToResume );
\r
1154 /* Remove the task from whichever list it is currently in, and place
\r
1155 it in the ready list. */
\r
1156 pxTCB = ( tskTCB * ) xTaskToResume;
\r
1158 /* The parameter cannot be NULL as it is impossible to resume the
\r
1159 currently executing task. */
\r
1160 if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
\r
1162 taskENTER_CRITICAL();
\r
1164 if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
\r
1166 traceTASK_RESUME( pxTCB );
\r
1168 /* As we are in a critical section we can access the ready
\r
1169 lists even if the scheduler is suspended. */
\r
1170 uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1171 prvAddTaskToReadyQueue( pxTCB );
\r
1173 /* We may have just resumed a higher priority task. */
\r
1174 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1176 /* This yield may not cause the task just resumed to run, but
\r
1177 will leave the lists in the correct state for the next yield. */
\r
1178 portYIELD_WITHIN_API();
\r
1182 taskEXIT_CRITICAL();
\r
1186 #endif /* INCLUDE_vTaskSuspend */
\r
1188 /*-----------------------------------------------------------*/
\r
1190 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
\r
1192 portBASE_TYPE xTaskResumeFromISR( xTaskHandle xTaskToResume )
\r
1194 portBASE_TYPE xYieldRequired = pdFALSE;
\r
1196 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
1198 configASSERT( xTaskToResume );
\r
1200 pxTCB = ( tskTCB * ) xTaskToResume;
\r
1202 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1204 if( xTaskIsTaskSuspended( pxTCB ) == pdTRUE )
\r
1206 traceTASK_RESUME_FROM_ISR( pxTCB );
\r
1208 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
\r
1210 xYieldRequired = ( pxTCB->uxPriority >= pxCurrentTCB->uxPriority );
\r
1211 uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1212 prvAddTaskToReadyQueue( pxTCB );
\r
1216 /* We cannot access the delayed or ready lists, so will hold this
\r
1217 task pending until the scheduler is resumed, at which point a
\r
1218 yield will be performed if necessary. */
\r
1219 vListInsertEnd( ( xList * ) &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
1223 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1225 return xYieldRequired;
\r
1228 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
\r
1229 /*-----------------------------------------------------------*/
\r
1231 void vTaskStartScheduler( void )
\r
1233 portBASE_TYPE xReturn;
\r
1235 /* Add the idle task at the lowest priority. */
\r
1236 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
1238 /* Create the idle task, storing its handle in xIdleTaskHandle so it can
\r
1239 be returned by the xTaskGetIdleTaskHandle() function. */
\r
1240 xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle );
\r
1244 /* Create the idle task without storing its handle. */
\r
1245 xReturn = xTaskCreate( prvIdleTask, ( signed char * ) "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), NULL );
\r
1247 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
\r
1249 #if ( configUSE_TIMERS == 1 )
\r
1251 if( xReturn == pdPASS )
\r
1253 xReturn = xTimerCreateTimerTask();
\r
1256 #endif /* configUSE_TIMERS */
\r
1258 if( xReturn == pdPASS )
\r
1260 /* Interrupts are turned off here, to ensure a tick does not occur
\r
1261 before or during the call to xPortStartScheduler(). The stacks of
\r
1262 the created tasks contain a status word with interrupts switched on
\r
1263 so interrupts will automatically get re-enabled when the first task
\r
1266 STEPPING THROUGH HERE USING A DEBUGGER CAN CAUSE BIG PROBLEMS IF THE
\r
1267 DEBUGGER ALLOWS INTERRUPTS TO BE PROCESSED. */
\r
1268 portDISABLE_INTERRUPTS();
\r
1270 xSchedulerRunning = pdTRUE;
\r
1271 xTickCount = ( portTickType ) 0U;
\r
1273 /* If configGENERATE_RUN_TIME_STATS is defined then the following
\r
1274 macro must be defined to configure the timer/counter used to generate
\r
1275 the run time counter time base. */
\r
1276 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
\r
1278 /* Setting up the timer tick is hardware specific and thus in the
\r
1279 portable interface. */
\r
1280 if( xPortStartScheduler() != pdFALSE )
\r
1282 /* Should not reach here as if the scheduler is running the
\r
1283 function will not return. */
\r
1287 /* Should only reach here if a task calls xTaskEndScheduler(). */
\r
1292 /* This line will only be reached if the kernel could not be started,
\r
1293 because there was not enough FreeRTOS heap to create the idle task
\r
1294 or the timer task. */
\r
1295 configASSERT( xReturn );
\r
1298 /*-----------------------------------------------------------*/
\r
1300 void vTaskEndScheduler( void )
\r
1302 /* Stop the scheduler interrupts and call the portable scheduler end
\r
1303 routine so the original ISRs can be restored if necessary. The port
\r
1304 layer must ensure interrupts enable bit is left in the correct state. */
\r
1305 portDISABLE_INTERRUPTS();
\r
1306 xSchedulerRunning = pdFALSE;
\r
1307 vPortEndScheduler();
\r
1309 /*----------------------------------------------------------*/
\r
1311 void vTaskSuspendAll( void )
\r
1313 /* A critical section is not required as the variable is of type
\r
1315 ++uxSchedulerSuspended;
\r
1317 /*----------------------------------------------------------*/
\r
1319 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
1321 static portTickType prvGetExpectedIdleTime( void )
\r
1323 portTickType xReturn;
\r
1325 if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
\r
1329 else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
\r
1331 /* There are other idle priority tasks in the ready state. If
\r
1332 time slicing is used then the very next tick interrupt must be
\r
1338 xReturn = xNextTaskUnblockTime - xTickCount;
\r
1344 #endif /* configUSE_TICKLESS_IDLE */
\r
1345 /*----------------------------------------------------------*/
\r
1347 signed portBASE_TYPE xTaskResumeAll( void )
\r
1349 register tskTCB *pxTCB;
\r
1350 signed portBASE_TYPE xAlreadyYielded = pdFALSE;
\r
1352 /* If uxSchedulerSuspended is zero then this function does not match a
\r
1353 previous call to vTaskSuspendAll(). */
\r
1354 configASSERT( uxSchedulerSuspended );
\r
1356 /* It is possible that an ISR caused a task to be removed from an event
\r
1357 list while the scheduler was suspended. If this was the case then the
\r
1358 removed task will have been added to the xPendingReadyList. Once the
\r
1359 scheduler has been resumed it is safe to move all the pending ready
\r
1360 tasks from this list into their appropriate ready list. */
\r
1361 taskENTER_CRITICAL();
\r
1363 --uxSchedulerSuspended;
\r
1365 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
\r
1367 if( uxCurrentNumberOfTasks > ( unsigned portBASE_TYPE ) 0U )
\r
1369 portBASE_TYPE xYieldRequired = pdFALSE;
\r
1371 /* Move any readied tasks from the pending list into the
\r
1372 appropriate ready list. */
\r
1373 while( listLIST_IS_EMPTY( ( xList * ) &xPendingReadyList ) == pdFALSE )
\r
1375 pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xPendingReadyList ) );
\r
1376 uxListRemove( &( pxTCB->xEventListItem ) );
\r
1377 uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1378 prvAddTaskToReadyQueue( pxTCB );
\r
1380 /* If we have moved a task that has a priority higher than
\r
1381 the current task then we should yield. */
\r
1382 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1384 xYieldRequired = pdTRUE;
\r
1388 /* If any ticks occurred while the scheduler was suspended then
\r
1389 they should be processed now. This ensures the tick count does not
\r
1390 slip, and that any delayed tasks are resumed at the correct time. */
\r
1391 if( uxMissedTicks > ( unsigned portBASE_TYPE ) 0U )
\r
1393 while( uxMissedTicks > ( unsigned portBASE_TYPE ) 0U )
\r
1395 vTaskIncrementTick();
\r
1399 /* As we have processed some ticks it is appropriate to yield
\r
1400 to ensure the highest priority task that is ready to run is
\r
1401 the task actually running. */
\r
1402 #if configUSE_PREEMPTION == 1
\r
1404 xYieldRequired = pdTRUE;
\r
1409 if( ( xYieldRequired == pdTRUE ) || ( xMissedYield == pdTRUE ) )
\r
1411 xAlreadyYielded = pdTRUE;
\r
1412 xMissedYield = pdFALSE;
\r
1413 portYIELD_WITHIN_API();
\r
1418 taskEXIT_CRITICAL();
\r
1420 return xAlreadyYielded;
\r
1422 /*-----------------------------------------------------------*/
\r
1424 portTickType xTaskGetTickCount( void )
\r
1426 portTickType xTicks;
\r
1428 /* Critical section required if running on a 16 bit processor. */
\r
1429 taskENTER_CRITICAL();
\r
1431 xTicks = xTickCount;
\r
1433 taskEXIT_CRITICAL();
\r
1437 /*-----------------------------------------------------------*/
\r
1439 portTickType xTaskGetTickCountFromISR( void )
\r
1441 portTickType xReturn;
\r
1442 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
1444 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1445 xReturn = xTickCount;
\r
1446 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1450 /*-----------------------------------------------------------*/
\r
1452 unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
\r
1454 /* A critical section is not required because the variables are of type
\r
1456 return uxCurrentNumberOfTasks;
\r
1458 /*-----------------------------------------------------------*/
\r
1460 #if ( INCLUDE_pcTaskGetTaskName == 1 )
\r
1462 signed char *pcTaskGetTaskName( xTaskHandle xTaskToQuery )
\r
1466 /* If null is passed in here then the name of the calling task is being queried. */
\r
1467 pxTCB = prvGetTCBFromHandle( xTaskToQuery );
\r
1468 configASSERT( pxTCB );
\r
1469 return &( pxTCB->pcTaskName[ 0 ] );
\r
1472 #endif /* INCLUDE_pcTaskGetTaskName */
\r
1473 /*-----------------------------------------------------------*/
\r
1475 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1477 void vTaskList( signed char *pcWriteBuffer )
\r
1479 unsigned portBASE_TYPE uxQueue;
\r
1481 /* This is a VERY costly function that should be used for debug only.
\r
1482 It leaves interrupts disabled for a LONG time. */
\r
1484 vTaskSuspendAll();
\r
1486 /* Run through all the lists that could potentially contain a TCB and
\r
1487 report the task name, state and stack high water mark. */
\r
1489 *pcWriteBuffer = ( signed char ) 0x00;
\r
1490 strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" );
\r
1492 uxQueue = uxTopUsedPriority + ( unsigned portBASE_TYPE ) 1U;
\r
1498 if( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) == pdFALSE )
\r
1500 prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), tskREADY_CHAR );
\r
1502 }while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY );
\r
1504 if( listLIST_IS_EMPTY( pxDelayedTaskList ) == pdFALSE )
\r
1506 prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, tskBLOCKED_CHAR );
\r
1509 if( listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) == pdFALSE )
\r
1511 prvListTaskWithinSingleList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, tskBLOCKED_CHAR );
\r
1514 #if( INCLUDE_vTaskDelete == 1 )
\r
1516 if( listLIST_IS_EMPTY( &xTasksWaitingTermination ) == pdFALSE )
\r
1518 prvListTaskWithinSingleList( pcWriteBuffer, &xTasksWaitingTermination, tskDELETED_CHAR );
\r
1523 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1525 if( listLIST_IS_EMPTY( &xSuspendedTaskList ) == pdFALSE )
\r
1527 prvListTaskWithinSingleList( pcWriteBuffer, &xSuspendedTaskList, tskSUSPENDED_CHAR );
\r
1535 #endif /* configUSE_TRACE_FACILITY */
\r
1536 /*----------------------------------------------------------*/
\r
1538 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
1540 void vTaskGetRunTimeStats( signed char *pcWriteBuffer )
\r
1542 unsigned portBASE_TYPE uxQueue;
\r
1543 unsigned long ulTotalRunTimeDiv100;
\r
1545 /* This is a VERY costly function that should be used for debug only.
\r
1546 It leaves interrupts disabled for a LONG time. */
\r
1548 vTaskSuspendAll();
\r
1550 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
1551 portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
\r
1553 ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
1556 /* Divide ulTotalRunTime by 100 to make the percentage caluclations
\r
1557 simpler in the prvGenerateRunTimeStatsForTasksInList() function. */
\r
1558 ulTotalRunTimeDiv100 = ulTotalRunTime / 100UL;
\r
1560 /* Run through all the lists that could potentially contain a TCB,
\r
1561 generating a table of run timer percentages in the provided
\r
1564 *pcWriteBuffer = ( signed char ) 0x00;
\r
1565 strcat( ( char * ) pcWriteBuffer, ( const char * ) "\r\n" );
\r
1567 uxQueue = uxTopUsedPriority + ( unsigned portBASE_TYPE ) 1U;
\r
1573 if( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxQueue ] ) ) == pdFALSE )
\r
1575 prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) &( pxReadyTasksLists[ uxQueue ] ), ulTotalRunTimeDiv100 );
\r
1577 }while( uxQueue > ( unsigned short ) tskIDLE_PRIORITY );
\r
1579 if( listLIST_IS_EMPTY( pxDelayedTaskList ) == pdFALSE )
\r
1581 prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxDelayedTaskList, ulTotalRunTimeDiv100 );
\r
1584 if( listLIST_IS_EMPTY( pxOverflowDelayedTaskList ) == pdFALSE )
\r
1586 prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, ( xList * ) pxOverflowDelayedTaskList, ulTotalRunTimeDiv100 );
\r
1589 #if ( INCLUDE_vTaskDelete == 1 )
\r
1591 if( listLIST_IS_EMPTY( &xTasksWaitingTermination ) == pdFALSE )
\r
1593 prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, &xTasksWaitingTermination, ulTotalRunTimeDiv100 );
\r
1598 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1600 if( listLIST_IS_EMPTY( &xSuspendedTaskList ) == pdFALSE )
\r
1602 prvGenerateRunTimeStatsForTasksInList( pcWriteBuffer, &xSuspendedTaskList, ulTotalRunTimeDiv100 );
\r
1610 #endif /* configGENERATE_RUN_TIME_STATS */
\r
1611 /*----------------------------------------------------------*/
\r
1613 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
1615 xTaskHandle xTaskGetIdleTaskHandle( void )
\r
1617 /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
\r
1618 started, then xIdleTaskHandle will be NULL. */
\r
1619 configASSERT( ( xIdleTaskHandle != NULL ) );
\r
1620 return xIdleTaskHandle;
\r
1623 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
\r
1624 /*----------------------------------------------------------*/
\r
1626 /* This conditional compilation should use inequality to 0, not equality to 1.
\r
1627 This is to ensure vTaskStepTick() is available when user defined low power mode
\r
1628 implementations require configUSE_TICKLESS_IDLE to be set to a value other than
\r
1630 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
1632 void vTaskStepTick( portTickType xTicksToJump )
\r
1634 configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
\r
1635 xTickCount += xTicksToJump;
\r
1638 #endif /* configUSE_TICKLESS_IDLE */
\r
1639 /*----------------------------------------------------------*/
\r
1641 void vTaskIncrementTick( void )
\r
1645 /* Called by the portable layer each time a tick interrupt occurs.
\r
1646 Increments the tick then checks to see if the new tick value will cause any
\r
1647 tasks to be unblocked. */
\r
1648 traceTASK_INCREMENT_TICK( xTickCount );
\r
1649 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
\r
1652 if( xTickCount == ( portTickType ) 0U )
\r
1656 /* Tick count has overflowed so we need to swap the delay lists.
\r
1657 If there are any items in pxDelayedTaskList here then there is
\r
1659 configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) );
\r
1661 pxTemp = pxDelayedTaskList;
\r
1662 pxDelayedTaskList = pxOverflowDelayedTaskList;
\r
1663 pxOverflowDelayedTaskList = pxTemp;
\r
1664 xNumOfOverflows++;
\r
1666 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
\r
1668 /* The new current delayed list is empty. Set
\r
1669 xNextTaskUnblockTime to the maximum possible value so it is
\r
1670 extremely unlikely that the
\r
1671 if( xTickCount >= xNextTaskUnblockTime ) test will pass until
\r
1672 there is an item in the delayed list. */
\r
1673 xNextTaskUnblockTime = portMAX_DELAY;
\r
1677 /* The new current delayed list is not empty, get the value of
\r
1678 the item at the head of the delayed list. This is the time at
\r
1679 which the task at the head of the delayed list should be removed
\r
1680 from the Blocked state. */
\r
1681 pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
\r
1682 xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
\r
1686 /* See if this tick has made a timeout expire. */
\r
1687 prvCheckDelayedTasks();
\r
1693 /* The tick hook gets called at regular intervals, even if the
\r
1694 scheduler is locked. */
\r
1695 #if ( configUSE_TICK_HOOK == 1 )
\r
1697 vApplicationTickHook();
\r
1702 #if ( configUSE_TICK_HOOK == 1 )
\r
1704 /* Guard against the tick hook being called when the missed tick
\r
1705 count is being unwound (when the scheduler is being unlocked. */
\r
1706 if( uxMissedTicks == ( unsigned portBASE_TYPE ) 0U )
\r
1708 vApplicationTickHook();
\r
1711 #endif /* configUSE_TICK_HOOK */
\r
1713 /*-----------------------------------------------------------*/
\r
1715 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
1717 void vTaskSetApplicationTaskTag( xTaskHandle xTask, pdTASK_HOOK_CODE pxHookFunction )
\r
1721 /* If xTask is NULL then we are setting our own task hook. */
\r
1722 if( xTask == NULL )
\r
1724 xTCB = ( tskTCB * ) pxCurrentTCB;
\r
1728 xTCB = ( tskTCB * ) xTask;
\r
1731 /* Save the hook function in the TCB. A critical section is required as
\r
1732 the value can be accessed from an interrupt. */
\r
1733 taskENTER_CRITICAL();
\r
1734 xTCB->pxTaskTag = pxHookFunction;
\r
1735 taskEXIT_CRITICAL();
\r
1738 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
1739 /*-----------------------------------------------------------*/
\r
1741 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
1743 pdTASK_HOOK_CODE xTaskGetApplicationTaskTag( xTaskHandle xTask )
\r
1746 pdTASK_HOOK_CODE xReturn;
\r
1748 /* If xTask is NULL then we are setting our own task hook. */
\r
1749 if( xTask == NULL )
\r
1751 xTCB = ( tskTCB * ) pxCurrentTCB;
\r
1755 xTCB = ( tskTCB * ) xTask;
\r
1758 /* Save the hook function in the TCB. A critical section is required as
\r
1759 the value can be accessed from an interrupt. */
\r
1760 taskENTER_CRITICAL();
\r
1761 xReturn = xTCB->pxTaskTag;
\r
1762 taskEXIT_CRITICAL();
\r
1767 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
1768 /*-----------------------------------------------------------*/
\r
1770 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
1772 portBASE_TYPE xTaskCallApplicationTaskHook( xTaskHandle xTask, void *pvParameter )
\r
1775 portBASE_TYPE xReturn;
\r
1777 /* If xTask is NULL then we are calling our own task hook. */
\r
1778 if( xTask == NULL )
\r
1780 xTCB = ( tskTCB * ) pxCurrentTCB;
\r
1784 xTCB = ( tskTCB * ) xTask;
\r
1787 if( xTCB->pxTaskTag != NULL )
\r
1789 xReturn = xTCB->pxTaskTag( pvParameter );
\r
1799 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
1800 /*-----------------------------------------------------------*/
\r
1802 void vTaskSwitchContext( void )
\r
1804 if( uxSchedulerSuspended != ( unsigned portBASE_TYPE ) pdFALSE )
\r
1806 /* The scheduler is currently suspended - do not allow a context
\r
1808 xMissedYield = pdTRUE;
\r
1812 traceTASK_SWITCHED_OUT();
\r
1814 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
1816 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
1817 portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
\r
1819 ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
1822 /* Add the amount of time the task has been running to the accumulated
\r
1823 time so far. The time the task started running was stored in
\r
1824 ulTaskSwitchedInTime. Note that there is no overflow protection here
\r
1825 so count values are only valid until the timer overflows. Generally
\r
1826 this will be about 1 hour assuming a 1uS timer increment. */
\r
1827 pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
\r
1828 ulTaskSwitchedInTime = ulTotalRunTime;
\r
1830 #endif /* configGENERATE_RUN_TIME_STATS */
\r
1832 taskFIRST_CHECK_FOR_STACK_OVERFLOW();
\r
1833 taskSECOND_CHECK_FOR_STACK_OVERFLOW();
\r
1835 taskSELECT_HIGHEST_PRIORITY_TASK();
\r
1837 traceTASK_SWITCHED_IN();
\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 prvAddTaskToReadyQueue( 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 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2004 /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is
\r
2005 the maximum block time then the task should block indefinitely, and
\r
2006 therefore never time out. */
\r
2007 if( *pxTicksToWait == portMAX_DELAY )
\r
2009 xReturn = pdFALSE;
\r
2011 else /* We are not blocking indefinitely, perform the checks below. */
\r
2014 if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( ( portTickType ) xTickCount >= ( portTickType ) pxTimeOut->xTimeOnEntering ) )
\r
2016 /* The tick count is greater than the time at which vTaskSetTimeout()
\r
2017 was called, but has also overflowed since vTaskSetTimeOut() was called.
\r
2018 It must have wrapped all the way around and gone past us again. This
\r
2019 passed since vTaskSetTimeout() was called. */
\r
2022 else if( ( ( portTickType ) ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering ) ) < ( portTickType ) *pxTicksToWait )
\r
2024 /* Not a genuine timeout. Adjust parameters for time remaining. */
\r
2025 *pxTicksToWait -= ( ( portTickType ) xTickCount - ( portTickType ) pxTimeOut->xTimeOnEntering );
\r
2026 vTaskSetTimeOutState( pxTimeOut );
\r
2027 xReturn = pdFALSE;
\r
2034 taskEXIT_CRITICAL();
\r
2038 /*-----------------------------------------------------------*/
\r
2040 void vTaskMissedYield( void )
\r
2042 xMissedYield = pdTRUE;
\r
2044 /*-----------------------------------------------------------*/
\r
2046 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2048 unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask )
\r
2050 unsigned portBASE_TYPE uxReturn;
\r
2053 if( xTask != NULL )
\r
2055 pxTCB = ( tskTCB * ) xTask;
\r
2056 uxReturn = pxTCB->uxTaskNumber;
\r
2066 #endif /* configUSE_TRACE_FACILITY */
\r
2067 /*-----------------------------------------------------------*/
\r
2069 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2071 void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle )
\r
2075 if( xTask != NULL )
\r
2077 pxTCB = ( tskTCB * ) xTask;
\r
2078 pxTCB->uxTaskNumber = uxHandle;
\r
2082 #endif /* configUSE_TRACE_FACILITY */
\r
2085 * -----------------------------------------------------------
\r
2087 * ----------------------------------------------------------
\r
2089 * The portTASK_FUNCTION() macro is used to allow port/compiler specific
\r
2090 * language extensions. The equivalent prototype for this function is:
\r
2092 * void prvIdleTask( void *pvParameters );
\r
2095 static portTASK_FUNCTION( prvIdleTask, pvParameters )
\r
2097 /* Stop warnings. */
\r
2098 ( void ) pvParameters;
\r
2102 /* See if any tasks have been deleted. */
\r
2103 prvCheckTasksWaitingTermination();
\r
2105 #if ( configUSE_PREEMPTION == 0 )
\r
2107 /* If we are not using preemption we keep forcing a task switch to
\r
2108 see if any other task has become available. If we are using
\r
2109 preemption we don't need to do this as any task becoming available
\r
2110 will automatically get the processor anyway. */
\r
2113 #endif /* configUSE_PREEMPTION */
\r
2115 #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
\r
2117 /* When using preemption tasks of equal priority will be
\r
2118 timesliced. If a task that is sharing the idle priority is ready
\r
2119 to run then the idle task should yield before the end of the
\r
2122 A critical region is not required here as we are just reading from
\r
2123 the list, and an occasional incorrect value will not matter. If
\r
2124 the ready list at the idle priority contains more than one task
\r
2125 then a task other than the idle task is ready to execute. */
\r
2126 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( unsigned portBASE_TYPE ) 1 )
\r
2131 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
\r
2133 #if ( configUSE_IDLE_HOOK == 1 )
\r
2135 extern void vApplicationIdleHook( void );
\r
2137 /* Call the user defined function from within the idle task. This
\r
2138 allows the application designer to add background functionality
\r
2139 without the overhead of a separate task.
\r
2140 NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
\r
2141 CALL A FUNCTION THAT MIGHT BLOCK. */
\r
2142 vApplicationIdleHook();
\r
2144 #endif /* configUSE_IDLE_HOOK */
\r
2146 /* This conditional compilation should use inequality to 0, not equality
\r
2147 to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
\r
2148 user defined low power mode implementations require
\r
2149 configUSE_TICKLESS_IDLE to be set to a value other than 1. */
\r
2150 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
2152 portTickType xExpectedIdleTime;
\r
2154 /* It is not desirable to suspend then resume the scheduler on
\r
2155 each iteration of the idle task. Therefore, a preliminary
\r
2156 test of the expected idle time is performed without the
\r
2157 scheduler suspended. The result here is not necessarily
\r
2159 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
2161 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
2163 vTaskSuspendAll();
\r
2165 /* Now the scheduler is suspended, the expected idle
\r
2166 time can be sampled again, and this time its value can
\r
2168 configASSERT( xNextTaskUnblockTime >= xTickCount );
\r
2169 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
2171 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
2173 portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
\r
2179 #endif /* configUSE_TICKLESS_IDLE */
\r
2181 } /*lint !e715 pvParameters is not accessed but all task functions require the same prototype. */
\r
2182 /*-----------------------------------------------------------*/
\r
2184 #if configUSE_TICKLESS_IDLE != 0
\r
2186 eSleepModeStatus eTaskConfirmSleepModeStatus( void )
\r
2188 eSleepModeStatus eReturn = eStandardSleep;
\r
2190 if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
\r
2192 /* A task was made ready while the scheduler was suspended. */
\r
2193 eReturn = eAbortSleep;
\r
2195 else if( xMissedYield != pdFALSE )
\r
2197 /* A yield was pended while the scheduler was suspended. */
\r
2198 eReturn = eAbortSleep;
\r
2202 #if configUSE_TIMERS == 0
\r
2204 /* The idle task exists in addition to the application tasks. */
\r
2205 const unsigned portBASE_TYPE uxNonApplicationTasks = 1;
\r
2207 /* If timers are not being used and all the tasks are in the
\r
2208 suspended list (which might mean they have an infinite block
\r
2209 time rather than actually being suspended) then it is safe to
\r
2210 turn all clocks off and just wait for external interrupts. */
\r
2211 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
\r
2213 eReturn = eNoTasksWaitingTimeout;
\r
2216 #endif /* configUSE_TIMERS */
\r
2221 #endif /* configUSE_TICKLESS_IDLE */
\r
2222 /*-----------------------------------------------------------*/
\r
2224 static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth )
\r
2226 /* Store the function name in the TCB. */
\r
2227 #if configMAX_TASK_NAME_LEN > 1
\r
2229 /* Don't bring strncpy into the build unnecessarily. */
\r
2230 strncpy( ( char * ) pxTCB->pcTaskName, ( const char * ) pcName, ( unsigned short ) configMAX_TASK_NAME_LEN );
\r
2232 #endif /* configMAX_TASK_NAME_LEN */
\r
2233 pxTCB->pcTaskName[ ( unsigned short ) configMAX_TASK_NAME_LEN - ( unsigned short ) 1 ] = ( signed char ) '\0';
\r
2235 /* This is used as an array index so must ensure it's not too large. First
\r
2236 remove the privilege bit if one is present. */
\r
2237 if( uxPriority >= configMAX_PRIORITIES )
\r
2239 uxPriority = configMAX_PRIORITIES - ( unsigned portBASE_TYPE ) 1U;
\r
2242 pxTCB->uxPriority = uxPriority;
\r
2243 #if ( configUSE_MUTEXES == 1 )
\r
2245 pxTCB->uxBasePriority = uxPriority;
\r
2247 #endif /* configUSE_MUTEXES */
\r
2249 vListInitialiseItem( &( pxTCB->xGenericListItem ) );
\r
2250 vListInitialiseItem( &( pxTCB->xEventListItem ) );
\r
2252 /* Set the pxTCB as a link back from the xListItem. This is so we can get
\r
2253 back to the containing TCB from a generic item in a list. */
\r
2254 listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB );
\r
2256 /* Event lists are always in priority order. */
\r
2257 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) uxPriority );
\r
2258 listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB );
\r
2260 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
2262 pxTCB->uxCriticalNesting = ( unsigned portBASE_TYPE ) 0U;
\r
2264 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
2266 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2268 pxTCB->pxTaskTag = NULL;
\r
2270 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2272 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
2274 pxTCB->ulRunTimeCounter = 0UL;
\r
2276 #endif /* configGENERATE_RUN_TIME_STATS */
\r
2278 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
2280 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth );
\r
2282 #else /* portUSING_MPU_WRAPPERS */
\r
2284 ( void ) xRegions;
\r
2285 ( void ) usStackDepth;
\r
2287 #endif /* portUSING_MPU_WRAPPERS */
\r
2289 /*-----------------------------------------------------------*/
\r
2291 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
2293 void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions )
\r
2297 if( xTaskToModify == pxCurrentTCB )
\r
2299 xTaskToModify = NULL;
\r
2302 /* If null is passed in here then we are deleting ourselves. */
\r
2303 pxTCB = prvGetTCBFromHandle( xTaskToModify );
\r
2305 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
\r
2308 #endif /* portUSING_MPU_WRAPPERS */
\r
2309 /*-----------------------------------------------------------*/
\r
2311 static void prvInitialiseTaskLists( void )
\r
2313 unsigned portBASE_TYPE uxPriority;
\r
2315 for( uxPriority = ( unsigned portBASE_TYPE ) 0U; uxPriority < configMAX_PRIORITIES; uxPriority++ )
\r
2317 vListInitialise( ( xList * ) &( pxReadyTasksLists[ uxPriority ] ) );
\r
2320 vListInitialise( ( xList * ) &xDelayedTaskList1 );
\r
2321 vListInitialise( ( xList * ) &xDelayedTaskList2 );
\r
2322 vListInitialise( ( xList * ) &xPendingReadyList );
\r
2324 #if ( INCLUDE_vTaskDelete == 1 )
\r
2326 vListInitialise( ( xList * ) &xTasksWaitingTermination );
\r
2328 #endif /* INCLUDE_vTaskDelete */
\r
2330 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2332 vListInitialise( ( xList * ) &xSuspendedTaskList );
\r
2334 #endif /* INCLUDE_vTaskSuspend */
\r
2336 /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
\r
2338 pxDelayedTaskList = &xDelayedTaskList1;
\r
2339 pxOverflowDelayedTaskList = &xDelayedTaskList2;
\r
2341 /*-----------------------------------------------------------*/
\r
2343 static void prvCheckTasksWaitingTermination( void )
\r
2345 #if ( INCLUDE_vTaskDelete == 1 )
\r
2347 portBASE_TYPE xListIsEmpty;
\r
2349 /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
\r
2350 too often in the idle task. */
\r
2351 while( uxTasksDeleted > ( unsigned portBASE_TYPE ) 0U )
\r
2353 vTaskSuspendAll();
\r
2354 xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
\r
2357 if( xListIsEmpty == pdFALSE )
\r
2361 taskENTER_CRITICAL();
\r
2363 pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( ( ( xList * ) &xTasksWaitingTermination ) );
\r
2364 uxListRemove( &( pxTCB->xGenericListItem ) );
\r
2365 --uxCurrentNumberOfTasks;
\r
2368 taskEXIT_CRITICAL();
\r
2370 prvDeleteTCB( pxTCB );
\r
2374 #endif /* vTaskDelete */
\r
2376 /*-----------------------------------------------------------*/
\r
2378 static void prvAddCurrentTaskToDelayedList( portTickType xTimeToWake )
\r
2380 /* The list item will be inserted in wake time order. */
\r
2381 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
\r
2383 if( xTimeToWake < xTickCount )
\r
2385 /* Wake time has overflowed. Place this item in the overflow list. */
\r
2386 vListInsert( ( xList * ) pxOverflowDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
\r
2390 /* The wake time has not overflowed, so we can use the current block list. */
\r
2391 vListInsert( ( xList * ) pxDelayedTaskList, ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) );
\r
2393 /* If the task entering the blocked state was placed at the head of the
\r
2394 list of blocked tasks then xNextTaskUnblockTime needs to be updated
\r
2396 if( xTimeToWake < xNextTaskUnblockTime )
\r
2398 xNextTaskUnblockTime = xTimeToWake;
\r
2402 /*-----------------------------------------------------------*/
\r
2404 static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer )
\r
2408 /* Allocate space for the TCB. Where the memory comes from depends on
\r
2409 the implementation of the port malloc function. */
\r
2410 pxNewTCB = ( tskTCB * ) pvPortMalloc( sizeof( tskTCB ) );
\r
2412 if( pxNewTCB != NULL )
\r
2414 /* Allocate space for the stack used by the task being created.
\r
2415 The base of the stack memory stored in the TCB so the task can
\r
2416 be deleted later if required. */
\r
2417 pxNewTCB->pxStack = ( portSTACK_TYPE * ) pvPortMallocAligned( ( ( ( size_t )usStackDepth ) * sizeof( portSTACK_TYPE ) ), puxStackBuffer );
\r
2419 if( pxNewTCB->pxStack == NULL )
\r
2421 /* Could not allocate the stack. Delete the allocated TCB. */
\r
2422 vPortFree( pxNewTCB );
\r
2427 /* Just to help debugging. */
\r
2428 memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( portSTACK_TYPE ) );
\r
2434 /*-----------------------------------------------------------*/
\r
2436 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2438 static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus )
\r
2440 volatile tskTCB *pxNextTCB, *pxFirstTCB;
\r
2441 unsigned short usStackRemaining;
\r
2442 PRIVILEGED_DATA static char pcStatusString[ configMAX_TASK_NAME_LEN + 30 ];
\r
2444 /* Write the details of all the TCB's in pxList into the buffer. */
\r
2445 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
\r
2448 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
\r
2449 #if ( portSTACK_GROWTH > 0 )
\r
2451 usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxEndOfStack );
\r
2455 usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack );
\r
2459 sprintf( pcStatusString, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxNextTCB->pcTaskName, cStatus, ( unsigned int ) pxNextTCB->uxPriority, ( unsigned int ) usStackRemaining, ( unsigned int ) pxNextTCB->uxTCBNumber );
\r
2460 strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatusString );
\r
2462 } while( pxNextTCB != pxFirstTCB );
\r
2465 #endif /* configUSE_TRACE_FACILITY */
\r
2466 /*-----------------------------------------------------------*/
\r
2468 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
2470 static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTimeDiv100 )
\r
2472 volatile tskTCB *pxNextTCB, *pxFirstTCB;
\r
2473 unsigned long ulStatsAsPercentage;
\r
2474 size_t xExistingStringLength;
\r
2476 /* Write the run time stats of all the TCB's in pxList into the buffer. */
\r
2477 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
\r
2480 /* Get next TCB from the list. */
\r
2481 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
\r
2483 /* Divide by zero check. */
\r
2484 if( ulTotalRunTimeDiv100 > 0UL )
\r
2486 xExistingStringLength = strlen( pcWriteBuffer );
\r
2488 /* Has the task run at all? */
\r
2489 if( pxNextTCB->ulRunTimeCounter == 0UL )
\r
2491 /* The task has used no CPU time at all. */
\r
2492 sprintf( &( pcWriteBuffer[ xExistingStringLength ] ), ( char * ) "%s\t\t0\t\t0%%\r\n", pxNextTCB->pcTaskName );
\r
2496 /* What percentage of the total run time has the task used?
\r
2497 This will always be rounded down to the nearest integer.
\r
2498 ulTotalRunTimeDiv100 has already been divided by 100. */
\r
2499 ulStatsAsPercentage = pxNextTCB->ulRunTimeCounter / ulTotalRunTimeDiv100;
\r
2501 if( ulStatsAsPercentage > 0UL )
\r
2503 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
2505 sprintf( &( pcWriteBuffer[ xExistingStringLength ] ), ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter, ulStatsAsPercentage );
\r
2509 /* sizeof( int ) == sizeof( long ) so a smaller
\r
2510 printf() library can be used. */
\r
2511 sprintf( &( pcWriteBuffer[ xExistingStringLength ] ), ( char * ) "%s\t\t%u\t\t%u%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );
\r
2517 /* If the percentage is zero here then the task has
\r
2518 consumed less than 1% of the total run time. */
\r
2519 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
2521 sprintf( &( pcWriteBuffer[ xExistingStringLength ] ), ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter );
\r
2525 /* sizeof( int ) == sizeof( long ) so a smaller
\r
2526 printf() library can be used. */
\r
2527 sprintf( &( pcWriteBuffer[ xExistingStringLength ] ), ( char * ) "%s\t\t%u\t\t<1%%\r\n", pxNextTCB->pcTaskName, ( unsigned int ) pxNextTCB->ulRunTimeCounter );
\r
2534 } while( pxNextTCB != pxFirstTCB );
\r
2537 #endif /* configGENERATE_RUN_TIME_STATS */
\r
2538 /*-----------------------------------------------------------*/
\r
2540 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
2542 static unsigned short usTaskCheckFreeStackSpace( const unsigned char * pucStackByte )
\r
2544 register unsigned short usCount = 0U;
\r
2546 while( *pucStackByte == tskSTACK_FILL_BYTE )
\r
2548 pucStackByte -= portSTACK_GROWTH;
\r
2552 usCount /= sizeof( portSTACK_TYPE );
\r
2557 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */
\r
2558 /*-----------------------------------------------------------*/
\r
2560 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
\r
2562 unsigned portBASE_TYPE uxTaskGetStackHighWaterMark( xTaskHandle xTask )
\r
2565 unsigned char *pcEndOfStack;
\r
2566 unsigned portBASE_TYPE uxReturn;
\r
2568 pxTCB = prvGetTCBFromHandle( xTask );
\r
2570 #if portSTACK_GROWTH < 0
\r
2572 pcEndOfStack = ( unsigned char * ) pxTCB->pxStack;
\r
2576 pcEndOfStack = ( unsigned char * ) pxTCB->pxEndOfStack;
\r
2580 uxReturn = ( unsigned portBASE_TYPE ) usTaskCheckFreeStackSpace( pcEndOfStack );
\r
2585 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
\r
2586 /*-----------------------------------------------------------*/
\r
2588 #if ( INCLUDE_vTaskDelete == 1 )
\r
2590 static void prvDeleteTCB( tskTCB *pxTCB )
\r
2592 /* This call is required specifically for the TriCore port. It must be
\r
2593 above the vPortFree() calls. The call is also used by ports/demos that
\r
2594 want to allocate and clean RAM statically. */
\r
2595 portCLEAN_UP_TCB( pxTCB );
\r
2597 /* Free up the memory allocated by the scheduler for the task. It is up to
\r
2598 the task to free any memory allocated at the application level. */
\r
2599 vPortFreeAligned( pxTCB->pxStack );
\r
2600 vPortFree( pxTCB );
\r
2603 #endif /* INCLUDE_vTaskDelete */
\r
2604 /*-----------------------------------------------------------*/
\r
2606 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
\r
2608 xTaskHandle xTaskGetCurrentTaskHandle( void )
\r
2610 xTaskHandle xReturn;
\r
2612 /* A critical section is not required as this is not called from
\r
2613 an interrupt and the current TCB will always be the same for any
\r
2614 individual execution thread. */
\r
2615 xReturn = pxCurrentTCB;
\r
2620 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
\r
2621 /*-----------------------------------------------------------*/
\r
2623 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
2625 portBASE_TYPE xTaskGetSchedulerState( void )
\r
2627 portBASE_TYPE xReturn;
\r
2629 if( xSchedulerRunning == pdFALSE )
\r
2631 xReturn = taskSCHEDULER_NOT_STARTED;
\r
2635 if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )
\r
2637 xReturn = taskSCHEDULER_RUNNING;
\r
2641 xReturn = taskSCHEDULER_SUSPENDED;
\r
2648 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
\r
2649 /*-----------------------------------------------------------*/
\r
2651 #if ( configUSE_MUTEXES == 1 )
\r
2653 void vTaskPriorityInherit( xTaskHandle * const pxMutexHolder )
\r
2655 tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;
\r
2657 /* If the mutex was given back by an interrupt while the queue was
\r
2658 locked then the mutex holder might now be NULL. */
\r
2659 if( pxMutexHolder != NULL )
\r
2661 if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
\r
2663 /* Adjust the mutex holder state to account for its new priority. */
\r
2664 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority );
\r
2666 /* If the task being modified is in the ready state it will need to
\r
2667 be moved into a new list. */
\r
2668 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
\r
2670 if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
\r
2672 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
2675 /* Inherit the priority before being moved into the new list. */
\r
2676 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
2677 prvAddTaskToReadyQueue( pxTCB );
\r
2681 /* Just inherit the priority. */
\r
2682 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
2685 traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );
\r
2690 #endif /* configUSE_MUTEXES */
\r
2691 /*-----------------------------------------------------------*/
\r
2693 #if ( configUSE_MUTEXES == 1 )
\r
2695 void vTaskPriorityDisinherit( xTaskHandle * const pxMutexHolder )
\r
2697 tskTCB * const pxTCB = ( tskTCB * ) pxMutexHolder;
\r
2699 if( pxMutexHolder != NULL )
\r
2701 if( pxTCB->uxPriority != pxTCB->uxBasePriority )
\r
2703 /* We must be the running task to be able to give the mutex back.
\r
2704 Remove ourselves from the ready list we currently appear in. */
\r
2705 if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )
\r
2707 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
2710 /* Disinherit the priority before adding the task into the new
\r
2712 traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
\r
2713 pxTCB->uxPriority = pxTCB->uxBasePriority;
\r
2714 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxTCB->uxPriority );
\r
2715 prvAddTaskToReadyQueue( pxTCB );
\r
2720 #endif /* configUSE_MUTEXES */
\r
2721 /*-----------------------------------------------------------*/
\r
2723 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
2725 void vTaskEnterCritical( void )
\r
2727 portDISABLE_INTERRUPTS();
\r
2729 if( xSchedulerRunning != pdFALSE )
\r
2731 ( pxCurrentTCB->uxCriticalNesting )++;
\r
2735 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
2736 /*-----------------------------------------------------------*/
\r
2738 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
2740 void vTaskExitCritical( void )
\r
2742 if( xSchedulerRunning != pdFALSE )
\r
2744 if( pxCurrentTCB->uxCriticalNesting > 0U )
\r
2746 ( pxCurrentTCB->uxCriticalNesting )--;
\r
2748 if( pxCurrentTCB->uxCriticalNesting == 0U )
\r
2750 portENABLE_INTERRUPTS();
\r
2756 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
2757 /*-----------------------------------------------------------*/
\r