2 FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
\r
5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
7 This file is part of the FreeRTOS distribution.
\r
9 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
10 the terms of the GNU General Public License (version 2) as published by the
\r
11 Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
\r
13 ***************************************************************************
\r
14 >>! NOTE: The modification to the GPL is included to allow you to !<<
\r
15 >>! distribute a combined work that includes FreeRTOS without being !<<
\r
16 >>! obliged to provide the source code for proprietary components !<<
\r
17 >>! outside of the FreeRTOS kernel. !<<
\r
18 ***************************************************************************
\r
20 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
21 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
22 FOR A PARTICULAR PURPOSE. Full license text is available on the following
\r
23 link: http://www.freertos.org/a00114.html
\r
25 ***************************************************************************
\r
27 * FreeRTOS provides completely free yet professionally developed, *
\r
28 * robust, strictly quality controlled, supported, and cross *
\r
29 * platform software that is more than just the market leader, it *
\r
30 * is the industry's de facto standard. *
\r
32 * Help yourself get started quickly while simultaneously helping *
\r
33 * to support the FreeRTOS project by purchasing a FreeRTOS *
\r
34 * tutorial book, reference manual, or both: *
\r
35 * http://www.FreeRTOS.org/Documentation *
\r
37 ***************************************************************************
\r
39 http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
\r
40 the FAQ page "My application does not run, what could be wrong?". Have you
\r
41 defined configASSERT()?
\r
43 http://www.FreeRTOS.org/support - In return for receiving this top quality
\r
44 embedded software for free we request you assist our global community by
\r
45 participating in the support forum.
\r
47 http://www.FreeRTOS.org/training - Investing in training allows your team to
\r
48 be as productive as possible as early as possible. Now you can receive
\r
49 FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
\r
50 Ltd, and the world's leading authority on the world's leading RTOS.
\r
52 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
53 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
\r
54 compatible FAT file system, and our tiny thread aware UDP/IP stack.
\r
56 http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
\r
57 Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
\r
59 http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
\r
60 Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
\r
61 licenses offer ticketed support, indemnification and commercial middleware.
\r
63 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
64 engineered and independently SIL3 certified version for use in safety and
\r
65 mission critical applications that require provable dependability.
\r
70 /* Standard includes. */
\r
74 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
\r
75 all the API functions to use the MPU wrappers. That should only be done when
\r
76 task.h is included from an application file. */
\r
77 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
79 /* FreeRTOS includes. */
\r
80 #include "FreeRTOS.h"
\r
83 #include "StackMacros.h"
\r
85 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the
\r
86 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
\r
87 header files above, but not in this file, in order to generate the correct
\r
88 privileged Vs unprivileged linkage and placement. */
\r
89 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
\r
91 /* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting
\r
92 functions but without including stdio.h here. */
\r
93 #if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 )
\r
94 /* At the bottom of this file are two optional functions that can be used
\r
95 to generate human readable text from the raw data generated by the
\r
96 uxTaskGetSystemState() function. Note the formatting functions are provided
\r
97 for convenience only, and are NOT considered part of the kernel. */
\r
99 #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
\r
101 #if( configUSE_PREEMPTION == 0 )
\r
102 /* If the cooperative scheduler is being used then a yield should not be
\r
103 performed just because a higher priority task has been woken. */
\r
104 #define taskYIELD_IF_USING_PREEMPTION()
\r
106 #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
\r
109 /* Values that can be assigned to the ucNotifyState member of the TCB. */
\r
110 #define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 )
\r
111 #define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 )
\r
112 #define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 )
\r
115 * The value used to fill the stack of a task when the task is created. This
\r
116 * is used purely for checking the high water mark for tasks.
\r
118 #define tskSTACK_FILL_BYTE ( 0xa5U )
\r
120 /* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using
\r
121 dynamically allocated RAM, in which case when any task is deleted it is known
\r
122 that both the task's stack and TCB need to be freed. Sometimes the
\r
123 FreeRTOSConfig.h settings only allow a task to be created using statically
\r
124 allocated RAM, in which case when any task is deleted it is known that neither
\r
125 the task's stack or TCB should be freed. Sometimes the FreeRTOSConfig.h
\r
126 settings allow a task to be created using either statically or dynamically
\r
127 allocated RAM, in which case a member of the TCB is used to record whether the
\r
128 stack and/or TCB were allocated statically or dynamically, so when a task is
\r
129 deleted the RAM that was allocated dynamically is freed again and no attempt is
\r
130 made to free the RAM that was allocated statically.
\r
131 tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is only true if it is possible for a
\r
132 task to be created using either statically or dynamically allocated RAM. Note
\r
133 that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with
\r
134 a statically allocated stack and a dynamically allocated TCB.
\r
135 !!!NOTE!!! If the definition of tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is
\r
136 changed then the definition of StaticTask_t must also be updated. */
\r
137 #define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) || ( portUSING_MPU_WRAPPERS == 1 ) )
\r
138 #define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 0 )
\r
139 #define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 )
\r
140 #define tskSTATICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 2 )
\r
142 /* If any of the following are set then task stacks are filled with a known
\r
143 value so the high water mark can be determined. If none of the following are
\r
144 set then don't fill the stack so there is no unnecessary dependency on memset. */
\r
145 #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
146 #define tskSET_NEW_STACKS_TO_KNOWN_VALUE 1
\r
148 #define tskSET_NEW_STACKS_TO_KNOWN_VALUE 0
\r
152 * Macros used by vListTask to indicate which state a task is in.
\r
154 #define tskBLOCKED_CHAR ( 'B' )
\r
155 #define tskREADY_CHAR ( 'R' )
\r
156 #define tskDELETED_CHAR ( 'D' )
\r
157 #define tskSUSPENDED_CHAR ( 'S' )
\r
160 * Some kernel aware debuggers require the data the debugger needs access to be
\r
161 * global, rather than file scope.
\r
163 #ifdef portREMOVE_STATIC_QUALIFIER
\r
167 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
\r
169 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
\r
170 performed in a generic way that is not optimised to any particular
\r
171 microcontroller architecture. */
\r
173 /* uxTopReadyPriority holds the priority of the highest priority ready
\r
175 #define taskRECORD_READY_PRIORITY( uxPriority ) \
\r
177 if( ( uxPriority ) > uxTopReadyPriority ) \
\r
179 uxTopReadyPriority = ( uxPriority ); \
\r
181 } /* taskRECORD_READY_PRIORITY */
\r
183 /*-----------------------------------------------------------*/
\r
185 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
187 UBaseType_t uxTopPriority = uxTopReadyPriority; \
\r
189 /* Find the highest priority queue that contains ready tasks. */ \
\r
190 while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \
\r
192 configASSERT( uxTopPriority ); \
\r
196 /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
\r
197 the same priority get an equal share of the processor time. */ \
\r
198 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
\r
199 uxTopReadyPriority = uxTopPriority; \
\r
200 } /* taskSELECT_HIGHEST_PRIORITY_TASK */
\r
202 /*-----------------------------------------------------------*/
\r
204 /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
\r
205 they are only required when a port optimised method of task selection is
\r
207 #define taskRESET_READY_PRIORITY( uxPriority )
\r
208 #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
210 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
212 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
\r
213 performed in a way that is tailored to the particular microcontroller
\r
214 architecture being used. */
\r
216 /* A port optimised version is provided. Call the port defined macros. */
\r
217 #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
219 /*-----------------------------------------------------------*/
\r
221 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
223 UBaseType_t uxTopPriority; \
\r
225 /* Find the highest priority list that contains ready tasks. */ \
\r
226 portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
\r
227 configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
\r
228 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
\r
229 } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
\r
231 /*-----------------------------------------------------------*/
\r
233 /* A port optimised version is provided, call it only if the TCB being reset
\r
234 is being referenced from a ready list. If it is referenced from a delayed
\r
235 or suspended list then it won't be in a ready list. */
\r
236 #define taskRESET_READY_PRIORITY( uxPriority ) \
\r
238 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \
\r
240 portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \
\r
244 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
246 /*-----------------------------------------------------------*/
\r
248 /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
\r
249 count overflows. */
\r
250 #define taskSWITCH_DELAYED_LISTS() \
\r
254 /* The delayed tasks list should be empty when the lists are switched. */ \
\r
255 configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \
\r
257 pxTemp = pxDelayedTaskList; \
\r
258 pxDelayedTaskList = pxOverflowDelayedTaskList; \
\r
259 pxOverflowDelayedTaskList = pxTemp; \
\r
260 xNumOfOverflows++; \
\r
261 prvResetNextTaskUnblockTime(); \
\r
264 /*-----------------------------------------------------------*/
\r
267 * Place the task represented by pxTCB into the appropriate ready list for
\r
268 * the task. It is inserted at the end of the list.
\r
270 #define prvAddTaskToReadyList( pxTCB ) \
\r
271 traceMOVED_TASK_TO_READY_STATE( pxTCB ); \
\r
272 taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
\r
273 vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
\r
274 tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )
\r
275 /*-----------------------------------------------------------*/
\r
278 * Several functions take an TaskHandle_t parameter that can optionally be NULL,
\r
279 * where NULL is used to indicate that the handle of the currently executing
\r
280 * task should be used in place of the parameter. This macro simply checks to
\r
281 * see if the parameter is NULL and returns a pointer to the appropriate TCB.
\r
283 #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TCB_t * ) pxCurrentTCB : ( TCB_t * ) ( pxHandle ) )
\r
285 /* The item value of the event list item is normally used to hold the priority
\r
286 of the task to which it belongs (coded to allow it to be held in reverse
\r
287 priority order). However, it is occasionally borrowed for other purposes. It
\r
288 is important its value is not updated due to a task priority change while it is
\r
289 being used for another purpose. The following bit definition is used to inform
\r
290 the scheduler that the value should not be changed - in which case it is the
\r
291 responsibility of whichever module is using the value to ensure it gets set back
\r
292 to its original value when it is released. */
\r
293 #if( configUSE_16_BIT_TICKS == 1 )
\r
294 #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U
\r
296 #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL
\r
300 * Task control block. A task control block (TCB) is allocated for each task,
\r
301 * and stores task state information, including a pointer to the task's context
\r
302 * (the task's run time environment, including register values)
\r
304 typedef struct tskTaskControlBlock
\r
306 volatile StackType_t *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
\r
308 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
309 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
312 ListItem_t xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
\r
313 ListItem_t xEventListItem; /*< Used to reference a task from an event list. */
\r
314 UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */
\r
315 StackType_t *pxStack; /*< Points to the start of the stack. */
\r
316 char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
318 #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
\r
319 StackType_t *pxEndOfStack; /*< Points to the highest valid address for the stack. */
\r
322 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
323 UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
\r
326 #if ( configUSE_TRACE_FACILITY == 1 )
\r
327 UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */
\r
328 UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
\r
331 #if ( configUSE_MUTEXES == 1 )
\r
332 UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
\r
333 UBaseType_t uxMutexesHeld;
\r
336 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
337 TaskHookFunction_t pxTaskTag;
\r
340 #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
\r
341 void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
\r
344 #if( configGENERATE_RUN_TIME_STATS == 1 )
\r
345 uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
\r
348 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
349 /* Allocate a Newlib reent structure that is specific to this task.
\r
350 Note Newlib support has been included by popular demand, but is not
\r
351 used by the FreeRTOS maintainers themselves. FreeRTOS is not
\r
352 responsible for resulting newlib operation. User must be familiar with
\r
353 newlib and must provide system-wide implementations of the necessary
\r
354 stubs. Be warned that (at the time of writing) the current newlib design
\r
355 implements a system-wide malloc() that must be provided with locks. */
\r
356 struct _reent xNewLib_reent;
\r
359 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
360 volatile uint32_t ulNotifiedValue;
\r
361 volatile uint8_t ucNotifyState;
\r
364 /* See the comments above the definition of
\r
365 tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
\r
366 #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */
\r
367 uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
\r
370 #if( INCLUDE_xTaskAbortDelay == 1 )
\r
371 uint8_t ucDelayAborted;
\r
376 /* The old tskTCB name is maintained above then typedefed to the new TCB_t name
\r
377 below to enable the use of older kernel aware debuggers. */
\r
378 typedef tskTCB TCB_t;
\r
380 /*lint -save -e956 A manual analysis and inspection has been used to determine
\r
381 which static variables must be declared volatile. */
\r
383 PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
\r
385 /* Lists for ready and blocked tasks. --------------------*/
\r
386 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */
\r
387 PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */
\r
388 PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
\r
389 PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */
\r
390 PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */
\r
391 PRIVILEGED_DATA static List_t xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready list when the scheduler is resumed. */
\r
393 #if( INCLUDE_vTaskDelete == 1 )
\r
395 PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */
\r
396 PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;
\r
400 #if ( INCLUDE_vTaskSuspend == 1 )
\r
402 PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */
\r
406 /* Other file private variables. --------------------------------*/
\r
407 PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
\r
408 PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U;
\r
409 PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
\r
410 PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
\r
411 PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U;
\r
412 PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE;
\r
413 PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
\r
414 PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
\r
415 PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */
\r
416 PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle = NULL; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */
\r
418 /* Context switches are held pending while the scheduler is suspended. Also,
\r
419 interrupts must not manipulate the xStateListItem of a TCB, or any of the
\r
420 lists the xStateListItem can be referenced from, if the scheduler is suspended.
\r
421 If an interrupt needs to unblock a task while the scheduler is suspended then it
\r
422 moves the task's event list item into the xPendingReadyList, ready for the
\r
423 kernel to move the task from the pending ready list into the real ready list
\r
424 when the scheduler is unsuspended. The pending ready list itself can only be
\r
425 accessed from a critical section. */
\r
426 PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE;
\r
428 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
430 PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
\r
431 PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */
\r
437 /*-----------------------------------------------------------*/
\r
439 /* Callback function prototypes. --------------------------*/
\r
440 #if( configCHECK_FOR_STACK_OVERFLOW > 0 )
\r
442 extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName );
\r
446 #if( configUSE_TICK_HOOK > 0 )
\r
448 extern void vApplicationTickHook( void );
\r
452 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
454 extern void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );
\r
458 /* File private functions. --------------------------------*/
\r
461 * Utility task that simply returns pdTRUE if the task referenced by xTask is
\r
462 * currently in the Suspended state, or pdFALSE if the task referenced by xTask
\r
463 * is in any other state.
\r
465 #if ( INCLUDE_vTaskSuspend == 1 )
\r
467 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
\r
469 #endif /* INCLUDE_vTaskSuspend */
\r
472 * Utility to ready all the lists used by the scheduler. This is called
\r
473 * automatically upon the creation of the first task.
\r
475 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
\r
478 * The idle task, which as all tasks is implemented as a never ending loop.
\r
479 * The idle task is automatically created and added to the ready lists upon
\r
480 * creation of the first user task.
\r
482 * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
\r
483 * language extensions. The equivalent prototype for this function is:
\r
485 * void prvIdleTask( void *pvParameters );
\r
488 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
\r
491 * Utility to free all memory allocated by the scheduler to hold a TCB,
\r
492 * including the stack pointed to by the TCB.
\r
494 * This does not free memory allocated by the task itself (i.e. memory
\r
495 * allocated by calls to pvPortMalloc from within the tasks application code).
\r
497 #if ( INCLUDE_vTaskDelete == 1 )
\r
499 static void prvDeleteTCB( TCB_t *pxTCB ) PRIVILEGED_FUNCTION;
\r
504 * Used only by the idle task. This checks to see if anything has been placed
\r
505 * in the list of tasks waiting to be deleted. If so the task is cleaned up
\r
506 * and its TCB deleted.
\r
508 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
\r
511 * The currently executing task is entering the Blocked state. Add the task to
\r
512 * either the current or the overflow delayed task list.
\r
514 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION;
\r
517 * Fills an TaskStatus_t structure with information on each task that is
\r
518 * referenced from the pxList list (which may be a ready list, a delayed list,
\r
519 * a suspended list, etc.).
\r
521 * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
\r
522 * NORMAL APPLICATION CODE.
\r
524 #if ( configUSE_TRACE_FACILITY == 1 )
\r
526 static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;
\r
531 * Searches pxList for a task with name pcNameToQuery - returning a handle to
\r
532 * the task if it is found, or NULL if the task is not found.
\r
534 #if ( INCLUDE_xTaskGetHandle == 1 )
\r
536 static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] ) PRIVILEGED_FUNCTION;
\r
541 * When a task is created, the stack of the task is filled with a known value.
\r
542 * This function determines the 'high water mark' of the task stack by
\r
543 * determining how much of the stack remains at the original preset value.
\r
545 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
547 static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
\r
552 * Return the amount of time, in ticks, that will pass before the kernel will
\r
553 * next move a task from the Blocked state to the Running state.
\r
555 * This conditional compilation should use inequality to 0, not equality to 1.
\r
556 * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
\r
557 * defined low power mode implementations require configUSE_TICKLESS_IDLE to be
\r
558 * set to a value other than 1.
\r
560 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
562 static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
\r
567 * Set xNextTaskUnblockTime to the time at which the next Blocked state task
\r
568 * will exit the Blocked state.
\r
570 static void prvResetNextTaskUnblockTime( void );
\r
572 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
575 * Helper function used to pad task names with spaces when printing out
\r
576 * human readable tables of task information.
\r
578 static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName ) PRIVILEGED_FUNCTION;
\r
583 * Called after a Task_t structure has been allocated either statically or
\r
584 * dynamically to fill in the structure's members.
\r
586 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
\r
587 const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
588 const uint32_t ulStackDepth,
\r
589 void * const pvParameters,
\r
590 UBaseType_t uxPriority,
\r
591 TaskHandle_t * const pxCreatedTask,
\r
593 const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION;
\r
596 * Called after a new task has been created and initialised to place the task
\r
597 * under the control of the scheduler.
\r
599 static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
\r
602 * freertos_tasks_c_additions_init() should only be called if the user definable
\r
603 * macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is the only macro
\r
604 * called by the function.
\r
606 #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
\r
608 static void freertos_tasks_c_additions_init( void ) PRIVILEGED_FUNCTION;
\r
612 /*-----------------------------------------------------------*/
\r
614 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
616 TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
\r
617 const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
618 const uint32_t ulStackDepth,
\r
619 void * const pvParameters,
\r
620 UBaseType_t uxPriority,
\r
621 StackType_t * const puxStackBuffer,
\r
622 StaticTask_t * const pxTaskBuffer )
\r
625 TaskHandle_t xReturn;
\r
627 configASSERT( puxStackBuffer != NULL );
\r
628 configASSERT( pxTaskBuffer != NULL );
\r
630 #if( configASSERT_DEFINED == 1 )
\r
632 /* Sanity check that the size of the structure used to declare a
\r
633 variable of type StaticTask_t equals the size of the real task
\r
635 volatile size_t xSize = sizeof( StaticTask_t );
\r
636 configASSERT( xSize == sizeof( TCB_t ) );
\r
638 #endif /* configASSERT_DEFINED */
\r
641 if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
\r
643 /* The memory used for the task's TCB and stack are passed into this
\r
644 function - use them. */
\r
645 pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
\r
646 pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;
\r
648 #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */
\r
650 /* Tasks can be created statically or dynamically, so note this
\r
651 task was created statically in case the task is later deleted. */
\r
652 pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
\r
654 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
656 prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL );
\r
657 prvAddNewTaskToReadyList( pxNewTCB );
\r
667 #endif /* SUPPORT_STATIC_ALLOCATION */
\r
668 /*-----------------------------------------------------------*/
\r
670 #if( portUSING_MPU_WRAPPERS == 1 )
\r
672 BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
\r
675 BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
\r
677 configASSERT( pxTaskDefinition->puxStackBuffer );
\r
679 if( pxTaskDefinition->puxStackBuffer != NULL )
\r
681 /* Allocate space for the TCB. Where the memory comes from depends
\r
682 on the implementation of the port malloc function and whether or
\r
683 not static allocation is being used. */
\r
684 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
\r
686 if( pxNewTCB != NULL )
\r
688 /* Store the stack location in the TCB. */
\r
689 pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
\r
691 /* Tasks can be created statically or dynamically, so note
\r
692 this task had a statically allocated stack in case it is
\r
693 later deleted. The TCB was allocated dynamically. */
\r
694 pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY;
\r
696 prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
\r
697 pxTaskDefinition->pcName,
\r
698 ( uint32_t ) pxTaskDefinition->usStackDepth,
\r
699 pxTaskDefinition->pvParameters,
\r
700 pxTaskDefinition->uxPriority,
\r
701 pxCreatedTask, pxNewTCB,
\r
702 pxTaskDefinition->xRegions );
\r
704 prvAddNewTaskToReadyList( pxNewTCB );
\r
712 #endif /* portUSING_MPU_WRAPPERS */
\r
713 /*-----------------------------------------------------------*/
\r
715 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
\r
717 BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
\r
718 const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
719 const uint16_t usStackDepth,
\r
720 void * const pvParameters,
\r
721 UBaseType_t uxPriority,
\r
722 TaskHandle_t * const pxCreatedTask )
\r
725 BaseType_t xReturn;
\r
727 /* If the stack grows down then allocate the stack then the TCB so the stack
\r
728 does not grow into the TCB. Likewise if the stack grows up then allocate
\r
729 the TCB then the stack. */
\r
730 #if( portSTACK_GROWTH > 0 )
\r
732 /* Allocate space for the TCB. Where the memory comes from depends on
\r
733 the implementation of the port malloc function and whether or not static
\r
734 allocation is being used. */
\r
735 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
\r
737 if( pxNewTCB != NULL )
\r
739 /* Allocate space for the stack used by the task being created.
\r
740 The base of the stack memory stored in the TCB so the task can
\r
741 be deleted later if required. */
\r
742 pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
744 if( pxNewTCB->pxStack == NULL )
\r
746 /* Could not allocate the stack. Delete the allocated TCB. */
\r
747 vPortFree( pxNewTCB );
\r
752 #else /* portSTACK_GROWTH */
\r
754 StackType_t *pxStack;
\r
756 /* Allocate space for the stack used by the task being created. */
\r
757 pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
759 if( pxStack != NULL )
\r
761 /* Allocate space for the TCB. */
\r
762 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e961 MISRA exception as the casts are only redundant for some paths. */
\r
764 if( pxNewTCB != NULL )
\r
766 /* Store the stack location in the TCB. */
\r
767 pxNewTCB->pxStack = pxStack;
\r
771 /* The stack cannot be used as the TCB was not created. Free
\r
773 vPortFree( pxStack );
\r
781 #endif /* portSTACK_GROWTH */
\r
783 if( pxNewTCB != NULL )
\r
785 #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */
\r
787 /* Tasks can be created statically or dynamically, so note this
\r
788 task was created dynamically in case it is later deleted. */
\r
789 pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
\r
791 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
793 prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
\r
794 prvAddNewTaskToReadyList( pxNewTCB );
\r
799 xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
\r
805 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
806 /*-----------------------------------------------------------*/
\r
808 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
\r
809 const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
810 const uint32_t ulStackDepth,
\r
811 void * const pvParameters,
\r
812 UBaseType_t uxPriority,
\r
813 TaskHandle_t * const pxCreatedTask,
\r
815 const MemoryRegion_t * const xRegions )
\r
817 StackType_t *pxTopOfStack;
\r
820 #if( portUSING_MPU_WRAPPERS == 1 )
\r
821 /* Should the task be created in privileged mode? */
\r
822 BaseType_t xRunPrivileged;
\r
823 if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
\r
825 xRunPrivileged = pdTRUE;
\r
829 xRunPrivileged = pdFALSE;
\r
831 uxPriority &= ~portPRIVILEGE_BIT;
\r
832 #endif /* portUSING_MPU_WRAPPERS == 1 */
\r
834 /* Avoid dependency on memset() if it is not required. */
\r
835 #if( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 )
\r
837 /* Fill the stack with a known value to assist debugging. */
\r
838 ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );
\r
840 #endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */
\r
842 /* Calculate the top of stack address. This depends on whether the stack
\r
843 grows from high memory to low (as per the 80x86) or vice versa.
\r
844 portSTACK_GROWTH is used to make the result positive or negative as required
\r
846 #if( portSTACK_GROWTH < 0 )
\r
848 pxTopOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
\r
849 pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); /*lint !e923 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. */
\r
851 /* Check the alignment of the calculated top of stack is correct. */
\r
852 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
854 #if( configRECORD_STACK_HIGH_ADDRESS == 1 )
\r
856 /* Also record the stack's high address, which may assist
\r
858 pxNewTCB->pxEndOfStack = pxTopOfStack;
\r
860 #endif /* configRECORD_STACK_HIGH_ADDRESS */
\r
862 #else /* portSTACK_GROWTH */
\r
864 pxTopOfStack = pxNewTCB->pxStack;
\r
866 /* Check the alignment of the stack buffer is correct. */
\r
867 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
869 /* The other extreme of the stack space is required if stack checking is
\r
871 pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
\r
873 #endif /* portSTACK_GROWTH */
\r
875 /* Store the task name in the TCB. */
\r
876 for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
\r
878 pxNewTCB->pcTaskName[ x ] = pcName[ x ];
\r
880 /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
\r
881 configMAX_TASK_NAME_LEN characters just in case the memory after the
\r
882 string is not accessible (extremely unlikely). */
\r
883 if( pcName[ x ] == 0x00 )
\r
889 mtCOVERAGE_TEST_MARKER();
\r
893 /* Ensure the name string is terminated in the case that the string length
\r
894 was greater or equal to configMAX_TASK_NAME_LEN. */
\r
895 pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
\r
897 /* This is used as an array index so must ensure it's not too large. First
\r
898 remove the privilege bit if one is present. */
\r
899 if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
\r
901 uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
\r
905 mtCOVERAGE_TEST_MARKER();
\r
908 pxNewTCB->uxPriority = uxPriority;
\r
909 #if ( configUSE_MUTEXES == 1 )
\r
911 pxNewTCB->uxBasePriority = uxPriority;
\r
912 pxNewTCB->uxMutexesHeld = 0;
\r
914 #endif /* configUSE_MUTEXES */
\r
916 vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
\r
917 vListInitialiseItem( &( pxNewTCB->xEventListItem ) );
\r
919 /* Set the pxNewTCB as a link back from the ListItem_t. This is so we can get
\r
920 back to the containing TCB from a generic item in a list. */
\r
921 listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );
\r
923 /* Event lists are always in priority order. */
\r
924 listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
925 listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );
\r
927 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
929 pxNewTCB->uxCriticalNesting = ( UBaseType_t ) 0U;
\r
931 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
933 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
935 pxNewTCB->pxTaskTag = NULL;
\r
937 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
939 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
941 pxNewTCB->ulRunTimeCounter = 0UL;
\r
943 #endif /* configGENERATE_RUN_TIME_STATS */
\r
945 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
947 vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth );
\r
951 /* Avoid compiler warning about unreferenced parameter. */
\r
956 #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
\r
958 for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ )
\r
960 pxNewTCB->pvThreadLocalStoragePointers[ x ] = NULL;
\r
965 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
\r
967 pxNewTCB->ulNotifiedValue = 0;
\r
968 pxNewTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
\r
972 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
974 /* Initialise this task's Newlib reent structure. */
\r
975 _REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) );
\r
979 #if( INCLUDE_xTaskAbortDelay == 1 )
\r
981 pxNewTCB->ucDelayAborted = pdFALSE;
\r
985 /* Initialize the TCB stack to look as if the task was already running,
\r
986 but had been interrupted by the scheduler. The return address is set
\r
987 to the start of the task function. Once the stack has been initialised
\r
988 the top of stack variable is updated. */
\r
989 #if( portUSING_MPU_WRAPPERS == 1 )
\r
991 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
\r
993 #else /* portUSING_MPU_WRAPPERS */
\r
995 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
\r
997 #endif /* portUSING_MPU_WRAPPERS */
\r
999 if( ( void * ) pxCreatedTask != NULL )
\r
1001 /* Pass the handle out in an anonymous way. The handle can be used to
\r
1002 change the created task's priority, delete the created task, etc.*/
\r
1003 *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
\r
1007 mtCOVERAGE_TEST_MARKER();
\r
1010 /*-----------------------------------------------------------*/
\r
1012 static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
\r
1014 /* Ensure interrupts don't access the task lists while the lists are being
\r
1016 taskENTER_CRITICAL();
\r
1018 uxCurrentNumberOfTasks++;
\r
1019 if( pxCurrentTCB == NULL )
\r
1021 /* There are no other tasks, or all the other tasks are in
\r
1022 the suspended state - make this the current task. */
\r
1023 pxCurrentTCB = pxNewTCB;
\r
1025 if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
\r
1027 /* This is the first task to be created so do the preliminary
\r
1028 initialisation required. We will not recover if this call
\r
1029 fails, but we will report the failure. */
\r
1030 prvInitialiseTaskLists();
\r
1034 mtCOVERAGE_TEST_MARKER();
\r
1039 /* If the scheduler is not already running, make this task the
\r
1040 current task if it is the highest priority task to be created
\r
1042 if( xSchedulerRunning == pdFALSE )
\r
1044 if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )
\r
1046 pxCurrentTCB = pxNewTCB;
\r
1050 mtCOVERAGE_TEST_MARKER();
\r
1055 mtCOVERAGE_TEST_MARKER();
\r
1061 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1063 /* Add a counter into the TCB for tracing only. */
\r
1064 pxNewTCB->uxTCBNumber = uxTaskNumber;
\r
1066 #endif /* configUSE_TRACE_FACILITY */
\r
1067 traceTASK_CREATE( pxNewTCB );
\r
1069 prvAddTaskToReadyList( pxNewTCB );
\r
1071 portSETUP_TCB( pxNewTCB );
\r
1073 taskEXIT_CRITICAL();
\r
1075 if( xSchedulerRunning != pdFALSE )
\r
1077 /* If the created task is of a higher priority than the current task
\r
1078 then it should run now. */
\r
1079 if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority )
\r
1081 taskYIELD_IF_USING_PREEMPTION();
\r
1085 mtCOVERAGE_TEST_MARKER();
\r
1090 mtCOVERAGE_TEST_MARKER();
\r
1093 /*-----------------------------------------------------------*/
\r
1095 #if ( INCLUDE_vTaskDelete == 1 )
\r
1097 void vTaskDelete( TaskHandle_t xTaskToDelete )
\r
1101 taskENTER_CRITICAL();
\r
1103 /* If null is passed in here then it is the calling task that is
\r
1105 pxTCB = prvGetTCBFromHandle( xTaskToDelete );
\r
1107 /* Remove task from the ready list. */
\r
1108 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
1110 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
1114 mtCOVERAGE_TEST_MARKER();
\r
1117 /* Is the task waiting on an event also? */
\r
1118 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
1120 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1124 mtCOVERAGE_TEST_MARKER();
\r
1127 /* Increment the uxTaskNumber also so kernel aware debuggers can
\r
1128 detect that the task lists need re-generating. This is done before
\r
1129 portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will
\r
1133 if( pxTCB == pxCurrentTCB )
\r
1135 /* A task is deleting itself. This cannot complete within the
\r
1136 task itself, as a context switch to another task is required.
\r
1137 Place the task in the termination list. The idle task will
\r
1138 check the termination list and free up any memory allocated by
\r
1139 the scheduler for the TCB and stack of the deleted task. */
\r
1140 vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );
\r
1142 /* Increment the ucTasksDeleted variable so the idle task knows
\r
1143 there is a task that has been deleted and that it should therefore
\r
1144 check the xTasksWaitingTermination list. */
\r
1145 ++uxDeletedTasksWaitingCleanUp;
\r
1147 /* The pre-delete hook is primarily for the Windows simulator,
\r
1148 in which Windows specific clean up operations are performed,
\r
1149 after which it is not possible to yield away from this task -
\r
1150 hence xYieldPending is used to latch that a context switch is
\r
1152 portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
\r
1156 --uxCurrentNumberOfTasks;
\r
1157 prvDeleteTCB( pxTCB );
\r
1159 /* Reset the next expected unblock time in case it referred to
\r
1160 the task that has just been deleted. */
\r
1161 prvResetNextTaskUnblockTime();
\r
1164 traceTASK_DELETE( pxTCB );
\r
1166 taskEXIT_CRITICAL();
\r
1168 /* Force a reschedule if it is the currently running task that has just
\r
1170 if( xSchedulerRunning != pdFALSE )
\r
1172 if( pxTCB == pxCurrentTCB )
\r
1174 configASSERT( uxSchedulerSuspended == 0 );
\r
1175 portYIELD_WITHIN_API();
\r
1179 mtCOVERAGE_TEST_MARKER();
\r
1184 #endif /* INCLUDE_vTaskDelete */
\r
1185 /*-----------------------------------------------------------*/
\r
1187 #if ( INCLUDE_vTaskDelayUntil == 1 )
\r
1189 void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
\r
1191 TickType_t xTimeToWake;
\r
1192 BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
\r
1194 configASSERT( pxPreviousWakeTime );
\r
1195 configASSERT( ( xTimeIncrement > 0U ) );
\r
1196 configASSERT( uxSchedulerSuspended == 0 );
\r
1198 vTaskSuspendAll();
\r
1200 /* Minor optimisation. The tick count cannot change in this
\r
1202 const TickType_t xConstTickCount = xTickCount;
\r
1204 /* Generate the tick time at which the task wants to wake. */
\r
1205 xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
\r
1207 if( xConstTickCount < *pxPreviousWakeTime )
\r
1209 /* The tick count has overflowed since this function was
\r
1210 lasted called. In this case the only time we should ever
\r
1211 actually delay is if the wake time has also overflowed,
\r
1212 and the wake time is greater than the tick time. When this
\r
1213 is the case it is as if neither time had overflowed. */
\r
1214 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
\r
1216 xShouldDelay = pdTRUE;
\r
1220 mtCOVERAGE_TEST_MARKER();
\r
1225 /* The tick time has not overflowed. In this case we will
\r
1226 delay if either the wake time has overflowed, and/or the
\r
1227 tick time is less than the wake time. */
\r
1228 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
\r
1230 xShouldDelay = pdTRUE;
\r
1234 mtCOVERAGE_TEST_MARKER();
\r
1238 /* Update the wake time ready for the next call. */
\r
1239 *pxPreviousWakeTime = xTimeToWake;
\r
1241 if( xShouldDelay != pdFALSE )
\r
1243 traceTASK_DELAY_UNTIL( xTimeToWake );
\r
1245 /* prvAddCurrentTaskToDelayedList() needs the block time, not
\r
1246 the time to wake, so subtract the current tick count. */
\r
1247 prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE );
\r
1251 mtCOVERAGE_TEST_MARKER();
\r
1254 xAlreadyYielded = xTaskResumeAll();
\r
1256 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
1257 have put ourselves to sleep. */
\r
1258 if( xAlreadyYielded == pdFALSE )
\r
1260 portYIELD_WITHIN_API();
\r
1264 mtCOVERAGE_TEST_MARKER();
\r
1268 #endif /* INCLUDE_vTaskDelayUntil */
\r
1269 /*-----------------------------------------------------------*/
\r
1271 #if ( INCLUDE_vTaskDelay == 1 )
\r
1273 void vTaskDelay( const TickType_t xTicksToDelay )
\r
1275 BaseType_t xAlreadyYielded = pdFALSE;
\r
1277 /* A delay time of zero just forces a reschedule. */
\r
1278 if( xTicksToDelay > ( TickType_t ) 0U )
\r
1280 configASSERT( uxSchedulerSuspended == 0 );
\r
1281 vTaskSuspendAll();
\r
1283 traceTASK_DELAY();
\r
1285 /* A task that is removed from the event list while the
\r
1286 scheduler is suspended will not get placed in the ready
\r
1287 list or removed from the blocked list until the scheduler
\r
1290 This task cannot be in an event list as it is the currently
\r
1291 executing task. */
\r
1292 prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
\r
1294 xAlreadyYielded = xTaskResumeAll();
\r
1298 mtCOVERAGE_TEST_MARKER();
\r
1301 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
1302 have put ourselves to sleep. */
\r
1303 if( xAlreadyYielded == pdFALSE )
\r
1305 portYIELD_WITHIN_API();
\r
1309 mtCOVERAGE_TEST_MARKER();
\r
1313 #endif /* INCLUDE_vTaskDelay */
\r
1314 /*-----------------------------------------------------------*/
\r
1316 #if( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) )
\r
1318 eTaskState eTaskGetState( TaskHandle_t xTask )
\r
1320 eTaskState eReturn;
\r
1321 List_t *pxStateList;
\r
1322 const TCB_t * const pxTCB = ( TCB_t * ) xTask;
\r
1324 configASSERT( pxTCB );
\r
1326 if( pxTCB == pxCurrentTCB )
\r
1328 /* The task calling this function is querying its own state. */
\r
1329 eReturn = eRunning;
\r
1333 taskENTER_CRITICAL();
\r
1335 pxStateList = ( List_t * ) listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) );
\r
1337 taskEXIT_CRITICAL();
\r
1339 if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) )
\r
1341 /* The task being queried is referenced from one of the Blocked
\r
1343 eReturn = eBlocked;
\r
1346 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1347 else if( pxStateList == &xSuspendedTaskList )
\r
1349 /* The task being queried is referenced from the suspended
\r
1350 list. Is it genuinely suspended or is it block
\r
1352 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
\r
1354 eReturn = eSuspended;
\r
1358 eReturn = eBlocked;
\r
1363 #if ( INCLUDE_vTaskDelete == 1 )
\r
1364 else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) )
\r
1366 /* The task being queried is referenced from the deleted
\r
1367 tasks list, or it is not referenced from any lists at
\r
1369 eReturn = eDeleted;
\r
1373 else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */
\r
1375 /* If the task is not in any other state, it must be in the
\r
1376 Ready (including pending ready) state. */
\r
1382 } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
\r
1384 #endif /* INCLUDE_eTaskGetState */
\r
1385 /*-----------------------------------------------------------*/
\r
1387 #if ( INCLUDE_uxTaskPriorityGet == 1 )
\r
1389 UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask )
\r
1392 UBaseType_t uxReturn;
\r
1394 taskENTER_CRITICAL();
\r
1396 /* If null is passed in here then it is the priority of the that
\r
1397 called uxTaskPriorityGet() that is being queried. */
\r
1398 pxTCB = prvGetTCBFromHandle( xTask );
\r
1399 uxReturn = pxTCB->uxPriority;
\r
1401 taskEXIT_CRITICAL();
\r
1406 #endif /* INCLUDE_uxTaskPriorityGet */
\r
1407 /*-----------------------------------------------------------*/
\r
1409 #if ( INCLUDE_uxTaskPriorityGet == 1 )
\r
1411 UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask )
\r
1414 UBaseType_t uxReturn, uxSavedInterruptState;
\r
1416 /* RTOS ports that support interrupt nesting have the concept of a
\r
1417 maximum system call (or maximum API call) interrupt priority.
\r
1418 Interrupts that are above the maximum system call priority are keep
\r
1419 permanently enabled, even when the RTOS kernel is in a critical section,
\r
1420 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
1421 is defined in FreeRTOSConfig.h then
\r
1422 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1423 failure if a FreeRTOS API function is called from an interrupt that has
\r
1424 been assigned a priority above the configured maximum system call
\r
1425 priority. Only FreeRTOS functions that end in FromISR can be called
\r
1426 from interrupts that have been assigned a priority at or (logically)
\r
1427 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
1428 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
1429 simple as possible. More information (albeit Cortex-M specific) is
\r
1430 provided on the following link:
\r
1431 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1432 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1434 uxSavedInterruptState = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1436 /* If null is passed in here then it is the priority of the calling
\r
1437 task that is being queried. */
\r
1438 pxTCB = prvGetTCBFromHandle( xTask );
\r
1439 uxReturn = pxTCB->uxPriority;
\r
1441 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState );
\r
1446 #endif /* INCLUDE_uxTaskPriorityGet */
\r
1447 /*-----------------------------------------------------------*/
\r
1449 #if ( INCLUDE_vTaskPrioritySet == 1 )
\r
1451 void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )
\r
1454 UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;
\r
1455 BaseType_t xYieldRequired = pdFALSE;
\r
1457 configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
\r
1459 /* Ensure the new priority is valid. */
\r
1460 if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
\r
1462 uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
\r
1466 mtCOVERAGE_TEST_MARKER();
\r
1469 taskENTER_CRITICAL();
\r
1471 /* If null is passed in here then it is the priority of the calling
\r
1472 task that is being changed. */
\r
1473 pxTCB = prvGetTCBFromHandle( xTask );
\r
1475 traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
\r
1477 #if ( configUSE_MUTEXES == 1 )
\r
1479 uxCurrentBasePriority = pxTCB->uxBasePriority;
\r
1483 uxCurrentBasePriority = pxTCB->uxPriority;
\r
1487 if( uxCurrentBasePriority != uxNewPriority )
\r
1489 /* The priority change may have readied a task of higher
\r
1490 priority than the calling task. */
\r
1491 if( uxNewPriority > uxCurrentBasePriority )
\r
1493 if( pxTCB != pxCurrentTCB )
\r
1495 /* The priority of a task other than the currently
\r
1496 running task is being raised. Is the priority being
\r
1497 raised above that of the running task? */
\r
1498 if( uxNewPriority >= pxCurrentTCB->uxPriority )
\r
1500 xYieldRequired = pdTRUE;
\r
1504 mtCOVERAGE_TEST_MARKER();
\r
1509 /* The priority of the running task is being raised,
\r
1510 but the running task must already be the highest
\r
1511 priority task able to run so no yield is required. */
\r
1514 else if( pxTCB == pxCurrentTCB )
\r
1516 /* Setting the priority of the running task down means
\r
1517 there may now be another task of higher priority that
\r
1518 is ready to execute. */
\r
1519 xYieldRequired = pdTRUE;
\r
1523 /* Setting the priority of any other task down does not
\r
1524 require a yield as the running task must be above the
\r
1525 new priority of the task being modified. */
\r
1528 /* Remember the ready list the task might be referenced from
\r
1529 before its uxPriority member is changed so the
\r
1530 taskRESET_READY_PRIORITY() macro can function correctly. */
\r
1531 uxPriorityUsedOnEntry = pxTCB->uxPriority;
\r
1533 #if ( configUSE_MUTEXES == 1 )
\r
1535 /* Only change the priority being used if the task is not
\r
1536 currently using an inherited priority. */
\r
1537 if( pxTCB->uxBasePriority == pxTCB->uxPriority )
\r
1539 pxTCB->uxPriority = uxNewPriority;
\r
1543 mtCOVERAGE_TEST_MARKER();
\r
1546 /* The base priority gets set whatever. */
\r
1547 pxTCB->uxBasePriority = uxNewPriority;
\r
1551 pxTCB->uxPriority = uxNewPriority;
\r
1555 /* Only reset the event list item value if the value is not
\r
1556 being used for anything else. */
\r
1557 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
\r
1559 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
1563 mtCOVERAGE_TEST_MARKER();
\r
1566 /* If the task is in the blocked or suspended list we need do
\r
1567 nothing more than change it's priority variable. However, if
\r
1568 the task is in a ready list it needs to be removed and placed
\r
1569 in the list appropriate to its new priority. */
\r
1570 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
\r
1572 /* The task is currently in its ready list - remove before adding
\r
1573 it to it's new ready list. As we are in a critical section we
\r
1574 can do this even if the scheduler is suspended. */
\r
1575 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
1577 /* It is known that the task is in its ready list so
\r
1578 there is no need to check again and the port level
\r
1579 reset macro can be called directly. */
\r
1580 portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
\r
1584 mtCOVERAGE_TEST_MARKER();
\r
1586 prvAddTaskToReadyList( pxTCB );
\r
1590 mtCOVERAGE_TEST_MARKER();
\r
1593 if( xYieldRequired != pdFALSE )
\r
1595 taskYIELD_IF_USING_PREEMPTION();
\r
1599 mtCOVERAGE_TEST_MARKER();
\r
1602 /* Remove compiler warning about unused variables when the port
\r
1603 optimised task selection is not being used. */
\r
1604 ( void ) uxPriorityUsedOnEntry;
\r
1607 taskEXIT_CRITICAL();
\r
1610 #endif /* INCLUDE_vTaskPrioritySet */
\r
1611 /*-----------------------------------------------------------*/
\r
1613 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1615 void vTaskSuspend( TaskHandle_t xTaskToSuspend )
\r
1619 taskENTER_CRITICAL();
\r
1621 /* If null is passed in here then it is the running task that is
\r
1622 being suspended. */
\r
1623 pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
\r
1625 traceTASK_SUSPEND( pxTCB );
\r
1627 /* Remove task from the ready/delayed list and place in the
\r
1628 suspended list. */
\r
1629 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
1631 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
1635 mtCOVERAGE_TEST_MARKER();
\r
1638 /* Is the task waiting on an event also? */
\r
1639 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
1641 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1645 mtCOVERAGE_TEST_MARKER();
\r
1648 vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
\r
1650 taskEXIT_CRITICAL();
\r
1652 if( xSchedulerRunning != pdFALSE )
\r
1654 /* Reset the next expected unblock time in case it referred to the
\r
1655 task that is now in the Suspended state. */
\r
1656 taskENTER_CRITICAL();
\r
1658 prvResetNextTaskUnblockTime();
\r
1660 taskEXIT_CRITICAL();
\r
1664 mtCOVERAGE_TEST_MARKER();
\r
1667 if( pxTCB == pxCurrentTCB )
\r
1669 if( xSchedulerRunning != pdFALSE )
\r
1671 /* The current task has just been suspended. */
\r
1672 configASSERT( uxSchedulerSuspended == 0 );
\r
1673 portYIELD_WITHIN_API();
\r
1677 /* The scheduler is not running, but the task that was pointed
\r
1678 to by pxCurrentTCB has just been suspended and pxCurrentTCB
\r
1679 must be adjusted to point to a different task. */
\r
1680 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )
\r
1682 /* No other tasks are ready, so set pxCurrentTCB back to
\r
1683 NULL so when the next task is created pxCurrentTCB will
\r
1684 be set to point to it no matter what its relative priority
\r
1686 pxCurrentTCB = NULL;
\r
1690 vTaskSwitchContext();
\r
1696 mtCOVERAGE_TEST_MARKER();
\r
1700 #endif /* INCLUDE_vTaskSuspend */
\r
1701 /*-----------------------------------------------------------*/
\r
1703 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1705 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
\r
1707 BaseType_t xReturn = pdFALSE;
\r
1708 const TCB_t * const pxTCB = ( TCB_t * ) xTask;
\r
1710 /* Accesses xPendingReadyList so must be called from a critical
\r
1713 /* It does not make sense to check if the calling task is suspended. */
\r
1714 configASSERT( xTask );
\r
1716 /* Is the task being resumed actually in the suspended list? */
\r
1717 if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE )
\r
1719 /* Has the task already been resumed from within an ISR? */
\r
1720 if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
\r
1722 /* Is it in the suspended list because it is in the Suspended
\r
1723 state, or because is is blocked with no timeout? */
\r
1724 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) /*lint !e961. The cast is only redundant when NULL is used. */
\r
1730 mtCOVERAGE_TEST_MARKER();
\r
1735 mtCOVERAGE_TEST_MARKER();
\r
1740 mtCOVERAGE_TEST_MARKER();
\r
1744 } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
\r
1746 #endif /* INCLUDE_vTaskSuspend */
\r
1747 /*-----------------------------------------------------------*/
\r
1749 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1751 void vTaskResume( TaskHandle_t xTaskToResume )
\r
1753 TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
\r
1755 /* It does not make sense to resume the calling task. */
\r
1756 configASSERT( xTaskToResume );
\r
1758 /* The parameter cannot be NULL as it is impossible to resume the
\r
1759 currently executing task. */
\r
1760 if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
\r
1762 taskENTER_CRITICAL();
\r
1764 if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
\r
1766 traceTASK_RESUME( pxTCB );
\r
1768 /* As we are in a critical section we can access the ready
\r
1769 lists even if the scheduler is suspended. */
\r
1770 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
1771 prvAddTaskToReadyList( pxTCB );
\r
1773 /* We may have just resumed a higher priority task. */
\r
1774 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1776 /* This yield may not cause the task just resumed to run,
\r
1777 but will leave the lists in the correct state for the
\r
1779 taskYIELD_IF_USING_PREEMPTION();
\r
1783 mtCOVERAGE_TEST_MARKER();
\r
1788 mtCOVERAGE_TEST_MARKER();
\r
1791 taskEXIT_CRITICAL();
\r
1795 mtCOVERAGE_TEST_MARKER();
\r
1799 #endif /* INCLUDE_vTaskSuspend */
\r
1801 /*-----------------------------------------------------------*/
\r
1803 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
\r
1805 BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
\r
1807 BaseType_t xYieldRequired = pdFALSE;
\r
1808 TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
\r
1809 UBaseType_t uxSavedInterruptStatus;
\r
1811 configASSERT( xTaskToResume );
\r
1813 /* RTOS ports that support interrupt nesting have the concept of a
\r
1814 maximum system call (or maximum API call) interrupt priority.
\r
1815 Interrupts that are above the maximum system call priority are keep
\r
1816 permanently enabled, even when the RTOS kernel is in a critical section,
\r
1817 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
1818 is defined in FreeRTOSConfig.h then
\r
1819 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1820 failure if a FreeRTOS API function is called from an interrupt that has
\r
1821 been assigned a priority above the configured maximum system call
\r
1822 priority. Only FreeRTOS functions that end in FromISR can be called
\r
1823 from interrupts that have been assigned a priority at or (logically)
\r
1824 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
1825 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
1826 simple as possible. More information (albeit Cortex-M specific) is
\r
1827 provided on the following link:
\r
1828 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1829 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1831 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1833 if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
\r
1835 traceTASK_RESUME_FROM_ISR( pxTCB );
\r
1837 /* Check the ready lists can be accessed. */
\r
1838 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
1840 /* Ready lists can be accessed so move the task from the
\r
1841 suspended list to the ready list directly. */
\r
1842 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1844 xYieldRequired = pdTRUE;
\r
1848 mtCOVERAGE_TEST_MARKER();
\r
1851 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
1852 prvAddTaskToReadyList( pxTCB );
\r
1856 /* The delayed or ready lists cannot be accessed so the task
\r
1857 is held in the pending ready list until the scheduler is
\r
1859 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
1864 mtCOVERAGE_TEST_MARKER();
\r
1867 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1869 return xYieldRequired;
\r
1872 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
\r
1873 /*-----------------------------------------------------------*/
\r
1875 void vTaskStartScheduler( void )
\r
1877 BaseType_t xReturn;
\r
1879 /* Add the idle task at the lowest priority. */
\r
1880 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
1882 StaticTask_t *pxIdleTaskTCBBuffer = NULL;
\r
1883 StackType_t *pxIdleTaskStackBuffer = NULL;
\r
1884 uint32_t ulIdleTaskStackSize;
\r
1886 /* The Idle task is created using user provided RAM - obtain the
\r
1887 address of the RAM then create the idle task. */
\r
1888 vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );
\r
1889 xIdleTaskHandle = xTaskCreateStatic( prvIdleTask,
\r
1891 ulIdleTaskStackSize,
\r
1892 ( void * ) NULL, /*lint !e961. The cast is not redundant for all compilers. */
\r
1893 ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),
\r
1894 pxIdleTaskStackBuffer,
\r
1895 pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
\r
1897 if( xIdleTaskHandle != NULL )
\r
1908 /* The Idle task is being created using dynamically allocated RAM. */
\r
1909 xReturn = xTaskCreate( prvIdleTask,
\r
1910 "IDLE", configMINIMAL_STACK_SIZE,
\r
1912 ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),
\r
1913 &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
\r
1915 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
1917 #if ( configUSE_TIMERS == 1 )
\r
1919 if( xReturn == pdPASS )
\r
1921 xReturn = xTimerCreateTimerTask();
\r
1925 mtCOVERAGE_TEST_MARKER();
\r
1928 #endif /* configUSE_TIMERS */
\r
1930 if( xReturn == pdPASS )
\r
1932 /* freertos_tasks_c_additions_init() should only be called if the user
\r
1933 definable macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is
\r
1934 the only macro called by the function. */
\r
1935 #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
\r
1937 freertos_tasks_c_additions_init();
\r
1941 /* Interrupts are turned off here, to ensure a tick does not occur
\r
1942 before or during the call to xPortStartScheduler(). The stacks of
\r
1943 the created tasks contain a status word with interrupts switched on
\r
1944 so interrupts will automatically get re-enabled when the first task
\r
1946 portDISABLE_INTERRUPTS();
\r
1948 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
1950 /* Switch Newlib's _impure_ptr variable to point to the _reent
\r
1951 structure specific to the task that will run first. */
\r
1952 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
\r
1954 #endif /* configUSE_NEWLIB_REENTRANT */
\r
1956 xNextTaskUnblockTime = portMAX_DELAY;
\r
1957 xSchedulerRunning = pdTRUE;
\r
1958 xTickCount = ( TickType_t ) 0U;
\r
1960 /* If configGENERATE_RUN_TIME_STATS is defined then the following
\r
1961 macro must be defined to configure the timer/counter used to generate
\r
1962 the run time counter time base. NOTE: If configGENERATE_RUN_TIME_STATS
\r
1963 is set to 0 and the following line fails to build then ensure you do not
\r
1964 have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your
\r
1965 FreeRTOSConfig.h file. */
\r
1966 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
\r
1968 /* Setting up the timer tick is hardware specific and thus in the
\r
1969 portable interface. */
\r
1970 if( xPortStartScheduler() != pdFALSE )
\r
1972 /* Should not reach here as if the scheduler is running the
\r
1973 function will not return. */
\r
1977 /* Should only reach here if a task calls xTaskEndScheduler(). */
\r
1982 /* This line will only be reached if the kernel could not be started,
\r
1983 because there was not enough FreeRTOS heap to create the idle task
\r
1984 or the timer task. */
\r
1985 configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );
\r
1988 /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,
\r
1989 meaning xIdleTaskHandle is not used anywhere else. */
\r
1990 ( void ) xIdleTaskHandle;
\r
1992 /*-----------------------------------------------------------*/
\r
1994 void vTaskEndScheduler( void )
\r
1996 /* Stop the scheduler interrupts and call the portable scheduler end
\r
1997 routine so the original ISRs can be restored if necessary. The port
\r
1998 layer must ensure interrupts enable bit is left in the correct state. */
\r
1999 portDISABLE_INTERRUPTS();
\r
2000 xSchedulerRunning = pdFALSE;
\r
2001 vPortEndScheduler();
\r
2003 /*----------------------------------------------------------*/
\r
2005 void vTaskSuspendAll( void )
\r
2007 /* A critical section is not required as the variable is of type
\r
2008 BaseType_t. Please read Richard Barry's reply in the following link to a
\r
2009 post in the FreeRTOS support forum before reporting this as a bug! -
\r
2010 http://goo.gl/wu4acr */
\r
2011 ++uxSchedulerSuspended;
\r
2013 /*----------------------------------------------------------*/
\r
2015 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
2017 static TickType_t prvGetExpectedIdleTime( void )
\r
2019 TickType_t xReturn;
\r
2020 UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;
\r
2022 /* uxHigherPriorityReadyTasks takes care of the case where
\r
2023 configUSE_PREEMPTION is 0, so there may be tasks above the idle priority
\r
2024 task that are in the Ready state, even though the idle task is
\r
2026 #if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
\r
2028 if( uxTopReadyPriority > tskIDLE_PRIORITY )
\r
2030 uxHigherPriorityReadyTasks = pdTRUE;
\r
2035 const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;
\r
2037 /* When port optimised task selection is used the uxTopReadyPriority
\r
2038 variable is used as a bit map. If bits other than the least
\r
2039 significant bit are set then there are tasks that have a priority
\r
2040 above the idle priority that are in the Ready state. This takes
\r
2041 care of the case where the co-operative scheduler is in use. */
\r
2042 if( uxTopReadyPriority > uxLeastSignificantBit )
\r
2044 uxHigherPriorityReadyTasks = pdTRUE;
\r
2049 if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
\r
2053 else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
\r
2055 /* There are other idle priority tasks in the ready state. If
\r
2056 time slicing is used then the very next tick interrupt must be
\r
2060 else if( uxHigherPriorityReadyTasks != pdFALSE )
\r
2062 /* There are tasks in the Ready state that have a priority above the
\r
2063 idle priority. This path can only be reached if
\r
2064 configUSE_PREEMPTION is 0. */
\r
2069 xReturn = xNextTaskUnblockTime - xTickCount;
\r
2075 #endif /* configUSE_TICKLESS_IDLE */
\r
2076 /*----------------------------------------------------------*/
\r
2078 BaseType_t xTaskResumeAll( void )
\r
2080 TCB_t *pxTCB = NULL;
\r
2081 BaseType_t xAlreadyYielded = pdFALSE;
\r
2083 /* If uxSchedulerSuspended is zero then this function does not match a
\r
2084 previous call to vTaskSuspendAll(). */
\r
2085 configASSERT( uxSchedulerSuspended );
\r
2087 /* It is possible that an ISR caused a task to be removed from an event
\r
2088 list while the scheduler was suspended. If this was the case then the
\r
2089 removed task will have been added to the xPendingReadyList. Once the
\r
2090 scheduler has been resumed it is safe to move all the pending ready
\r
2091 tasks from this list into their appropriate ready list. */
\r
2092 taskENTER_CRITICAL();
\r
2094 --uxSchedulerSuspended;
\r
2096 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
2098 if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )
\r
2100 /* Move any readied tasks from the pending list into the
\r
2101 appropriate ready list. */
\r
2102 while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
\r
2104 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );
\r
2105 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
2106 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
2107 prvAddTaskToReadyList( pxTCB );
\r
2109 /* If the moved task has a priority higher than the current
\r
2110 task then a yield must be performed. */
\r
2111 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
2113 xYieldPending = pdTRUE;
\r
2117 mtCOVERAGE_TEST_MARKER();
\r
2121 if( pxTCB != NULL )
\r
2123 /* A task was unblocked while the scheduler was suspended,
\r
2124 which may have prevented the next unblock time from being
\r
2125 re-calculated, in which case re-calculate it now. Mainly
\r
2126 important for low power tickless implementations, where
\r
2127 this can prevent an unnecessary exit from low power
\r
2129 prvResetNextTaskUnblockTime();
\r
2132 /* If any ticks occurred while the scheduler was suspended then
\r
2133 they should be processed now. This ensures the tick count does
\r
2134 not slip, and that any delayed tasks are resumed at the correct
\r
2137 UBaseType_t uxPendedCounts = uxPendedTicks; /* Non-volatile copy. */
\r
2139 if( uxPendedCounts > ( UBaseType_t ) 0U )
\r
2143 if( xTaskIncrementTick() != pdFALSE )
\r
2145 xYieldPending = pdTRUE;
\r
2149 mtCOVERAGE_TEST_MARKER();
\r
2152 } while( uxPendedCounts > ( UBaseType_t ) 0U );
\r
2154 uxPendedTicks = 0;
\r
2158 mtCOVERAGE_TEST_MARKER();
\r
2162 if( xYieldPending != pdFALSE )
\r
2164 #if( configUSE_PREEMPTION != 0 )
\r
2166 xAlreadyYielded = pdTRUE;
\r
2169 taskYIELD_IF_USING_PREEMPTION();
\r
2173 mtCOVERAGE_TEST_MARKER();
\r
2179 mtCOVERAGE_TEST_MARKER();
\r
2182 taskEXIT_CRITICAL();
\r
2184 return xAlreadyYielded;
\r
2186 /*-----------------------------------------------------------*/
\r
2188 TickType_t xTaskGetTickCount( void )
\r
2190 TickType_t xTicks;
\r
2192 /* Critical section required if running on a 16 bit processor. */
\r
2193 portTICK_TYPE_ENTER_CRITICAL();
\r
2195 xTicks = xTickCount;
\r
2197 portTICK_TYPE_EXIT_CRITICAL();
\r
2201 /*-----------------------------------------------------------*/
\r
2203 TickType_t xTaskGetTickCountFromISR( void )
\r
2205 TickType_t xReturn;
\r
2206 UBaseType_t uxSavedInterruptStatus;
\r
2208 /* RTOS ports that support interrupt nesting have the concept of a maximum
\r
2209 system call (or maximum API call) interrupt priority. Interrupts that are
\r
2210 above the maximum system call priority are kept permanently enabled, even
\r
2211 when the RTOS kernel is in a critical section, but cannot make any calls to
\r
2212 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
\r
2213 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
2214 failure if a FreeRTOS API function is called from an interrupt that has been
\r
2215 assigned a priority above the configured maximum system call priority.
\r
2216 Only FreeRTOS functions that end in FromISR can be called from interrupts
\r
2217 that have been assigned a priority at or (logically) below the maximum
\r
2218 system call interrupt priority. FreeRTOS maintains a separate interrupt
\r
2219 safe API to ensure interrupt entry is as fast and as simple as possible.
\r
2220 More information (albeit Cortex-M specific) is provided on the following
\r
2221 link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
2222 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
2224 uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR();
\r
2226 xReturn = xTickCount;
\r
2228 portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
2232 /*-----------------------------------------------------------*/
\r
2234 UBaseType_t uxTaskGetNumberOfTasks( void )
\r
2236 /* A critical section is not required because the variables are of type
\r
2238 return uxCurrentNumberOfTasks;
\r
2240 /*-----------------------------------------------------------*/
\r
2242 char *pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
2246 /* If null is passed in here then the name of the calling task is being
\r
2248 pxTCB = prvGetTCBFromHandle( xTaskToQuery );
\r
2249 configASSERT( pxTCB );
\r
2250 return &( pxTCB->pcTaskName[ 0 ] );
\r
2252 /*-----------------------------------------------------------*/
\r
2254 #if ( INCLUDE_xTaskGetHandle == 1 )
\r
2256 static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] )
\r
2258 TCB_t *pxNextTCB, *pxFirstTCB, *pxReturn = NULL;
\r
2262 /* This function is called with the scheduler suspended. */
\r
2264 if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
\r
2266 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
\r
2270 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
\r
2272 /* Check each character in the name looking for a match or
\r
2274 for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
\r
2276 cNextChar = pxNextTCB->pcTaskName[ x ];
\r
2278 if( cNextChar != pcNameToQuery[ x ] )
\r
2280 /* Characters didn't match. */
\r
2283 else if( cNextChar == 0x00 )
\r
2285 /* Both strings terminated, a match must have been
\r
2287 pxReturn = pxNextTCB;
\r
2292 mtCOVERAGE_TEST_MARKER();
\r
2296 if( pxReturn != NULL )
\r
2298 /* The handle has been found. */
\r
2302 } while( pxNextTCB != pxFirstTCB );
\r
2306 mtCOVERAGE_TEST_MARKER();
\r
2312 #endif /* INCLUDE_xTaskGetHandle */
\r
2313 /*-----------------------------------------------------------*/
\r
2315 #if ( INCLUDE_xTaskGetHandle == 1 )
\r
2317 TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
2319 UBaseType_t uxQueue = configMAX_PRIORITIES;
\r
2322 /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */
\r
2323 configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN );
\r
2325 vTaskSuspendAll();
\r
2327 /* Search the ready lists. */
\r
2331 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery );
\r
2333 if( pxTCB != NULL )
\r
2335 /* Found the handle. */
\r
2339 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2341 /* Search the delayed lists. */
\r
2342 if( pxTCB == NULL )
\r
2344 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery );
\r
2347 if( pxTCB == NULL )
\r
2349 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery );
\r
2352 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2354 if( pxTCB == NULL )
\r
2356 /* Search the suspended list. */
\r
2357 pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery );
\r
2362 #if( INCLUDE_vTaskDelete == 1 )
\r
2364 if( pxTCB == NULL )
\r
2366 /* Search the deleted list. */
\r
2367 pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery );
\r
2372 ( void ) xTaskResumeAll();
\r
2374 return ( TaskHandle_t ) pxTCB;
\r
2377 #endif /* INCLUDE_xTaskGetHandle */
\r
2378 /*-----------------------------------------------------------*/
\r
2380 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2382 UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime )
\r
2384 UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
\r
2386 vTaskSuspendAll();
\r
2388 /* Is there a space in the array for each task in the system? */
\r
2389 if( uxArraySize >= uxCurrentNumberOfTasks )
\r
2391 /* Fill in an TaskStatus_t structure with information on each
\r
2392 task in the Ready state. */
\r
2396 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
\r
2398 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2400 /* Fill in an TaskStatus_t structure with information on each
\r
2401 task in the Blocked state. */
\r
2402 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );
\r
2403 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );
\r
2405 #if( INCLUDE_vTaskDelete == 1 )
\r
2407 /* Fill in an TaskStatus_t structure with information on
\r
2408 each task that has been deleted but not yet cleaned up. */
\r
2409 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
\r
2413 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2415 /* Fill in an TaskStatus_t structure with information on
\r
2416 each task in the Suspended state. */
\r
2417 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
\r
2421 #if ( configGENERATE_RUN_TIME_STATS == 1)
\r
2423 if( pulTotalRunTime != NULL )
\r
2425 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
2426 portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
\r
2428 *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
2434 if( pulTotalRunTime != NULL )
\r
2436 *pulTotalRunTime = 0;
\r
2443 mtCOVERAGE_TEST_MARKER();
\r
2446 ( void ) xTaskResumeAll();
\r
2451 #endif /* configUSE_TRACE_FACILITY */
\r
2452 /*----------------------------------------------------------*/
\r
2454 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
2456 TaskHandle_t xTaskGetIdleTaskHandle( void )
\r
2458 /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
\r
2459 started, then xIdleTaskHandle will be NULL. */
\r
2460 configASSERT( ( xIdleTaskHandle != NULL ) );
\r
2461 return xIdleTaskHandle;
\r
2464 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
\r
2465 /*----------------------------------------------------------*/
\r
2467 /* This conditional compilation should use inequality to 0, not equality to 1.
\r
2468 This is to ensure vTaskStepTick() is available when user defined low power mode
\r
2469 implementations require configUSE_TICKLESS_IDLE to be set to a value other than
\r
2471 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
2473 void vTaskStepTick( const TickType_t xTicksToJump )
\r
2475 /* Correct the tick count value after a period during which the tick
\r
2476 was suppressed. Note this does *not* call the tick hook function for
\r
2477 each stepped tick. */
\r
2478 configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
\r
2479 xTickCount += xTicksToJump;
\r
2480 traceINCREASE_TICK_COUNT( xTicksToJump );
\r
2483 #endif /* configUSE_TICKLESS_IDLE */
\r
2484 /*----------------------------------------------------------*/
\r
2486 #if ( INCLUDE_xTaskAbortDelay == 1 )
\r
2488 BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
\r
2490 TCB_t *pxTCB = ( TCB_t * ) xTask;
\r
2491 BaseType_t xReturn = pdFALSE;
\r
2493 configASSERT( pxTCB );
\r
2495 vTaskSuspendAll();
\r
2497 /* A task can only be prematurely removed from the Blocked state if
\r
2498 it is actually in the Blocked state. */
\r
2499 if( eTaskGetState( xTask ) == eBlocked )
\r
2501 /* Remove the reference to the task from the blocked list. An
\r
2502 interrupt won't touch the xStateListItem because the
\r
2503 scheduler is suspended. */
\r
2504 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
2506 /* Is the task waiting on an event also? If so remove it from
\r
2507 the event list too. Interrupts can touch the event list item,
\r
2508 even though the scheduler is suspended, so a critical section
\r
2510 taskENTER_CRITICAL();
\r
2512 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
2514 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
2515 pxTCB->ucDelayAborted = pdTRUE;
\r
2519 mtCOVERAGE_TEST_MARKER();
\r
2522 taskEXIT_CRITICAL();
\r
2524 /* Place the unblocked task into the appropriate ready list. */
\r
2525 prvAddTaskToReadyList( pxTCB );
\r
2527 /* A task being unblocked cannot cause an immediate context
\r
2528 switch if preemption is turned off. */
\r
2529 #if ( configUSE_PREEMPTION == 1 )
\r
2531 /* Preemption is on, but a context switch should only be
\r
2532 performed if the unblocked task has a priority that is
\r
2533 equal to or higher than the currently executing task. */
\r
2534 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
2536 /* Pend the yield to be performed when the scheduler
\r
2537 is unsuspended. */
\r
2538 xYieldPending = pdTRUE;
\r
2542 mtCOVERAGE_TEST_MARKER();
\r
2545 #endif /* configUSE_PREEMPTION */
\r
2549 mtCOVERAGE_TEST_MARKER();
\r
2552 ( void ) xTaskResumeAll();
\r
2557 #endif /* INCLUDE_xTaskAbortDelay */
\r
2558 /*----------------------------------------------------------*/
\r
2560 BaseType_t xTaskIncrementTick( void )
\r
2563 TickType_t xItemValue;
\r
2564 BaseType_t xSwitchRequired = pdFALSE;
\r
2566 /* Called by the portable layer each time a tick interrupt occurs.
\r
2567 Increments the tick then checks to see if the new tick value will cause any
\r
2568 tasks to be unblocked. */
\r
2569 traceTASK_INCREMENT_TICK( xTickCount );
\r
2570 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
2572 /* Minor optimisation. The tick count cannot change in this
\r
2574 const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
\r
2576 /* Increment the RTOS tick, switching the delayed and overflowed
\r
2577 delayed lists if it wraps to 0. */
\r
2578 xTickCount = xConstTickCount;
\r
2580 if( xConstTickCount == ( TickType_t ) 0U ) /*lint !e774 'if' does not always evaluate to false as it is looking for an overflow. */
\r
2582 taskSWITCH_DELAYED_LISTS();
\r
2586 mtCOVERAGE_TEST_MARKER();
\r
2589 /* See if this tick has made a timeout expire. Tasks are stored in
\r
2590 the queue in the order of their wake time - meaning once one task
\r
2591 has been found whose block time has not expired there is no need to
\r
2592 look any further down the list. */
\r
2593 if( xConstTickCount >= xNextTaskUnblockTime )
\r
2597 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
\r
2599 /* The delayed list is empty. Set xNextTaskUnblockTime
\r
2600 to the maximum possible value so it is extremely
\r
2602 if( xTickCount >= xNextTaskUnblockTime ) test will pass
\r
2603 next time through. */
\r
2604 xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2609 /* The delayed list is not empty, get the value of the
\r
2610 item at the head of the delayed list. This is the time
\r
2611 at which the task at the head of the delayed list must
\r
2612 be removed from the Blocked state. */
\r
2613 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
\r
2614 xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );
\r
2616 if( xConstTickCount < xItemValue )
\r
2618 /* It is not time to unblock this item yet, but the
\r
2619 item value is the time at which the task at the head
\r
2620 of the blocked list must be removed from the Blocked
\r
2621 state - so record the item value in
\r
2622 xNextTaskUnblockTime. */
\r
2623 xNextTaskUnblockTime = xItemValue;
\r
2628 mtCOVERAGE_TEST_MARKER();
\r
2631 /* It is time to remove the item from the Blocked state. */
\r
2632 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
2634 /* Is the task waiting on an event also? If so remove
\r
2635 it from the event list. */
\r
2636 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
2638 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
2642 mtCOVERAGE_TEST_MARKER();
\r
2645 /* Place the unblocked task into the appropriate ready
\r
2647 prvAddTaskToReadyList( pxTCB );
\r
2649 /* A task being unblocked cannot cause an immediate
\r
2650 context switch if preemption is turned off. */
\r
2651 #if ( configUSE_PREEMPTION == 1 )
\r
2653 /* Preemption is on, but a context switch should
\r
2654 only be performed if the unblocked task has a
\r
2655 priority that is equal to or higher than the
\r
2656 currently executing task. */
\r
2657 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
2659 xSwitchRequired = pdTRUE;
\r
2663 mtCOVERAGE_TEST_MARKER();
\r
2666 #endif /* configUSE_PREEMPTION */
\r
2671 /* Tasks of equal priority to the currently running task will share
\r
2672 processing time (time slice) if preemption is on, and the application
\r
2673 writer has not explicitly turned time slicing off. */
\r
2674 #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
\r
2676 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )
\r
2678 xSwitchRequired = pdTRUE;
\r
2682 mtCOVERAGE_TEST_MARKER();
\r
2685 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
\r
2687 #if ( configUSE_TICK_HOOK == 1 )
\r
2689 /* Guard against the tick hook being called when the pended tick
\r
2690 count is being unwound (when the scheduler is being unlocked). */
\r
2691 if( uxPendedTicks == ( UBaseType_t ) 0U )
\r
2693 vApplicationTickHook();
\r
2697 mtCOVERAGE_TEST_MARKER();
\r
2700 #endif /* configUSE_TICK_HOOK */
\r
2706 /* The tick hook gets called at regular intervals, even if the
\r
2707 scheduler is locked. */
\r
2708 #if ( configUSE_TICK_HOOK == 1 )
\r
2710 vApplicationTickHook();
\r
2715 #if ( configUSE_PREEMPTION == 1 )
\r
2717 if( xYieldPending != pdFALSE )
\r
2719 xSwitchRequired = pdTRUE;
\r
2723 mtCOVERAGE_TEST_MARKER();
\r
2726 #endif /* configUSE_PREEMPTION */
\r
2728 return xSwitchRequired;
\r
2730 /*-----------------------------------------------------------*/
\r
2732 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2734 void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction )
\r
2738 /* If xTask is NULL then it is the task hook of the calling task that is
\r
2740 if( xTask == NULL )
\r
2742 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2746 xTCB = ( TCB_t * ) xTask;
\r
2749 /* Save the hook function in the TCB. A critical section is required as
\r
2750 the value can be accessed from an interrupt. */
\r
2751 taskENTER_CRITICAL();
\r
2752 xTCB->pxTaskTag = pxHookFunction;
\r
2753 taskEXIT_CRITICAL();
\r
2756 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2757 /*-----------------------------------------------------------*/
\r
2759 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2761 TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
\r
2764 TaskHookFunction_t xReturn;
\r
2766 /* If xTask is NULL then we are setting our own task hook. */
\r
2767 if( xTask == NULL )
\r
2769 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2773 xTCB = ( TCB_t * ) xTask;
\r
2776 /* Save the hook function in the TCB. A critical section is required as
\r
2777 the value can be accessed from an interrupt. */
\r
2778 taskENTER_CRITICAL();
\r
2780 xReturn = xTCB->pxTaskTag;
\r
2782 taskEXIT_CRITICAL();
\r
2787 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2788 /*-----------------------------------------------------------*/
\r
2790 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2792 BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter )
\r
2795 BaseType_t xReturn;
\r
2797 /* If xTask is NULL then we are calling our own task hook. */
\r
2798 if( xTask == NULL )
\r
2800 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2804 xTCB = ( TCB_t * ) xTask;
\r
2807 if( xTCB->pxTaskTag != NULL )
\r
2809 xReturn = xTCB->pxTaskTag( pvParameter );
\r
2819 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2820 /*-----------------------------------------------------------*/
\r
2822 void vTaskSwitchContext( void )
\r
2824 if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )
\r
2826 /* The scheduler is currently suspended - do not allow a context
\r
2828 xYieldPending = pdTRUE;
\r
2832 xYieldPending = pdFALSE;
\r
2833 traceTASK_SWITCHED_OUT();
\r
2835 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
2837 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
2838 portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
\r
2840 ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
2843 /* Add the amount of time the task has been running to the
\r
2844 accumulated time so far. The time the task started running was
\r
2845 stored in ulTaskSwitchedInTime. Note that there is no overflow
\r
2846 protection here so count values are only valid until the timer
\r
2847 overflows. The guard against negative values is to protect
\r
2848 against suspect run time stat counter implementations - which
\r
2849 are provided by the application, not the kernel. */
\r
2850 if( ulTotalRunTime > ulTaskSwitchedInTime )
\r
2852 pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
\r
2856 mtCOVERAGE_TEST_MARKER();
\r
2858 ulTaskSwitchedInTime = ulTotalRunTime;
\r
2860 #endif /* configGENERATE_RUN_TIME_STATS */
\r
2862 /* Check for stack overflow, if configured. */
\r
2863 taskCHECK_FOR_STACK_OVERFLOW();
\r
2865 /* Select a new task to run using either the generic C or port
\r
2866 optimised asm code. */
\r
2867 taskSELECT_HIGHEST_PRIORITY_TASK();
\r
2868 traceTASK_SWITCHED_IN();
\r
2870 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
2872 /* Switch Newlib's _impure_ptr variable to point to the _reent
\r
2873 structure specific to this task. */
\r
2874 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
\r
2876 #endif /* configUSE_NEWLIB_REENTRANT */
\r
2879 /*-----------------------------------------------------------*/
\r
2881 void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )
\r
2883 configASSERT( pxEventList );
\r
2885 /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
\r
2886 SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
\r
2888 /* Place the event list item of the TCB in the appropriate event list.
\r
2889 This is placed in the list in priority order so the highest priority task
\r
2890 is the first to be woken by the event. The queue that contains the event
\r
2891 list is locked, preventing simultaneous access from interrupts. */
\r
2892 vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2894 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
\r
2896 /*-----------------------------------------------------------*/
\r
2898 void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait )
\r
2900 configASSERT( pxEventList );
\r
2902 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
\r
2903 the event groups implementation. */
\r
2904 configASSERT( uxSchedulerSuspended != 0 );
\r
2906 /* Store the item value in the event list item. It is safe to access the
\r
2907 event list item here as interrupts won't access the event list item of a
\r
2908 task that is not in the Blocked state. */
\r
2909 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
\r
2911 /* Place the event list item of the TCB at the end of the appropriate event
\r
2912 list. It is safe to access the event list here because it is part of an
\r
2913 event group implementation - and interrupts don't access event groups
\r
2914 directly (instead they access them indirectly by pending function calls to
\r
2915 the task level). */
\r
2916 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2918 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
\r
2920 /*-----------------------------------------------------------*/
\r
2922 #if( configUSE_TIMERS == 1 )
\r
2924 void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely )
\r
2926 configASSERT( pxEventList );
\r
2928 /* This function should not be called by application code hence the
\r
2929 'Restricted' in its name. It is not part of the public API. It is
\r
2930 designed for use by kernel code, and has special calling requirements -
\r
2931 it should be called with the scheduler suspended. */
\r
2934 /* Place the event list item of the TCB in the appropriate event list.
\r
2935 In this case it is assume that this is the only task that is going to
\r
2936 be waiting on this event list, so the faster vListInsertEnd() function
\r
2937 can be used in place of vListInsert. */
\r
2938 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2940 /* If the task should block indefinitely then set the block time to a
\r
2941 value that will be recognised as an indefinite delay inside the
\r
2942 prvAddCurrentTaskToDelayedList() function. */
\r
2943 if( xWaitIndefinitely != pdFALSE )
\r
2945 xTicksToWait = portMAX_DELAY;
\r
2948 traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) );
\r
2949 prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely );
\r
2952 #endif /* configUSE_TIMERS */
\r
2953 /*-----------------------------------------------------------*/
\r
2955 BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
\r
2957 TCB_t *pxUnblockedTCB;
\r
2958 BaseType_t xReturn;
\r
2960 /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be
\r
2961 called from a critical section within an ISR. */
\r
2963 /* The event list is sorted in priority order, so the first in the list can
\r
2964 be removed as it is known to be the highest priority. Remove the TCB from
\r
2965 the delayed list, and add it to the ready list.
\r
2967 If an event is for a queue that is locked then this function will never
\r
2968 get called - the lock count on the queue will get modified instead. This
\r
2969 means exclusive access to the event list is guaranteed here.
\r
2971 This function assumes that a check has already been made to ensure that
\r
2972 pxEventList is not empty. */
\r
2973 pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
\r
2974 configASSERT( pxUnblockedTCB );
\r
2975 ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
\r
2977 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
2979 ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
\r
2980 prvAddTaskToReadyList( pxUnblockedTCB );
\r
2984 /* The delayed and ready lists cannot be accessed, so hold this task
\r
2985 pending until the scheduler is resumed. */
\r
2986 vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
\r
2989 if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
2991 /* Return true if the task removed from the event list has a higher
\r
2992 priority than the calling task. This allows the calling task to know if
\r
2993 it should force a context switch now. */
\r
2996 /* Mark that a yield is pending in case the user is not using the
\r
2997 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
\r
2998 xYieldPending = pdTRUE;
\r
3002 xReturn = pdFALSE;
\r
3005 #if( configUSE_TICKLESS_IDLE != 0 )
\r
3007 /* If a task is blocked on a kernel object then xNextTaskUnblockTime
\r
3008 might be set to the blocked task's time out time. If the task is
\r
3009 unblocked for a reason other than a timeout xNextTaskUnblockTime is
\r
3010 normally left unchanged, because it is automatically reset to a new
\r
3011 value when the tick count equals xNextTaskUnblockTime. However if
\r
3012 tickless idling is used it might be more important to enter sleep mode
\r
3013 at the earliest possible time - so reset xNextTaskUnblockTime here to
\r
3014 ensure it is updated at the earliest possible time. */
\r
3015 prvResetNextTaskUnblockTime();
\r
3021 /*-----------------------------------------------------------*/
\r
3023 void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )
\r
3025 TCB_t *pxUnblockedTCB;
\r
3027 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
\r
3028 the event flags implementation. */
\r
3029 configASSERT( uxSchedulerSuspended != pdFALSE );
\r
3031 /* Store the new item value in the event list. */
\r
3032 listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
\r
3034 /* Remove the event list form the event flag. Interrupts do not access
\r
3036 pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem );
\r
3037 configASSERT( pxUnblockedTCB );
\r
3038 ( void ) uxListRemove( pxEventListItem );
\r
3040 /* Remove the task from the delayed list and add it to the ready list. The
\r
3041 scheduler is suspended so interrupts will not be accessing the ready
\r
3043 ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
\r
3044 prvAddTaskToReadyList( pxUnblockedTCB );
\r
3046 if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
3048 /* The unblocked task has a priority above that of the calling task, so
\r
3049 a context switch is required. This function is called with the
\r
3050 scheduler suspended so xYieldPending is set so the context switch
\r
3051 occurs immediately that the scheduler is resumed (unsuspended). */
\r
3052 xYieldPending = pdTRUE;
\r
3055 /*-----------------------------------------------------------*/
\r
3057 void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
\r
3059 configASSERT( pxTimeOut );
\r
3060 pxTimeOut->xOverflowCount = xNumOfOverflows;
\r
3061 pxTimeOut->xTimeOnEntering = xTickCount;
\r
3063 /*-----------------------------------------------------------*/
\r
3065 BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait )
\r
3067 BaseType_t xReturn;
\r
3069 configASSERT( pxTimeOut );
\r
3070 configASSERT( pxTicksToWait );
\r
3072 taskENTER_CRITICAL();
\r
3074 /* Minor optimisation. The tick count cannot change in this block. */
\r
3075 const TickType_t xConstTickCount = xTickCount;
\r
3077 #if( INCLUDE_xTaskAbortDelay == 1 )
\r
3078 if( pxCurrentTCB->ucDelayAborted != pdFALSE )
\r
3080 /* The delay was aborted, which is not the same as a time out,
\r
3081 but has the same result. */
\r
3082 pxCurrentTCB->ucDelayAborted = pdFALSE;
\r
3088 #if ( INCLUDE_vTaskSuspend == 1 )
\r
3089 if( *pxTicksToWait == portMAX_DELAY )
\r
3091 /* If INCLUDE_vTaskSuspend is set to 1 and the block time
\r
3092 specified is the maximum block time then the task should block
\r
3093 indefinitely, and therefore never time out. */
\r
3094 xReturn = pdFALSE;
\r
3099 if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
\r
3101 /* The tick count is greater than the time at which
\r
3102 vTaskSetTimeout() was called, but has also overflowed since
\r
3103 vTaskSetTimeOut() was called. It must have wrapped all the way
\r
3104 around and gone past again. This passed since vTaskSetTimeout()
\r
3108 else if( ( ( TickType_t ) ( xConstTickCount - pxTimeOut->xTimeOnEntering ) ) < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */
\r
3110 /* Not a genuine timeout. Adjust parameters for time remaining. */
\r
3111 *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );
\r
3112 vTaskSetTimeOutState( pxTimeOut );
\r
3113 xReturn = pdFALSE;
\r
3120 taskEXIT_CRITICAL();
\r
3124 /*-----------------------------------------------------------*/
\r
3126 void vTaskMissedYield( void )
\r
3128 xYieldPending = pdTRUE;
\r
3130 /*-----------------------------------------------------------*/
\r
3132 #if ( configUSE_TRACE_FACILITY == 1 )
\r
3134 UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )
\r
3136 UBaseType_t uxReturn;
\r
3139 if( xTask != NULL )
\r
3141 pxTCB = ( TCB_t * ) xTask;
\r
3142 uxReturn = pxTCB->uxTaskNumber;
\r
3152 #endif /* configUSE_TRACE_FACILITY */
\r
3153 /*-----------------------------------------------------------*/
\r
3155 #if ( configUSE_TRACE_FACILITY == 1 )
\r
3157 void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle )
\r
3161 if( xTask != NULL )
\r
3163 pxTCB = ( TCB_t * ) xTask;
\r
3164 pxTCB->uxTaskNumber = uxHandle;
\r
3168 #endif /* configUSE_TRACE_FACILITY */
\r
3171 * -----------------------------------------------------------
\r
3173 * ----------------------------------------------------------
\r
3175 * The portTASK_FUNCTION() macro is used to allow port/compiler specific
\r
3176 * language extensions. The equivalent prototype for this function is:
\r
3178 * void prvIdleTask( void *pvParameters );
\r
3181 static portTASK_FUNCTION( prvIdleTask, pvParameters )
\r
3183 /* Stop warnings. */
\r
3184 ( void ) pvParameters;
\r
3186 /** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
\r
3187 SCHEDULER IS STARTED. **/
\r
3191 /* See if any tasks have deleted themselves - if so then the idle task
\r
3192 is responsible for freeing the deleted task's TCB and stack. */
\r
3193 prvCheckTasksWaitingTermination();
\r
3195 #if ( configUSE_PREEMPTION == 0 )
\r
3197 /* If we are not using preemption we keep forcing a task switch to
\r
3198 see if any other task has become available. If we are using
\r
3199 preemption we don't need to do this as any task becoming available
\r
3200 will automatically get the processor anyway. */
\r
3203 #endif /* configUSE_PREEMPTION */
\r
3205 #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
\r
3207 /* When using preemption tasks of equal priority will be
\r
3208 timesliced. If a task that is sharing the idle priority is ready
\r
3209 to run then the idle task should yield before the end of the
\r
3212 A critical region is not required here as we are just reading from
\r
3213 the list, and an occasional incorrect value will not matter. If
\r
3214 the ready list at the idle priority contains more than one task
\r
3215 then a task other than the idle task is ready to execute. */
\r
3216 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )
\r
3222 mtCOVERAGE_TEST_MARKER();
\r
3225 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
\r
3227 #if ( configUSE_IDLE_HOOK == 1 )
\r
3229 extern void vApplicationIdleHook( void );
\r
3231 /* Call the user defined function from within the idle task. This
\r
3232 allows the application designer to add background functionality
\r
3233 without the overhead of a separate task.
\r
3234 NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
\r
3235 CALL A FUNCTION THAT MIGHT BLOCK. */
\r
3236 vApplicationIdleHook();
\r
3238 #endif /* configUSE_IDLE_HOOK */
\r
3240 /* This conditional compilation should use inequality to 0, not equality
\r
3241 to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
\r
3242 user defined low power mode implementations require
\r
3243 configUSE_TICKLESS_IDLE to be set to a value other than 1. */
\r
3244 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
3246 TickType_t xExpectedIdleTime;
\r
3248 /* It is not desirable to suspend then resume the scheduler on
\r
3249 each iteration of the idle task. Therefore, a preliminary
\r
3250 test of the expected idle time is performed without the
\r
3251 scheduler suspended. The result here is not necessarily
\r
3253 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
3255 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
3257 vTaskSuspendAll();
\r
3259 /* Now the scheduler is suspended, the expected idle
\r
3260 time can be sampled again, and this time its value can
\r
3262 configASSERT( xNextTaskUnblockTime >= xTickCount );
\r
3263 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
3265 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
3267 traceLOW_POWER_IDLE_BEGIN();
\r
3268 portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
\r
3269 traceLOW_POWER_IDLE_END();
\r
3273 mtCOVERAGE_TEST_MARKER();
\r
3276 ( void ) xTaskResumeAll();
\r
3280 mtCOVERAGE_TEST_MARKER();
\r
3283 #endif /* configUSE_TICKLESS_IDLE */
\r
3286 /*-----------------------------------------------------------*/
\r
3288 #if( configUSE_TICKLESS_IDLE != 0 )
\r
3290 eSleepModeStatus eTaskConfirmSleepModeStatus( void )
\r
3292 /* The idle task exists in addition to the application tasks. */
\r
3293 const UBaseType_t uxNonApplicationTasks = 1;
\r
3294 eSleepModeStatus eReturn = eStandardSleep;
\r
3296 if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
\r
3298 /* A task was made ready while the scheduler was suspended. */
\r
3299 eReturn = eAbortSleep;
\r
3301 else if( xYieldPending != pdFALSE )
\r
3303 /* A yield was pended while the scheduler was suspended. */
\r
3304 eReturn = eAbortSleep;
\r
3308 /* If all the tasks are in the suspended list (which might mean they
\r
3309 have an infinite block time rather than actually being suspended)
\r
3310 then it is safe to turn all clocks off and just wait for external
\r
3312 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
\r
3314 eReturn = eNoTasksWaitingTimeout;
\r
3318 mtCOVERAGE_TEST_MARKER();
\r
3325 #endif /* configUSE_TICKLESS_IDLE */
\r
3326 /*-----------------------------------------------------------*/
\r
3328 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
\r
3330 void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue )
\r
3334 if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS )
\r
3336 pxTCB = prvGetTCBFromHandle( xTaskToSet );
\r
3337 pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue;
\r
3341 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
\r
3342 /*-----------------------------------------------------------*/
\r
3344 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
\r
3346 void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex )
\r
3348 void *pvReturn = NULL;
\r
3351 if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS )
\r
3353 pxTCB = prvGetTCBFromHandle( xTaskToQuery );
\r
3354 pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ];
\r
3364 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
\r
3365 /*-----------------------------------------------------------*/
\r
3367 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
3369 void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions )
\r
3373 /* If null is passed in here then we are modifying the MPU settings of
\r
3374 the calling task. */
\r
3375 pxTCB = prvGetTCBFromHandle( xTaskToModify );
\r
3377 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
\r
3380 #endif /* portUSING_MPU_WRAPPERS */
\r
3381 /*-----------------------------------------------------------*/
\r
3383 static void prvInitialiseTaskLists( void )
\r
3385 UBaseType_t uxPriority;
\r
3387 for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
\r
3389 vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
\r
3392 vListInitialise( &xDelayedTaskList1 );
\r
3393 vListInitialise( &xDelayedTaskList2 );
\r
3394 vListInitialise( &xPendingReadyList );
\r
3396 #if ( INCLUDE_vTaskDelete == 1 )
\r
3398 vListInitialise( &xTasksWaitingTermination );
\r
3400 #endif /* INCLUDE_vTaskDelete */
\r
3402 #if ( INCLUDE_vTaskSuspend == 1 )
\r
3404 vListInitialise( &xSuspendedTaskList );
\r
3406 #endif /* INCLUDE_vTaskSuspend */
\r
3408 /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
\r
3410 pxDelayedTaskList = &xDelayedTaskList1;
\r
3411 pxOverflowDelayedTaskList = &xDelayedTaskList2;
\r
3413 /*-----------------------------------------------------------*/
\r
3415 static void prvCheckTasksWaitingTermination( void )
\r
3418 /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/
\r
3420 #if ( INCLUDE_vTaskDelete == 1 )
\r
3422 BaseType_t xListIsEmpty;
\r
3424 /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
\r
3425 too often in the idle task. */
\r
3426 while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
\r
3428 vTaskSuspendAll();
\r
3430 xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
\r
3432 ( void ) xTaskResumeAll();
\r
3434 if( xListIsEmpty == pdFALSE )
\r
3438 taskENTER_CRITICAL();
\r
3440 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
\r
3441 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
3442 --uxCurrentNumberOfTasks;
\r
3443 --uxDeletedTasksWaitingCleanUp;
\r
3445 taskEXIT_CRITICAL();
\r
3447 prvDeleteTCB( pxTCB );
\r
3451 mtCOVERAGE_TEST_MARKER();
\r
3455 #endif /* INCLUDE_vTaskDelete */
\r
3457 /*-----------------------------------------------------------*/
\r
3459 #if( configUSE_TRACE_FACILITY == 1 )
\r
3461 void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState )
\r
3465 /* xTask is NULL then get the state of the calling task. */
\r
3466 pxTCB = prvGetTCBFromHandle( xTask );
\r
3468 pxTaskStatus->xHandle = ( TaskHandle_t ) pxTCB;
\r
3469 pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName [ 0 ] );
\r
3470 pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority;
\r
3471 pxTaskStatus->pxStackBase = pxTCB->pxStack;
\r
3472 pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber;
\r
3474 #if ( INCLUDE_vTaskSuspend == 1 )
\r
3476 /* If the task is in the suspended list then there is a chance it is
\r
3477 actually just blocked indefinitely - so really it should be reported as
\r
3478 being in the Blocked state. */
\r
3479 if( pxTaskStatus->eCurrentState == eSuspended )
\r
3481 vTaskSuspendAll();
\r
3483 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
3485 pxTaskStatus->eCurrentState = eBlocked;
\r
3488 ( void ) xTaskResumeAll();
\r
3491 #endif /* INCLUDE_vTaskSuspend */
\r
3493 #if ( configUSE_MUTEXES == 1 )
\r
3495 pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;
\r
3499 pxTaskStatus->uxBasePriority = 0;
\r
3503 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
3505 pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter;
\r
3509 pxTaskStatus->ulRunTimeCounter = 0;
\r
3513 /* Obtaining the task state is a little fiddly, so is only done if the value
\r
3514 of eState passed into this function is eInvalid - otherwise the state is
\r
3515 just set to whatever is passed in. */
\r
3516 if( eState != eInvalid )
\r
3518 pxTaskStatus->eCurrentState = eState;
\r
3522 pxTaskStatus->eCurrentState = eTaskGetState( xTask );
\r
3525 /* Obtaining the stack space takes some time, so the xGetFreeStackSpace
\r
3526 parameter is provided to allow it to be skipped. */
\r
3527 if( xGetFreeStackSpace != pdFALSE )
\r
3529 #if ( portSTACK_GROWTH > 0 )
\r
3531 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack );
\r
3535 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack );
\r
3541 pxTaskStatus->usStackHighWaterMark = 0;
\r
3545 #endif /* configUSE_TRACE_FACILITY */
\r
3546 /*-----------------------------------------------------------*/
\r
3548 #if ( configUSE_TRACE_FACILITY == 1 )
\r
3550 static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )
\r
3552 configLIST_VOLATILE TCB_t *pxNextTCB, *pxFirstTCB;
\r
3553 UBaseType_t uxTask = 0;
\r
3555 if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
\r
3557 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
\r
3559 /* Populate an TaskStatus_t structure within the
\r
3560 pxTaskStatusArray array for each task that is referenced from
\r
3561 pxList. See the definition of TaskStatus_t in task.h for the
\r
3562 meaning of each TaskStatus_t structure member. */
\r
3565 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
\r
3566 vTaskGetInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState );
\r
3568 } while( pxNextTCB != pxFirstTCB );
\r
3572 mtCOVERAGE_TEST_MARKER();
\r
3578 #endif /* configUSE_TRACE_FACILITY */
\r
3579 /*-----------------------------------------------------------*/
\r
3581 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
3583 static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
\r
3585 uint32_t ulCount = 0U;
\r
3587 while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE )
\r
3589 pucStackByte -= portSTACK_GROWTH;
\r
3593 ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */
\r
3595 return ( uint16_t ) ulCount;
\r
3598 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */
\r
3599 /*-----------------------------------------------------------*/
\r
3601 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
\r
3603 UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
\r
3606 uint8_t *pucEndOfStack;
\r
3607 UBaseType_t uxReturn;
\r
3609 pxTCB = prvGetTCBFromHandle( xTask );
\r
3611 #if portSTACK_GROWTH < 0
\r
3613 pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
\r
3617 pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
\r
3621 uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );
\r
3626 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
\r
3627 /*-----------------------------------------------------------*/
\r
3629 #if ( INCLUDE_vTaskDelete == 1 )
\r
3631 static void prvDeleteTCB( TCB_t *pxTCB )
\r
3633 /* This call is required specifically for the TriCore port. It must be
\r
3634 above the vPortFree() calls. The call is also used by ports/demos that
\r
3635 want to allocate and clean RAM statically. */
\r
3636 portCLEAN_UP_TCB( pxTCB );
\r
3638 /* Free up the memory allocated by the scheduler for the task. It is up
\r
3639 to the task to free any memory allocated at the application level. */
\r
3640 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
3642 _reclaim_reent( &( pxTCB->xNewLib_reent ) );
\r
3644 #endif /* configUSE_NEWLIB_REENTRANT */
\r
3646 #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
\r
3648 /* The task can only have been allocated dynamically - free both
\r
3649 the stack and TCB. */
\r
3650 vPortFree( pxTCB->pxStack );
\r
3651 vPortFree( pxTCB );
\r
3653 #elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */
\r
3655 /* The task could have been allocated statically or dynamically, so
\r
3656 check what was statically allocated before trying to free the
\r
3658 if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB )
\r
3660 /* Both the stack and TCB were allocated dynamically, so both
\r
3662 vPortFree( pxTCB->pxStack );
\r
3663 vPortFree( pxTCB );
\r
3665 else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY )
\r
3667 /* Only the stack was statically allocated, so the TCB is the
\r
3668 only memory that must be freed. */
\r
3669 vPortFree( pxTCB );
\r
3673 /* Neither the stack nor the TCB were allocated dynamically, so
\r
3674 nothing needs to be freed. */
\r
3675 configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB )
\r
3676 mtCOVERAGE_TEST_MARKER();
\r
3679 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
3682 #endif /* INCLUDE_vTaskDelete */
\r
3683 /*-----------------------------------------------------------*/
\r
3685 static void prvResetNextTaskUnblockTime( void )
\r
3689 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
\r
3691 /* The new current delayed list is empty. Set xNextTaskUnblockTime to
\r
3692 the maximum possible value so it is extremely unlikely that the
\r
3693 if( xTickCount >= xNextTaskUnblockTime ) test will pass until
\r
3694 there is an item in the delayed list. */
\r
3695 xNextTaskUnblockTime = portMAX_DELAY;
\r
3699 /* The new current delayed list is not empty, get the value of
\r
3700 the item at the head of the delayed list. This is the time at
\r
3701 which the task at the head of the delayed list should be removed
\r
3702 from the Blocked state. */
\r
3703 ( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
\r
3704 xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xStateListItem ) );
\r
3707 /*-----------------------------------------------------------*/
\r
3709 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
\r
3711 TaskHandle_t xTaskGetCurrentTaskHandle( void )
\r
3713 TaskHandle_t xReturn;
\r
3715 /* A critical section is not required as this is not called from
\r
3716 an interrupt and the current TCB will always be the same for any
\r
3717 individual execution thread. */
\r
3718 xReturn = pxCurrentTCB;
\r
3723 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
\r
3724 /*-----------------------------------------------------------*/
\r
3726 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
3728 BaseType_t xTaskGetSchedulerState( void )
\r
3730 BaseType_t xReturn;
\r
3732 if( xSchedulerRunning == pdFALSE )
\r
3734 xReturn = taskSCHEDULER_NOT_STARTED;
\r
3738 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
3740 xReturn = taskSCHEDULER_RUNNING;
\r
3744 xReturn = taskSCHEDULER_SUSPENDED;
\r
3751 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
\r
3752 /*-----------------------------------------------------------*/
\r
3754 #if ( configUSE_MUTEXES == 1 )
\r
3756 void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
\r
3758 TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
\r
3760 /* If the mutex was given back by an interrupt while the queue was
\r
3761 locked then the mutex holder might now be NULL. */
\r
3762 if( pxMutexHolder != NULL )
\r
3764 /* If the holder of the mutex has a priority below the priority of
\r
3765 the task attempting to obtain the mutex then it will temporarily
\r
3766 inherit the priority of the task attempting to obtain the mutex. */
\r
3767 if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
\r
3769 /* Adjust the mutex holder state to account for its new
\r
3770 priority. Only reset the event list item value if the value is
\r
3771 not being used for anything else. */
\r
3772 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
\r
3774 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
3778 mtCOVERAGE_TEST_MARKER();
\r
3781 /* If the task being modified is in the ready state it will need
\r
3782 to be moved into a new list. */
\r
3783 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
\r
3785 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
3787 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
3791 mtCOVERAGE_TEST_MARKER();
\r
3794 /* Inherit the priority before being moved into the new list. */
\r
3795 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
3796 prvAddTaskToReadyList( pxTCB );
\r
3800 /* Just inherit the priority. */
\r
3801 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
3804 traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );
\r
3808 mtCOVERAGE_TEST_MARKER();
\r
3813 mtCOVERAGE_TEST_MARKER();
\r
3817 #endif /* configUSE_MUTEXES */
\r
3818 /*-----------------------------------------------------------*/
\r
3820 #if ( configUSE_MUTEXES == 1 )
\r
3822 BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )
\r
3824 TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
\r
3825 BaseType_t xReturn = pdFALSE;
\r
3827 if( pxMutexHolder != NULL )
\r
3829 /* A task can only have an inherited priority if it holds the mutex.
\r
3830 If the mutex is held by a task then it cannot be given from an
\r
3831 interrupt, and if a mutex is given by the holding task then it must
\r
3832 be the running state task. */
\r
3833 configASSERT( pxTCB == pxCurrentTCB );
\r
3835 configASSERT( pxTCB->uxMutexesHeld );
\r
3836 ( pxTCB->uxMutexesHeld )--;
\r
3838 /* Has the holder of the mutex inherited the priority of another
\r
3840 if( pxTCB->uxPriority != pxTCB->uxBasePriority )
\r
3842 /* Only disinherit if no other mutexes are held. */
\r
3843 if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
\r
3845 /* A task can only have an inherited priority if it holds
\r
3846 the mutex. If the mutex is held by a task then it cannot be
\r
3847 given from an interrupt, and if a mutex is given by the
\r
3848 holding task then it must be the running state task. Remove
\r
3849 the holding task from the ready list. */
\r
3850 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
3852 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
3856 mtCOVERAGE_TEST_MARKER();
\r
3859 /* Disinherit the priority before adding the task into the
\r
3860 new ready list. */
\r
3861 traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
\r
3862 pxTCB->uxPriority = pxTCB->uxBasePriority;
\r
3864 /* Reset the event list item value. It cannot be in use for
\r
3865 any other purpose if this task is running, and it must be
\r
3866 running to give back the mutex. */
\r
3867 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
3868 prvAddTaskToReadyList( pxTCB );
\r
3870 /* Return true to indicate that a context switch is required.
\r
3871 This is only actually required in the corner case whereby
\r
3872 multiple mutexes were held and the mutexes were given back
\r
3873 in an order different to that in which they were taken.
\r
3874 If a context switch did not occur when the first mutex was
\r
3875 returned, even if a task was waiting on it, then a context
\r
3876 switch should occur when the last mutex is returned whether
\r
3877 a task is waiting on it or not. */
\r
3882 mtCOVERAGE_TEST_MARKER();
\r
3887 mtCOVERAGE_TEST_MARKER();
\r
3892 mtCOVERAGE_TEST_MARKER();
\r
3898 #endif /* configUSE_MUTEXES */
\r
3899 /*-----------------------------------------------------------*/
\r
3901 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
3903 void vTaskEnterCritical( void )
\r
3905 portDISABLE_INTERRUPTS();
\r
3907 if( xSchedulerRunning != pdFALSE )
\r
3909 ( pxCurrentTCB->uxCriticalNesting )++;
\r
3911 /* This is not the interrupt safe version of the enter critical
\r
3912 function so assert() if it is being called from an interrupt
\r
3913 context. Only API functions that end in "FromISR" can be used in an
\r
3914 interrupt. Only assert if the critical nesting count is 1 to
\r
3915 protect against recursive calls if the assert function also uses a
\r
3916 critical section. */
\r
3917 if( pxCurrentTCB->uxCriticalNesting == 1 )
\r
3919 portASSERT_IF_IN_ISR();
\r
3924 mtCOVERAGE_TEST_MARKER();
\r
3928 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
3929 /*-----------------------------------------------------------*/
\r
3931 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
3933 void vTaskExitCritical( void )
\r
3935 if( xSchedulerRunning != pdFALSE )
\r
3937 if( pxCurrentTCB->uxCriticalNesting > 0U )
\r
3939 ( pxCurrentTCB->uxCriticalNesting )--;
\r
3941 if( pxCurrentTCB->uxCriticalNesting == 0U )
\r
3943 portENABLE_INTERRUPTS();
\r
3947 mtCOVERAGE_TEST_MARKER();
\r
3952 mtCOVERAGE_TEST_MARKER();
\r
3957 mtCOVERAGE_TEST_MARKER();
\r
3961 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
3962 /*-----------------------------------------------------------*/
\r
3964 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
3966 static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName )
\r
3970 /* Start by copying the entire string. */
\r
3971 strcpy( pcBuffer, pcTaskName );
\r
3973 /* Pad the end of the string with spaces to ensure columns line up when
\r
3975 for( x = strlen( pcBuffer ); x < ( size_t ) ( configMAX_TASK_NAME_LEN - 1 ); x++ )
\r
3977 pcBuffer[ x ] = ' ';
\r
3981 pcBuffer[ x ] = 0x00;
\r
3983 /* Return the new end of string. */
\r
3984 return &( pcBuffer[ x ] );
\r
3987 #endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
\r
3988 /*-----------------------------------------------------------*/
\r
3990 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
3992 void vTaskList( char * pcWriteBuffer )
\r
3994 TaskStatus_t *pxTaskStatusArray;
\r
3995 volatile UBaseType_t uxArraySize, x;
\r
4001 * This function is provided for convenience only, and is used by many
\r
4002 * of the demo applications. Do not consider it to be part of the
\r
4005 * vTaskList() calls uxTaskGetSystemState(), then formats part of the
\r
4006 * uxTaskGetSystemState() output into a human readable table that
\r
4007 * displays task names, states and stack usage.
\r
4009 * vTaskList() has a dependency on the sprintf() C library function that
\r
4010 * might bloat the code size, use a lot of stack, and provide different
\r
4011 * results on different platforms. An alternative, tiny, third party,
\r
4012 * and limited functionality implementation of sprintf() is provided in
\r
4013 * many of the FreeRTOS/Demo sub-directories in a file called
\r
4014 * printf-stdarg.c (note printf-stdarg.c does not provide a full
\r
4015 * snprintf() implementation!).
\r
4017 * It is recommended that production systems call uxTaskGetSystemState()
\r
4018 * directly to get access to raw stats data, rather than indirectly
\r
4019 * through a call to vTaskList().
\r
4023 /* Make sure the write buffer does not contain a string. */
\r
4024 *pcWriteBuffer = 0x00;
\r
4026 /* Take a snapshot of the number of tasks in case it changes while this
\r
4027 function is executing. */
\r
4028 uxArraySize = uxCurrentNumberOfTasks;
\r
4030 /* Allocate an array index for each task. NOTE! if
\r
4031 configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
\r
4032 equate to NULL. */
\r
4033 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
\r
4035 if( pxTaskStatusArray != NULL )
\r
4037 /* Generate the (binary) data. */
\r
4038 uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
\r
4040 /* Create a human readable table from the binary data. */
\r
4041 for( x = 0; x < uxArraySize; x++ )
\r
4043 switch( pxTaskStatusArray[ x ].eCurrentState )
\r
4045 case eReady: cStatus = tskREADY_CHAR;
\r
4048 case eBlocked: cStatus = tskBLOCKED_CHAR;
\r
4051 case eSuspended: cStatus = tskSUSPENDED_CHAR;
\r
4054 case eDeleted: cStatus = tskDELETED_CHAR;
\r
4057 default: /* Should not get here, but it is included
\r
4058 to prevent static checking errors. */
\r
4063 /* Write the task name to the string, padding with spaces so it
\r
4064 can be printed in tabular form more easily. */
\r
4065 pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
\r
4067 /* Write the rest of the string. */
\r
4068 sprintf( pcWriteBuffer, "\t%c\t%u\t%u\t%u\r\n", cStatus, ( unsigned int ) pxTaskStatusArray[ x ].uxCurrentPriority, ( unsigned int ) pxTaskStatusArray[ x ].usStackHighWaterMark, ( unsigned int ) pxTaskStatusArray[ x ].xTaskNumber );
\r
4069 pcWriteBuffer += strlen( pcWriteBuffer );
\r
4072 /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
\r
4073 is 0 then vPortFree() will be #defined to nothing. */
\r
4074 vPortFree( pxTaskStatusArray );
\r
4078 mtCOVERAGE_TEST_MARKER();
\r
4082 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
\r
4083 /*----------------------------------------------------------*/
\r
4085 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
4087 void vTaskGetRunTimeStats( char *pcWriteBuffer )
\r
4089 TaskStatus_t *pxTaskStatusArray;
\r
4090 volatile UBaseType_t uxArraySize, x;
\r
4091 uint32_t ulTotalTime, ulStatsAsPercentage;
\r
4093 #if( configUSE_TRACE_FACILITY != 1 )
\r
4095 #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats().
\r
4102 * This function is provided for convenience only, and is used by many
\r
4103 * of the demo applications. Do not consider it to be part of the
\r
4106 * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part
\r
4107 * of the uxTaskGetSystemState() output into a human readable table that
\r
4108 * displays the amount of time each task has spent in the Running state
\r
4109 * in both absolute and percentage terms.
\r
4111 * vTaskGetRunTimeStats() has a dependency on the sprintf() C library
\r
4112 * function that might bloat the code size, use a lot of stack, and
\r
4113 * provide different results on different platforms. An alternative,
\r
4114 * tiny, third party, and limited functionality implementation of
\r
4115 * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in
\r
4116 * a file called printf-stdarg.c (note printf-stdarg.c does not provide
\r
4117 * a full snprintf() implementation!).
\r
4119 * It is recommended that production systems call uxTaskGetSystemState()
\r
4120 * directly to get access to raw stats data, rather than indirectly
\r
4121 * through a call to vTaskGetRunTimeStats().
\r
4124 /* Make sure the write buffer does not contain a string. */
\r
4125 *pcWriteBuffer = 0x00;
\r
4127 /* Take a snapshot of the number of tasks in case it changes while this
\r
4128 function is executing. */
\r
4129 uxArraySize = uxCurrentNumberOfTasks;
\r
4131 /* Allocate an array index for each task. NOTE! If
\r
4132 configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
\r
4133 equate to NULL. */
\r
4134 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
\r
4136 if( pxTaskStatusArray != NULL )
\r
4138 /* Generate the (binary) data. */
\r
4139 uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
\r
4141 /* For percentage calculations. */
\r
4142 ulTotalTime /= 100UL;
\r
4144 /* Avoid divide by zero errors. */
\r
4145 if( ulTotalTime > 0 )
\r
4147 /* Create a human readable table from the binary data. */
\r
4148 for( x = 0; x < uxArraySize; x++ )
\r
4150 /* What percentage of the total run time has the task used?
\r
4151 This will always be rounded down to the nearest integer.
\r
4152 ulTotalRunTimeDiv100 has already been divided by 100. */
\r
4153 ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
\r
4155 /* Write the task name to the string, padding with
\r
4156 spaces so it can be printed in tabular form more
\r
4158 pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
\r
4160 if( ulStatsAsPercentage > 0UL )
\r
4162 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
4164 sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
\r
4168 /* sizeof( int ) == sizeof( long ) so a smaller
\r
4169 printf() library can be used. */
\r
4170 sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );
\r
4176 /* If the percentage is zero here then the task has
\r
4177 consumed less than 1% of the total run time. */
\r
4178 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
4180 sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter );
\r
4184 /* sizeof( int ) == sizeof( long ) so a smaller
\r
4185 printf() library can be used. */
\r
4186 sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter );
\r
4191 pcWriteBuffer += strlen( pcWriteBuffer );
\r
4196 mtCOVERAGE_TEST_MARKER();
\r
4199 /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
\r
4200 is 0 then vPortFree() will be #defined to nothing. */
\r
4201 vPortFree( pxTaskStatusArray );
\r
4205 mtCOVERAGE_TEST_MARKER();
\r
4209 #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
\r
4210 /*-----------------------------------------------------------*/
\r
4212 TickType_t uxTaskResetEventItemValue( void )
\r
4214 TickType_t uxReturn;
\r
4216 uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );
\r
4218 /* Reset the event list item to its normal value - so it can be used with
\r
4219 queues and semaphores. */
\r
4220 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
4224 /*-----------------------------------------------------------*/
\r
4226 #if ( configUSE_MUTEXES == 1 )
\r
4228 void *pvTaskIncrementMutexHeldCount( void )
\r
4230 /* If xSemaphoreCreateMutex() is called before any tasks have been created
\r
4231 then pxCurrentTCB will be NULL. */
\r
4232 if( pxCurrentTCB != NULL )
\r
4234 ( pxCurrentTCB->uxMutexesHeld )++;
\r
4237 return pxCurrentTCB;
\r
4240 #endif /* configUSE_MUTEXES */
\r
4241 /*-----------------------------------------------------------*/
\r
4243 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4245 uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )
\r
4247 uint32_t ulReturn;
\r
4249 taskENTER_CRITICAL();
\r
4251 /* Only block if the notification count is not already non-zero. */
\r
4252 if( pxCurrentTCB->ulNotifiedValue == 0UL )
\r
4254 /* Mark this task as waiting for a notification. */
\r
4255 pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;
\r
4257 if( xTicksToWait > ( TickType_t ) 0 )
\r
4259 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
\r
4260 traceTASK_NOTIFY_TAKE_BLOCK();
\r
4262 /* All ports are written to allow a yield in a critical
\r
4263 section (some will yield immediately, others wait until the
\r
4264 critical section exits) - but it is not something that
\r
4265 application code should ever do. */
\r
4266 portYIELD_WITHIN_API();
\r
4270 mtCOVERAGE_TEST_MARKER();
\r
4275 mtCOVERAGE_TEST_MARKER();
\r
4278 taskEXIT_CRITICAL();
\r
4280 taskENTER_CRITICAL();
\r
4282 traceTASK_NOTIFY_TAKE();
\r
4283 ulReturn = pxCurrentTCB->ulNotifiedValue;
\r
4285 if( ulReturn != 0UL )
\r
4287 if( xClearCountOnExit != pdFALSE )
\r
4289 pxCurrentTCB->ulNotifiedValue = 0UL;
\r
4293 pxCurrentTCB->ulNotifiedValue = ulReturn - ( uint32_t ) 1;
\r
4298 mtCOVERAGE_TEST_MARKER();
\r
4301 pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
\r
4303 taskEXIT_CRITICAL();
\r
4308 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4309 /*-----------------------------------------------------------*/
\r
4311 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4313 BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait )
\r
4315 BaseType_t xReturn;
\r
4317 taskENTER_CRITICAL();
\r
4319 /* Only block if a notification is not already pending. */
\r
4320 if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED )
\r
4322 /* Clear bits in the task's notification value as bits may get
\r
4323 set by the notifying task or interrupt. This can be used to
\r
4324 clear the value to zero. */
\r
4325 pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry;
\r
4327 /* Mark this task as waiting for a notification. */
\r
4328 pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;
\r
4330 if( xTicksToWait > ( TickType_t ) 0 )
\r
4332 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
\r
4333 traceTASK_NOTIFY_WAIT_BLOCK();
\r
4335 /* All ports are written to allow a yield in a critical
\r
4336 section (some will yield immediately, others wait until the
\r
4337 critical section exits) - but it is not something that
\r
4338 application code should ever do. */
\r
4339 portYIELD_WITHIN_API();
\r
4343 mtCOVERAGE_TEST_MARKER();
\r
4348 mtCOVERAGE_TEST_MARKER();
\r
4351 taskEXIT_CRITICAL();
\r
4353 taskENTER_CRITICAL();
\r
4355 traceTASK_NOTIFY_WAIT();
\r
4357 if( pulNotificationValue != NULL )
\r
4359 /* Output the current notification value, which may or may not
\r
4361 *pulNotificationValue = pxCurrentTCB->ulNotifiedValue;
\r
4364 /* If ucNotifyValue is set then either the task never entered the
\r
4365 blocked state (because a notification was already pending) or the
\r
4366 task unblocked because of a notification. Otherwise the task
\r
4367 unblocked because of a timeout. */
\r
4368 if( pxCurrentTCB->ucNotifyState == taskWAITING_NOTIFICATION )
\r
4370 /* A notification was not received. */
\r
4371 xReturn = pdFALSE;
\r
4375 /* A notification was already pending or a notification was
\r
4376 received while the task was waiting. */
\r
4377 pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnExit;
\r
4381 pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
\r
4383 taskEXIT_CRITICAL();
\r
4388 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4389 /*-----------------------------------------------------------*/
\r
4391 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4393 BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue )
\r
4396 BaseType_t xReturn = pdPASS;
\r
4397 uint8_t ucOriginalNotifyState;
\r
4399 configASSERT( xTaskToNotify );
\r
4400 pxTCB = ( TCB_t * ) xTaskToNotify;
\r
4402 taskENTER_CRITICAL();
\r
4404 if( pulPreviousNotificationValue != NULL )
\r
4406 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
\r
4409 ucOriginalNotifyState = pxTCB->ucNotifyState;
\r
4411 pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
\r
4416 pxTCB->ulNotifiedValue |= ulValue;
\r
4420 ( pxTCB->ulNotifiedValue )++;
\r
4423 case eSetValueWithOverwrite :
\r
4424 pxTCB->ulNotifiedValue = ulValue;
\r
4427 case eSetValueWithoutOverwrite :
\r
4428 if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
\r
4430 pxTCB->ulNotifiedValue = ulValue;
\r
4434 /* The value could not be written to the task. */
\r
4440 /* The task is being notified without its notify value being
\r
4445 traceTASK_NOTIFY();
\r
4447 /* If the task is in the blocked state specifically to wait for a
\r
4448 notification then unblock it now. */
\r
4449 if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
\r
4451 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
4452 prvAddTaskToReadyList( pxTCB );
\r
4454 /* The task should not have been on an event list. */
\r
4455 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
\r
4457 #if( configUSE_TICKLESS_IDLE != 0 )
\r
4459 /* If a task is blocked waiting for a notification then
\r
4460 xNextTaskUnblockTime might be set to the blocked task's time
\r
4461 out time. If the task is unblocked for a reason other than
\r
4462 a timeout xNextTaskUnblockTime is normally left unchanged,
\r
4463 because it will automatically get reset to a new value when
\r
4464 the tick count equals xNextTaskUnblockTime. However if
\r
4465 tickless idling is used it might be more important to enter
\r
4466 sleep mode at the earliest possible time - so reset
\r
4467 xNextTaskUnblockTime here to ensure it is updated at the
\r
4468 earliest possible time. */
\r
4469 prvResetNextTaskUnblockTime();
\r
4473 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
4475 /* The notified task has a priority above the currently
\r
4476 executing task so a yield is required. */
\r
4477 taskYIELD_IF_USING_PREEMPTION();
\r
4481 mtCOVERAGE_TEST_MARKER();
\r
4486 mtCOVERAGE_TEST_MARKER();
\r
4489 taskEXIT_CRITICAL();
\r
4494 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4495 /*-----------------------------------------------------------*/
\r
4497 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4499 BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken )
\r
4502 uint8_t ucOriginalNotifyState;
\r
4503 BaseType_t xReturn = pdPASS;
\r
4504 UBaseType_t uxSavedInterruptStatus;
\r
4506 configASSERT( xTaskToNotify );
\r
4508 /* RTOS ports that support interrupt nesting have the concept of a
\r
4509 maximum system call (or maximum API call) interrupt priority.
\r
4510 Interrupts that are above the maximum system call priority are keep
\r
4511 permanently enabled, even when the RTOS kernel is in a critical section,
\r
4512 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
4513 is defined in FreeRTOSConfig.h then
\r
4514 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
4515 failure if a FreeRTOS API function is called from an interrupt that has
\r
4516 been assigned a priority above the configured maximum system call
\r
4517 priority. Only FreeRTOS functions that end in FromISR can be called
\r
4518 from interrupts that have been assigned a priority at or (logically)
\r
4519 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
4520 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
4521 simple as possible. More information (albeit Cortex-M specific) is
\r
4522 provided on the following link:
\r
4523 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
4524 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
4526 pxTCB = ( TCB_t * ) xTaskToNotify;
\r
4528 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
4530 if( pulPreviousNotificationValue != NULL )
\r
4532 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
\r
4535 ucOriginalNotifyState = pxTCB->ucNotifyState;
\r
4536 pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
\r
4541 pxTCB->ulNotifiedValue |= ulValue;
\r
4545 ( pxTCB->ulNotifiedValue )++;
\r
4548 case eSetValueWithOverwrite :
\r
4549 pxTCB->ulNotifiedValue = ulValue;
\r
4552 case eSetValueWithoutOverwrite :
\r
4553 if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
\r
4555 pxTCB->ulNotifiedValue = ulValue;
\r
4559 /* The value could not be written to the task. */
\r
4565 /* The task is being notified without its notify value being
\r
4570 traceTASK_NOTIFY_FROM_ISR();
\r
4572 /* If the task is in the blocked state specifically to wait for a
\r
4573 notification then unblock it now. */
\r
4574 if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
\r
4576 /* The task should not have been on an event list. */
\r
4577 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
\r
4579 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
4581 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
4582 prvAddTaskToReadyList( pxTCB );
\r
4586 /* The delayed and ready lists cannot be accessed, so hold
\r
4587 this task pending until the scheduler is resumed. */
\r
4588 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
4591 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
4593 /* The notified task has a priority above the currently
\r
4594 executing task so a yield is required. */
\r
4595 if( pxHigherPriorityTaskWoken != NULL )
\r
4597 *pxHigherPriorityTaskWoken = pdTRUE;
\r
4601 /* Mark that a yield is pending in case the user is not
\r
4602 using the "xHigherPriorityTaskWoken" parameter to an ISR
\r
4603 safe FreeRTOS function. */
\r
4604 xYieldPending = pdTRUE;
\r
4609 mtCOVERAGE_TEST_MARKER();
\r
4613 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
4618 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4619 /*-----------------------------------------------------------*/
\r
4621 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4623 void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken )
\r
4626 uint8_t ucOriginalNotifyState;
\r
4627 UBaseType_t uxSavedInterruptStatus;
\r
4629 configASSERT( xTaskToNotify );
\r
4631 /* RTOS ports that support interrupt nesting have the concept of a
\r
4632 maximum system call (or maximum API call) interrupt priority.
\r
4633 Interrupts that are above the maximum system call priority are keep
\r
4634 permanently enabled, even when the RTOS kernel is in a critical section,
\r
4635 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
4636 is defined in FreeRTOSConfig.h then
\r
4637 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
4638 failure if a FreeRTOS API function is called from an interrupt that has
\r
4639 been assigned a priority above the configured maximum system call
\r
4640 priority. Only FreeRTOS functions that end in FromISR can be called
\r
4641 from interrupts that have been assigned a priority at or (logically)
\r
4642 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
4643 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
4644 simple as possible. More information (albeit Cortex-M specific) is
\r
4645 provided on the following link:
\r
4646 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
4647 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
4649 pxTCB = ( TCB_t * ) xTaskToNotify;
\r
4651 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
4653 ucOriginalNotifyState = pxTCB->ucNotifyState;
\r
4654 pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
\r
4656 /* 'Giving' is equivalent to incrementing a count in a counting
\r
4658 ( pxTCB->ulNotifiedValue )++;
\r
4660 traceTASK_NOTIFY_GIVE_FROM_ISR();
\r
4662 /* If the task is in the blocked state specifically to wait for a
\r
4663 notification then unblock it now. */
\r
4664 if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
\r
4666 /* The task should not have been on an event list. */
\r
4667 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
\r
4669 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
4671 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
4672 prvAddTaskToReadyList( pxTCB );
\r
4676 /* The delayed and ready lists cannot be accessed, so hold
\r
4677 this task pending until the scheduler is resumed. */
\r
4678 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
4681 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
4683 /* The notified task has a priority above the currently
\r
4684 executing task so a yield is required. */
\r
4685 if( pxHigherPriorityTaskWoken != NULL )
\r
4687 *pxHigherPriorityTaskWoken = pdTRUE;
\r
4691 /* Mark that a yield is pending in case the user is not
\r
4692 using the "xHigherPriorityTaskWoken" parameter in an ISR
\r
4693 safe FreeRTOS function. */
\r
4694 xYieldPending = pdTRUE;
\r
4699 mtCOVERAGE_TEST_MARKER();
\r
4703 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
4706 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4708 /*-----------------------------------------------------------*/
\r
4710 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4712 BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask )
\r
4715 BaseType_t xReturn;
\r
4717 /* If null is passed in here then it is the calling task that is having
\r
4718 its notification state cleared. */
\r
4719 pxTCB = prvGetTCBFromHandle( xTask );
\r
4721 taskENTER_CRITICAL();
\r
4723 if( pxTCB->ucNotifyState == taskNOTIFICATION_RECEIVED )
\r
4725 pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
\r
4733 taskEXIT_CRITICAL();
\r
4738 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4739 /*-----------------------------------------------------------*/
\r
4742 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely )
\r
4744 TickType_t xTimeToWake;
\r
4745 const TickType_t xConstTickCount = xTickCount;
\r
4747 #if( INCLUDE_xTaskAbortDelay == 1 )
\r
4749 /* About to enter a delayed list, so ensure the ucDelayAborted flag is
\r
4750 reset to pdFALSE so it can be detected as having been set to pdTRUE
\r
4751 when the task leaves the Blocked state. */
\r
4752 pxCurrentTCB->ucDelayAborted = pdFALSE;
\r
4756 /* Remove the task from the ready list before adding it to the blocked list
\r
4757 as the same list item is used for both lists. */
\r
4758 if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
4760 /* The current task must be in a ready list, so there is no need to
\r
4761 check, and the port reset macro can be called directly. */
\r
4762 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
4766 mtCOVERAGE_TEST_MARKER();
\r
4769 #if ( INCLUDE_vTaskSuspend == 1 )
\r
4771 if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )
\r
4773 /* Add the task to the suspended task list instead of a delayed task
\r
4774 list to ensure it is not woken by a timing event. It will block
\r
4776 vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
4780 /* Calculate the time at which the task should be woken if the event
\r
4781 does not occur. This may overflow but this doesn't matter, the
\r
4782 kernel will manage it correctly. */
\r
4783 xTimeToWake = xConstTickCount + xTicksToWait;
\r
4785 /* The list item will be inserted in wake time order. */
\r
4786 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
\r
4788 if( xTimeToWake < xConstTickCount )
\r
4790 /* Wake time has overflowed. Place this item in the overflow
\r
4792 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
4796 /* The wake time has not overflowed, so the current block list
\r
4798 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
4800 /* If the task entering the blocked state was placed at the
\r
4801 head of the list of blocked tasks then xNextTaskUnblockTime
\r
4802 needs to be updated too. */
\r
4803 if( xTimeToWake < xNextTaskUnblockTime )
\r
4805 xNextTaskUnblockTime = xTimeToWake;
\r
4809 mtCOVERAGE_TEST_MARKER();
\r
4814 #else /* INCLUDE_vTaskSuspend */
\r
4816 /* Calculate the time at which the task should be woken if the event
\r
4817 does not occur. This may overflow but this doesn't matter, the kernel
\r
4818 will manage it correctly. */
\r
4819 xTimeToWake = xConstTickCount + xTicksToWait;
\r
4821 /* The list item will be inserted in wake time order. */
\r
4822 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
\r
4824 if( xTimeToWake < xConstTickCount )
\r
4826 /* Wake time has overflowed. Place this item in the overflow list. */
\r
4827 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
4831 /* The wake time has not overflowed, so the current block list is used. */
\r
4832 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
4834 /* If the task entering the blocked state was placed at the head of the
\r
4835 list of blocked tasks then xNextTaskUnblockTime needs to be updated
\r
4837 if( xTimeToWake < xNextTaskUnblockTime )
\r
4839 xNextTaskUnblockTime = xTimeToWake;
\r
4843 mtCOVERAGE_TEST_MARKER();
\r
4847 /* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */
\r
4848 ( void ) xCanBlockIndefinitely;
\r
4850 #endif /* INCLUDE_vTaskSuspend */
\r
4853 /* Code below here allows additional code to be inserted into this source file,
\r
4854 especially where access to file scope functions and data is needed (for example
\r
4855 when performing module tests). */
\r
4857 #ifdef FREERTOS_MODULE_TEST
\r
4858 #include "tasks_test_access_functions.h"
\r
4862 #if( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 )
\r
4864 #include "freertos_tasks_c_additions.h"
\r
4866 static void freertos_tasks_c_additions_init( void )
\r
4868 #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
\r
4869 FREERTOS_TASKS_C_ADDITIONS_INIT();
\r