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 #define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) || ( portUSING_MPU_WRAPPERS == 1 ) )
\r
136 #define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 0 )
\r
137 #define tskSTATICALLY_ALLOCATED_STACK_ONLY ( ( uint8_t ) 1 )
\r
138 #define tskSTATICALLY_ALLOCATED_STACK_AND_TCB ( ( uint8_t ) 2 )
\r
140 /* If any of the following are set then task stacks are filled with a known
\r
141 value so the high water mark can be determined. If none of the following are
\r
142 set then don't fill the stack so there is no unnecessary dependency on memset. */
\r
143 #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
144 #define tskSET_NEW_STACKS_TO_KNOWN_VALUE 1
\r
146 #define tskSET_NEW_STACKS_TO_KNOWN_VALUE 0
\r
150 * Macros used by vListTask to indicate which state a task is in.
\r
152 #define tskBLOCKED_CHAR ( 'B' )
\r
153 #define tskREADY_CHAR ( 'R' )
\r
154 #define tskDELETED_CHAR ( 'D' )
\r
155 #define tskSUSPENDED_CHAR ( 'S' )
\r
158 * Some kernel aware debuggers require the data the debugger needs access to be
\r
159 * global, rather than file scope.
\r
161 #ifdef portREMOVE_STATIC_QUALIFIER
\r
165 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
\r
167 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
\r
168 performed in a generic way that is not optimised to any particular
\r
169 microcontroller architecture. */
\r
171 /* uxTopReadyPriority holds the priority of the highest priority ready
\r
173 #define taskRECORD_READY_PRIORITY( uxPriority ) \
\r
175 if( ( uxPriority ) > uxTopReadyPriority ) \
\r
177 uxTopReadyPriority = ( uxPriority ); \
\r
179 } /* taskRECORD_READY_PRIORITY */
\r
181 /*-----------------------------------------------------------*/
\r
183 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
185 UBaseType_t uxTopPriority = uxTopReadyPriority; \
\r
187 /* Find the highest priority queue that contains ready tasks. */ \
\r
188 while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopPriority ] ) ) ) \
\r
190 configASSERT( uxTopPriority ); \
\r
194 /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
\r
195 the same priority get an equal share of the processor time. */ \
\r
196 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
\r
197 uxTopReadyPriority = uxTopPriority; \
\r
198 } /* taskSELECT_HIGHEST_PRIORITY_TASK */
\r
200 /*-----------------------------------------------------------*/
\r
202 /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
\r
203 they are only required when a port optimised method of task selection is
\r
205 #define taskRESET_READY_PRIORITY( uxPriority )
\r
206 #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
208 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
210 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
\r
211 performed in a way that is tailored to the particular microcontroller
\r
212 architecture being used. */
\r
214 /* A port optimised version is provided. Call the port defined macros. */
\r
215 #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
217 /*-----------------------------------------------------------*/
\r
219 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
221 UBaseType_t uxTopPriority; \
\r
223 /* Find the highest priority list that contains ready tasks. */ \
\r
224 portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
\r
225 configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
\r
226 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
\r
227 } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
\r
229 /*-----------------------------------------------------------*/
\r
231 /* A port optimised version is provided, call it only if the TCB being reset
\r
232 is being referenced from a ready list. If it is referenced from a delayed
\r
233 or suspended list then it won't be in a ready list. */
\r
234 #define taskRESET_READY_PRIORITY( uxPriority ) \
\r
236 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \
\r
238 portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \
\r
242 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
244 /*-----------------------------------------------------------*/
\r
246 /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
\r
247 count overflows. */
\r
248 #define taskSWITCH_DELAYED_LISTS() \
\r
252 /* The delayed tasks list should be empty when the lists are switched. */ \
\r
253 configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \
\r
255 pxTemp = pxDelayedTaskList; \
\r
256 pxDelayedTaskList = pxOverflowDelayedTaskList; \
\r
257 pxOverflowDelayedTaskList = pxTemp; \
\r
258 xNumOfOverflows++; \
\r
259 prvResetNextTaskUnblockTime(); \
\r
262 /*-----------------------------------------------------------*/
\r
265 * Place the task represented by pxTCB into the appropriate ready list for
\r
266 * the task. It is inserted at the end of the list.
\r
268 #define prvAddTaskToReadyList( pxTCB ) \
\r
269 traceMOVED_TASK_TO_READY_STATE( pxTCB ); \
\r
270 taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
\r
271 vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
\r
272 tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )
\r
273 /*-----------------------------------------------------------*/
\r
276 * Several functions take an TaskHandle_t parameter that can optionally be NULL,
\r
277 * where NULL is used to indicate that the handle of the currently executing
\r
278 * task should be used in place of the parameter. This macro simply checks to
\r
279 * see if the parameter is NULL and returns a pointer to the appropriate TCB.
\r
281 #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TCB_t * ) pxCurrentTCB : ( TCB_t * ) ( pxHandle ) )
\r
283 /* The item value of the event list item is normally used to hold the priority
\r
284 of the task to which it belongs (coded to allow it to be held in reverse
\r
285 priority order). However, it is occasionally borrowed for other purposes. It
\r
286 is important its value is not updated due to a task priority change while it is
\r
287 being used for another purpose. The following bit definition is used to inform
\r
288 the scheduler that the value should not be changed - in which case it is the
\r
289 responsibility of whichever module is using the value to ensure it gets set back
\r
290 to its original value when it is released. */
\r
291 #if( configUSE_16_BIT_TICKS == 1 )
\r
292 #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U
\r
294 #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL
\r
298 * Task control block. A task control block (TCB) is allocated for each task,
\r
299 * and stores task state information, including a pointer to the task's context
\r
300 * (the task's run time environment, including register values)
\r
302 typedef struct tskTaskControlBlock
\r
304 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
306 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
307 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
310 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
311 ListItem_t xEventListItem; /*< Used to reference a task from an event list. */
\r
312 UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */
\r
313 StackType_t *pxStack; /*< Points to the start of the stack. */
\r
314 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
316 #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
\r
317 StackType_t *pxEndOfStack; /*< Points to the highest valid address for the stack. */
\r
320 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
321 UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
\r
324 #if ( configUSE_TRACE_FACILITY == 1 )
\r
325 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
326 UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
\r
329 #if ( configUSE_MUTEXES == 1 )
\r
330 UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
\r
331 UBaseType_t uxMutexesHeld;
\r
334 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
335 TaskHookFunction_t pxTaskTag;
\r
338 #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
\r
339 void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
\r
342 #if( configGENERATE_RUN_TIME_STATS == 1 )
\r
343 uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
\r
346 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
347 /* Allocate a Newlib reent structure that is specific to this task.
\r
348 Note Newlib support has been included by popular demand, but is not
\r
349 used by the FreeRTOS maintainers themselves. FreeRTOS is not
\r
350 responsible for resulting newlib operation. User must be familiar with
\r
351 newlib and must provide system-wide implementations of the necessary
\r
352 stubs. Be warned that (at the time of writing) the current newlib design
\r
353 implements a system-wide malloc() that must be provided with locks. */
\r
354 struct _reent xNewLib_reent;
\r
357 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
358 volatile uint32_t ulNotifiedValue;
\r
359 volatile uint8_t ucNotifyState;
\r
362 /* See the comments above the definition of
\r
363 tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
\r
364 #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */
\r
365 uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
\r
368 #if( INCLUDE_xTaskAbortDelay == 1 )
\r
369 uint8_t ucDelayAborted;
\r
374 /* The old tskTCB name is maintained above then typedefed to the new TCB_t name
\r
375 below to enable the use of older kernel aware debuggers. */
\r
376 typedef tskTCB TCB_t;
\r
378 /*lint -save -e956 A manual analysis and inspection has been used to determine
\r
379 which static variables must be declared volatile. */
\r
381 PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
\r
383 /* Lists for ready and blocked tasks. --------------------*/
\r
384 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */
\r
385 PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */
\r
386 PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
\r
387 PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */
\r
388 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
389 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
391 #if( INCLUDE_vTaskDelete == 1 )
\r
393 PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */
\r
394 PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;
\r
398 #if ( INCLUDE_vTaskSuspend == 1 )
\r
400 PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */
\r
404 /* Other file private variables. --------------------------------*/
\r
405 PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
\r
406 PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U;
\r
407 PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
\r
408 PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
\r
409 PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U;
\r
410 PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE;
\r
411 PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
\r
412 PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
\r
413 PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */
\r
414 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
416 /* Context switches are held pending while the scheduler is suspended. Also,
\r
417 interrupts must not manipulate the xStateListItem of a TCB, or any of the
\r
418 lists the xStateListItem can be referenced from, if the scheduler is suspended.
\r
419 If an interrupt needs to unblock a task while the scheduler is suspended then it
\r
420 moves the task's event list item into the xPendingReadyList, ready for the
\r
421 kernel to move the task from the pending ready list into the real ready list
\r
422 when the scheduler is unsuspended. The pending ready list itself can only be
\r
423 accessed from a critical section. */
\r
424 PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE;
\r
426 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
428 PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
\r
429 PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */
\r
435 /*-----------------------------------------------------------*/
\r
437 /* Callback function prototypes. --------------------------*/
\r
438 #if( configCHECK_FOR_STACK_OVERFLOW > 0 )
\r
439 extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName );
\r
442 #if( configUSE_TICK_HOOK > 0 )
\r
443 extern void vApplicationTickHook( void );
\r
446 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
447 extern void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );
\r
450 /* File private functions. --------------------------------*/
\r
453 * Utility task that simply returns pdTRUE if the task referenced by xTask is
\r
454 * currently in the Suspended state, or pdFALSE if the task referenced by xTask
\r
455 * is in any other state.
\r
457 #if ( INCLUDE_vTaskSuspend == 1 )
\r
458 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
\r
459 #endif /* INCLUDE_vTaskSuspend */
\r
462 * Utility to ready all the lists used by the scheduler. This is called
\r
463 * automatically upon the creation of the first task.
\r
465 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
\r
468 * The idle task, which as all tasks is implemented as a never ending loop.
\r
469 * The idle task is automatically created and added to the ready lists upon
\r
470 * creation of the first user task.
\r
472 * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
\r
473 * language extensions. The equivalent prototype for this function is:
\r
475 * void prvIdleTask( void *pvParameters );
\r
478 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
\r
481 * Utility to free all memory allocated by the scheduler to hold a TCB,
\r
482 * including the stack pointed to by the TCB.
\r
484 * This does not free memory allocated by the task itself (i.e. memory
\r
485 * allocated by calls to pvPortMalloc from within the tasks application code).
\r
487 #if ( INCLUDE_vTaskDelete == 1 )
\r
489 static void prvDeleteTCB( TCB_t *pxTCB ) PRIVILEGED_FUNCTION;
\r
494 * Used only by the idle task. This checks to see if anything has been placed
\r
495 * in the list of tasks waiting to be deleted. If so the task is cleaned up
\r
496 * and its TCB deleted.
\r
498 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
\r
501 * The currently executing task is entering the Blocked state. Add the task to
\r
502 * either the current or the overflow delayed task list.
\r
504 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION;
\r
507 * Fills an TaskStatus_t structure with information on each task that is
\r
508 * referenced from the pxList list (which may be a ready list, a delayed list,
\r
509 * a suspended list, etc.).
\r
511 * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
\r
512 * NORMAL APPLICATION CODE.
\r
514 #if ( configUSE_TRACE_FACILITY == 1 )
\r
516 static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;
\r
521 * Searches pxList for a task with name pcNameToQuery - returning a handle to
\r
522 * the task if it is found, or NULL if the task is not found.
\r
524 #if ( INCLUDE_xTaskGetHandle == 1 )
\r
526 static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] ) PRIVILEGED_FUNCTION;
\r
531 * When a task is created, the stack of the task is filled with a known value.
\r
532 * This function determines the 'high water mark' of the task stack by
\r
533 * determining how much of the stack remains at the original preset value.
\r
535 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
537 static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
\r
542 * Return the amount of time, in ticks, that will pass before the kernel will
\r
543 * next move a task from the Blocked state to the Running state.
\r
545 * This conditional compilation should use inequality to 0, not equality to 1.
\r
546 * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
\r
547 * defined low power mode implementations require configUSE_TICKLESS_IDLE to be
\r
548 * set to a value other than 1.
\r
550 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
552 static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
\r
557 * Set xNextTaskUnblockTime to the time at which the next Blocked state task
\r
558 * will exit the Blocked state.
\r
560 static void prvResetNextTaskUnblockTime( void );
\r
562 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
565 * Helper function used to pad task names with spaces when printing out
\r
566 * human readable tables of task information.
\r
568 static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName ) PRIVILEGED_FUNCTION;
\r
573 * Called after a Task_t structure has been allocated either statically or
\r
574 * dynamically to fill in the structure's members.
\r
576 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
\r
577 const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
578 const uint32_t ulStackDepth,
\r
579 void * const pvParameters,
\r
580 UBaseType_t uxPriority,
\r
581 TaskHandle_t * const pxCreatedTask,
\r
583 const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION;
\r
586 * Called after a new task has been created and initialised to place the task
\r
587 * under the control of the scheduler.
\r
589 static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
\r
591 /*-----------------------------------------------------------*/
\r
593 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
595 TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
\r
596 const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
597 const uint32_t ulStackDepth,
\r
598 void * const pvParameters,
\r
599 UBaseType_t uxPriority,
\r
600 StackType_t * const puxStackBuffer,
\r
601 StaticTask_t * const pxTaskBuffer )
\r
604 TaskHandle_t xReturn;
\r
606 configASSERT( puxStackBuffer != NULL );
\r
607 configASSERT( pxTaskBuffer != NULL );
\r
609 if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
\r
611 /* The memory used for the task's TCB and stack are passed into this
\r
612 function - use them. */
\r
613 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
614 pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;
\r
616 #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */
\r
618 /* Tasks can be created statically or dynamically, so note this
\r
619 task was created statically in case the task is later deleted. */
\r
620 pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
\r
622 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
624 prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL );
\r
625 prvAddNewTaskToReadyList( pxNewTCB );
\r
635 #endif /* SUPPORT_STATIC_ALLOCATION */
\r
636 /*-----------------------------------------------------------*/
\r
638 #if( portUSING_MPU_WRAPPERS == 1 )
\r
640 BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
\r
643 BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
\r
645 configASSERT( pxTaskDefinition->puxStackBuffer );
\r
647 if( pxTaskDefinition->puxStackBuffer != NULL )
\r
649 /* Allocate space for the TCB. Where the memory comes from depends
\r
650 on the implementation of the port malloc function and whether or
\r
651 not static allocation is being used. */
\r
652 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
\r
654 if( pxNewTCB != NULL )
\r
656 /* Store the stack location in the TCB. */
\r
657 pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
\r
659 /* Tasks can be created statically or dynamically, so note
\r
660 this task had a statically allocated stack in case it is
\r
661 later deleted. The TCB was allocated dynamically. */
\r
662 pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_ONLY;
\r
664 prvInitialiseNewTask( pxTaskDefinition->pvTaskCode,
\r
665 pxTaskDefinition->pcName,
\r
666 ( uint32_t ) pxTaskDefinition->usStackDepth,
\r
667 pxTaskDefinition->pvParameters,
\r
668 pxTaskDefinition->uxPriority,
\r
669 pxCreatedTask, pxNewTCB,
\r
670 pxTaskDefinition->xRegions );
\r
672 prvAddNewTaskToReadyList( pxNewTCB );
\r
680 #endif /* portUSING_MPU_WRAPPERS */
\r
681 /*-----------------------------------------------------------*/
\r
683 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
\r
685 BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
\r
686 const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
687 const uint16_t usStackDepth,
\r
688 void * const pvParameters,
\r
689 UBaseType_t uxPriority,
\r
690 TaskHandle_t * const pxCreatedTask )
\r
693 BaseType_t xReturn;
\r
695 /* If the stack grows down then allocate the stack then the TCB so the stack
\r
696 does not grow into the TCB. Likewise if the stack grows up then allocate
\r
697 the TCB then the stack. */
\r
698 #if( portSTACK_GROWTH > 0 )
\r
700 /* Allocate space for the TCB. Where the memory comes from depends on
\r
701 the implementation of the port malloc function and whether or not static
\r
702 allocation is being used. */
\r
703 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
\r
705 if( pxNewTCB != NULL )
\r
707 /* Allocate space for the stack used by the task being created.
\r
708 The base of the stack memory stored in the TCB so the task can
\r
709 be deleted later if required. */
\r
710 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
712 if( pxNewTCB->pxStack == NULL )
\r
714 /* Could not allocate the stack. Delete the allocated TCB. */
\r
715 vPortFree( pxNewTCB );
\r
720 #else /* portSTACK_GROWTH */
\r
722 StackType_t *pxStack;
\r
724 /* Allocate space for the stack used by the task being created. */
\r
725 pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
727 if( pxStack != NULL )
\r
729 /* Allocate space for the TCB. */
\r
730 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e961 MISRA exception as the casts are only redundant for some paths. */
\r
732 if( pxNewTCB != NULL )
\r
734 /* Store the stack location in the TCB. */
\r
735 pxNewTCB->pxStack = pxStack;
\r
739 /* The stack cannot be used as the TCB was not created. Free
\r
741 vPortFree( pxStack );
\r
749 #endif /* portSTACK_GROWTH */
\r
751 if( pxNewTCB != NULL )
\r
753 #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */
\r
755 /* Tasks can be created statically or dynamically, so note this
\r
756 task was created dynamically in case it is later deleted. */
\r
757 pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
\r
759 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
761 prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
\r
762 prvAddNewTaskToReadyList( pxNewTCB );
\r
767 xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
\r
773 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
774 /*-----------------------------------------------------------*/
\r
776 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
\r
777 const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
778 const uint32_t ulStackDepth,
\r
779 void * const pvParameters,
\r
780 UBaseType_t uxPriority,
\r
781 TaskHandle_t * const pxCreatedTask,
\r
783 const MemoryRegion_t * const xRegions )
\r
785 StackType_t *pxTopOfStack;
\r
788 #if( portUSING_MPU_WRAPPERS == 1 )
\r
789 /* Should the task be created in privileged mode? */
\r
790 BaseType_t xRunPrivileged;
\r
791 if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
\r
793 xRunPrivileged = pdTRUE;
\r
797 xRunPrivileged = pdFALSE;
\r
799 uxPriority &= ~portPRIVILEGE_BIT;
\r
800 #endif /* portUSING_MPU_WRAPPERS == 1 */
\r
802 /* Avoid dependency on memset() if it is not required. */
\r
803 #if( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 )
\r
805 /* Fill the stack with a known value to assist debugging. */
\r
806 ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );
\r
808 #endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */
\r
810 /* Calculate the top of stack address. This depends on whether the stack
\r
811 grows from high memory to low (as per the 80x86) or vice versa.
\r
812 portSTACK_GROWTH is used to make the result positive or negative as required
\r
814 #if( portSTACK_GROWTH < 0 )
\r
816 pxTopOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
\r
817 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
819 /* Check the alignment of the calculated top of stack is correct. */
\r
820 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
822 #if( configRECORD_STACK_HIGH_ADDRESS == 1 )
\r
824 /* Also record the stack's high address, which may assist
\r
826 pxNewTCB->pxEndOfStack = pxTopOfStack;
\r
828 #endif /* configRECORD_STACK_HIGH_ADDRESS */
\r
830 #else /* portSTACK_GROWTH */
\r
832 pxTopOfStack = pxNewTCB->pxStack;
\r
834 /* Check the alignment of the stack buffer is correct. */
\r
835 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
837 /* The other extreme of the stack space is required if stack checking is
\r
839 pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( ulStackDepth - ( uint32_t ) 1 );
\r
841 #endif /* portSTACK_GROWTH */
\r
843 /* Store the task name in the TCB. */
\r
844 for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
\r
846 pxNewTCB->pcTaskName[ x ] = pcName[ x ];
\r
848 /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
\r
849 configMAX_TASK_NAME_LEN characters just in case the memory after the
\r
850 string is not accessible (extremely unlikely). */
\r
851 if( pcName[ x ] == 0x00 )
\r
857 mtCOVERAGE_TEST_MARKER();
\r
861 /* Ensure the name string is terminated in the case that the string length
\r
862 was greater or equal to configMAX_TASK_NAME_LEN. */
\r
863 pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
\r
865 /* This is used as an array index so must ensure it's not too large. First
\r
866 remove the privilege bit if one is present. */
\r
867 if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
\r
869 uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
\r
873 mtCOVERAGE_TEST_MARKER();
\r
876 pxNewTCB->uxPriority = uxPriority;
\r
877 #if ( configUSE_MUTEXES == 1 )
\r
879 pxNewTCB->uxBasePriority = uxPriority;
\r
880 pxNewTCB->uxMutexesHeld = 0;
\r
882 #endif /* configUSE_MUTEXES */
\r
884 vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
\r
885 vListInitialiseItem( &( pxNewTCB->xEventListItem ) );
\r
887 /* Set the pxNewTCB as a link back from the ListItem_t. This is so we can get
\r
888 back to the containing TCB from a generic item in a list. */
\r
889 listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );
\r
891 /* Event lists are always in priority order. */
\r
892 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
893 listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );
\r
895 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
897 pxNewTCB->uxCriticalNesting = ( UBaseType_t ) 0U;
\r
899 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
901 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
903 pxNewTCB->pxTaskTag = NULL;
\r
905 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
907 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
909 pxNewTCB->ulRunTimeCounter = 0UL;
\r
911 #endif /* configGENERATE_RUN_TIME_STATS */
\r
913 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
915 vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, ulStackDepth );
\r
919 /* Avoid compiler warning about unreferenced parameter. */
\r
924 #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
\r
926 for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ )
\r
928 pxNewTCB->pvThreadLocalStoragePointers[ x ] = NULL;
\r
933 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
\r
935 pxNewTCB->ulNotifiedValue = 0;
\r
936 pxNewTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
\r
940 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
942 /* Initialise this task's Newlib reent structure. */
\r
943 _REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) );
\r
947 #if( INCLUDE_xTaskAbortDelay == 1 )
\r
949 pxNewTCB->ucDelayAborted = pdFALSE;
\r
953 /* Initialize the TCB stack to look as if the task was already running,
\r
954 but had been interrupted by the scheduler. The return address is set
\r
955 to the start of the task function. Once the stack has been initialised
\r
956 the top of stack variable is updated. */
\r
957 #if( portUSING_MPU_WRAPPERS == 1 )
\r
959 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
\r
961 #else /* portUSING_MPU_WRAPPERS */
\r
963 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
\r
965 #endif /* portUSING_MPU_WRAPPERS */
\r
967 if( ( void * ) pxCreatedTask != NULL )
\r
969 /* Pass the handle out in an anonymous way. The handle can be used to
\r
970 change the created task's priority, delete the created task, etc.*/
\r
971 *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
\r
975 mtCOVERAGE_TEST_MARKER();
\r
978 /*-----------------------------------------------------------*/
\r
980 static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
\r
982 /* Ensure interrupts don't access the task lists while the lists are being
\r
984 taskENTER_CRITICAL();
\r
986 uxCurrentNumberOfTasks++;
\r
987 if( pxCurrentTCB == NULL )
\r
989 /* There are no other tasks, or all the other tasks are in
\r
990 the suspended state - make this the current task. */
\r
991 pxCurrentTCB = pxNewTCB;
\r
993 if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
\r
995 /* This is the first task to be created so do the preliminary
\r
996 initialisation required. We will not recover if this call
\r
997 fails, but we will report the failure. */
\r
998 prvInitialiseTaskLists();
\r
1002 mtCOVERAGE_TEST_MARKER();
\r
1007 /* If the scheduler is not already running, make this task the
\r
1008 current task if it is the highest priority task to be created
\r
1010 if( xSchedulerRunning == pdFALSE )
\r
1012 if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )
\r
1014 pxCurrentTCB = pxNewTCB;
\r
1018 mtCOVERAGE_TEST_MARKER();
\r
1023 mtCOVERAGE_TEST_MARKER();
\r
1029 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1031 /* Add a counter into the TCB for tracing only. */
\r
1032 pxNewTCB->uxTCBNumber = uxTaskNumber;
\r
1034 #endif /* configUSE_TRACE_FACILITY */
\r
1035 traceTASK_CREATE( pxNewTCB );
\r
1037 prvAddTaskToReadyList( pxNewTCB );
\r
1039 portSETUP_TCB( pxNewTCB );
\r
1041 taskEXIT_CRITICAL();
\r
1043 if( xSchedulerRunning != pdFALSE )
\r
1045 /* If the created task is of a higher priority than the current task
\r
1046 then it should run now. */
\r
1047 if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority )
\r
1049 taskYIELD_IF_USING_PREEMPTION();
\r
1053 mtCOVERAGE_TEST_MARKER();
\r
1058 mtCOVERAGE_TEST_MARKER();
\r
1061 /*-----------------------------------------------------------*/
\r
1063 #if ( INCLUDE_vTaskDelete == 1 )
\r
1065 void vTaskDelete( TaskHandle_t xTaskToDelete )
\r
1069 taskENTER_CRITICAL();
\r
1071 /* If null is passed in here then it is the calling task that is
\r
1073 pxTCB = prvGetTCBFromHandle( xTaskToDelete );
\r
1075 /* Remove task from the ready list. */
\r
1076 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
1078 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
1082 mtCOVERAGE_TEST_MARKER();
\r
1085 /* Is the task waiting on an event also? */
\r
1086 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
1088 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1092 mtCOVERAGE_TEST_MARKER();
\r
1095 /* Increment the uxTaskNumber also so kernel aware debuggers can
\r
1096 detect that the task lists need re-generating. This is done before
\r
1097 portPRE_TASK_DELETE_HOOK() as in the Windows port that macro will
\r
1101 if( pxTCB == pxCurrentTCB )
\r
1103 /* A task is deleting itself. This cannot complete within the
\r
1104 task itself, as a context switch to another task is required.
\r
1105 Place the task in the termination list. The idle task will
\r
1106 check the termination list and free up any memory allocated by
\r
1107 the scheduler for the TCB and stack of the deleted task. */
\r
1108 vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );
\r
1110 /* Increment the ucTasksDeleted variable so the idle task knows
\r
1111 there is a task that has been deleted and that it should therefore
\r
1112 check the xTasksWaitingTermination list. */
\r
1113 ++uxDeletedTasksWaitingCleanUp;
\r
1115 /* The pre-delete hook is primarily for the Windows simulator,
\r
1116 in which Windows specific clean up operations are performed,
\r
1117 after which it is not possible to yield away from this task -
\r
1118 hence xYieldPending is used to latch that a context switch is
\r
1120 portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
\r
1124 --uxCurrentNumberOfTasks;
\r
1125 prvDeleteTCB( pxTCB );
\r
1127 /* Reset the next expected unblock time in case it referred to
\r
1128 the task that has just been deleted. */
\r
1129 prvResetNextTaskUnblockTime();
\r
1132 traceTASK_DELETE( pxTCB );
\r
1134 taskEXIT_CRITICAL();
\r
1136 /* Force a reschedule if it is the currently running task that has just
\r
1138 if( xSchedulerRunning != pdFALSE )
\r
1140 if( pxTCB == pxCurrentTCB )
\r
1142 configASSERT( uxSchedulerSuspended == 0 );
\r
1143 portYIELD_WITHIN_API();
\r
1147 mtCOVERAGE_TEST_MARKER();
\r
1152 #endif /* INCLUDE_vTaskDelete */
\r
1153 /*-----------------------------------------------------------*/
\r
1155 #if ( INCLUDE_vTaskDelayUntil == 1 )
\r
1157 void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
\r
1159 TickType_t xTimeToWake;
\r
1160 BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
\r
1162 configASSERT( pxPreviousWakeTime );
\r
1163 configASSERT( ( xTimeIncrement > 0U ) );
\r
1164 configASSERT( uxSchedulerSuspended == 0 );
\r
1166 vTaskSuspendAll();
\r
1168 /* Minor optimisation. The tick count cannot change in this
\r
1170 const TickType_t xConstTickCount = xTickCount;
\r
1172 /* Generate the tick time at which the task wants to wake. */
\r
1173 xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
\r
1175 if( xConstTickCount < *pxPreviousWakeTime )
\r
1177 /* The tick count has overflowed since this function was
\r
1178 lasted called. In this case the only time we should ever
\r
1179 actually delay is if the wake time has also overflowed,
\r
1180 and the wake time is greater than the tick time. When this
\r
1181 is the case it is as if neither time had overflowed. */
\r
1182 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
\r
1184 xShouldDelay = pdTRUE;
\r
1188 mtCOVERAGE_TEST_MARKER();
\r
1193 /* The tick time has not overflowed. In this case we will
\r
1194 delay if either the wake time has overflowed, and/or the
\r
1195 tick time is less than the wake time. */
\r
1196 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
\r
1198 xShouldDelay = pdTRUE;
\r
1202 mtCOVERAGE_TEST_MARKER();
\r
1206 /* Update the wake time ready for the next call. */
\r
1207 *pxPreviousWakeTime = xTimeToWake;
\r
1209 if( xShouldDelay != pdFALSE )
\r
1211 traceTASK_DELAY_UNTIL( xTimeToWake );
\r
1213 /* prvAddCurrentTaskToDelayedList() needs the block time, not
\r
1214 the time to wake, so subtract the current tick count. */
\r
1215 prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE );
\r
1219 mtCOVERAGE_TEST_MARKER();
\r
1222 xAlreadyYielded = xTaskResumeAll();
\r
1224 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
1225 have put ourselves to sleep. */
\r
1226 if( xAlreadyYielded == pdFALSE )
\r
1228 portYIELD_WITHIN_API();
\r
1232 mtCOVERAGE_TEST_MARKER();
\r
1236 #endif /* INCLUDE_vTaskDelayUntil */
\r
1237 /*-----------------------------------------------------------*/
\r
1239 #if ( INCLUDE_vTaskDelay == 1 )
\r
1241 void vTaskDelay( const TickType_t xTicksToDelay )
\r
1243 BaseType_t xAlreadyYielded = pdFALSE;
\r
1245 /* A delay time of zero just forces a reschedule. */
\r
1246 if( xTicksToDelay > ( TickType_t ) 0U )
\r
1248 configASSERT( uxSchedulerSuspended == 0 );
\r
1249 vTaskSuspendAll();
\r
1251 traceTASK_DELAY();
\r
1253 /* A task that is removed from the event list while the
\r
1254 scheduler is suspended will not get placed in the ready
\r
1255 list or removed from the blocked list until the scheduler
\r
1258 This task cannot be in an event list as it is the currently
\r
1259 executing task. */
\r
1260 prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
\r
1262 xAlreadyYielded = xTaskResumeAll();
\r
1266 mtCOVERAGE_TEST_MARKER();
\r
1269 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
1270 have put ourselves to sleep. */
\r
1271 if( xAlreadyYielded == pdFALSE )
\r
1273 portYIELD_WITHIN_API();
\r
1277 mtCOVERAGE_TEST_MARKER();
\r
1281 #endif /* INCLUDE_vTaskDelay */
\r
1282 /*-----------------------------------------------------------*/
\r
1284 #if( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) )
\r
1286 eTaskState eTaskGetState( TaskHandle_t xTask )
\r
1288 eTaskState eReturn;
\r
1289 List_t *pxStateList;
\r
1290 const TCB_t * const pxTCB = ( TCB_t * ) xTask;
\r
1292 configASSERT( pxTCB );
\r
1294 if( pxTCB == pxCurrentTCB )
\r
1296 /* The task calling this function is querying its own state. */
\r
1297 eReturn = eRunning;
\r
1301 taskENTER_CRITICAL();
\r
1303 pxStateList = ( List_t * ) listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) );
\r
1305 taskEXIT_CRITICAL();
\r
1307 if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) )
\r
1309 /* The task being queried is referenced from one of the Blocked
\r
1311 eReturn = eBlocked;
\r
1314 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1315 else if( pxStateList == &xSuspendedTaskList )
\r
1317 /* The task being queried is referenced from the suspended
\r
1318 list. Is it genuinely suspended or is it block
\r
1320 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
\r
1322 eReturn = eSuspended;
\r
1326 eReturn = eBlocked;
\r
1331 #if ( INCLUDE_vTaskDelete == 1 )
\r
1332 else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) )
\r
1334 /* The task being queried is referenced from the deleted
\r
1335 tasks list, or it is not referenced from any lists at
\r
1337 eReturn = eDeleted;
\r
1341 else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */
\r
1343 /* If the task is not in any other state, it must be in the
\r
1344 Ready (including pending ready) state. */
\r
1350 } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
\r
1352 #endif /* INCLUDE_eTaskGetState */
\r
1353 /*-----------------------------------------------------------*/
\r
1355 #if ( INCLUDE_uxTaskPriorityGet == 1 )
\r
1357 UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask )
\r
1360 UBaseType_t uxReturn;
\r
1362 taskENTER_CRITICAL();
\r
1364 /* If null is passed in here then it is the priority of the that
\r
1365 called uxTaskPriorityGet() that is being queried. */
\r
1366 pxTCB = prvGetTCBFromHandle( xTask );
\r
1367 uxReturn = pxTCB->uxPriority;
\r
1369 taskEXIT_CRITICAL();
\r
1374 #endif /* INCLUDE_uxTaskPriorityGet */
\r
1375 /*-----------------------------------------------------------*/
\r
1377 #if ( INCLUDE_uxTaskPriorityGet == 1 )
\r
1379 UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask )
\r
1382 UBaseType_t uxReturn, uxSavedInterruptState;
\r
1384 /* RTOS ports that support interrupt nesting have the concept of a
\r
1385 maximum system call (or maximum API call) interrupt priority.
\r
1386 Interrupts that are above the maximum system call priority are keep
\r
1387 permanently enabled, even when the RTOS kernel is in a critical section,
\r
1388 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
1389 is defined in FreeRTOSConfig.h then
\r
1390 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1391 failure if a FreeRTOS API function is called from an interrupt that has
\r
1392 been assigned a priority above the configured maximum system call
\r
1393 priority. Only FreeRTOS functions that end in FromISR can be called
\r
1394 from interrupts that have been assigned a priority at or (logically)
\r
1395 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
1396 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
1397 simple as possible. More information (albeit Cortex-M specific) is
\r
1398 provided on the following link:
\r
1399 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1400 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1402 uxSavedInterruptState = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1404 /* If null is passed in here then it is the priority of the calling
\r
1405 task that is being queried. */
\r
1406 pxTCB = prvGetTCBFromHandle( xTask );
\r
1407 uxReturn = pxTCB->uxPriority;
\r
1409 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState );
\r
1414 #endif /* INCLUDE_uxTaskPriorityGet */
\r
1415 /*-----------------------------------------------------------*/
\r
1417 #if ( INCLUDE_vTaskPrioritySet == 1 )
\r
1419 void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )
\r
1422 UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;
\r
1423 BaseType_t xYieldRequired = pdFALSE;
\r
1425 configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
\r
1427 /* Ensure the new priority is valid. */
\r
1428 if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
\r
1430 uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
\r
1434 mtCOVERAGE_TEST_MARKER();
\r
1437 taskENTER_CRITICAL();
\r
1439 /* If null is passed in here then it is the priority of the calling
\r
1440 task that is being changed. */
\r
1441 pxTCB = prvGetTCBFromHandle( xTask );
\r
1443 traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
\r
1445 #if ( configUSE_MUTEXES == 1 )
\r
1447 uxCurrentBasePriority = pxTCB->uxBasePriority;
\r
1451 uxCurrentBasePriority = pxTCB->uxPriority;
\r
1455 if( uxCurrentBasePriority != uxNewPriority )
\r
1457 /* The priority change may have readied a task of higher
\r
1458 priority than the calling task. */
\r
1459 if( uxNewPriority > uxCurrentBasePriority )
\r
1461 if( pxTCB != pxCurrentTCB )
\r
1463 /* The priority of a task other than the currently
\r
1464 running task is being raised. Is the priority being
\r
1465 raised above that of the running task? */
\r
1466 if( uxNewPriority >= pxCurrentTCB->uxPriority )
\r
1468 xYieldRequired = pdTRUE;
\r
1472 mtCOVERAGE_TEST_MARKER();
\r
1477 /* The priority of the running task is being raised,
\r
1478 but the running task must already be the highest
\r
1479 priority task able to run so no yield is required. */
\r
1482 else if( pxTCB == pxCurrentTCB )
\r
1484 /* Setting the priority of the running task down means
\r
1485 there may now be another task of higher priority that
\r
1486 is ready to execute. */
\r
1487 xYieldRequired = pdTRUE;
\r
1491 /* Setting the priority of any other task down does not
\r
1492 require a yield as the running task must be above the
\r
1493 new priority of the task being modified. */
\r
1496 /* Remember the ready list the task might be referenced from
\r
1497 before its uxPriority member is changed so the
\r
1498 taskRESET_READY_PRIORITY() macro can function correctly. */
\r
1499 uxPriorityUsedOnEntry = pxTCB->uxPriority;
\r
1501 #if ( configUSE_MUTEXES == 1 )
\r
1503 /* Only change the priority being used if the task is not
\r
1504 currently using an inherited priority. */
\r
1505 if( pxTCB->uxBasePriority == pxTCB->uxPriority )
\r
1507 pxTCB->uxPriority = uxNewPriority;
\r
1511 mtCOVERAGE_TEST_MARKER();
\r
1514 /* The base priority gets set whatever. */
\r
1515 pxTCB->uxBasePriority = uxNewPriority;
\r
1519 pxTCB->uxPriority = uxNewPriority;
\r
1523 /* Only reset the event list item value if the value is not
\r
1524 being used for anything else. */
\r
1525 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
\r
1527 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
1531 mtCOVERAGE_TEST_MARKER();
\r
1534 /* If the task is in the blocked or suspended list we need do
\r
1535 nothing more than change it's priority variable. However, if
\r
1536 the task is in a ready list it needs to be removed and placed
\r
1537 in the list appropriate to its new priority. */
\r
1538 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
\r
1540 /* The task is currently in its ready list - remove before adding
\r
1541 it to it's new ready list. As we are in a critical section we
\r
1542 can do this even if the scheduler is suspended. */
\r
1543 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
1545 /* It is known that the task is in its ready list so
\r
1546 there is no need to check again and the port level
\r
1547 reset macro can be called directly. */
\r
1548 portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
\r
1552 mtCOVERAGE_TEST_MARKER();
\r
1554 prvAddTaskToReadyList( pxTCB );
\r
1558 mtCOVERAGE_TEST_MARKER();
\r
1561 if( xYieldRequired != pdFALSE )
\r
1563 taskYIELD_IF_USING_PREEMPTION();
\r
1567 mtCOVERAGE_TEST_MARKER();
\r
1570 /* Remove compiler warning about unused variables when the port
\r
1571 optimised task selection is not being used. */
\r
1572 ( void ) uxPriorityUsedOnEntry;
\r
1575 taskEXIT_CRITICAL();
\r
1578 #endif /* INCLUDE_vTaskPrioritySet */
\r
1579 /*-----------------------------------------------------------*/
\r
1581 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1583 void vTaskSuspend( TaskHandle_t xTaskToSuspend )
\r
1587 taskENTER_CRITICAL();
\r
1589 /* If null is passed in here then it is the running task that is
\r
1590 being suspended. */
\r
1591 pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
\r
1593 traceTASK_SUSPEND( pxTCB );
\r
1595 /* Remove task from the ready/delayed list and place in the
\r
1596 suspended list. */
\r
1597 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
1599 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
1603 mtCOVERAGE_TEST_MARKER();
\r
1606 /* Is the task waiting on an event also? */
\r
1607 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
1609 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1613 mtCOVERAGE_TEST_MARKER();
\r
1616 vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
\r
1618 taskEXIT_CRITICAL();
\r
1620 if( xSchedulerRunning != pdFALSE )
\r
1622 /* Reset the next expected unblock time in case it referred to the
\r
1623 task that is now in the Suspended state. */
\r
1624 taskENTER_CRITICAL();
\r
1626 prvResetNextTaskUnblockTime();
\r
1628 taskEXIT_CRITICAL();
\r
1632 mtCOVERAGE_TEST_MARKER();
\r
1635 if( pxTCB == pxCurrentTCB )
\r
1637 if( xSchedulerRunning != pdFALSE )
\r
1639 /* The current task has just been suspended. */
\r
1640 configASSERT( uxSchedulerSuspended == 0 );
\r
1641 portYIELD_WITHIN_API();
\r
1645 /* The scheduler is not running, but the task that was pointed
\r
1646 to by pxCurrentTCB has just been suspended and pxCurrentTCB
\r
1647 must be adjusted to point to a different task. */
\r
1648 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )
\r
1650 /* No other tasks are ready, so set pxCurrentTCB back to
\r
1651 NULL so when the next task is created pxCurrentTCB will
\r
1652 be set to point to it no matter what its relative priority
\r
1654 pxCurrentTCB = NULL;
\r
1658 vTaskSwitchContext();
\r
1664 mtCOVERAGE_TEST_MARKER();
\r
1668 #endif /* INCLUDE_vTaskSuspend */
\r
1669 /*-----------------------------------------------------------*/
\r
1671 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1673 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
\r
1675 BaseType_t xReturn = pdFALSE;
\r
1676 const TCB_t * const pxTCB = ( TCB_t * ) xTask;
\r
1678 /* Accesses xPendingReadyList so must be called from a critical
\r
1681 /* It does not make sense to check if the calling task is suspended. */
\r
1682 configASSERT( xTask );
\r
1684 /* Is the task being resumed actually in the suspended list? */
\r
1685 if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE )
\r
1687 /* Has the task already been resumed from within an ISR? */
\r
1688 if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
\r
1690 /* Is it in the suspended list because it is in the Suspended
\r
1691 state, or because is is blocked with no timeout? */
\r
1692 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) /*lint !e961. The cast is only redundant when NULL is used. */
\r
1698 mtCOVERAGE_TEST_MARKER();
\r
1703 mtCOVERAGE_TEST_MARKER();
\r
1708 mtCOVERAGE_TEST_MARKER();
\r
1712 } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
\r
1714 #endif /* INCLUDE_vTaskSuspend */
\r
1715 /*-----------------------------------------------------------*/
\r
1717 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1719 void vTaskResume( TaskHandle_t xTaskToResume )
\r
1721 TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
\r
1723 /* It does not make sense to resume the calling task. */
\r
1724 configASSERT( xTaskToResume );
\r
1726 /* The parameter cannot be NULL as it is impossible to resume the
\r
1727 currently executing task. */
\r
1728 if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
\r
1730 taskENTER_CRITICAL();
\r
1732 if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
\r
1734 traceTASK_RESUME( pxTCB );
\r
1736 /* As we are in a critical section we can access the ready
\r
1737 lists even if the scheduler is suspended. */
\r
1738 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
1739 prvAddTaskToReadyList( pxTCB );
\r
1741 /* We may have just resumed a higher priority task. */
\r
1742 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1744 /* This yield may not cause the task just resumed to run,
\r
1745 but will leave the lists in the correct state for the
\r
1747 taskYIELD_IF_USING_PREEMPTION();
\r
1751 mtCOVERAGE_TEST_MARKER();
\r
1756 mtCOVERAGE_TEST_MARKER();
\r
1759 taskEXIT_CRITICAL();
\r
1763 mtCOVERAGE_TEST_MARKER();
\r
1767 #endif /* INCLUDE_vTaskSuspend */
\r
1769 /*-----------------------------------------------------------*/
\r
1771 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
\r
1773 BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
\r
1775 BaseType_t xYieldRequired = pdFALSE;
\r
1776 TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
\r
1777 UBaseType_t uxSavedInterruptStatus;
\r
1779 configASSERT( xTaskToResume );
\r
1781 /* RTOS ports that support interrupt nesting have the concept of a
\r
1782 maximum system call (or maximum API call) interrupt priority.
\r
1783 Interrupts that are above the maximum system call priority are keep
\r
1784 permanently enabled, even when the RTOS kernel is in a critical section,
\r
1785 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
1786 is defined in FreeRTOSConfig.h then
\r
1787 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1788 failure if a FreeRTOS API function is called from an interrupt that has
\r
1789 been assigned a priority above the configured maximum system call
\r
1790 priority. Only FreeRTOS functions that end in FromISR can be called
\r
1791 from interrupts that have been assigned a priority at or (logically)
\r
1792 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
1793 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
1794 simple as possible. More information (albeit Cortex-M specific) is
\r
1795 provided on the following link:
\r
1796 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1797 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1799 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1801 if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
\r
1803 traceTASK_RESUME_FROM_ISR( pxTCB );
\r
1805 /* Check the ready lists can be accessed. */
\r
1806 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
1808 /* Ready lists can be accessed so move the task from the
\r
1809 suspended list to the ready list directly. */
\r
1810 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1812 xYieldRequired = pdTRUE;
\r
1816 mtCOVERAGE_TEST_MARKER();
\r
1819 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
1820 prvAddTaskToReadyList( pxTCB );
\r
1824 /* The delayed or ready lists cannot be accessed so the task
\r
1825 is held in the pending ready list until the scheduler is
\r
1827 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
1832 mtCOVERAGE_TEST_MARKER();
\r
1835 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1837 return xYieldRequired;
\r
1840 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
\r
1841 /*-----------------------------------------------------------*/
\r
1843 void vTaskStartScheduler( void )
\r
1845 BaseType_t xReturn;
\r
1847 /* Add the idle task at the lowest priority. */
\r
1848 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
1850 StaticTask_t *pxIdleTaskTCBBuffer = NULL;
\r
1851 StackType_t *pxIdleTaskStackBuffer = NULL;
\r
1852 uint32_t ulIdleTaskStackSize;
\r
1854 /* The Idle task is created using user provided RAM - obtain the
\r
1855 address of the RAM then create the idle task. */
\r
1856 vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );
\r
1857 xIdleTaskHandle = xTaskCreateStatic( prvIdleTask,
\r
1859 ulIdleTaskStackSize,
\r
1860 ( void * ) NULL, /*lint !e961. The cast is not redundant for all compilers. */
\r
1861 ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),
\r
1862 pxIdleTaskStackBuffer,
\r
1863 pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
\r
1865 if( xIdleTaskHandle != NULL )
\r
1876 /* The Idle task is being created using dynamically allocated RAM. */
\r
1877 xReturn = xTaskCreate( prvIdleTask,
\r
1878 "IDLE", configMINIMAL_STACK_SIZE,
\r
1880 ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),
\r
1881 &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
\r
1883 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
1885 #if ( configUSE_TIMERS == 1 )
\r
1887 if( xReturn == pdPASS )
\r
1889 xReturn = xTimerCreateTimerTask();
\r
1893 mtCOVERAGE_TEST_MARKER();
\r
1896 #endif /* configUSE_TIMERS */
\r
1898 if( xReturn == pdPASS )
\r
1900 /* Interrupts are turned off here, to ensure a tick does not occur
\r
1901 before or during the call to xPortStartScheduler(). The stacks of
\r
1902 the created tasks contain a status word with interrupts switched on
\r
1903 so interrupts will automatically get re-enabled when the first task
\r
1905 portDISABLE_INTERRUPTS();
\r
1907 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
1909 /* Switch Newlib's _impure_ptr variable to point to the _reent
\r
1910 structure specific to the task that will run first. */
\r
1911 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
\r
1913 #endif /* configUSE_NEWLIB_REENTRANT */
\r
1915 xNextTaskUnblockTime = portMAX_DELAY;
\r
1916 xSchedulerRunning = pdTRUE;
\r
1917 xTickCount = ( TickType_t ) 0U;
\r
1919 /* If configGENERATE_RUN_TIME_STATS is defined then the following
\r
1920 macro must be defined to configure the timer/counter used to generate
\r
1921 the run time counter time base. NOTE: If configGENERATE_RUN_TIME_STATS
\r
1922 is set to 0 and the following line fails to build then ensure you do not
\r
1923 have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your
\r
1924 FreeRTOSConfig.h file. */
\r
1925 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
\r
1927 /* Setting up the timer tick is hardware specific and thus in the
\r
1928 portable interface. */
\r
1929 if( xPortStartScheduler() != pdFALSE )
\r
1931 /* Should not reach here as if the scheduler is running the
\r
1932 function will not return. */
\r
1936 /* Should only reach here if a task calls xTaskEndScheduler(). */
\r
1941 /* This line will only be reached if the kernel could not be started,
\r
1942 because there was not enough FreeRTOS heap to create the idle task
\r
1943 or the timer task. */
\r
1944 configASSERT( xReturn != errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY );
\r
1947 /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,
\r
1948 meaning xIdleTaskHandle is not used anywhere else. */
\r
1949 ( void ) xIdleTaskHandle;
\r
1951 /*-----------------------------------------------------------*/
\r
1953 void vTaskEndScheduler( void )
\r
1955 /* Stop the scheduler interrupts and call the portable scheduler end
\r
1956 routine so the original ISRs can be restored if necessary. The port
\r
1957 layer must ensure interrupts enable bit is left in the correct state. */
\r
1958 portDISABLE_INTERRUPTS();
\r
1959 xSchedulerRunning = pdFALSE;
\r
1960 vPortEndScheduler();
\r
1962 /*----------------------------------------------------------*/
\r
1964 void vTaskSuspendAll( void )
\r
1966 /* A critical section is not required as the variable is of type
\r
1967 BaseType_t. Please read Richard Barry's reply in the following link to a
\r
1968 post in the FreeRTOS support forum before reporting this as a bug! -
\r
1969 http://goo.gl/wu4acr */
\r
1970 ++uxSchedulerSuspended;
\r
1972 /*----------------------------------------------------------*/
\r
1974 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
1976 static TickType_t prvGetExpectedIdleTime( void )
\r
1978 TickType_t xReturn;
\r
1979 UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;
\r
1981 /* uxHigherPriorityReadyTasks takes care of the case where
\r
1982 configUSE_PREEMPTION is 0, so there may be tasks above the idle priority
\r
1983 task that are in the Ready state, even though the idle task is
\r
1985 #if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
\r
1987 if( uxTopReadyPriority > tskIDLE_PRIORITY )
\r
1989 uxHigherPriorityReadyTasks = pdTRUE;
\r
1994 const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;
\r
1996 /* When port optimised task selection is used the uxTopReadyPriority
\r
1997 variable is used as a bit map. If bits other than the least
\r
1998 significant bit are set then there are tasks that have a priority
\r
1999 above the idle priority that are in the Ready state. This takes
\r
2000 care of the case where the co-operative scheduler is in use. */
\r
2001 if( uxTopReadyPriority > uxLeastSignificantBit )
\r
2003 uxHigherPriorityReadyTasks = pdTRUE;
\r
2008 if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
\r
2012 else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
\r
2014 /* There are other idle priority tasks in the ready state. If
\r
2015 time slicing is used then the very next tick interrupt must be
\r
2019 else if( uxHigherPriorityReadyTasks != pdFALSE )
\r
2021 /* There are tasks in the Ready state that have a priority above the
\r
2022 idle priority. This path can only be reached if
\r
2023 configUSE_PREEMPTION is 0. */
\r
2028 xReturn = xNextTaskUnblockTime - xTickCount;
\r
2034 #endif /* configUSE_TICKLESS_IDLE */
\r
2035 /*----------------------------------------------------------*/
\r
2037 BaseType_t xTaskResumeAll( void )
\r
2039 TCB_t *pxTCB = NULL;
\r
2040 BaseType_t xAlreadyYielded = pdFALSE;
\r
2042 /* If uxSchedulerSuspended is zero then this function does not match a
\r
2043 previous call to vTaskSuspendAll(). */
\r
2044 configASSERT( uxSchedulerSuspended );
\r
2046 /* It is possible that an ISR caused a task to be removed from an event
\r
2047 list while the scheduler was suspended. If this was the case then the
\r
2048 removed task will have been added to the xPendingReadyList. Once the
\r
2049 scheduler has been resumed it is safe to move all the pending ready
\r
2050 tasks from this list into their appropriate ready list. */
\r
2051 taskENTER_CRITICAL();
\r
2053 --uxSchedulerSuspended;
\r
2055 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
2057 if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )
\r
2059 /* Move any readied tasks from the pending list into the
\r
2060 appropriate ready list. */
\r
2061 while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
\r
2063 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );
\r
2064 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
2065 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
2066 prvAddTaskToReadyList( pxTCB );
\r
2068 /* If the moved task has a priority higher than the current
\r
2069 task then a yield must be performed. */
\r
2070 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
2072 xYieldPending = pdTRUE;
\r
2076 mtCOVERAGE_TEST_MARKER();
\r
2080 if( pxTCB != NULL )
\r
2082 /* A task was unblocked while the scheduler was suspended,
\r
2083 which may have prevented the next unblock time from being
\r
2084 re-calculated, in which case re-calculate it now. Mainly
\r
2085 important for low power tickless implementations, where
\r
2086 this can prevent an unnecessary exit from low power
\r
2088 prvResetNextTaskUnblockTime();
\r
2091 /* If any ticks occurred while the scheduler was suspended then
\r
2092 they should be processed now. This ensures the tick count does
\r
2093 not slip, and that any delayed tasks are resumed at the correct
\r
2096 UBaseType_t uxPendedCounts = uxPendedTicks; /* Non-volatile copy. */
\r
2098 if( uxPendedCounts > ( UBaseType_t ) 0U )
\r
2102 if( xTaskIncrementTick() != pdFALSE )
\r
2104 xYieldPending = pdTRUE;
\r
2108 mtCOVERAGE_TEST_MARKER();
\r
2111 } while( uxPendedCounts > ( UBaseType_t ) 0U );
\r
2113 uxPendedTicks = 0;
\r
2117 mtCOVERAGE_TEST_MARKER();
\r
2121 if( xYieldPending != pdFALSE )
\r
2123 #if( configUSE_PREEMPTION != 0 )
\r
2125 xAlreadyYielded = pdTRUE;
\r
2128 taskYIELD_IF_USING_PREEMPTION();
\r
2132 mtCOVERAGE_TEST_MARKER();
\r
2138 mtCOVERAGE_TEST_MARKER();
\r
2141 taskEXIT_CRITICAL();
\r
2143 return xAlreadyYielded;
\r
2145 /*-----------------------------------------------------------*/
\r
2147 TickType_t xTaskGetTickCount( void )
\r
2149 TickType_t xTicks;
\r
2151 /* Critical section required if running on a 16 bit processor. */
\r
2152 portTICK_TYPE_ENTER_CRITICAL();
\r
2154 xTicks = xTickCount;
\r
2156 portTICK_TYPE_EXIT_CRITICAL();
\r
2160 /*-----------------------------------------------------------*/
\r
2162 TickType_t xTaskGetTickCountFromISR( void )
\r
2164 TickType_t xReturn;
\r
2165 UBaseType_t uxSavedInterruptStatus;
\r
2167 /* RTOS ports that support interrupt nesting have the concept of a maximum
\r
2168 system call (or maximum API call) interrupt priority. Interrupts that are
\r
2169 above the maximum system call priority are kept permanently enabled, even
\r
2170 when the RTOS kernel is in a critical section, but cannot make any calls to
\r
2171 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
\r
2172 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
2173 failure if a FreeRTOS API function is called from an interrupt that has been
\r
2174 assigned a priority above the configured maximum system call priority.
\r
2175 Only FreeRTOS functions that end in FromISR can be called from interrupts
\r
2176 that have been assigned a priority at or (logically) below the maximum
\r
2177 system call interrupt priority. FreeRTOS maintains a separate interrupt
\r
2178 safe API to ensure interrupt entry is as fast and as simple as possible.
\r
2179 More information (albeit Cortex-M specific) is provided on the following
\r
2180 link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
2181 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
2183 uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR();
\r
2185 xReturn = xTickCount;
\r
2187 portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
2191 /*-----------------------------------------------------------*/
\r
2193 UBaseType_t uxTaskGetNumberOfTasks( void )
\r
2195 /* A critical section is not required because the variables are of type
\r
2197 return uxCurrentNumberOfTasks;
\r
2199 /*-----------------------------------------------------------*/
\r
2201 char *pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
2205 /* If null is passed in here then the name of the calling task is being
\r
2207 pxTCB = prvGetTCBFromHandle( xTaskToQuery );
\r
2208 configASSERT( pxTCB );
\r
2209 return &( pxTCB->pcTaskName[ 0 ] );
\r
2211 /*-----------------------------------------------------------*/
\r
2213 #if ( INCLUDE_xTaskGetHandle == 1 )
\r
2215 static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] )
\r
2217 TCB_t *pxNextTCB, *pxFirstTCB, *pxReturn = NULL;
\r
2221 /* This function is called with the scheduler suspended. */
\r
2223 if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
\r
2225 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
\r
2229 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
\r
2231 /* Check each character in the name looking for a match or
\r
2233 for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
\r
2235 cNextChar = pxNextTCB->pcTaskName[ x ];
\r
2237 if( cNextChar != pcNameToQuery[ x ] )
\r
2239 /* Characters didn't match. */
\r
2242 else if( cNextChar == 0x00 )
\r
2244 /* Both strings terminated, a match must have been
\r
2246 pxReturn = pxNextTCB;
\r
2251 mtCOVERAGE_TEST_MARKER();
\r
2255 if( pxReturn != NULL )
\r
2257 /* The handle has been found. */
\r
2261 } while( pxNextTCB != pxFirstTCB );
\r
2265 mtCOVERAGE_TEST_MARKER();
\r
2271 #endif /* INCLUDE_xTaskGetHandle */
\r
2272 /*-----------------------------------------------------------*/
\r
2274 #if ( INCLUDE_xTaskGetHandle == 1 )
\r
2276 TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
2278 UBaseType_t uxQueue = configMAX_PRIORITIES;
\r
2281 /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */
\r
2282 configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN );
\r
2284 vTaskSuspendAll();
\r
2286 /* Search the ready lists. */
\r
2290 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery );
\r
2292 if( pxTCB != NULL )
\r
2294 /* Found the handle. */
\r
2298 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2300 /* Search the delayed lists. */
\r
2301 if( pxTCB == NULL )
\r
2303 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery );
\r
2306 if( pxTCB == NULL )
\r
2308 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery );
\r
2311 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2313 if( pxTCB == NULL )
\r
2315 /* Search the suspended list. */
\r
2316 pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery );
\r
2321 #if( INCLUDE_vTaskDelete == 1 )
\r
2323 if( pxTCB == NULL )
\r
2325 /* Search the deleted list. */
\r
2326 pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery );
\r
2331 ( void ) xTaskResumeAll();
\r
2333 return ( TaskHandle_t ) pxTCB;
\r
2336 #endif /* INCLUDE_xTaskGetHandle */
\r
2337 /*-----------------------------------------------------------*/
\r
2339 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2341 UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime )
\r
2343 UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
\r
2345 vTaskSuspendAll();
\r
2347 /* Is there a space in the array for each task in the system? */
\r
2348 if( uxArraySize >= uxCurrentNumberOfTasks )
\r
2350 /* Fill in an TaskStatus_t structure with information on each
\r
2351 task in the Ready state. */
\r
2355 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
\r
2357 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2359 /* Fill in an TaskStatus_t structure with information on each
\r
2360 task in the Blocked state. */
\r
2361 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );
\r
2362 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );
\r
2364 #if( INCLUDE_vTaskDelete == 1 )
\r
2366 /* Fill in an TaskStatus_t structure with information on
\r
2367 each task that has been deleted but not yet cleaned up. */
\r
2368 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
\r
2372 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2374 /* Fill in an TaskStatus_t structure with information on
\r
2375 each task in the Suspended state. */
\r
2376 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
\r
2380 #if ( configGENERATE_RUN_TIME_STATS == 1)
\r
2382 if( pulTotalRunTime != NULL )
\r
2384 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
2385 portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
\r
2387 *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
2393 if( pulTotalRunTime != NULL )
\r
2395 *pulTotalRunTime = 0;
\r
2402 mtCOVERAGE_TEST_MARKER();
\r
2405 ( void ) xTaskResumeAll();
\r
2410 #endif /* configUSE_TRACE_FACILITY */
\r
2411 /*----------------------------------------------------------*/
\r
2413 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
2415 TaskHandle_t xTaskGetIdleTaskHandle( void )
\r
2417 /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
\r
2418 started, then xIdleTaskHandle will be NULL. */
\r
2419 configASSERT( ( xIdleTaskHandle != NULL ) );
\r
2420 return xIdleTaskHandle;
\r
2423 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
\r
2424 /*----------------------------------------------------------*/
\r
2426 /* This conditional compilation should use inequality to 0, not equality to 1.
\r
2427 This is to ensure vTaskStepTick() is available when user defined low power mode
\r
2428 implementations require configUSE_TICKLESS_IDLE to be set to a value other than
\r
2430 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
2432 void vTaskStepTick( const TickType_t xTicksToJump )
\r
2434 /* Correct the tick count value after a period during which the tick
\r
2435 was suppressed. Note this does *not* call the tick hook function for
\r
2436 each stepped tick. */
\r
2437 configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
\r
2438 xTickCount += xTicksToJump;
\r
2439 traceINCREASE_TICK_COUNT( xTicksToJump );
\r
2442 #endif /* configUSE_TICKLESS_IDLE */
\r
2443 /*----------------------------------------------------------*/
\r
2445 #if ( INCLUDE_xTaskAbortDelay == 1 )
\r
2447 BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
\r
2449 TCB_t *pxTCB = ( TCB_t * ) xTask;
\r
2450 BaseType_t xReturn = pdFALSE;
\r
2452 configASSERT( pxTCB );
\r
2454 vTaskSuspendAll();
\r
2456 /* A task can only be prematurely removed from the Blocked state if
\r
2457 it is actually in the Blocked state. */
\r
2458 if( eTaskGetState( xTask ) == eBlocked )
\r
2460 /* Remove the reference to the task from the blocked list. An
\r
2461 interrupt won't touch the xStateListItem because the
\r
2462 scheduler is suspended. */
\r
2463 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
2465 /* Is the task waiting on an event also? If so remove it from
\r
2466 the event list too. Interrupts can touch the event list item,
\r
2467 even though the scheduler is suspended, so a critical section
\r
2469 taskENTER_CRITICAL();
\r
2471 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
2473 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
2474 pxTCB->ucDelayAborted = pdTRUE;
\r
2478 mtCOVERAGE_TEST_MARKER();
\r
2481 taskEXIT_CRITICAL();
\r
2483 /* Place the unblocked task into the appropriate ready list. */
\r
2484 prvAddTaskToReadyList( pxTCB );
\r
2486 /* A task being unblocked cannot cause an immediate context
\r
2487 switch if preemption is turned off. */
\r
2488 #if ( configUSE_PREEMPTION == 1 )
\r
2490 /* Preemption is on, but a context switch should only be
\r
2491 performed if the unblocked task has a priority that is
\r
2492 equal to or higher than the currently executing task. */
\r
2493 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
2495 /* Pend the yield to be performed when the scheduler
\r
2496 is unsuspended. */
\r
2497 xYieldPending = pdTRUE;
\r
2501 mtCOVERAGE_TEST_MARKER();
\r
2504 #endif /* configUSE_PREEMPTION */
\r
2508 mtCOVERAGE_TEST_MARKER();
\r
2511 ( void ) xTaskResumeAll();
\r
2516 #endif /* INCLUDE_xTaskAbortDelay */
\r
2517 /*----------------------------------------------------------*/
\r
2519 BaseType_t xTaskIncrementTick( void )
\r
2522 TickType_t xItemValue;
\r
2523 BaseType_t xSwitchRequired = pdFALSE;
\r
2525 /* Called by the portable layer each time a tick interrupt occurs.
\r
2526 Increments the tick then checks to see if the new tick value will cause any
\r
2527 tasks to be unblocked. */
\r
2528 traceTASK_INCREMENT_TICK( xTickCount );
\r
2529 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
2531 /* Minor optimisation. The tick count cannot change in this
\r
2533 const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
\r
2535 /* Increment the RTOS tick, switching the delayed and overflowed
\r
2536 delayed lists if it wraps to 0. */
\r
2537 xTickCount = xConstTickCount;
\r
2539 if( xConstTickCount == ( TickType_t ) 0U ) /*lint !e774 'if' does not always evaluate to false as it is looking for an overflow. */
\r
2541 taskSWITCH_DELAYED_LISTS();
\r
2545 mtCOVERAGE_TEST_MARKER();
\r
2548 /* See if this tick has made a timeout expire. Tasks are stored in
\r
2549 the queue in the order of their wake time - meaning once one task
\r
2550 has been found whose block time has not expired there is no need to
\r
2551 look any further down the list. */
\r
2552 if( xConstTickCount >= xNextTaskUnblockTime )
\r
2556 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
\r
2558 /* The delayed list is empty. Set xNextTaskUnblockTime
\r
2559 to the maximum possible value so it is extremely
\r
2561 if( xTickCount >= xNextTaskUnblockTime ) test will pass
\r
2562 next time through. */
\r
2563 xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2568 /* The delayed list is not empty, get the value of the
\r
2569 item at the head of the delayed list. This is the time
\r
2570 at which the task at the head of the delayed list must
\r
2571 be removed from the Blocked state. */
\r
2572 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
\r
2573 xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );
\r
2575 if( xConstTickCount < xItemValue )
\r
2577 /* It is not time to unblock this item yet, but the
\r
2578 item value is the time at which the task at the head
\r
2579 of the blocked list must be removed from the Blocked
\r
2580 state - so record the item value in
\r
2581 xNextTaskUnblockTime. */
\r
2582 xNextTaskUnblockTime = xItemValue;
\r
2587 mtCOVERAGE_TEST_MARKER();
\r
2590 /* It is time to remove the item from the Blocked state. */
\r
2591 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
2593 /* Is the task waiting on an event also? If so remove
\r
2594 it from the event list. */
\r
2595 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
2597 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
2601 mtCOVERAGE_TEST_MARKER();
\r
2604 /* Place the unblocked task into the appropriate ready
\r
2606 prvAddTaskToReadyList( pxTCB );
\r
2608 /* A task being unblocked cannot cause an immediate
\r
2609 context switch if preemption is turned off. */
\r
2610 #if ( configUSE_PREEMPTION == 1 )
\r
2612 /* Preemption is on, but a context switch should
\r
2613 only be performed if the unblocked task has a
\r
2614 priority that is equal to or higher than the
\r
2615 currently executing task. */
\r
2616 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
2618 xSwitchRequired = pdTRUE;
\r
2622 mtCOVERAGE_TEST_MARKER();
\r
2625 #endif /* configUSE_PREEMPTION */
\r
2630 /* Tasks of equal priority to the currently running task will share
\r
2631 processing time (time slice) if preemption is on, and the application
\r
2632 writer has not explicitly turned time slicing off. */
\r
2633 #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
\r
2635 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )
\r
2637 xSwitchRequired = pdTRUE;
\r
2641 mtCOVERAGE_TEST_MARKER();
\r
2644 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
\r
2646 #if ( configUSE_TICK_HOOK == 1 )
\r
2648 /* Guard against the tick hook being called when the pended tick
\r
2649 count is being unwound (when the scheduler is being unlocked). */
\r
2650 if( uxPendedTicks == ( UBaseType_t ) 0U )
\r
2652 vApplicationTickHook();
\r
2656 mtCOVERAGE_TEST_MARKER();
\r
2659 #endif /* configUSE_TICK_HOOK */
\r
2665 /* The tick hook gets called at regular intervals, even if the
\r
2666 scheduler is locked. */
\r
2667 #if ( configUSE_TICK_HOOK == 1 )
\r
2669 vApplicationTickHook();
\r
2674 #if ( configUSE_PREEMPTION == 1 )
\r
2676 if( xYieldPending != pdFALSE )
\r
2678 xSwitchRequired = pdTRUE;
\r
2682 mtCOVERAGE_TEST_MARKER();
\r
2685 #endif /* configUSE_PREEMPTION */
\r
2687 return xSwitchRequired;
\r
2689 /*-----------------------------------------------------------*/
\r
2691 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2693 void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction )
\r
2697 /* If xTask is NULL then it is the task hook of the calling task that is
\r
2699 if( xTask == NULL )
\r
2701 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2705 xTCB = ( TCB_t * ) xTask;
\r
2708 /* Save the hook function in the TCB. A critical section is required as
\r
2709 the value can be accessed from an interrupt. */
\r
2710 taskENTER_CRITICAL();
\r
2711 xTCB->pxTaskTag = pxHookFunction;
\r
2712 taskEXIT_CRITICAL();
\r
2715 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2716 /*-----------------------------------------------------------*/
\r
2718 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2720 TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
\r
2723 TaskHookFunction_t xReturn;
\r
2725 /* If xTask is NULL then we are setting our own task hook. */
\r
2726 if( xTask == NULL )
\r
2728 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2732 xTCB = ( TCB_t * ) xTask;
\r
2735 /* Save the hook function in the TCB. A critical section is required as
\r
2736 the value can be accessed from an interrupt. */
\r
2737 taskENTER_CRITICAL();
\r
2739 xReturn = xTCB->pxTaskTag;
\r
2741 taskEXIT_CRITICAL();
\r
2746 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2747 /*-----------------------------------------------------------*/
\r
2749 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2751 BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter )
\r
2754 BaseType_t xReturn;
\r
2756 /* If xTask is NULL then we are calling our own task hook. */
\r
2757 if( xTask == NULL )
\r
2759 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2763 xTCB = ( TCB_t * ) xTask;
\r
2766 if( xTCB->pxTaskTag != NULL )
\r
2768 xReturn = xTCB->pxTaskTag( pvParameter );
\r
2778 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2779 /*-----------------------------------------------------------*/
\r
2781 void vTaskSwitchContext( void )
\r
2783 if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )
\r
2785 /* The scheduler is currently suspended - do not allow a context
\r
2787 xYieldPending = pdTRUE;
\r
2791 xYieldPending = pdFALSE;
\r
2792 traceTASK_SWITCHED_OUT();
\r
2794 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
2796 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
2797 portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
\r
2799 ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
2802 /* Add the amount of time the task has been running to the
\r
2803 accumulated time so far. The time the task started running was
\r
2804 stored in ulTaskSwitchedInTime. Note that there is no overflow
\r
2805 protection here so count values are only valid until the timer
\r
2806 overflows. The guard against negative values is to protect
\r
2807 against suspect run time stat counter implementations - which
\r
2808 are provided by the application, not the kernel. */
\r
2809 if( ulTotalRunTime > ulTaskSwitchedInTime )
\r
2811 pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
\r
2815 mtCOVERAGE_TEST_MARKER();
\r
2817 ulTaskSwitchedInTime = ulTotalRunTime;
\r
2819 #endif /* configGENERATE_RUN_TIME_STATS */
\r
2821 /* Check for stack overflow, if configured. */
\r
2822 taskCHECK_FOR_STACK_OVERFLOW();
\r
2824 /* Select a new task to run using either the generic C or port
\r
2825 optimised asm code. */
\r
2826 taskSELECT_HIGHEST_PRIORITY_TASK();
\r
2827 traceTASK_SWITCHED_IN();
\r
2829 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
2831 /* Switch Newlib's _impure_ptr variable to point to the _reent
\r
2832 structure specific to this task. */
\r
2833 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
\r
2835 #endif /* configUSE_NEWLIB_REENTRANT */
\r
2838 /*-----------------------------------------------------------*/
\r
2840 void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )
\r
2842 configASSERT( pxEventList );
\r
2844 /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
\r
2845 SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
\r
2847 /* Place the event list item of the TCB in the appropriate event list.
\r
2848 This is placed in the list in priority order so the highest priority task
\r
2849 is the first to be woken by the event. The queue that contains the event
\r
2850 list is locked, preventing simultaneous access from interrupts. */
\r
2851 vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2853 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
\r
2855 /*-----------------------------------------------------------*/
\r
2857 void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait )
\r
2859 configASSERT( pxEventList );
\r
2861 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
\r
2862 the event groups implementation. */
\r
2863 configASSERT( uxSchedulerSuspended != 0 );
\r
2865 /* Store the item value in the event list item. It is safe to access the
\r
2866 event list item here as interrupts won't access the event list item of a
\r
2867 task that is not in the Blocked state. */
\r
2868 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
\r
2870 /* Place the event list item of the TCB at the end of the appropriate event
\r
2871 list. It is safe to access the event list here because it is part of an
\r
2872 event group implementation - and interrupts don't access event groups
\r
2873 directly (instead they access them indirectly by pending function calls to
\r
2874 the task level). */
\r
2875 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2877 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
\r
2879 /*-----------------------------------------------------------*/
\r
2881 #if( configUSE_TIMERS == 1 )
\r
2883 void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely )
\r
2885 configASSERT( pxEventList );
\r
2887 /* This function should not be called by application code hence the
\r
2888 'Restricted' in its name. It is not part of the public API. It is
\r
2889 designed for use by kernel code, and has special calling requirements -
\r
2890 it should be called with the scheduler suspended. */
\r
2893 /* Place the event list item of the TCB in the appropriate event list.
\r
2894 In this case it is assume that this is the only task that is going to
\r
2895 be waiting on this event list, so the faster vListInsertEnd() function
\r
2896 can be used in place of vListInsert. */
\r
2897 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2899 /* If the task should block indefinitely then set the block time to a
\r
2900 value that will be recognised as an indefinite delay inside the
\r
2901 prvAddCurrentTaskToDelayedList() function. */
\r
2902 if( xWaitIndefinitely != pdFALSE )
\r
2904 xTicksToWait = portMAX_DELAY;
\r
2907 traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) );
\r
2908 prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely );
\r
2911 #endif /* configUSE_TIMERS */
\r
2912 /*-----------------------------------------------------------*/
\r
2914 BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
\r
2916 TCB_t *pxUnblockedTCB;
\r
2917 BaseType_t xReturn;
\r
2919 /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be
\r
2920 called from a critical section within an ISR. */
\r
2922 /* The event list is sorted in priority order, so the first in the list can
\r
2923 be removed as it is known to be the highest priority. Remove the TCB from
\r
2924 the delayed list, and add it to the ready list.
\r
2926 If an event is for a queue that is locked then this function will never
\r
2927 get called - the lock count on the queue will get modified instead. This
\r
2928 means exclusive access to the event list is guaranteed here.
\r
2930 This function assumes that a check has already been made to ensure that
\r
2931 pxEventList is not empty. */
\r
2932 pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
\r
2933 configASSERT( pxUnblockedTCB );
\r
2934 ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
\r
2936 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
2938 ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
\r
2939 prvAddTaskToReadyList( pxUnblockedTCB );
\r
2943 /* The delayed and ready lists cannot be accessed, so hold this task
\r
2944 pending until the scheduler is resumed. */
\r
2945 vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
\r
2948 if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
2950 /* Return true if the task removed from the event list has a higher
\r
2951 priority than the calling task. This allows the calling task to know if
\r
2952 it should force a context switch now. */
\r
2955 /* Mark that a yield is pending in case the user is not using the
\r
2956 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
\r
2957 xYieldPending = pdTRUE;
\r
2961 xReturn = pdFALSE;
\r
2964 #if( configUSE_TICKLESS_IDLE != 0 )
\r
2966 /* If a task is blocked on a kernel object then xNextTaskUnblockTime
\r
2967 might be set to the blocked task's time out time. If the task is
\r
2968 unblocked for a reason other than a timeout xNextTaskUnblockTime is
\r
2969 normally left unchanged, because it is automatically reset to a new
\r
2970 value when the tick count equals xNextTaskUnblockTime. However if
\r
2971 tickless idling is used it might be more important to enter sleep mode
\r
2972 at the earliest possible time - so reset xNextTaskUnblockTime here to
\r
2973 ensure it is updated at the earliest possible time. */
\r
2974 prvResetNextTaskUnblockTime();
\r
2980 /*-----------------------------------------------------------*/
\r
2982 void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )
\r
2984 TCB_t *pxUnblockedTCB;
\r
2986 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
\r
2987 the event flags implementation. */
\r
2988 configASSERT( uxSchedulerSuspended != pdFALSE );
\r
2990 /* Store the new item value in the event list. */
\r
2991 listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
\r
2993 /* Remove the event list form the event flag. Interrupts do not access
\r
2995 pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem );
\r
2996 configASSERT( pxUnblockedTCB );
\r
2997 ( void ) uxListRemove( pxEventListItem );
\r
2999 /* Remove the task from the delayed list and add it to the ready list. The
\r
3000 scheduler is suspended so interrupts will not be accessing the ready
\r
3002 ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
\r
3003 prvAddTaskToReadyList( pxUnblockedTCB );
\r
3005 if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
3007 /* The unblocked task has a priority above that of the calling task, so
\r
3008 a context switch is required. This function is called with the
\r
3009 scheduler suspended so xYieldPending is set so the context switch
\r
3010 occurs immediately that the scheduler is resumed (unsuspended). */
\r
3011 xYieldPending = pdTRUE;
\r
3014 /*-----------------------------------------------------------*/
\r
3016 void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
\r
3018 configASSERT( pxTimeOut );
\r
3019 pxTimeOut->xOverflowCount = xNumOfOverflows;
\r
3020 pxTimeOut->xTimeOnEntering = xTickCount;
\r
3022 /*-----------------------------------------------------------*/
\r
3024 BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait )
\r
3026 BaseType_t xReturn;
\r
3028 configASSERT( pxTimeOut );
\r
3029 configASSERT( pxTicksToWait );
\r
3031 taskENTER_CRITICAL();
\r
3033 /* Minor optimisation. The tick count cannot change in this block. */
\r
3034 const TickType_t xConstTickCount = xTickCount;
\r
3036 #if( INCLUDE_xTaskAbortDelay == 1 )
\r
3037 if( pxCurrentTCB->ucDelayAborted != pdFALSE )
\r
3039 /* The delay was aborted, which is not the same as a time out,
\r
3040 but has the same result. */
\r
3041 pxCurrentTCB->ucDelayAborted = pdFALSE;
\r
3047 #if ( INCLUDE_vTaskSuspend == 1 )
\r
3048 if( *pxTicksToWait == portMAX_DELAY )
\r
3050 /* If INCLUDE_vTaskSuspend is set to 1 and the block time
\r
3051 specified is the maximum block time then the task should block
\r
3052 indefinitely, and therefore never time out. */
\r
3053 xReturn = pdFALSE;
\r
3058 if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
\r
3060 /* The tick count is greater than the time at which
\r
3061 vTaskSetTimeout() was called, but has also overflowed since
\r
3062 vTaskSetTimeOut() was called. It must have wrapped all the way
\r
3063 around and gone past again. This passed since vTaskSetTimeout()
\r
3067 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
3069 /* Not a genuine timeout. Adjust parameters for time remaining. */
\r
3070 *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );
\r
3071 vTaskSetTimeOutState( pxTimeOut );
\r
3072 xReturn = pdFALSE;
\r
3079 taskEXIT_CRITICAL();
\r
3083 /*-----------------------------------------------------------*/
\r
3085 void vTaskMissedYield( void )
\r
3087 xYieldPending = pdTRUE;
\r
3089 /*-----------------------------------------------------------*/
\r
3091 #if ( configUSE_TRACE_FACILITY == 1 )
\r
3093 UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )
\r
3095 UBaseType_t uxReturn;
\r
3098 if( xTask != NULL )
\r
3100 pxTCB = ( TCB_t * ) xTask;
\r
3101 uxReturn = pxTCB->uxTaskNumber;
\r
3111 #endif /* configUSE_TRACE_FACILITY */
\r
3112 /*-----------------------------------------------------------*/
\r
3114 #if ( configUSE_TRACE_FACILITY == 1 )
\r
3116 void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle )
\r
3120 if( xTask != NULL )
\r
3122 pxTCB = ( TCB_t * ) xTask;
\r
3123 pxTCB->uxTaskNumber = uxHandle;
\r
3127 #endif /* configUSE_TRACE_FACILITY */
\r
3130 * -----------------------------------------------------------
\r
3132 * ----------------------------------------------------------
\r
3134 * The portTASK_FUNCTION() macro is used to allow port/compiler specific
\r
3135 * language extensions. The equivalent prototype for this function is:
\r
3137 * void prvIdleTask( void *pvParameters );
\r
3140 static portTASK_FUNCTION( prvIdleTask, pvParameters )
\r
3142 /* Stop warnings. */
\r
3143 ( void ) pvParameters;
\r
3145 /** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
\r
3146 SCHEDULER IS STARTED. **/
\r
3150 /* See if any tasks have deleted themselves - if so then the idle task
\r
3151 is responsible for freeing the deleted task's TCB and stack. */
\r
3152 prvCheckTasksWaitingTermination();
\r
3154 #if ( configUSE_PREEMPTION == 0 )
\r
3156 /* If we are not using preemption we keep forcing a task switch to
\r
3157 see if any other task has become available. If we are using
\r
3158 preemption we don't need to do this as any task becoming available
\r
3159 will automatically get the processor anyway. */
\r
3162 #endif /* configUSE_PREEMPTION */
\r
3164 #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
\r
3166 /* When using preemption tasks of equal priority will be
\r
3167 timesliced. If a task that is sharing the idle priority is ready
\r
3168 to run then the idle task should yield before the end of the
\r
3171 A critical region is not required here as we are just reading from
\r
3172 the list, and an occasional incorrect value will not matter. If
\r
3173 the ready list at the idle priority contains more than one task
\r
3174 then a task other than the idle task is ready to execute. */
\r
3175 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )
\r
3181 mtCOVERAGE_TEST_MARKER();
\r
3184 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
\r
3186 #if ( configUSE_IDLE_HOOK == 1 )
\r
3188 extern void vApplicationIdleHook( void );
\r
3190 /* Call the user defined function from within the idle task. This
\r
3191 allows the application designer to add background functionality
\r
3192 without the overhead of a separate task.
\r
3193 NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
\r
3194 CALL A FUNCTION THAT MIGHT BLOCK. */
\r
3195 vApplicationIdleHook();
\r
3197 #endif /* configUSE_IDLE_HOOK */
\r
3199 /* This conditional compilation should use inequality to 0, not equality
\r
3200 to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
\r
3201 user defined low power mode implementations require
\r
3202 configUSE_TICKLESS_IDLE to be set to a value other than 1. */
\r
3203 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
3205 TickType_t xExpectedIdleTime;
\r
3207 /* It is not desirable to suspend then resume the scheduler on
\r
3208 each iteration of the idle task. Therefore, a preliminary
\r
3209 test of the expected idle time is performed without the
\r
3210 scheduler suspended. The result here is not necessarily
\r
3212 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
3214 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
3216 vTaskSuspendAll();
\r
3218 /* Now the scheduler is suspended, the expected idle
\r
3219 time can be sampled again, and this time its value can
\r
3221 configASSERT( xNextTaskUnblockTime >= xTickCount );
\r
3222 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
3224 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
3226 traceLOW_POWER_IDLE_BEGIN();
\r
3227 portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
\r
3228 traceLOW_POWER_IDLE_END();
\r
3232 mtCOVERAGE_TEST_MARKER();
\r
3235 ( void ) xTaskResumeAll();
\r
3239 mtCOVERAGE_TEST_MARKER();
\r
3242 #endif /* configUSE_TICKLESS_IDLE */
\r
3245 /*-----------------------------------------------------------*/
\r
3247 #if( configUSE_TICKLESS_IDLE != 0 )
\r
3249 eSleepModeStatus eTaskConfirmSleepModeStatus( void )
\r
3251 /* The idle task exists in addition to the application tasks. */
\r
3252 const UBaseType_t uxNonApplicationTasks = 1;
\r
3253 eSleepModeStatus eReturn = eStandardSleep;
\r
3255 if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
\r
3257 /* A task was made ready while the scheduler was suspended. */
\r
3258 eReturn = eAbortSleep;
\r
3260 else if( xYieldPending != pdFALSE )
\r
3262 /* A yield was pended while the scheduler was suspended. */
\r
3263 eReturn = eAbortSleep;
\r
3267 /* If all the tasks are in the suspended list (which might mean they
\r
3268 have an infinite block time rather than actually being suspended)
\r
3269 then it is safe to turn all clocks off and just wait for external
\r
3271 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
\r
3273 eReturn = eNoTasksWaitingTimeout;
\r
3277 mtCOVERAGE_TEST_MARKER();
\r
3284 #endif /* configUSE_TICKLESS_IDLE */
\r
3285 /*-----------------------------------------------------------*/
\r
3287 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
\r
3289 void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue )
\r
3293 if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS )
\r
3295 pxTCB = prvGetTCBFromHandle( xTaskToSet );
\r
3296 pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue;
\r
3300 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
\r
3301 /*-----------------------------------------------------------*/
\r
3303 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
\r
3305 void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex )
\r
3307 void *pvReturn = NULL;
\r
3310 if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS )
\r
3312 pxTCB = prvGetTCBFromHandle( xTaskToQuery );
\r
3313 pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ];
\r
3323 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
\r
3324 /*-----------------------------------------------------------*/
\r
3326 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
3328 void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions )
\r
3332 /* If null is passed in here then we are modifying the MPU settings of
\r
3333 the calling task. */
\r
3334 pxTCB = prvGetTCBFromHandle( xTaskToModify );
\r
3336 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
\r
3339 #endif /* portUSING_MPU_WRAPPERS */
\r
3340 /*-----------------------------------------------------------*/
\r
3342 static void prvInitialiseTaskLists( void )
\r
3344 UBaseType_t uxPriority;
\r
3346 for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
\r
3348 vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
\r
3351 vListInitialise( &xDelayedTaskList1 );
\r
3352 vListInitialise( &xDelayedTaskList2 );
\r
3353 vListInitialise( &xPendingReadyList );
\r
3355 #if ( INCLUDE_vTaskDelete == 1 )
\r
3357 vListInitialise( &xTasksWaitingTermination );
\r
3359 #endif /* INCLUDE_vTaskDelete */
\r
3361 #if ( INCLUDE_vTaskSuspend == 1 )
\r
3363 vListInitialise( &xSuspendedTaskList );
\r
3365 #endif /* INCLUDE_vTaskSuspend */
\r
3367 /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
\r
3369 pxDelayedTaskList = &xDelayedTaskList1;
\r
3370 pxOverflowDelayedTaskList = &xDelayedTaskList2;
\r
3372 /*-----------------------------------------------------------*/
\r
3374 static void prvCheckTasksWaitingTermination( void )
\r
3377 /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/
\r
3379 #if ( INCLUDE_vTaskDelete == 1 )
\r
3381 BaseType_t xListIsEmpty;
\r
3383 /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
\r
3384 too often in the idle task. */
\r
3385 while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
\r
3387 vTaskSuspendAll();
\r
3389 xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
\r
3391 ( void ) xTaskResumeAll();
\r
3393 if( xListIsEmpty == pdFALSE )
\r
3397 taskENTER_CRITICAL();
\r
3399 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
\r
3400 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
3401 --uxCurrentNumberOfTasks;
\r
3402 --uxDeletedTasksWaitingCleanUp;
\r
3404 taskEXIT_CRITICAL();
\r
3406 prvDeleteTCB( pxTCB );
\r
3410 mtCOVERAGE_TEST_MARKER();
\r
3414 #endif /* INCLUDE_vTaskDelete */
\r
3416 /*-----------------------------------------------------------*/
\r
3418 #if( configUSE_TRACE_FACILITY == 1 )
\r
3420 void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState )
\r
3424 /* xTask is NULL then get the state of the calling task. */
\r
3425 pxTCB = prvGetTCBFromHandle( xTask );
\r
3427 pxTaskStatus->xHandle = ( TaskHandle_t ) pxTCB;
\r
3428 pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName [ 0 ] );
\r
3429 pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority;
\r
3430 pxTaskStatus->pxStackBase = pxTCB->pxStack;
\r
3431 pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber;
\r
3433 #if ( INCLUDE_vTaskSuspend == 1 )
\r
3435 /* If the task is in the suspended list then there is a chance it is
\r
3436 actually just blocked indefinitely - so really it should be reported as
\r
3437 being in the Blocked state. */
\r
3438 if( pxTaskStatus->eCurrentState == eSuspended )
\r
3440 vTaskSuspendAll();
\r
3442 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
3444 pxTaskStatus->eCurrentState = eBlocked;
\r
3447 ( void ) xTaskResumeAll();
\r
3450 #endif /* INCLUDE_vTaskSuspend */
\r
3452 #if ( configUSE_MUTEXES == 1 )
\r
3454 pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;
\r
3458 pxTaskStatus->uxBasePriority = 0;
\r
3462 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
3464 pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter;
\r
3468 pxTaskStatus->ulRunTimeCounter = 0;
\r
3472 /* Obtaining the task state is a little fiddly, so is only done if the value
\r
3473 of eState passed into this function is eInvalid - otherwise the state is
\r
3474 just set to whatever is passed in. */
\r
3475 if( eState != eInvalid )
\r
3477 pxTaskStatus->eCurrentState = eState;
\r
3481 pxTaskStatus->eCurrentState = eTaskGetState( xTask );
\r
3484 /* Obtaining the stack space takes some time, so the xGetFreeStackSpace
\r
3485 parameter is provided to allow it to be skipped. */
\r
3486 if( xGetFreeStackSpace != pdFALSE )
\r
3488 #if ( portSTACK_GROWTH > 0 )
\r
3490 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack );
\r
3494 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack );
\r
3500 pxTaskStatus->usStackHighWaterMark = 0;
\r
3504 #endif /* configUSE_TRACE_FACILITY */
\r
3505 /*-----------------------------------------------------------*/
\r
3507 #if ( configUSE_TRACE_FACILITY == 1 )
\r
3509 static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )
\r
3511 configLIST_VOLATILE TCB_t *pxNextTCB, *pxFirstTCB;
\r
3512 UBaseType_t uxTask = 0;
\r
3514 if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
\r
3516 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
\r
3518 /* Populate an TaskStatus_t structure within the
\r
3519 pxTaskStatusArray array for each task that is referenced from
\r
3520 pxList. See the definition of TaskStatus_t in task.h for the
\r
3521 meaning of each TaskStatus_t structure member. */
\r
3524 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
\r
3525 vTaskGetInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState );
\r
3527 } while( pxNextTCB != pxFirstTCB );
\r
3531 mtCOVERAGE_TEST_MARKER();
\r
3537 #endif /* configUSE_TRACE_FACILITY */
\r
3538 /*-----------------------------------------------------------*/
\r
3540 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
3542 static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
\r
3544 uint32_t ulCount = 0U;
\r
3546 while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE )
\r
3548 pucStackByte -= portSTACK_GROWTH;
\r
3552 ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */
\r
3554 return ( uint16_t ) ulCount;
\r
3557 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */
\r
3558 /*-----------------------------------------------------------*/
\r
3560 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
\r
3562 UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
\r
3565 uint8_t *pucEndOfStack;
\r
3566 UBaseType_t uxReturn;
\r
3568 pxTCB = prvGetTCBFromHandle( xTask );
\r
3570 #if portSTACK_GROWTH < 0
\r
3572 pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
\r
3576 pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
\r
3580 uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );
\r
3585 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
\r
3586 /*-----------------------------------------------------------*/
\r
3588 #if ( INCLUDE_vTaskDelete == 1 )
\r
3590 static void prvDeleteTCB( TCB_t *pxTCB )
\r
3592 /* This call is required specifically for the TriCore port. It must be
\r
3593 above the vPortFree() calls. The call is also used by ports/demos that
\r
3594 want to allocate and clean RAM statically. */
\r
3595 portCLEAN_UP_TCB( pxTCB );
\r
3597 /* Free up the memory allocated by the scheduler for the task. It is up
\r
3598 to the task to free any memory allocated at the application level. */
\r
3599 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
3601 _reclaim_reent( &( pxTCB->xNewLib_reent ) );
\r
3603 #endif /* configUSE_NEWLIB_REENTRANT */
\r
3605 #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( portUSING_MPU_WRAPPERS == 0 ) )
\r
3607 /* The task can only have been allocated dynamically - free both
\r
3608 the stack and TCB. */
\r
3609 vPortFree( pxTCB->pxStack );
\r
3610 vPortFree( pxTCB );
\r
3612 #elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */
\r
3614 /* The task could have been allocated statically or dynamically, so
\r
3615 check what was statically allocated before trying to free the
\r
3617 if( pxTCB->ucStaticallyAllocated == tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB )
\r
3619 /* Both the stack and TCB were allocated dynamically, so both
\r
3621 vPortFree( pxTCB->pxStack );
\r
3622 vPortFree( pxTCB );
\r
3624 else if( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_ONLY )
\r
3626 /* Only the stack was statically allocated, so the TCB is the
\r
3627 only memory that must be freed. */
\r
3628 vPortFree( pxTCB );
\r
3632 /* Neither the stack nor the TCB were allocated dynamically, so
\r
3633 nothing needs to be freed. */
\r
3634 configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB )
\r
3635 mtCOVERAGE_TEST_MARKER();
\r
3638 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
3641 #endif /* INCLUDE_vTaskDelete */
\r
3642 /*-----------------------------------------------------------*/
\r
3644 static void prvResetNextTaskUnblockTime( void )
\r
3648 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
\r
3650 /* The new current delayed list is empty. Set xNextTaskUnblockTime to
\r
3651 the maximum possible value so it is extremely unlikely that the
\r
3652 if( xTickCount >= xNextTaskUnblockTime ) test will pass until
\r
3653 there is an item in the delayed list. */
\r
3654 xNextTaskUnblockTime = portMAX_DELAY;
\r
3658 /* The new current delayed list is not empty, get the value of
\r
3659 the item at the head of the delayed list. This is the time at
\r
3660 which the task at the head of the delayed list should be removed
\r
3661 from the Blocked state. */
\r
3662 ( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
\r
3663 xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xStateListItem ) );
\r
3666 /*-----------------------------------------------------------*/
\r
3668 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
\r
3670 TaskHandle_t xTaskGetCurrentTaskHandle( void )
\r
3672 TaskHandle_t xReturn;
\r
3674 /* A critical section is not required as this is not called from
\r
3675 an interrupt and the current TCB will always be the same for any
\r
3676 individual execution thread. */
\r
3677 xReturn = pxCurrentTCB;
\r
3682 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
\r
3683 /*-----------------------------------------------------------*/
\r
3685 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
3687 BaseType_t xTaskGetSchedulerState( void )
\r
3689 BaseType_t xReturn;
\r
3691 if( xSchedulerRunning == pdFALSE )
\r
3693 xReturn = taskSCHEDULER_NOT_STARTED;
\r
3697 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
3699 xReturn = taskSCHEDULER_RUNNING;
\r
3703 xReturn = taskSCHEDULER_SUSPENDED;
\r
3710 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
\r
3711 /*-----------------------------------------------------------*/
\r
3713 #if ( configUSE_MUTEXES == 1 )
\r
3715 void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
\r
3717 TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
\r
3719 /* If the mutex was given back by an interrupt while the queue was
\r
3720 locked then the mutex holder might now be NULL. */
\r
3721 if( pxMutexHolder != NULL )
\r
3723 /* If the holder of the mutex has a priority below the priority of
\r
3724 the task attempting to obtain the mutex then it will temporarily
\r
3725 inherit the priority of the task attempting to obtain the mutex. */
\r
3726 if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
\r
3728 /* Adjust the mutex holder state to account for its new
\r
3729 priority. Only reset the event list item value if the value is
\r
3730 not being used for anything else. */
\r
3731 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
\r
3733 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
3737 mtCOVERAGE_TEST_MARKER();
\r
3740 /* If the task being modified is in the ready state it will need
\r
3741 to be moved into a new list. */
\r
3742 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
\r
3744 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
3746 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
3750 mtCOVERAGE_TEST_MARKER();
\r
3753 /* Inherit the priority before being moved into the new list. */
\r
3754 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
3755 prvAddTaskToReadyList( pxTCB );
\r
3759 /* Just inherit the priority. */
\r
3760 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
3763 traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );
\r
3767 mtCOVERAGE_TEST_MARKER();
\r
3772 mtCOVERAGE_TEST_MARKER();
\r
3776 #endif /* configUSE_MUTEXES */
\r
3777 /*-----------------------------------------------------------*/
\r
3779 #if ( configUSE_MUTEXES == 1 )
\r
3781 BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )
\r
3783 TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
\r
3784 BaseType_t xReturn = pdFALSE;
\r
3786 if( pxMutexHolder != NULL )
\r
3788 /* A task can only have an inherited priority if it holds the mutex.
\r
3789 If the mutex is held by a task then it cannot be given from an
\r
3790 interrupt, and if a mutex is given by the holding task then it must
\r
3791 be the running state task. */
\r
3792 configASSERT( pxTCB == pxCurrentTCB );
\r
3794 configASSERT( pxTCB->uxMutexesHeld );
\r
3795 ( pxTCB->uxMutexesHeld )--;
\r
3797 /* Has the holder of the mutex inherited the priority of another
\r
3799 if( pxTCB->uxPriority != pxTCB->uxBasePriority )
\r
3801 /* Only disinherit if no other mutexes are held. */
\r
3802 if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
\r
3804 /* A task can only have an inherited priority if it holds
\r
3805 the mutex. If the mutex is held by a task then it cannot be
\r
3806 given from an interrupt, and if a mutex is given by the
\r
3807 holding task then it must be the running state task. Remove
\r
3808 the holding task from the ready list. */
\r
3809 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
3811 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
3815 mtCOVERAGE_TEST_MARKER();
\r
3818 /* Disinherit the priority before adding the task into the
\r
3819 new ready list. */
\r
3820 traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
\r
3821 pxTCB->uxPriority = pxTCB->uxBasePriority;
\r
3823 /* Reset the event list item value. It cannot be in use for
\r
3824 any other purpose if this task is running, and it must be
\r
3825 running to give back the mutex. */
\r
3826 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
3827 prvAddTaskToReadyList( pxTCB );
\r
3829 /* Return true to indicate that a context switch is required.
\r
3830 This is only actually required in the corner case whereby
\r
3831 multiple mutexes were held and the mutexes were given back
\r
3832 in an order different to that in which they were taken.
\r
3833 If a context switch did not occur when the first mutex was
\r
3834 returned, even if a task was waiting on it, then a context
\r
3835 switch should occur when the last mutex is returned whether
\r
3836 a task is waiting on it or not. */
\r
3841 mtCOVERAGE_TEST_MARKER();
\r
3846 mtCOVERAGE_TEST_MARKER();
\r
3851 mtCOVERAGE_TEST_MARKER();
\r
3857 #endif /* configUSE_MUTEXES */
\r
3858 /*-----------------------------------------------------------*/
\r
3860 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
3862 void vTaskEnterCritical( void )
\r
3864 portDISABLE_INTERRUPTS();
\r
3866 if( xSchedulerRunning != pdFALSE )
\r
3868 ( pxCurrentTCB->uxCriticalNesting )++;
\r
3870 /* This is not the interrupt safe version of the enter critical
\r
3871 function so assert() if it is being called from an interrupt
\r
3872 context. Only API functions that end in "FromISR" can be used in an
\r
3873 interrupt. Only assert if the critical nesting count is 1 to
\r
3874 protect against recursive calls if the assert function also uses a
\r
3875 critical section. */
\r
3876 if( pxCurrentTCB->uxCriticalNesting == 1 )
\r
3878 portASSERT_IF_IN_ISR();
\r
3883 mtCOVERAGE_TEST_MARKER();
\r
3887 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
3888 /*-----------------------------------------------------------*/
\r
3890 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
3892 void vTaskExitCritical( void )
\r
3894 if( xSchedulerRunning != pdFALSE )
\r
3896 if( pxCurrentTCB->uxCriticalNesting > 0U )
\r
3898 ( pxCurrentTCB->uxCriticalNesting )--;
\r
3900 if( pxCurrentTCB->uxCriticalNesting == 0U )
\r
3902 portENABLE_INTERRUPTS();
\r
3906 mtCOVERAGE_TEST_MARKER();
\r
3911 mtCOVERAGE_TEST_MARKER();
\r
3916 mtCOVERAGE_TEST_MARKER();
\r
3920 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
3921 /*-----------------------------------------------------------*/
\r
3923 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
3925 static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName )
\r
3929 /* Start by copying the entire string. */
\r
3930 strcpy( pcBuffer, pcTaskName );
\r
3932 /* Pad the end of the string with spaces to ensure columns line up when
\r
3934 for( x = strlen( pcBuffer ); x < ( size_t ) ( configMAX_TASK_NAME_LEN - 1 ); x++ )
\r
3936 pcBuffer[ x ] = ' ';
\r
3940 pcBuffer[ x ] = 0x00;
\r
3942 /* Return the new end of string. */
\r
3943 return &( pcBuffer[ x ] );
\r
3946 #endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
\r
3947 /*-----------------------------------------------------------*/
\r
3949 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
3951 void vTaskList( char * pcWriteBuffer )
\r
3953 TaskStatus_t *pxTaskStatusArray;
\r
3954 volatile UBaseType_t uxArraySize, x;
\r
3960 * This function is provided for convenience only, and is used by many
\r
3961 * of the demo applications. Do not consider it to be part of the
\r
3964 * vTaskList() calls uxTaskGetSystemState(), then formats part of the
\r
3965 * uxTaskGetSystemState() output into a human readable table that
\r
3966 * displays task names, states and stack usage.
\r
3968 * vTaskList() has a dependency on the sprintf() C library function that
\r
3969 * might bloat the code size, use a lot of stack, and provide different
\r
3970 * results on different platforms. An alternative, tiny, third party,
\r
3971 * and limited functionality implementation of sprintf() is provided in
\r
3972 * many of the FreeRTOS/Demo sub-directories in a file called
\r
3973 * printf-stdarg.c (note printf-stdarg.c does not provide a full
\r
3974 * snprintf() implementation!).
\r
3976 * It is recommended that production systems call uxTaskGetSystemState()
\r
3977 * directly to get access to raw stats data, rather than indirectly
\r
3978 * through a call to vTaskList().
\r
3982 /* Make sure the write buffer does not contain a string. */
\r
3983 *pcWriteBuffer = 0x00;
\r
3985 /* Take a snapshot of the number of tasks in case it changes while this
\r
3986 function is executing. */
\r
3987 uxArraySize = uxCurrentNumberOfTasks;
\r
3989 /* Allocate an array index for each task. NOTE! if
\r
3990 configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
\r
3991 equate to NULL. */
\r
3992 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
\r
3994 if( pxTaskStatusArray != NULL )
\r
3996 /* Generate the (binary) data. */
\r
3997 uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
\r
3999 /* Create a human readable table from the binary data. */
\r
4000 for( x = 0; x < uxArraySize; x++ )
\r
4002 switch( pxTaskStatusArray[ x ].eCurrentState )
\r
4004 case eReady: cStatus = tskREADY_CHAR;
\r
4007 case eBlocked: cStatus = tskBLOCKED_CHAR;
\r
4010 case eSuspended: cStatus = tskSUSPENDED_CHAR;
\r
4013 case eDeleted: cStatus = tskDELETED_CHAR;
\r
4016 default: /* Should not get here, but it is included
\r
4017 to prevent static checking errors. */
\r
4022 /* Write the task name to the string, padding with spaces so it
\r
4023 can be printed in tabular form more easily. */
\r
4024 pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
\r
4026 /* Write the rest of the string. */
\r
4027 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
4028 pcWriteBuffer += strlen( pcWriteBuffer );
\r
4031 /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
\r
4032 is 0 then vPortFree() will be #defined to nothing. */
\r
4033 vPortFree( pxTaskStatusArray );
\r
4037 mtCOVERAGE_TEST_MARKER();
\r
4041 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
\r
4042 /*----------------------------------------------------------*/
\r
4044 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
4046 void vTaskGetRunTimeStats( char *pcWriteBuffer )
\r
4048 TaskStatus_t *pxTaskStatusArray;
\r
4049 volatile UBaseType_t uxArraySize, x;
\r
4050 uint32_t ulTotalTime, ulStatsAsPercentage;
\r
4052 #if( configUSE_TRACE_FACILITY != 1 )
\r
4054 #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats().
\r
4061 * This function is provided for convenience only, and is used by many
\r
4062 * of the demo applications. Do not consider it to be part of the
\r
4065 * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part
\r
4066 * of the uxTaskGetSystemState() output into a human readable table that
\r
4067 * displays the amount of time each task has spent in the Running state
\r
4068 * in both absolute and percentage terms.
\r
4070 * vTaskGetRunTimeStats() has a dependency on the sprintf() C library
\r
4071 * function that might bloat the code size, use a lot of stack, and
\r
4072 * provide different results on different platforms. An alternative,
\r
4073 * tiny, third party, and limited functionality implementation of
\r
4074 * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in
\r
4075 * a file called printf-stdarg.c (note printf-stdarg.c does not provide
\r
4076 * a full snprintf() implementation!).
\r
4078 * It is recommended that production systems call uxTaskGetSystemState()
\r
4079 * directly to get access to raw stats data, rather than indirectly
\r
4080 * through a call to vTaskGetRunTimeStats().
\r
4083 /* Make sure the write buffer does not contain a string. */
\r
4084 *pcWriteBuffer = 0x00;
\r
4086 /* Take a snapshot of the number of tasks in case it changes while this
\r
4087 function is executing. */
\r
4088 uxArraySize = uxCurrentNumberOfTasks;
\r
4090 /* Allocate an array index for each task. NOTE! If
\r
4091 configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
\r
4092 equate to NULL. */
\r
4093 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
\r
4095 if( pxTaskStatusArray != NULL )
\r
4097 /* Generate the (binary) data. */
\r
4098 uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
\r
4100 /* For percentage calculations. */
\r
4101 ulTotalTime /= 100UL;
\r
4103 /* Avoid divide by zero errors. */
\r
4104 if( ulTotalTime > 0 )
\r
4106 /* Create a human readable table from the binary data. */
\r
4107 for( x = 0; x < uxArraySize; x++ )
\r
4109 /* What percentage of the total run time has the task used?
\r
4110 This will always be rounded down to the nearest integer.
\r
4111 ulTotalRunTimeDiv100 has already been divided by 100. */
\r
4112 ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
\r
4114 /* Write the task name to the string, padding with
\r
4115 spaces so it can be printed in tabular form more
\r
4117 pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
\r
4119 if( ulStatsAsPercentage > 0UL )
\r
4121 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
4123 sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
\r
4127 /* sizeof( int ) == sizeof( long ) so a smaller
\r
4128 printf() library can be used. */
\r
4129 sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );
\r
4135 /* If the percentage is zero here then the task has
\r
4136 consumed less than 1% of the total run time. */
\r
4137 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
4139 sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter );
\r
4143 /* sizeof( int ) == sizeof( long ) so a smaller
\r
4144 printf() library can be used. */
\r
4145 sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter );
\r
4150 pcWriteBuffer += strlen( pcWriteBuffer );
\r
4155 mtCOVERAGE_TEST_MARKER();
\r
4158 /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
\r
4159 is 0 then vPortFree() will be #defined to nothing. */
\r
4160 vPortFree( pxTaskStatusArray );
\r
4164 mtCOVERAGE_TEST_MARKER();
\r
4168 #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
\r
4169 /*-----------------------------------------------------------*/
\r
4171 TickType_t uxTaskResetEventItemValue( void )
\r
4173 TickType_t uxReturn;
\r
4175 uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );
\r
4177 /* Reset the event list item to its normal value - so it can be used with
\r
4178 queues and semaphores. */
\r
4179 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
4183 /*-----------------------------------------------------------*/
\r
4185 #if ( configUSE_MUTEXES == 1 )
\r
4187 void *pvTaskIncrementMutexHeldCount( void )
\r
4189 /* If xSemaphoreCreateMutex() is called before any tasks have been created
\r
4190 then pxCurrentTCB will be NULL. */
\r
4191 if( pxCurrentTCB != NULL )
\r
4193 ( pxCurrentTCB->uxMutexesHeld )++;
\r
4196 return pxCurrentTCB;
\r
4199 #endif /* configUSE_MUTEXES */
\r
4200 /*-----------------------------------------------------------*/
\r
4202 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4204 uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )
\r
4206 uint32_t ulReturn;
\r
4208 taskENTER_CRITICAL();
\r
4210 /* Only block if the notification count is not already non-zero. */
\r
4211 if( pxCurrentTCB->ulNotifiedValue == 0UL )
\r
4213 /* Mark this task as waiting for a notification. */
\r
4214 pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;
\r
4216 if( xTicksToWait > ( TickType_t ) 0 )
\r
4218 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
\r
4219 traceTASK_NOTIFY_TAKE_BLOCK();
\r
4221 /* All ports are written to allow a yield in a critical
\r
4222 section (some will yield immediately, others wait until the
\r
4223 critical section exits) - but it is not something that
\r
4224 application code should ever do. */
\r
4225 portYIELD_WITHIN_API();
\r
4229 mtCOVERAGE_TEST_MARKER();
\r
4234 mtCOVERAGE_TEST_MARKER();
\r
4237 taskEXIT_CRITICAL();
\r
4239 taskENTER_CRITICAL();
\r
4241 traceTASK_NOTIFY_TAKE();
\r
4242 ulReturn = pxCurrentTCB->ulNotifiedValue;
\r
4244 if( ulReturn != 0UL )
\r
4246 if( xClearCountOnExit != pdFALSE )
\r
4248 pxCurrentTCB->ulNotifiedValue = 0UL;
\r
4252 pxCurrentTCB->ulNotifiedValue = ulReturn - ( uint32_t ) 1;
\r
4257 mtCOVERAGE_TEST_MARKER();
\r
4260 pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
\r
4262 taskEXIT_CRITICAL();
\r
4267 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4268 /*-----------------------------------------------------------*/
\r
4270 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4272 BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait )
\r
4274 BaseType_t xReturn;
\r
4276 taskENTER_CRITICAL();
\r
4278 /* Only block if a notification is not already pending. */
\r
4279 if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED )
\r
4281 /* Clear bits in the task's notification value as bits may get
\r
4282 set by the notifying task or interrupt. This can be used to
\r
4283 clear the value to zero. */
\r
4284 pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry;
\r
4286 /* Mark this task as waiting for a notification. */
\r
4287 pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;
\r
4289 if( xTicksToWait > ( TickType_t ) 0 )
\r
4291 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
\r
4292 traceTASK_NOTIFY_WAIT_BLOCK();
\r
4294 /* All ports are written to allow a yield in a critical
\r
4295 section (some will yield immediately, others wait until the
\r
4296 critical section exits) - but it is not something that
\r
4297 application code should ever do. */
\r
4298 portYIELD_WITHIN_API();
\r
4302 mtCOVERAGE_TEST_MARKER();
\r
4307 mtCOVERAGE_TEST_MARKER();
\r
4310 taskEXIT_CRITICAL();
\r
4312 taskENTER_CRITICAL();
\r
4314 traceTASK_NOTIFY_WAIT();
\r
4316 if( pulNotificationValue != NULL )
\r
4318 /* Output the current notification value, which may or may not
\r
4320 *pulNotificationValue = pxCurrentTCB->ulNotifiedValue;
\r
4323 /* If ucNotifyValue is set then either the task never entered the
\r
4324 blocked state (because a notification was already pending) or the
\r
4325 task unblocked because of a notification. Otherwise the task
\r
4326 unblocked because of a timeout. */
\r
4327 if( pxCurrentTCB->ucNotifyState == taskWAITING_NOTIFICATION )
\r
4329 /* A notification was not received. */
\r
4330 xReturn = pdFALSE;
\r
4334 /* A notification was already pending or a notification was
\r
4335 received while the task was waiting. */
\r
4336 pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnExit;
\r
4340 pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
\r
4342 taskEXIT_CRITICAL();
\r
4347 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4348 /*-----------------------------------------------------------*/
\r
4350 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4352 BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue )
\r
4355 BaseType_t xReturn = pdPASS;
\r
4356 uint8_t ucOriginalNotifyState;
\r
4358 configASSERT( xTaskToNotify );
\r
4359 pxTCB = ( TCB_t * ) xTaskToNotify;
\r
4361 taskENTER_CRITICAL();
\r
4363 if( pulPreviousNotificationValue != NULL )
\r
4365 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
\r
4368 ucOriginalNotifyState = pxTCB->ucNotifyState;
\r
4370 pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
\r
4375 pxTCB->ulNotifiedValue |= ulValue;
\r
4379 ( pxTCB->ulNotifiedValue )++;
\r
4382 case eSetValueWithOverwrite :
\r
4383 pxTCB->ulNotifiedValue = ulValue;
\r
4386 case eSetValueWithoutOverwrite :
\r
4387 if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
\r
4389 pxTCB->ulNotifiedValue = ulValue;
\r
4393 /* The value could not be written to the task. */
\r
4399 /* The task is being notified without its notify value being
\r
4404 traceTASK_NOTIFY();
\r
4406 /* If the task is in the blocked state specifically to wait for a
\r
4407 notification then unblock it now. */
\r
4408 if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
\r
4410 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
4411 prvAddTaskToReadyList( pxTCB );
\r
4413 /* The task should not have been on an event list. */
\r
4414 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
\r
4416 #if( configUSE_TICKLESS_IDLE != 0 )
\r
4418 /* If a task is blocked waiting for a notification then
\r
4419 xNextTaskUnblockTime might be set to the blocked task's time
\r
4420 out time. If the task is unblocked for a reason other than
\r
4421 a timeout xNextTaskUnblockTime is normally left unchanged,
\r
4422 because it will automatically get reset to a new value when
\r
4423 the tick count equals xNextTaskUnblockTime. However if
\r
4424 tickless idling is used it might be more important to enter
\r
4425 sleep mode at the earliest possible time - so reset
\r
4426 xNextTaskUnblockTime here to ensure it is updated at the
\r
4427 earliest possible time. */
\r
4428 prvResetNextTaskUnblockTime();
\r
4432 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
4434 /* The notified task has a priority above the currently
\r
4435 executing task so a yield is required. */
\r
4436 taskYIELD_IF_USING_PREEMPTION();
\r
4440 mtCOVERAGE_TEST_MARKER();
\r
4445 mtCOVERAGE_TEST_MARKER();
\r
4448 taskEXIT_CRITICAL();
\r
4453 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4454 /*-----------------------------------------------------------*/
\r
4456 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4458 BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken )
\r
4461 uint8_t ucOriginalNotifyState;
\r
4462 BaseType_t xReturn = pdPASS;
\r
4463 UBaseType_t uxSavedInterruptStatus;
\r
4465 configASSERT( xTaskToNotify );
\r
4467 /* RTOS ports that support interrupt nesting have the concept of a
\r
4468 maximum system call (or maximum API call) interrupt priority.
\r
4469 Interrupts that are above the maximum system call priority are keep
\r
4470 permanently enabled, even when the RTOS kernel is in a critical section,
\r
4471 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
4472 is defined in FreeRTOSConfig.h then
\r
4473 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
4474 failure if a FreeRTOS API function is called from an interrupt that has
\r
4475 been assigned a priority above the configured maximum system call
\r
4476 priority. Only FreeRTOS functions that end in FromISR can be called
\r
4477 from interrupts that have been assigned a priority at or (logically)
\r
4478 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
4479 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
4480 simple as possible. More information (albeit Cortex-M specific) is
\r
4481 provided on the following link:
\r
4482 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
4483 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
4485 pxTCB = ( TCB_t * ) xTaskToNotify;
\r
4487 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
4489 if( pulPreviousNotificationValue != NULL )
\r
4491 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
\r
4494 ucOriginalNotifyState = pxTCB->ucNotifyState;
\r
4495 pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
\r
4500 pxTCB->ulNotifiedValue |= ulValue;
\r
4504 ( pxTCB->ulNotifiedValue )++;
\r
4507 case eSetValueWithOverwrite :
\r
4508 pxTCB->ulNotifiedValue = ulValue;
\r
4511 case eSetValueWithoutOverwrite :
\r
4512 if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
\r
4514 pxTCB->ulNotifiedValue = ulValue;
\r
4518 /* The value could not be written to the task. */
\r
4524 /* The task is being notified without its notify value being
\r
4529 traceTASK_NOTIFY_FROM_ISR();
\r
4531 /* If the task is in the blocked state specifically to wait for a
\r
4532 notification then unblock it now. */
\r
4533 if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
\r
4535 /* The task should not have been on an event list. */
\r
4536 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
\r
4538 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
4540 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
4541 prvAddTaskToReadyList( pxTCB );
\r
4545 /* The delayed and ready lists cannot be accessed, so hold
\r
4546 this task pending until the scheduler is resumed. */
\r
4547 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
4550 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
4552 /* The notified task has a priority above the currently
\r
4553 executing task so a yield is required. */
\r
4554 if( pxHigherPriorityTaskWoken != NULL )
\r
4556 *pxHigherPriorityTaskWoken = pdTRUE;
\r
4560 /* Mark that a yield is pending in case the user is not
\r
4561 using the "xHigherPriorityTaskWoken" parameter to an ISR
\r
4562 safe FreeRTOS function. */
\r
4563 xYieldPending = pdTRUE;
\r
4568 mtCOVERAGE_TEST_MARKER();
\r
4572 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
4577 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4578 /*-----------------------------------------------------------*/
\r
4580 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4582 void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken )
\r
4585 uint8_t ucOriginalNotifyState;
\r
4586 UBaseType_t uxSavedInterruptStatus;
\r
4588 configASSERT( xTaskToNotify );
\r
4590 /* RTOS ports that support interrupt nesting have the concept of a
\r
4591 maximum system call (or maximum API call) interrupt priority.
\r
4592 Interrupts that are above the maximum system call priority are keep
\r
4593 permanently enabled, even when the RTOS kernel is in a critical section,
\r
4594 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
4595 is defined in FreeRTOSConfig.h then
\r
4596 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
4597 failure if a FreeRTOS API function is called from an interrupt that has
\r
4598 been assigned a priority above the configured maximum system call
\r
4599 priority. Only FreeRTOS functions that end in FromISR can be called
\r
4600 from interrupts that have been assigned a priority at or (logically)
\r
4601 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
4602 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
4603 simple as possible. More information (albeit Cortex-M specific) is
\r
4604 provided on the following link:
\r
4605 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
4606 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
4608 pxTCB = ( TCB_t * ) xTaskToNotify;
\r
4610 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
4612 ucOriginalNotifyState = pxTCB->ucNotifyState;
\r
4613 pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
\r
4615 /* 'Giving' is equivalent to incrementing a count in a counting
\r
4617 ( pxTCB->ulNotifiedValue )++;
\r
4619 traceTASK_NOTIFY_GIVE_FROM_ISR();
\r
4621 /* If the task is in the blocked state specifically to wait for a
\r
4622 notification then unblock it now. */
\r
4623 if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
\r
4625 /* The task should not have been on an event list. */
\r
4626 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
\r
4628 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
4630 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
4631 prvAddTaskToReadyList( pxTCB );
\r
4635 /* The delayed and ready lists cannot be accessed, so hold
\r
4636 this task pending until the scheduler is resumed. */
\r
4637 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
4640 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
4642 /* The notified task has a priority above the currently
\r
4643 executing task so a yield is required. */
\r
4644 if( pxHigherPriorityTaskWoken != NULL )
\r
4646 *pxHigherPriorityTaskWoken = pdTRUE;
\r
4650 /* Mark that a yield is pending in case the user is not
\r
4651 using the "xHigherPriorityTaskWoken" parameter in an ISR
\r
4652 safe FreeRTOS function. */
\r
4653 xYieldPending = pdTRUE;
\r
4658 mtCOVERAGE_TEST_MARKER();
\r
4662 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
4665 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4667 /*-----------------------------------------------------------*/
\r
4669 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4671 BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask )
\r
4674 BaseType_t xReturn;
\r
4676 /* If null is passed in here then it is the calling task that is having
\r
4677 its notification state cleared. */
\r
4678 pxTCB = prvGetTCBFromHandle( xTask );
\r
4680 taskENTER_CRITICAL();
\r
4682 if( pxTCB->ucNotifyState == taskNOTIFICATION_RECEIVED )
\r
4684 pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
\r
4692 taskEXIT_CRITICAL();
\r
4697 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4698 /*-----------------------------------------------------------*/
\r
4701 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely )
\r
4703 TickType_t xTimeToWake;
\r
4704 const TickType_t xConstTickCount = xTickCount;
\r
4706 #if( INCLUDE_xTaskAbortDelay == 1 )
\r
4708 /* About to enter a delayed list, so ensure the ucDelayAborted flag is
\r
4709 reset to pdFALSE so it can be detected as having been set to pdTRUE
\r
4710 when the task leaves the Blocked state. */
\r
4711 pxCurrentTCB->ucDelayAborted = pdFALSE;
\r
4715 /* Remove the task from the ready list before adding it to the blocked list
\r
4716 as the same list item is used for both lists. */
\r
4717 if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
4719 /* The current task must be in a ready list, so there is no need to
\r
4720 check, and the port reset macro can be called directly. */
\r
4721 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
4725 mtCOVERAGE_TEST_MARKER();
\r
4728 #if ( INCLUDE_vTaskSuspend == 1 )
\r
4730 if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )
\r
4732 /* Add the task to the suspended task list instead of a delayed task
\r
4733 list to ensure it is not woken by a timing event. It will block
\r
4735 vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
4739 /* Calculate the time at which the task should be woken if the event
\r
4740 does not occur. This may overflow but this doesn't matter, the
\r
4741 kernel will manage it correctly. */
\r
4742 xTimeToWake = xConstTickCount + xTicksToWait;
\r
4744 /* The list item will be inserted in wake time order. */
\r
4745 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
\r
4747 if( xTimeToWake < xConstTickCount )
\r
4749 /* Wake time has overflowed. Place this item in the overflow
\r
4751 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
4755 /* The wake time has not overflowed, so the current block list
\r
4757 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
4759 /* If the task entering the blocked state was placed at the
\r
4760 head of the list of blocked tasks then xNextTaskUnblockTime
\r
4761 needs to be updated too. */
\r
4762 if( xTimeToWake < xNextTaskUnblockTime )
\r
4764 xNextTaskUnblockTime = xTimeToWake;
\r
4768 mtCOVERAGE_TEST_MARKER();
\r
4773 #else /* INCLUDE_vTaskSuspend */
\r
4775 /* Calculate the time at which the task should be woken if the event
\r
4776 does not occur. This may overflow but this doesn't matter, the kernel
\r
4777 will manage it correctly. */
\r
4778 xTimeToWake = xConstTickCount + xTicksToWait;
\r
4780 /* The list item will be inserted in wake time order. */
\r
4781 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
\r
4783 if( xTimeToWake < xConstTickCount )
\r
4785 /* Wake time has overflowed. Place this item in the overflow list. */
\r
4786 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
4790 /* The wake time has not overflowed, so the current block list is used. */
\r
4791 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
4793 /* If the task entering the blocked state was placed at the head of the
\r
4794 list of blocked tasks then xNextTaskUnblockTime needs to be updated
\r
4796 if( xTimeToWake < xNextTaskUnblockTime )
\r
4798 xNextTaskUnblockTime = xTimeToWake;
\r
4802 mtCOVERAGE_TEST_MARKER();
\r
4806 /* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */
\r
4807 ( void ) xCanBlockIndefinitely;
\r
4809 #endif /* INCLUDE_vTaskSuspend */
\r
4812 /* Code below here allows additional code to be inserted into this source file,
\r
4813 especially where access to file scope functions and data is needed (for example
\r
4814 when performing module tests). */
\r
4816 #ifdef FREERTOS_MODULE_TEST
\r
4817 #include "tasks_test_access_functions.h"
\r
4821 #if( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 )
\r
4823 #include "freertos_tasks_c_additions.h"
\r
4825 static void freertos_tasks_c_additions_init( void )
\r
4827 #ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
\r
4828 FREERTOS_TASKS_C_ADDITIONS_INIT();
\r