2 FreeRTOS V9.0.0rc1 - 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
121 * Macros used by vListTask to indicate which state a task is in.
\r
123 #define tskBLOCKED_CHAR ( 'B' )
\r
124 #define tskREADY_CHAR ( 'R' )
\r
125 #define tskDELETED_CHAR ( 'D' )
\r
126 #define tskSUSPENDED_CHAR ( 'S' )
\r
129 * Some kernel aware debuggers require the data the debugger needs access to be
\r
130 * global, rather than file scope.
\r
132 #ifdef portREMOVE_STATIC_QUALIFIER
\r
136 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
\r
138 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
\r
139 performed in a generic way that is not optimised to any particular
\r
140 microcontroller architecture. */
\r
142 /* uxTopReadyPriority holds the priority of the highest priority ready
\r
144 #define taskRECORD_READY_PRIORITY( uxPriority ) \
\r
146 if( ( uxPriority ) > uxTopReadyPriority ) \
\r
148 uxTopReadyPriority = ( uxPriority ); \
\r
150 } /* taskRECORD_READY_PRIORITY */
\r
152 /*-----------------------------------------------------------*/
\r
154 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
156 /* Find the highest priority queue that contains ready tasks. */ \
\r
157 while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) \
\r
159 configASSERT( uxTopReadyPriority ); \
\r
160 --uxTopReadyPriority; \
\r
163 /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
\r
164 the same priority get an equal share of the processor time. */ \
\r
165 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \
\r
166 } /* taskSELECT_HIGHEST_PRIORITY_TASK */
\r
168 /*-----------------------------------------------------------*/
\r
170 /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
\r
171 they are only required when a port optimised method of task selection is
\r
173 #define taskRESET_READY_PRIORITY( uxPriority )
\r
174 #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
176 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
178 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
\r
179 performed in a way that is tailored to the particular microcontroller
\r
180 architecture being used. */
\r
182 /* A port optimised version is provided. Call the port defined macros. */
\r
183 #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
185 /*-----------------------------------------------------------*/
\r
187 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
189 UBaseType_t uxTopPriority; \
\r
191 /* Find the highest priority list that contains ready tasks. */ \
\r
192 portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
\r
193 configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
\r
194 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
\r
195 } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
\r
197 /*-----------------------------------------------------------*/
\r
199 /* A port optimised version is provided, call it only if the TCB being reset
\r
200 is being referenced from a ready list. If it is referenced from a delayed
\r
201 or suspended list then it won't be in a ready list. */
\r
202 #define taskRESET_READY_PRIORITY( uxPriority ) \
\r
204 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \
\r
206 portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \
\r
210 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
212 /*-----------------------------------------------------------*/
\r
214 /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
\r
215 count overflows. */
\r
216 #define taskSWITCH_DELAYED_LISTS() \
\r
220 /* The delayed tasks list should be empty when the lists are switched. */ \
\r
221 configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \
\r
223 pxTemp = pxDelayedTaskList; \
\r
224 pxDelayedTaskList = pxOverflowDelayedTaskList; \
\r
225 pxOverflowDelayedTaskList = pxTemp; \
\r
226 xNumOfOverflows++; \
\r
227 prvResetNextTaskUnblockTime(); \
\r
230 /*-----------------------------------------------------------*/
\r
233 * Place the task represented by pxTCB into the appropriate ready list for
\r
234 * the task. It is inserted at the end of the list.
\r
236 #define prvAddTaskToReadyList( pxTCB ) \
\r
237 traceMOVED_TASK_TO_READY_STATE( pxTCB ); \
\r
238 taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
\r
239 vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
\r
240 tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )
\r
241 /*-----------------------------------------------------------*/
\r
244 * Several functions take an TaskHandle_t parameter that can optionally be NULL,
\r
245 * where NULL is used to indicate that the handle of the currently executing
\r
246 * task should be used in place of the parameter. This macro simply checks to
\r
247 * see if the parameter is NULL and returns a pointer to the appropriate TCB.
\r
249 #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TCB_t * ) pxCurrentTCB : ( TCB_t * ) ( pxHandle ) )
\r
251 /* The item value of the event list item is normally used to hold the priority
\r
252 of the task to which it belongs (coded to allow it to be held in reverse
\r
253 priority order). However, it is occasionally borrowed for other purposes. It
\r
254 is important its value is not updated due to a task priority change while it is
\r
255 being used for another purpose. The following bit definition is used to inform
\r
256 the scheduler that the value should not be changed - in which case it is the
\r
257 responsibility of whichever module is using the value to ensure it gets set back
\r
258 to its original value when it is released. */
\r
259 #if( configUSE_16_BIT_TICKS == 1 )
\r
260 #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U
\r
262 #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL
\r
266 * Task control block. A task control block (TCB) is allocated for each task,
\r
267 * and stores task state information, including a pointer to the task's context
\r
268 * (the task's run time environment, including register values)
\r
270 typedef struct tskTaskControlBlock
\r
272 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
274 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
275 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
278 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
279 ListItem_t xEventListItem; /*< Used to reference a task from an event list. */
\r
280 UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */
\r
281 StackType_t *pxStack; /*< Points to the start of the stack. */
\r
282 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
284 #if ( portSTACK_GROWTH > 0 )
\r
285 StackType_t *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */
\r
288 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
289 UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
\r
292 #if ( configUSE_TRACE_FACILITY == 1 )
\r
293 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
294 UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
\r
297 #if ( configUSE_MUTEXES == 1 )
\r
298 UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
\r
299 UBaseType_t uxMutexesHeld;
\r
302 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
303 TaskHookFunction_t pxTaskTag;
\r
306 #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
\r
307 void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
\r
310 #if( configGENERATE_RUN_TIME_STATS == 1 )
\r
311 uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
\r
314 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
315 /* Allocate a Newlib reent structure that is specific to this task.
\r
316 Note Newlib support has been included by popular demand, but is not
\r
317 used by the FreeRTOS maintainers themselves. FreeRTOS is not
\r
318 responsible for resulting newlib operation. User must be familiar with
\r
319 newlib and must provide system-wide implementations of the necessary
\r
320 stubs. Be warned that (at the time of writing) the current newlib design
\r
321 implements a system-wide malloc() that must be provided with locks. */
\r
322 struct _reent xNewLib_reent;
\r
325 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
326 volatile uint32_t ulNotifiedValue;
\r
327 volatile uint8_t ucNotifyState;
\r
330 #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
\r
331 uint8_t ucStaticallyAllocated; /* Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
\r
334 #if( INCLUDE_xTaskAbortDelay == 1 )
\r
335 uint8_t ucDelayAborted;
\r
340 /* The old tskTCB name is maintained above then typedefed to the new TCB_t name
\r
341 below to enable the use of older kernel aware debuggers. */
\r
342 typedef tskTCB TCB_t;
\r
344 /*lint -e956 A manual analysis and inspection has been used to determine which
\r
345 static variables must be declared volatile. */
\r
347 PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
\r
349 /* Lists for ready and blocked tasks. --------------------*/
\r
350 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */
\r
351 PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */
\r
352 PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
\r
353 PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */
\r
354 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
355 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
357 #if( ( INCLUDE_vTaskDelete == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
\r
359 PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */
\r
360 PRIVILEGED_DATA static volatile UBaseType_t uxDeletedTasksWaitingCleanUp = ( UBaseType_t ) 0U;
\r
364 #if ( INCLUDE_vTaskSuspend == 1 )
\r
366 PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */
\r
370 /* Other file private variables. --------------------------------*/
\r
371 PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
\r
372 PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U;
\r
373 PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
\r
374 PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
\r
375 PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U;
\r
376 PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE;
\r
377 PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
\r
378 PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
\r
379 PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = ( TickType_t ) 0U; /* Initialised to portMAX_DELAY before the scheduler starts. */
\r
380 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
382 /* Context switches are held pending while the scheduler is suspended. Also,
\r
383 interrupts must not manipulate the xStateListItem of a TCB, or any of the
\r
384 lists the xStateListItem can be referenced from, if the scheduler is suspended.
\r
385 If an interrupt needs to unblock a task while the scheduler is suspended then it
\r
386 moves the task's event list item into the xPendingReadyList, ready for the
\r
387 kernel to move the task from the pending ready list into the real ready list
\r
388 when the scheduler is unsuspended. The pending ready list itself can only be
\r
389 accessed from a critical section. */
\r
390 PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE;
\r
392 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
394 PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
\r
395 PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */
\r
401 /*-----------------------------------------------------------*/
\r
403 /* Callback function prototypes. --------------------------*/
\r
404 #if( configCHECK_FOR_STACK_OVERFLOW > 0 )
\r
405 extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName );
\r
408 #if( configUSE_TICK_HOOK > 0 )
\r
409 extern void vApplicationTickHook( void );
\r
412 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
413 extern void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint16_t *pusIdleTaskStackSize );
\r
416 /* File private functions. --------------------------------*/
\r
419 * Utility task that simply returns pdTRUE if the task referenced by xTask is
\r
420 * currently in the Suspended state, or pdFALSE if the task referenced by xTask
\r
421 * is in any other state.
\r
423 #if ( INCLUDE_vTaskSuspend == 1 )
\r
424 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
\r
425 #endif /* INCLUDE_vTaskSuspend */
\r
428 * Utility to ready all the lists used by the scheduler. This is called
\r
429 * automatically upon the creation of the first task.
\r
431 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
\r
434 * The idle task, which as all tasks is implemented as a never ending loop.
\r
435 * The idle task is automatically created and added to the ready lists upon
\r
436 * creation of the first user task.
\r
438 * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
\r
439 * language extensions. The equivalent prototype for this function is:
\r
441 * void prvIdleTask( void *pvParameters );
\r
444 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
\r
447 * Utility to free all memory allocated by the scheduler to hold a TCB,
\r
448 * including the stack pointed to by the TCB.
\r
450 * This does not free memory allocated by the task itself (i.e. memory
\r
451 * allocated by calls to pvPortMalloc from within the tasks application code).
\r
453 #if ( INCLUDE_vTaskDelete == 1 )
\r
455 static void prvDeleteTCB( TCB_t *pxTCB ) PRIVILEGED_FUNCTION;
\r
460 * Used only by the idle task. This checks to see if anything has been placed
\r
461 * in the list of tasks waiting to be deleted. If so the task is cleaned up
\r
462 * and its TCB deleted.
\r
464 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
\r
467 * The currently executing task is entering the Blocked state. Add the task to
\r
468 * either the current or the overflow delayed task list.
\r
470 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely ) PRIVILEGED_FUNCTION;
\r
473 * Fills an TaskStatus_t structure with information on each task that is
\r
474 * referenced from the pxList list (which may be a ready list, a delayed list,
\r
475 * a suspended list, etc.).
\r
477 * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
\r
478 * NORMAL APPLICATION CODE.
\r
480 #if ( configUSE_TRACE_FACILITY == 1 )
\r
482 static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;
\r
487 * Searches pxList for a task with name pcNameToQuery - returning a handle to
\r
488 * the task if it is found, or NULL if the task is not found.
\r
490 #if ( INCLUDE_xTaskGetTaskHandle == 1 )
\r
492 static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] ) PRIVILEGED_FUNCTION;
\r
497 * When a task is created, the stack of the task is filled with a known value.
\r
498 * This function determines the 'high water mark' of the task stack by
\r
499 * determining how much of the stack remains at the original preset value.
\r
501 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
503 static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
\r
508 * Return the amount of time, in ticks, that will pass before the kernel will
\r
509 * next move a task from the Blocked state to the Running state.
\r
511 * This conditional compilation should use inequality to 0, not equality to 1.
\r
512 * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
\r
513 * defined low power mode implementations require configUSE_TICKLESS_IDLE to be
\r
514 * set to a value other than 1.
\r
516 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
518 static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
\r
523 * Set xNextTaskUnblockTime to the time at which the next Blocked state task
\r
524 * will exit the Blocked state.
\r
526 static void prvResetNextTaskUnblockTime( void );
\r
528 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
531 * Helper function used to pad task names with spaces when printing out
\r
532 * human readable tables of task information.
\r
534 static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName ) PRIVILEGED_FUNCTION;
\r
539 * Called after a Task_t structure has been allocated either statically or
\r
540 * dynamically to fill in the structure's members.
\r
542 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
545 * Called after a new task has been created and initialised to place the task
\r
546 * under the control of the scheduler.
\r
548 static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
\r
550 /*-----------------------------------------------------------*/
\r
552 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
554 BaseType_t xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
557 BaseType_t xReturn;
\r
559 configASSERT( puxStackBuffer != NULL );
\r
560 configASSERT( pxTaskBuffer != NULL );
\r
562 /* The memory used for the task's TCB and stack are passed into this
\r
563 function - use them. */
\r
564 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
566 if( pxNewTCB != NULL )
\r
568 pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;
\r
570 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
\r
572 /* Tasks can be created statically or dynamically, so note this
\r
573 task was created statically in case the task is later deleted. */
\r
574 pxNewTCB->ucStaticallyAllocated = pdTRUE;
\r
576 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
578 prvInitialiseNewTask( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB );
\r
579 prvAddNewTaskToReadyList( pxNewTCB );
\r
584 xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
\r
590 #endif /* SUPPORT_STATIC_ALLOCATION */
\r
591 /*-----------------------------------------------------------*/
\r
593 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
\r
595 BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
598 BaseType_t xReturn;
\r
600 /* If the stack grows down then allocate the stack then the TCB so the stack
\r
601 does not grow into the TCB. Likewise if the stack grows up then allocate
\r
602 the TCB then the stack. */
\r
603 #if( portSTACK_GROWTH > 0 )
\r
605 /* Allocate space for the TCB. Where the memory comes from depends on
\r
606 the implementation of the port malloc function and whether or not static
\r
607 allocation is being used. */
\r
608 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
\r
610 if( pxNewTCB != NULL )
\r
612 /* Allocate space for the stack used by the task being created.
\r
613 The base of the stack memory stored in the TCB so the task can
\r
614 be deleted later if required. */
\r
615 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
617 if( pxNewTCB->pxStack == NULL )
\r
619 /* Could not allocate the stack. Delete the allocated TCB. */
\r
620 vPortFree( pxNewTCB );
\r
625 #else /* portSTACK_GROWTH */
\r
627 StackType_t *pxStack;
\r
629 /* Allocate space for the stack used by the task being created. */
\r
630 pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
632 if( pxStack != NULL )
\r
634 /* Allocate space for the TCB. */
\r
635 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e961 MISRA exception as the casts are only redundant for some paths. */
\r
637 if( pxNewTCB != NULL )
\r
639 /* Store the stack location in the TCB. */
\r
640 pxNewTCB->pxStack = pxStack;
\r
644 /* The stack cannot be used as the TCB was not created. Free
\r
646 vPortFree( pxStack );
\r
654 #endif /* portSTACK_GROWTH */
\r
656 if( pxNewTCB != NULL )
\r
658 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
660 /* Tasks can be created statically or dynamically, so note this
\r
661 task was created dynamically in case it is later deleted. */
\r
662 pxNewTCB->ucStaticallyAllocated = pdFALSE;
\r
664 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
666 prvInitialiseNewTask( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB );
\r
667 prvAddNewTaskToReadyList( pxNewTCB );
\r
672 xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
\r
678 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
679 /*-----------------------------------------------------------*/
\r
681 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, TCB_t *pxNewTCB ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
683 StackType_t *pxTopOfStack;
\r
686 #if( portUSING_MPU_WRAPPERS == 1 )
\r
687 /* Should the task be created in privileged mode? */
\r
688 BaseType_t xRunPrivileged;
\r
689 if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
\r
691 xRunPrivileged = pdTRUE;
\r
695 xRunPrivileged = pdFALSE;
\r
697 uxPriority &= ~portPRIVILEGE_BIT;
\r
698 #endif /* portUSING_MPU_WRAPPERS == 1 */
\r
700 /* Avoid dependency on memset() if it is not required. */
\r
701 #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
703 /* Fill the stack with a known value to assist debugging. */
\r
704 ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( StackType_t ) );
\r
706 #endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */
\r
708 /* Calculate the top of stack address. This depends on whether the stack
\r
709 grows from high memory to low (as per the 80x86) or vice versa.
\r
710 portSTACK_GROWTH is used to make the result positive or negative as required
\r
712 #if( portSTACK_GROWTH < 0 )
\r
714 pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( uint16_t ) 1 );
\r
715 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
717 /* Check the alignment of the calculated top of stack is correct. */
\r
718 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
720 #else /* portSTACK_GROWTH */
\r
722 pxTopOfStack = pxNewTCB->pxStack;
\r
724 /* Check the alignment of the stack buffer is correct. */
\r
725 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
727 /* The other extreme of the stack space is required if stack checking is
\r
729 pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - ( uint16_t ) 1 );
\r
731 #endif /* portSTACK_GROWTH */
\r
733 /* Store the task name in the TCB. */
\r
734 for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
\r
736 pxNewTCB->pcTaskName[ x ] = pcName[ x ];
\r
738 /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
\r
739 configMAX_TASK_NAME_LEN characters just in case the memory after the
\r
740 string is not accessible (extremely unlikely). */
\r
741 if( pcName[ x ] == 0x00 )
\r
747 mtCOVERAGE_TEST_MARKER();
\r
751 /* Ensure the name string is terminated in the case that the string length
\r
752 was greater or equal to configMAX_TASK_NAME_LEN. */
\r
753 pxNewTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
\r
755 /* This is used as an array index so must ensure it's not too large. First
\r
756 remove the privilege bit if one is present. */
\r
757 if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
\r
759 uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
\r
763 mtCOVERAGE_TEST_MARKER();
\r
766 pxNewTCB->uxPriority = uxPriority;
\r
767 #if ( configUSE_MUTEXES == 1 )
\r
769 pxNewTCB->uxBasePriority = uxPriority;
\r
770 pxNewTCB->uxMutexesHeld = 0;
\r
772 #endif /* configUSE_MUTEXES */
\r
774 vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
\r
775 vListInitialiseItem( &( pxNewTCB->xEventListItem ) );
\r
777 /* Set the pxNewTCB as a link back from the ListItem_t. This is so we can get
\r
778 back to the containing TCB from a generic item in a list. */
\r
779 listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );
\r
781 /* Event lists are always in priority order. */
\r
782 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
783 listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );
\r
785 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
787 pxNewTCB->uxCriticalNesting = ( UBaseType_t ) 0U;
\r
789 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
791 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
793 pxNewTCB->pxTaskTag = NULL;
\r
795 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
797 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
799 pxNewTCB->ulRunTimeCounter = 0UL;
\r
801 #endif /* configGENERATE_RUN_TIME_STATS */
\r
803 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
805 vPortStoreTaskMPUSettings( &( pxNewTCB->xMPUSettings ), xRegions, pxNewTCB->pxStack, usStackDepth );
\r
809 #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
\r
811 for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ )
\r
813 pxNewTCB->pvThreadLocalStoragePointers[ x ] = NULL;
\r
818 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
\r
820 pxNewTCB->ulNotifiedValue = 0;
\r
821 pxNewTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
\r
825 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
827 /* Initialise this task's Newlib reent structure. */
\r
828 _REENT_INIT_PTR( ( &( pxNewTCB->xNewLib_reent ) ) );
\r
832 #if( INCLUDE_xTaskAbortDelay == 1 )
\r
834 pxNewTCB->ucDelayAborted = pdFALSE;
\r
838 /* Initialize the TCB stack to look as if the task was already running,
\r
839 but had been interrupted by the scheduler. The return address is set
\r
840 to the start of the task function. Once the stack has been initialised
\r
841 the top of stack variable is updated. */
\r
842 #if( portUSING_MPU_WRAPPERS == 1 )
\r
844 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
\r
846 #else /* portUSING_MPU_WRAPPERS */
\r
848 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
\r
850 #endif /* portUSING_MPU_WRAPPERS */
\r
852 if( ( void * ) pxCreatedTask != NULL )
\r
854 /* Pass the handle out in an anonymous way. The handle can be used to
\r
855 change the created task's priority, delete the created task, etc.*/
\r
856 *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
\r
860 mtCOVERAGE_TEST_MARKER();
\r
863 /*-----------------------------------------------------------*/
\r
865 static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
\r
867 /* Ensure interrupts don't access the task lists while the lists are being
\r
869 taskENTER_CRITICAL();
\r
871 uxCurrentNumberOfTasks++;
\r
872 if( pxCurrentTCB == NULL )
\r
874 /* There are no other tasks, or all the other tasks are in
\r
875 the suspended state - make this the current task. */
\r
876 pxCurrentTCB = pxNewTCB;
\r
878 if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
\r
880 /* This is the first task to be created so do the preliminary
\r
881 initialisation required. We will not recover if this call
\r
882 fails, but we will report the failure. */
\r
883 prvInitialiseTaskLists();
\r
887 mtCOVERAGE_TEST_MARKER();
\r
892 /* If the scheduler is not already running, make this task the
\r
893 current task if it is the highest priority task to be created
\r
895 if( xSchedulerRunning == pdFALSE )
\r
897 if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )
\r
899 pxCurrentTCB = pxNewTCB;
\r
903 mtCOVERAGE_TEST_MARKER();
\r
908 mtCOVERAGE_TEST_MARKER();
\r
914 #if ( configUSE_TRACE_FACILITY == 1 )
\r
916 /* Add a counter into the TCB for tracing only. */
\r
917 pxNewTCB->uxTCBNumber = uxTaskNumber;
\r
919 #endif /* configUSE_TRACE_FACILITY */
\r
920 traceTASK_CREATE( pxNewTCB );
\r
922 prvAddTaskToReadyList( pxNewTCB );
\r
924 portSETUP_TCB( pxNewTCB );
\r
926 taskEXIT_CRITICAL();
\r
928 if( xSchedulerRunning != pdFALSE )
\r
930 /* If the created task is of a higher priority than the current task
\r
931 then it should run now. */
\r
932 if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority )
\r
934 taskYIELD_IF_USING_PREEMPTION();
\r
938 mtCOVERAGE_TEST_MARKER();
\r
943 mtCOVERAGE_TEST_MARKER();
\r
946 /*-----------------------------------------------------------*/
\r
948 #if ( INCLUDE_vTaskDelete == 1 )
\r
950 void vTaskDelete( TaskHandle_t xTaskToDelete )
\r
954 taskENTER_CRITICAL();
\r
956 /* If null is passed in here then it is the calling task that is
\r
958 pxTCB = prvGetTCBFromHandle( xTaskToDelete );
\r
960 /* Remove task from the ready list. */
\r
961 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
963 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
967 mtCOVERAGE_TEST_MARKER();
\r
970 /* Is the task waiting on an event also? */
\r
971 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
973 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
977 mtCOVERAGE_TEST_MARKER();
\r
980 if( pxTCB == pxCurrentTCB )
\r
982 /* A task is deleting itself. This cannot complete within the
\r
983 task itself, as a context switch to another task is required.
\r
984 Place the task in the termination list. The idle task will
\r
985 check the termination list and free up any memory allocated by
\r
986 the scheduler for the TCB and stack of the deleted task. */
\r
987 vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xStateListItem ) );
\r
989 /* Increment the ucTasksDeleted variable so the idle task knows
\r
990 there is a task that has been deleted and that it should therefore
\r
991 check the xTasksWaitingTermination list. */
\r
992 ++uxDeletedTasksWaitingCleanUp;
\r
996 --uxCurrentNumberOfTasks;
\r
997 prvDeleteTCB( pxTCB );
\r
1000 /* Increment the uxTaskNumber also so kernel aware debuggers can
\r
1001 detect that the task lists need re-generating. */
\r
1004 traceTASK_DELETE( pxTCB );
\r
1006 taskEXIT_CRITICAL();
\r
1008 /* Force a reschedule if it is the currently running task that has just
\r
1010 if( xSchedulerRunning != pdFALSE )
\r
1012 if( pxTCB == pxCurrentTCB )
\r
1014 configASSERT( uxSchedulerSuspended == 0 );
\r
1016 /* The pre-delete hook is primarily for the Windows simulator,
\r
1017 in which Windows specific clean up operations are performed,
\r
1018 after which it is not possible to yield away from this task -
\r
1019 hence xYieldPending is used to latch that a context switch is
\r
1021 portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
\r
1022 portYIELD_WITHIN_API();
\r
1026 /* Reset the next expected unblock time in case it referred to
\r
1027 the task that has just been deleted. */
\r
1028 taskENTER_CRITICAL();
\r
1030 prvResetNextTaskUnblockTime();
\r
1032 taskEXIT_CRITICAL();
\r
1037 #endif /* INCLUDE_vTaskDelete */
\r
1038 /*-----------------------------------------------------------*/
\r
1040 #if ( INCLUDE_vTaskDelayUntil == 1 )
\r
1042 void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
\r
1044 TickType_t xTimeToWake;
\r
1045 BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
\r
1047 configASSERT( pxPreviousWakeTime );
\r
1048 configASSERT( ( xTimeIncrement > 0U ) );
\r
1049 configASSERT( uxSchedulerSuspended == 0 );
\r
1051 vTaskSuspendAll();
\r
1053 /* Minor optimisation. The tick count cannot change in this
\r
1055 const TickType_t xConstTickCount = xTickCount;
\r
1057 /* Generate the tick time at which the task wants to wake. */
\r
1058 xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
\r
1060 if( xConstTickCount < *pxPreviousWakeTime )
\r
1062 /* The tick count has overflowed since this function was
\r
1063 lasted called. In this case the only time we should ever
\r
1064 actually delay is if the wake time has also overflowed,
\r
1065 and the wake time is greater than the tick time. When this
\r
1066 is the case it is as if neither time had overflowed. */
\r
1067 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
\r
1069 xShouldDelay = pdTRUE;
\r
1073 mtCOVERAGE_TEST_MARKER();
\r
1078 /* The tick time has not overflowed. In this case we will
\r
1079 delay if either the wake time has overflowed, and/or the
\r
1080 tick time is less than the wake time. */
\r
1081 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
\r
1083 xShouldDelay = pdTRUE;
\r
1087 mtCOVERAGE_TEST_MARKER();
\r
1091 /* Update the wake time ready for the next call. */
\r
1092 *pxPreviousWakeTime = xTimeToWake;
\r
1094 if( xShouldDelay != pdFALSE )
\r
1096 traceTASK_DELAY_UNTIL( xTimeToWake );
\r
1098 /* prvAddCurrentTaskToDelayedList() needs the block time, not
\r
1099 the time to wake, so subtract the current tick count. */
\r
1100 prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE );
\r
1104 mtCOVERAGE_TEST_MARKER();
\r
1107 xAlreadyYielded = xTaskResumeAll();
\r
1109 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
1110 have put ourselves to sleep. */
\r
1111 if( xAlreadyYielded == pdFALSE )
\r
1113 portYIELD_WITHIN_API();
\r
1117 mtCOVERAGE_TEST_MARKER();
\r
1121 #endif /* INCLUDE_vTaskDelayUntil */
\r
1122 /*-----------------------------------------------------------*/
\r
1124 #if ( INCLUDE_vTaskDelay == 1 )
\r
1126 void vTaskDelay( const TickType_t xTicksToDelay )
\r
1128 BaseType_t xAlreadyYielded = pdFALSE;
\r
1130 /* A delay time of zero just forces a reschedule. */
\r
1131 if( xTicksToDelay > ( TickType_t ) 0U )
\r
1133 configASSERT( uxSchedulerSuspended == 0 );
\r
1134 vTaskSuspendAll();
\r
1136 traceTASK_DELAY();
\r
1138 /* A task that is removed from the event list while the
\r
1139 scheduler is suspended will not get placed in the ready
\r
1140 list or removed from the blocked list until the scheduler
\r
1143 This task cannot be in an event list as it is the currently
\r
1144 executing task. */
\r
1145 prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
\r
1147 xAlreadyYielded = xTaskResumeAll();
\r
1151 mtCOVERAGE_TEST_MARKER();
\r
1154 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
1155 have put ourselves to sleep. */
\r
1156 if( xAlreadyYielded == pdFALSE )
\r
1158 portYIELD_WITHIN_API();
\r
1162 mtCOVERAGE_TEST_MARKER();
\r
1166 #endif /* INCLUDE_vTaskDelay */
\r
1167 /*-----------------------------------------------------------*/
\r
1169 #if( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) )
\r
1171 eTaskState eTaskGetState( TaskHandle_t xTask )
\r
1173 eTaskState eReturn;
\r
1174 List_t *pxStateList;
\r
1175 const TCB_t * const pxTCB = ( TCB_t * ) xTask;
\r
1177 configASSERT( pxTCB );
\r
1179 if( pxTCB == pxCurrentTCB )
\r
1181 /* The task calling this function is querying its own state. */
\r
1182 eReturn = eRunning;
\r
1186 taskENTER_CRITICAL();
\r
1188 pxStateList = ( List_t * ) listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) );
\r
1190 taskEXIT_CRITICAL();
\r
1192 if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) )
\r
1194 /* The task being queried is referenced from one of the Blocked
\r
1196 eReturn = eBlocked;
\r
1199 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1200 else if( pxStateList == &xSuspendedTaskList )
\r
1202 /* The task being queried is referenced from the suspended
\r
1203 list. Is it genuinely suspended or is it block
\r
1205 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
\r
1207 eReturn = eSuspended;
\r
1211 eReturn = eBlocked;
\r
1216 #if ( INCLUDE_vTaskDelete == 1 )
\r
1217 else if( ( pxStateList == &xTasksWaitingTermination ) || ( pxStateList == NULL ) )
\r
1219 /* The task being queried is referenced from the deleted
\r
1220 tasks list, or it is not referenced from any lists at
\r
1222 eReturn = eDeleted;
\r
1226 else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */
\r
1228 /* If the task is not in any other state, it must be in the
\r
1229 Ready (including pending ready) state. */
\r
1235 } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
\r
1237 #endif /* INCLUDE_eTaskGetState */
\r
1238 /*-----------------------------------------------------------*/
\r
1240 #if ( INCLUDE_uxTaskPriorityGet == 1 )
\r
1242 UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask )
\r
1245 UBaseType_t uxReturn;
\r
1247 taskENTER_CRITICAL();
\r
1249 /* If null is passed in here then it is the priority of the that
\r
1250 called uxTaskPriorityGet() that is being queried. */
\r
1251 pxTCB = prvGetTCBFromHandle( xTask );
\r
1252 uxReturn = pxTCB->uxPriority;
\r
1254 taskEXIT_CRITICAL();
\r
1259 #endif /* INCLUDE_uxTaskPriorityGet */
\r
1260 /*-----------------------------------------------------------*/
\r
1262 #if ( INCLUDE_uxTaskPriorityGet == 1 )
\r
1264 UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask )
\r
1267 UBaseType_t uxReturn, uxSavedInterruptState;
\r
1269 /* RTOS ports that support interrupt nesting have the concept of a
\r
1270 maximum system call (or maximum API call) interrupt priority.
\r
1271 Interrupts that are above the maximum system call priority are keep
\r
1272 permanently enabled, even when the RTOS kernel is in a critical section,
\r
1273 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
1274 is defined in FreeRTOSConfig.h then
\r
1275 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1276 failure if a FreeRTOS API function is called from an interrupt that has
\r
1277 been assigned a priority above the configured maximum system call
\r
1278 priority. Only FreeRTOS functions that end in FromISR can be called
\r
1279 from interrupts that have been assigned a priority at or (logically)
\r
1280 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
1281 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
1282 simple as possible. More information (albeit Cortex-M specific) is
\r
1283 provided on the following link:
\r
1284 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1285 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1287 uxSavedInterruptState = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1289 /* If null is passed in here then it is the priority of the calling
\r
1290 task that is being queried. */
\r
1291 pxTCB = prvGetTCBFromHandle( xTask );
\r
1292 uxReturn = pxTCB->uxPriority;
\r
1294 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState );
\r
1299 #endif /* INCLUDE_uxTaskPriorityGet */
\r
1300 /*-----------------------------------------------------------*/
\r
1302 #if ( INCLUDE_vTaskPrioritySet == 1 )
\r
1304 void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )
\r
1307 UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;
\r
1308 BaseType_t xYieldRequired = pdFALSE;
\r
1310 configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
\r
1312 /* Ensure the new priority is valid. */
\r
1313 if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
\r
1315 uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
\r
1319 mtCOVERAGE_TEST_MARKER();
\r
1322 taskENTER_CRITICAL();
\r
1324 /* If null is passed in here then it is the priority of the calling
\r
1325 task that is being changed. */
\r
1326 pxTCB = prvGetTCBFromHandle( xTask );
\r
1328 traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
\r
1330 #if ( configUSE_MUTEXES == 1 )
\r
1332 uxCurrentBasePriority = pxTCB->uxBasePriority;
\r
1336 uxCurrentBasePriority = pxTCB->uxPriority;
\r
1340 if( uxCurrentBasePriority != uxNewPriority )
\r
1342 /* The priority change may have readied a task of higher
\r
1343 priority than the calling task. */
\r
1344 if( uxNewPriority > uxCurrentBasePriority )
\r
1346 if( pxTCB != pxCurrentTCB )
\r
1348 /* The priority of a task other than the currently
\r
1349 running task is being raised. Is the priority being
\r
1350 raised above that of the running task? */
\r
1351 if( uxNewPriority >= pxCurrentTCB->uxPriority )
\r
1353 xYieldRequired = pdTRUE;
\r
1357 mtCOVERAGE_TEST_MARKER();
\r
1362 /* The priority of the running task is being raised,
\r
1363 but the running task must already be the highest
\r
1364 priority task able to run so no yield is required. */
\r
1367 else if( pxTCB == pxCurrentTCB )
\r
1369 /* Setting the priority of the running task down means
\r
1370 there may now be another task of higher priority that
\r
1371 is ready to execute. */
\r
1372 xYieldRequired = pdTRUE;
\r
1376 /* Setting the priority of any other task down does not
\r
1377 require a yield as the running task must be above the
\r
1378 new priority of the task being modified. */
\r
1381 /* Remember the ready list the task might be referenced from
\r
1382 before its uxPriority member is changed so the
\r
1383 taskRESET_READY_PRIORITY() macro can function correctly. */
\r
1384 uxPriorityUsedOnEntry = pxTCB->uxPriority;
\r
1386 #if ( configUSE_MUTEXES == 1 )
\r
1388 /* Only change the priority being used if the task is not
\r
1389 currently using an inherited priority. */
\r
1390 if( pxTCB->uxBasePriority == pxTCB->uxPriority )
\r
1392 pxTCB->uxPriority = uxNewPriority;
\r
1396 mtCOVERAGE_TEST_MARKER();
\r
1399 /* The base priority gets set whatever. */
\r
1400 pxTCB->uxBasePriority = uxNewPriority;
\r
1404 pxTCB->uxPriority = uxNewPriority;
\r
1408 /* Only reset the event list item value if the value is not
\r
1409 being used for anything else. */
\r
1410 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
\r
1412 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
1416 mtCOVERAGE_TEST_MARKER();
\r
1419 /* If the task is in the blocked or suspended list we need do
\r
1420 nothing more than change it's priority variable. However, if
\r
1421 the task is in a ready list it needs to be removed and placed
\r
1422 in the list appropriate to its new priority. */
\r
1423 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
\r
1425 /* The task is currently in its ready list - remove before adding
\r
1426 it to it's new ready list. As we are in a critical section we
\r
1427 can do this even if the scheduler is suspended. */
\r
1428 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
1430 /* It is known that the task is in its ready list so
\r
1431 there is no need to check again and the port level
\r
1432 reset macro can be called directly. */
\r
1433 portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
\r
1437 mtCOVERAGE_TEST_MARKER();
\r
1439 prvAddTaskToReadyList( pxTCB );
\r
1443 mtCOVERAGE_TEST_MARKER();
\r
1446 if( xYieldRequired != pdFALSE )
\r
1448 taskYIELD_IF_USING_PREEMPTION();
\r
1452 mtCOVERAGE_TEST_MARKER();
\r
1455 /* Remove compiler warning about unused variables when the port
\r
1456 optimised task selection is not being used. */
\r
1457 ( void ) uxPriorityUsedOnEntry;
\r
1460 taskEXIT_CRITICAL();
\r
1463 #endif /* INCLUDE_vTaskPrioritySet */
\r
1464 /*-----------------------------------------------------------*/
\r
1466 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1468 void vTaskSuspend( TaskHandle_t xTaskToSuspend )
\r
1472 taskENTER_CRITICAL();
\r
1474 /* If null is passed in here then it is the running task that is
\r
1475 being suspended. */
\r
1476 pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
\r
1478 traceTASK_SUSPEND( pxTCB );
\r
1480 /* Remove task from the ready/delayed list and place in the
\r
1481 suspended list. */
\r
1482 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
1484 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
1488 mtCOVERAGE_TEST_MARKER();
\r
1491 /* Is the task waiting on an event also? */
\r
1492 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
1494 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1498 mtCOVERAGE_TEST_MARKER();
\r
1501 vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
\r
1503 taskEXIT_CRITICAL();
\r
1505 if( xSchedulerRunning != pdFALSE )
\r
1507 /* Reset the next expected unblock time in case it referred to the
\r
1508 task that is now in the Suspended state. */
\r
1509 taskENTER_CRITICAL();
\r
1511 prvResetNextTaskUnblockTime();
\r
1513 taskEXIT_CRITICAL();
\r
1517 mtCOVERAGE_TEST_MARKER();
\r
1520 if( pxTCB == pxCurrentTCB )
\r
1522 if( xSchedulerRunning != pdFALSE )
\r
1524 /* The current task has just been suspended. */
\r
1525 configASSERT( uxSchedulerSuspended == 0 );
\r
1526 portYIELD_WITHIN_API();
\r
1530 /* The scheduler is not running, but the task that was pointed
\r
1531 to by pxCurrentTCB has just been suspended and pxCurrentTCB
\r
1532 must be adjusted to point to a different task. */
\r
1533 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )
\r
1535 /* No other tasks are ready, so set pxCurrentTCB back to
\r
1536 NULL so when the next task is created pxCurrentTCB will
\r
1537 be set to point to it no matter what its relative priority
\r
1539 pxCurrentTCB = NULL;
\r
1543 vTaskSwitchContext();
\r
1549 mtCOVERAGE_TEST_MARKER();
\r
1553 #endif /* INCLUDE_vTaskSuspend */
\r
1554 /*-----------------------------------------------------------*/
\r
1556 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1558 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
\r
1560 BaseType_t xReturn = pdFALSE;
\r
1561 const TCB_t * const pxTCB = ( TCB_t * ) xTask;
\r
1563 /* Accesses xPendingReadyList so must be called from a critical
\r
1566 /* It does not make sense to check if the calling task is suspended. */
\r
1567 configASSERT( xTask );
\r
1569 /* Is the task being resumed actually in the suspended list? */
\r
1570 if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ) != pdFALSE )
\r
1572 /* Has the task already been resumed from within an ISR? */
\r
1573 if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
\r
1575 /* Is it in the suspended list because it is in the Suspended
\r
1576 state, or because is is blocked with no timeout? */
\r
1577 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )
\r
1583 mtCOVERAGE_TEST_MARKER();
\r
1588 mtCOVERAGE_TEST_MARKER();
\r
1593 mtCOVERAGE_TEST_MARKER();
\r
1597 } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
\r
1599 #endif /* INCLUDE_vTaskSuspend */
\r
1600 /*-----------------------------------------------------------*/
\r
1602 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1604 void vTaskResume( TaskHandle_t xTaskToResume )
\r
1606 TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
\r
1608 /* It does not make sense to resume the calling task. */
\r
1609 configASSERT( xTaskToResume );
\r
1611 /* The parameter cannot be NULL as it is impossible to resume the
\r
1612 currently executing task. */
\r
1613 if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
\r
1615 taskENTER_CRITICAL();
\r
1617 if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
\r
1619 traceTASK_RESUME( pxTCB );
\r
1621 /* As we are in a critical section we can access the ready
\r
1622 lists even if the scheduler is suspended. */
\r
1623 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
1624 prvAddTaskToReadyList( pxTCB );
\r
1626 /* We may have just resumed a higher priority task. */
\r
1627 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1629 /* This yield may not cause the task just resumed to run,
\r
1630 but will leave the lists in the correct state for the
\r
1632 taskYIELD_IF_USING_PREEMPTION();
\r
1636 mtCOVERAGE_TEST_MARKER();
\r
1641 mtCOVERAGE_TEST_MARKER();
\r
1644 taskEXIT_CRITICAL();
\r
1648 mtCOVERAGE_TEST_MARKER();
\r
1652 #endif /* INCLUDE_vTaskSuspend */
\r
1654 /*-----------------------------------------------------------*/
\r
1656 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
\r
1658 BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
\r
1660 BaseType_t xYieldRequired = pdFALSE;
\r
1661 TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
\r
1662 UBaseType_t uxSavedInterruptStatus;
\r
1664 configASSERT( xTaskToResume );
\r
1666 /* RTOS ports that support interrupt nesting have the concept of a
\r
1667 maximum system call (or maximum API call) interrupt priority.
\r
1668 Interrupts that are above the maximum system call priority are keep
\r
1669 permanently enabled, even when the RTOS kernel is in a critical section,
\r
1670 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
1671 is defined in FreeRTOSConfig.h then
\r
1672 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1673 failure if a FreeRTOS API function is called from an interrupt that has
\r
1674 been assigned a priority above the configured maximum system call
\r
1675 priority. Only FreeRTOS functions that end in FromISR can be called
\r
1676 from interrupts that have been assigned a priority at or (logically)
\r
1677 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
1678 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
1679 simple as possible. More information (albeit Cortex-M specific) is
\r
1680 provided on the following link:
\r
1681 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1682 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1684 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1686 if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
\r
1688 traceTASK_RESUME_FROM_ISR( pxTCB );
\r
1690 /* Check the ready lists can be accessed. */
\r
1691 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
1693 /* Ready lists can be accessed so move the task from the
\r
1694 suspended list to the ready list directly. */
\r
1695 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1697 xYieldRequired = pdTRUE;
\r
1701 mtCOVERAGE_TEST_MARKER();
\r
1704 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
1705 prvAddTaskToReadyList( pxTCB );
\r
1709 /* The delayed or ready lists cannot be accessed so the task
\r
1710 is held in the pending ready list until the scheduler is
\r
1712 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
1717 mtCOVERAGE_TEST_MARKER();
\r
1720 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1722 return xYieldRequired;
\r
1725 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
\r
1726 /*-----------------------------------------------------------*/
\r
1728 void vTaskStartScheduler( void )
\r
1730 BaseType_t xReturn;
\r
1731 uint16_t usIdleTaskStackSize = configMINIMAL_STACK_SIZE;
\r
1733 /* Add the idle task at the lowest priority. */
\r
1734 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
\r
1736 StaticTask_t *pxIdleTaskTCBBuffer = NULL;
\r
1737 StackType_t *pxIdleTaskStackBuffer = NULL;
\r
1739 /* The Idle task is created using user provided RAM - obtain the
\r
1740 address of the RAM then create the idle task. */
\r
1741 vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &usIdleTaskStackSize );
\r
1742 xReturn = xTaskCreateStatic( prvIdleTask, "IDLE", usIdleTaskStackSize, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle, pxIdleTaskStackBuffer, pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
\r
1746 /* The Idle task is being created using dynamically allocated RAM. */
\r
1747 xReturn = xTaskCreate( prvIdleTask, "IDLE", usIdleTaskStackSize, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), &xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
\r
1749 #endif /* configSUPPORT_STATIC_ALLOCATION */
\r
1751 #if ( configUSE_TIMERS == 1 )
\r
1753 if( xReturn == pdPASS )
\r
1755 xReturn = xTimerCreateTimerTask();
\r
1759 mtCOVERAGE_TEST_MARKER();
\r
1762 #endif /* configUSE_TIMERS */
\r
1764 if( xReturn == pdPASS )
\r
1766 /* Interrupts are turned off here, to ensure a tick does not occur
\r
1767 before or during the call to xPortStartScheduler(). The stacks of
\r
1768 the created tasks contain a status word with interrupts switched on
\r
1769 so interrupts will automatically get re-enabled when the first task
\r
1771 portDISABLE_INTERRUPTS();
\r
1773 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
1775 /* Switch Newlib's _impure_ptr variable to point to the _reent
\r
1776 structure specific to the task that will run first. */
\r
1777 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
\r
1779 #endif /* configUSE_NEWLIB_REENTRANT */
\r
1781 xNextTaskUnblockTime = portMAX_DELAY;
\r
1782 xSchedulerRunning = pdTRUE;
\r
1783 xTickCount = ( TickType_t ) 0U;
\r
1785 /* If configGENERATE_RUN_TIME_STATS is defined then the following
\r
1786 macro must be defined to configure the timer/counter used to generate
\r
1787 the run time counter time base. */
\r
1788 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
\r
1790 /* Setting up the timer tick is hardware specific and thus in the
\r
1791 portable interface. */
\r
1792 if( xPortStartScheduler() != pdFALSE )
\r
1794 /* Should not reach here as if the scheduler is running the
\r
1795 function will not return. */
\r
1799 /* Should only reach here if a task calls xTaskEndScheduler(). */
\r
1804 /* This line will only be reached if the kernel could not be started,
\r
1805 because there was not enough FreeRTOS heap to create the idle task
\r
1806 or the timer task. */
\r
1807 configASSERT( xReturn );
\r
1810 /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,
\r
1811 meaning xIdleTaskHandle is not used anywhere else. */
\r
1812 ( void ) xIdleTaskHandle;
\r
1814 /*-----------------------------------------------------------*/
\r
1816 void vTaskEndScheduler( void )
\r
1818 /* Stop the scheduler interrupts and call the portable scheduler end
\r
1819 routine so the original ISRs can be restored if necessary. The port
\r
1820 layer must ensure interrupts enable bit is left in the correct state. */
\r
1821 portDISABLE_INTERRUPTS();
\r
1822 xSchedulerRunning = pdFALSE;
\r
1823 vPortEndScheduler();
\r
1825 /*----------------------------------------------------------*/
\r
1827 void vTaskSuspendAll( void )
\r
1829 /* A critical section is not required as the variable is of type
\r
1830 BaseType_t. Please read Richard Barry's reply in the following link to a
\r
1831 post in the FreeRTOS support forum before reporting this as a bug! -
\r
1832 http://goo.gl/wu4acr */
\r
1833 ++uxSchedulerSuspended;
\r
1835 /*----------------------------------------------------------*/
\r
1837 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
1839 static TickType_t prvGetExpectedIdleTime( void )
\r
1841 TickType_t xReturn;
\r
1842 UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;
\r
1844 /* uxHigherPriorityReadyTasks takes care of the case where
\r
1845 configUSE_PREEMPTION is 0, so there may be tasks above the idle priority
\r
1846 task that are in the Ready state, even though the idle task is
\r
1848 #if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
\r
1850 if( uxTopReadyPriority > tskIDLE_PRIORITY )
\r
1852 uxHigherPriorityReadyTasks = pdTRUE;
\r
1857 const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;
\r
1859 /* When port optimised task selection is used the uxTopReadyPriority
\r
1860 variable is used as a bit map. If bits other than the least
\r
1861 significant bit are set then there are tasks that have a priority
\r
1862 above the idle priority that are in the Ready state. This takes
\r
1863 care of the case where the co-operative scheduler is in use. */
\r
1864 if( uxTopReadyPriority > uxLeastSignificantBit )
\r
1866 uxHigherPriorityReadyTasks = pdTRUE;
\r
1871 if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
\r
1875 else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
\r
1877 /* There are other idle priority tasks in the ready state. If
\r
1878 time slicing is used then the very next tick interrupt must be
\r
1882 else if( uxHigherPriorityReadyTasks != pdFALSE )
\r
1884 /* There are tasks in the Ready state that have a priority above the
\r
1885 idle priority. This path can only be reached if
\r
1886 configUSE_PREEMPTION is 0. */
\r
1891 xReturn = xNextTaskUnblockTime - xTickCount;
\r
1897 #endif /* configUSE_TICKLESS_IDLE */
\r
1898 /*----------------------------------------------------------*/
\r
1900 BaseType_t xTaskResumeAll( void )
\r
1902 TCB_t *pxTCB = NULL;
\r
1903 BaseType_t xAlreadyYielded = pdFALSE;
\r
1905 /* If uxSchedulerSuspended is zero then this function does not match a
\r
1906 previous call to vTaskSuspendAll(). */
\r
1907 configASSERT( uxSchedulerSuspended );
\r
1909 /* It is possible that an ISR caused a task to be removed from an event
\r
1910 list while the scheduler was suspended. If this was the case then the
\r
1911 removed task will have been added to the xPendingReadyList. Once the
\r
1912 scheduler has been resumed it is safe to move all the pending ready
\r
1913 tasks from this list into their appropriate ready list. */
\r
1914 taskENTER_CRITICAL();
\r
1916 --uxSchedulerSuspended;
\r
1918 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
1920 if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )
\r
1922 /* Move any readied tasks from the pending list into the
\r
1923 appropriate ready list. */
\r
1924 while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
\r
1926 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );
\r
1927 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1928 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
1929 prvAddTaskToReadyList( pxTCB );
\r
1931 /* If the moved task has a priority higher than the current
\r
1932 task then a yield must be performed. */
\r
1933 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1935 xYieldPending = pdTRUE;
\r
1939 mtCOVERAGE_TEST_MARKER();
\r
1943 if( pxTCB != NULL )
\r
1945 /* A task was unblocked while the scheduler was suspended,
\r
1946 which may have prevented the next unblock time from being
\r
1947 re-calculated, in which case re-calculate it now. Mainly
\r
1948 important for low power tickless implementations, where
\r
1949 this can prevent an unnecessary exit from low power
\r
1951 prvResetNextTaskUnblockTime();
\r
1954 /* If any ticks occurred while the scheduler was suspended then
\r
1955 they should be processed now. This ensures the tick count does
\r
1956 not slip, and that any delayed tasks are resumed at the correct
\r
1958 if( uxPendedTicks > ( UBaseType_t ) 0U )
\r
1960 while( uxPendedTicks > ( UBaseType_t ) 0U )
\r
1962 if( xTaskIncrementTick() != pdFALSE )
\r
1964 xYieldPending = pdTRUE;
\r
1968 mtCOVERAGE_TEST_MARKER();
\r
1975 mtCOVERAGE_TEST_MARKER();
\r
1978 if( xYieldPending != pdFALSE )
\r
1980 #if( configUSE_PREEMPTION != 0 )
\r
1982 xAlreadyYielded = pdTRUE;
\r
1985 taskYIELD_IF_USING_PREEMPTION();
\r
1989 mtCOVERAGE_TEST_MARKER();
\r
1995 mtCOVERAGE_TEST_MARKER();
\r
1998 taskEXIT_CRITICAL();
\r
2000 return xAlreadyYielded;
\r
2002 /*-----------------------------------------------------------*/
\r
2004 TickType_t xTaskGetTickCount( void )
\r
2006 TickType_t xTicks;
\r
2008 /* Critical section required if running on a 16 bit processor. */
\r
2009 portTICK_TYPE_ENTER_CRITICAL();
\r
2011 xTicks = xTickCount;
\r
2013 portTICK_TYPE_EXIT_CRITICAL();
\r
2017 /*-----------------------------------------------------------*/
\r
2019 TickType_t xTaskGetTickCountFromISR( void )
\r
2021 TickType_t xReturn;
\r
2022 UBaseType_t uxSavedInterruptStatus;
\r
2024 /* RTOS ports that support interrupt nesting have the concept of a maximum
\r
2025 system call (or maximum API call) interrupt priority. Interrupts that are
\r
2026 above the maximum system call priority are kept permanently enabled, even
\r
2027 when the RTOS kernel is in a critical section, but cannot make any calls to
\r
2028 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
\r
2029 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
2030 failure if a FreeRTOS API function is called from an interrupt that has been
\r
2031 assigned a priority above the configured maximum system call priority.
\r
2032 Only FreeRTOS functions that end in FromISR can be called from interrupts
\r
2033 that have been assigned a priority at or (logically) below the maximum
\r
2034 system call interrupt priority. FreeRTOS maintains a separate interrupt
\r
2035 safe API to ensure interrupt entry is as fast and as simple as possible.
\r
2036 More information (albeit Cortex-M specific) is provided on the following
\r
2037 link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
2038 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
2040 uxSavedInterruptStatus = portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR();
\r
2042 xReturn = xTickCount;
\r
2044 portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
2048 /*-----------------------------------------------------------*/
\r
2050 UBaseType_t uxTaskGetNumberOfTasks( void )
\r
2052 /* A critical section is not required because the variables are of type
\r
2054 return uxCurrentNumberOfTasks;
\r
2056 /*-----------------------------------------------------------*/
\r
2058 #if ( INCLUDE_pcTaskGetTaskName == 1 )
\r
2060 char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
2064 /* If null is passed in here then the name of the calling task is being
\r
2066 pxTCB = prvGetTCBFromHandle( xTaskToQuery );
\r
2067 configASSERT( pxTCB );
\r
2068 return &( pxTCB->pcTaskName[ 0 ] );
\r
2071 #endif /* INCLUDE_pcTaskGetTaskName */
\r
2072 /*-----------------------------------------------------------*/
\r
2074 #if ( INCLUDE_xTaskGetTaskHandle == 1 )
\r
2076 static TCB_t *prvSearchForNameWithinSingleList( List_t *pxList, const char pcNameToQuery[] )
\r
2078 TCB_t *pxNextTCB, *pxFirstTCB, *pxReturn = NULL;
\r
2082 /* This function is called with the scheduler suspended. */
\r
2084 if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
\r
2086 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
\r
2090 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
\r
2092 /* Check each character in the name looking for a match or
\r
2094 for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
\r
2096 cNextChar = pxNextTCB->pcTaskName[ x ];
\r
2098 if( cNextChar != pcNameToQuery[ x ] )
\r
2100 /* Characters didn't match. */
\r
2103 else if( cNextChar == 0x00 )
\r
2105 /* Both strings terminated, a match must have been
\r
2107 pxReturn = pxNextTCB;
\r
2112 mtCOVERAGE_TEST_MARKER();
\r
2116 if( pxReturn != NULL )
\r
2118 /* The handle has been found. */
\r
2122 } while( pxNextTCB != pxFirstTCB );
\r
2126 mtCOVERAGE_TEST_MARKER();
\r
2132 #endif /* INCLUDE_xTaskGetTaskHandle */
\r
2133 /*-----------------------------------------------------------*/
\r
2135 #if ( INCLUDE_xTaskGetTaskHandle == 1 )
\r
2137 TaskHandle_t xTaskGetTaskHandle( const char *pcNameToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
2139 UBaseType_t uxQueue = configMAX_PRIORITIES;
\r
2142 /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */
\r
2143 configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN );
\r
2145 vTaskSuspendAll();
\r
2147 /* Search the ready lists. */
\r
2151 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery );
\r
2153 if( pxTCB != NULL )
\r
2155 /* Found the handle. */
\r
2159 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2161 /* Search the delayed lists. */
\r
2162 if( pxTCB == NULL )
\r
2164 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery );
\r
2167 if( pxTCB == NULL )
\r
2169 pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery );
\r
2172 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2174 if( pxTCB == NULL )
\r
2176 /* Search the suspended list. */
\r
2177 pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery );
\r
2182 #if( INCLUDE_vTaskDelete == 1 )
\r
2184 if( pxTCB == NULL )
\r
2186 /* Search the deleted list. */
\r
2187 pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery );
\r
2192 ( void ) xTaskResumeAll();
\r
2194 return ( TaskHandle_t ) pxTCB;
\r
2197 #endif /* INCLUDE_xTaskGetTaskHandle */
\r
2198 /*-----------------------------------------------------------*/
\r
2200 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2202 UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime )
\r
2204 UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
\r
2206 vTaskSuspendAll();
\r
2208 /* Is there a space in the array for each task in the system? */
\r
2209 if( uxArraySize >= uxCurrentNumberOfTasks )
\r
2211 /* Fill in an TaskStatus_t structure with information on each
\r
2212 task in the Ready state. */
\r
2216 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
\r
2218 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2220 /* Fill in an TaskStatus_t structure with information on each
\r
2221 task in the Blocked state. */
\r
2222 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );
\r
2223 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );
\r
2225 #if( INCLUDE_vTaskDelete == 1 )
\r
2227 /* Fill in an TaskStatus_t structure with information on
\r
2228 each task that has been deleted but not yet cleaned up. */
\r
2229 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
\r
2233 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2235 /* Fill in an TaskStatus_t structure with information on
\r
2236 each task in the Suspended state. */
\r
2237 uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
\r
2241 #if ( configGENERATE_RUN_TIME_STATS == 1)
\r
2243 if( pulTotalRunTime != NULL )
\r
2245 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
2246 portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
\r
2248 *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
2254 if( pulTotalRunTime != NULL )
\r
2256 *pulTotalRunTime = 0;
\r
2263 mtCOVERAGE_TEST_MARKER();
\r
2266 ( void ) xTaskResumeAll();
\r
2271 #endif /* configUSE_TRACE_FACILITY */
\r
2272 /*----------------------------------------------------------*/
\r
2274 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
2276 TaskHandle_t xTaskGetIdleTaskHandle( void )
\r
2278 /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
\r
2279 started, then xIdleTaskHandle will be NULL. */
\r
2280 configASSERT( ( xIdleTaskHandle != NULL ) );
\r
2281 return xIdleTaskHandle;
\r
2284 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
\r
2285 /*----------------------------------------------------------*/
\r
2287 /* This conditional compilation should use inequality to 0, not equality to 1.
\r
2288 This is to ensure vTaskStepTick() is available when user defined low power mode
\r
2289 implementations require configUSE_TICKLESS_IDLE to be set to a value other than
\r
2291 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
2293 void vTaskStepTick( const TickType_t xTicksToJump )
\r
2295 /* Correct the tick count value after a period during which the tick
\r
2296 was suppressed. Note this does *not* call the tick hook function for
\r
2297 each stepped tick. */
\r
2298 configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
\r
2299 xTickCount += xTicksToJump;
\r
2300 traceINCREASE_TICK_COUNT( xTicksToJump );
\r
2303 #endif /* configUSE_TICKLESS_IDLE */
\r
2304 /*----------------------------------------------------------*/
\r
2306 #if ( INCLUDE_xTaskAbortDelay == 1 )
\r
2308 BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
\r
2310 TCB_t *pxTCB = ( TCB_t * ) xTask;
\r
2311 BaseType_t xReturn = pdFALSE;
\r
2313 configASSERT( pxTCB );
\r
2315 vTaskSuspendAll();
\r
2317 /* A task can only be prematurely removed from the Blocked state if
\r
2318 it is actually in the Blocked state. */
\r
2319 if( eTaskGetState( xTask ) == eBlocked )
\r
2321 /* Remove the reference to the task from the blocked list. An
\r
2322 interrupt won't touch the xStateListItem because the
\r
2323 scheduler is suspended. */
\r
2324 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
2326 /* Is the task waiting on an event also? If so remove it from
\r
2327 the event list too. Interrupts can touch the event list item,
\r
2328 even though the scheduler is suspended, so a critical section
\r
2330 taskENTER_CRITICAL();
\r
2332 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
2334 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
2335 pxTCB->ucDelayAborted = pdTRUE;
\r
2339 mtCOVERAGE_TEST_MARKER();
\r
2342 taskEXIT_CRITICAL();
\r
2344 /* Place the unblocked task into the appropriate ready list. */
\r
2345 prvAddTaskToReadyList( pxTCB );
\r
2347 /* A task being unblocked cannot cause an immediate context
\r
2348 switch if preemption is turned off. */
\r
2349 #if ( configUSE_PREEMPTION == 1 )
\r
2351 /* Preemption is on, but a context switch should only be
\r
2352 performed if the unblocked task has a priority that is
\r
2353 equal to or higher than the currently executing task. */
\r
2354 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
2356 /* Pend the yield to be performed when the scheduler
\r
2357 is unsuspended. */
\r
2358 xYieldPending = pdTRUE;
\r
2362 mtCOVERAGE_TEST_MARKER();
\r
2365 #endif /* configUSE_PREEMPTION */
\r
2369 mtCOVERAGE_TEST_MARKER();
\r
2377 #endif /* INCLUDE_xTaskAbortDelay */
\r
2378 /*----------------------------------------------------------*/
\r
2380 BaseType_t xTaskIncrementTick( void )
\r
2383 TickType_t xItemValue;
\r
2384 BaseType_t xSwitchRequired = pdFALSE;
\r
2386 /* Called by the portable layer each time a tick interrupt occurs.
\r
2387 Increments the tick then checks to see if the new tick value will cause any
\r
2388 tasks to be unblocked. */
\r
2389 traceTASK_INCREMENT_TICK( xTickCount );
\r
2390 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
2392 /* Increment the RTOS tick, switching the delayed and overflowed
\r
2393 delayed lists if it wraps to 0. */
\r
2397 /* Minor optimisation. The tick count cannot change in this
\r
2399 const TickType_t xConstTickCount = xTickCount;
\r
2401 if( xConstTickCount == ( TickType_t ) 0U )
\r
2403 taskSWITCH_DELAYED_LISTS();
\r
2407 mtCOVERAGE_TEST_MARKER();
\r
2410 /* See if this tick has made a timeout expire. Tasks are stored in
\r
2411 the queue in the order of their wake time - meaning once one task
\r
2412 has been found whose block time has not expired there is no need to
\r
2413 look any further down the list. */
\r
2414 if( xConstTickCount >= xNextTaskUnblockTime )
\r
2418 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
\r
2420 /* The delayed list is empty. Set xNextTaskUnblockTime
\r
2421 to the maximum possible value so it is extremely
\r
2423 if( xTickCount >= xNextTaskUnblockTime ) test will pass
\r
2424 next time through. */
\r
2425 xNextTaskUnblockTime = portMAX_DELAY; /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2430 /* The delayed list is not empty, get the value of the
\r
2431 item at the head of the delayed list. This is the time
\r
2432 at which the task at the head of the delayed list must
\r
2433 be removed from the Blocked state. */
\r
2434 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
\r
2435 xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xStateListItem ) );
\r
2437 if( xConstTickCount < xItemValue )
\r
2439 /* It is not time to unblock this item yet, but the
\r
2440 item value is the time at which the task at the head
\r
2441 of the blocked list must be removed from the Blocked
\r
2442 state - so record the item value in
\r
2443 xNextTaskUnblockTime. */
\r
2444 xNextTaskUnblockTime = xItemValue;
\r
2449 mtCOVERAGE_TEST_MARKER();
\r
2452 /* It is time to remove the item from the Blocked state. */
\r
2453 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
2455 /* Is the task waiting on an event also? If so remove
\r
2456 it from the event list. */
\r
2457 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
2459 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
2463 mtCOVERAGE_TEST_MARKER();
\r
2466 /* Place the unblocked task into the appropriate ready
\r
2468 prvAddTaskToReadyList( pxTCB );
\r
2470 /* A task being unblocked cannot cause an immediate
\r
2471 context switch if preemption is turned off. */
\r
2472 #if ( configUSE_PREEMPTION == 1 )
\r
2474 /* Preemption is on, but a context switch should
\r
2475 only be performed if the unblocked task has a
\r
2476 priority that is equal to or higher than the
\r
2477 currently executing task. */
\r
2478 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
2480 xSwitchRequired = pdTRUE;
\r
2484 mtCOVERAGE_TEST_MARKER();
\r
2487 #endif /* configUSE_PREEMPTION */
\r
2493 /* Tasks of equal priority to the currently running task will share
\r
2494 processing time (time slice) if preemption is on, and the application
\r
2495 writer has not explicitly turned time slicing off. */
\r
2496 #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
\r
2498 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )
\r
2500 xSwitchRequired = pdTRUE;
\r
2504 mtCOVERAGE_TEST_MARKER();
\r
2507 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
\r
2509 #if ( configUSE_TICK_HOOK == 1 )
\r
2511 /* Guard against the tick hook being called when the pended tick
\r
2512 count is being unwound (when the scheduler is being unlocked). */
\r
2513 if( uxPendedTicks == ( UBaseType_t ) 0U )
\r
2515 vApplicationTickHook();
\r
2519 mtCOVERAGE_TEST_MARKER();
\r
2522 #endif /* configUSE_TICK_HOOK */
\r
2528 /* The tick hook gets called at regular intervals, even if the
\r
2529 scheduler is locked. */
\r
2530 #if ( configUSE_TICK_HOOK == 1 )
\r
2532 vApplicationTickHook();
\r
2537 #if ( configUSE_PREEMPTION == 1 )
\r
2539 if( xYieldPending != pdFALSE )
\r
2541 xSwitchRequired = pdTRUE;
\r
2545 mtCOVERAGE_TEST_MARKER();
\r
2548 #endif /* configUSE_PREEMPTION */
\r
2550 return xSwitchRequired;
\r
2552 /*-----------------------------------------------------------*/
\r
2554 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2556 void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction )
\r
2560 /* If xTask is NULL then it is the task hook of the calling task that is
\r
2562 if( xTask == NULL )
\r
2564 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2568 xTCB = ( TCB_t * ) xTask;
\r
2571 /* Save the hook function in the TCB. A critical section is required as
\r
2572 the value can be accessed from an interrupt. */
\r
2573 taskENTER_CRITICAL();
\r
2574 xTCB->pxTaskTag = pxHookFunction;
\r
2575 taskEXIT_CRITICAL();
\r
2578 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2579 /*-----------------------------------------------------------*/
\r
2581 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2583 TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
\r
2586 TaskHookFunction_t xReturn;
\r
2588 /* If xTask is NULL then we are setting our own task hook. */
\r
2589 if( xTask == NULL )
\r
2591 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2595 xTCB = ( TCB_t * ) xTask;
\r
2598 /* Save the hook function in the TCB. A critical section is required as
\r
2599 the value can be accessed from an interrupt. */
\r
2600 taskENTER_CRITICAL();
\r
2602 xReturn = xTCB->pxTaskTag;
\r
2604 taskEXIT_CRITICAL();
\r
2609 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2610 /*-----------------------------------------------------------*/
\r
2612 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2614 BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter )
\r
2617 BaseType_t xReturn;
\r
2619 /* If xTask is NULL then we are calling our own task hook. */
\r
2620 if( xTask == NULL )
\r
2622 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2626 xTCB = ( TCB_t * ) xTask;
\r
2629 if( xTCB->pxTaskTag != NULL )
\r
2631 xReturn = xTCB->pxTaskTag( pvParameter );
\r
2641 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2642 /*-----------------------------------------------------------*/
\r
2644 void vTaskSwitchContext( void )
\r
2646 if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )
\r
2648 /* The scheduler is currently suspended - do not allow a context
\r
2650 xYieldPending = pdTRUE;
\r
2654 xYieldPending = pdFALSE;
\r
2655 traceTASK_SWITCHED_OUT();
\r
2657 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
2659 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
2660 portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
\r
2662 ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
2665 /* Add the amount of time the task has been running to the
\r
2666 accumulated time so far. The time the task started running was
\r
2667 stored in ulTaskSwitchedInTime. Note that there is no overflow
\r
2668 protection here so count values are only valid until the timer
\r
2669 overflows. The guard against negative values is to protect
\r
2670 against suspect run time stat counter implementations - which
\r
2671 are provided by the application, not the kernel. */
\r
2672 if( ulTotalRunTime > ulTaskSwitchedInTime )
\r
2674 pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
\r
2678 mtCOVERAGE_TEST_MARKER();
\r
2680 ulTaskSwitchedInTime = ulTotalRunTime;
\r
2682 #endif /* configGENERATE_RUN_TIME_STATS */
\r
2684 /* Check for stack overflow, if configured. */
\r
2685 taskCHECK_FOR_STACK_OVERFLOW();
\r
2687 /* Select a new task to run using either the generic C or port
\r
2688 optimised asm code. */
\r
2689 taskSELECT_HIGHEST_PRIORITY_TASK();
\r
2690 traceTASK_SWITCHED_IN();
\r
2692 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
2694 /* Switch Newlib's _impure_ptr variable to point to the _reent
\r
2695 structure specific to this task. */
\r
2696 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
\r
2698 #endif /* configUSE_NEWLIB_REENTRANT */
\r
2701 /*-----------------------------------------------------------*/
\r
2703 void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )
\r
2705 configASSERT( pxEventList );
\r
2707 /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
\r
2708 SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
\r
2710 /* Place the event list item of the TCB in the appropriate event list.
\r
2711 This is placed in the list in priority order so the highest priority task
\r
2712 is the first to be woken by the event. The queue that contains the event
\r
2713 list is locked, preventing simultaneous access from interrupts. */
\r
2714 vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2716 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
\r
2718 /*-----------------------------------------------------------*/
\r
2720 void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait )
\r
2722 configASSERT( pxEventList );
\r
2724 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
\r
2725 the event groups implementation. */
\r
2726 configASSERT( uxSchedulerSuspended != 0 );
\r
2728 /* Store the item value in the event list item. It is safe to access the
\r
2729 event list item here as interrupts won't access the event list item of a
\r
2730 task that is not in the Blocked state. */
\r
2731 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
\r
2733 /* Place the event list item of the TCB at the end of the appropriate event
\r
2734 list. It is safe to access the event list here because it is part of an
\r
2735 event group implementation - and interrupts don't access event groups
\r
2736 directly (instead they access them indirectly by pending function calls to
\r
2737 the task level). */
\r
2738 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2740 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
\r
2742 /*-----------------------------------------------------------*/
\r
2744 #if( configUSE_TIMERS == 1 )
\r
2746 void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely )
\r
2748 configASSERT( pxEventList );
\r
2750 /* This function should not be called by application code hence the
\r
2751 'Restricted' in its name. It is not part of the public API. It is
\r
2752 designed for use by kernel code, and has special calling requirements -
\r
2753 it should be called with the scheduler suspended. */
\r
2756 /* Place the event list item of the TCB in the appropriate event list.
\r
2757 In this case it is assume that this is the only task that is going to
\r
2758 be waiting on this event list, so the faster vListInsertEnd() function
\r
2759 can be used in place of vListInsert. */
\r
2760 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2762 /* If the task should block indefinitely then set the block time to a
\r
2763 value that will be recognised as an indefinite delay inside the
\r
2764 prvAddCurrentTaskToDelayedList() function. */
\r
2765 if( xWaitIndefinitely != pdFALSE )
\r
2767 xTicksToWait = portMAX_DELAY;
\r
2770 traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) );
\r
2771 prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely );
\r
2774 #endif /* configUSE_TIMERS */
\r
2775 /*-----------------------------------------------------------*/
\r
2777 BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
\r
2779 TCB_t *pxUnblockedTCB;
\r
2780 BaseType_t xReturn;
\r
2782 /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be
\r
2783 called from a critical section within an ISR. */
\r
2785 /* The event list is sorted in priority order, so the first in the list can
\r
2786 be removed as it is known to be the highest priority. Remove the TCB from
\r
2787 the delayed list, and add it to the ready list.
\r
2789 If an event is for a queue that is locked then this function will never
\r
2790 get called - the lock count on the queue will get modified instead. This
\r
2791 means exclusive access to the event list is guaranteed here.
\r
2793 This function assumes that a check has already been made to ensure that
\r
2794 pxEventList is not empty. */
\r
2795 pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
\r
2796 configASSERT( pxUnblockedTCB );
\r
2797 ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
\r
2799 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
2801 ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
\r
2802 prvAddTaskToReadyList( pxUnblockedTCB );
\r
2806 /* The delayed and ready lists cannot be accessed, so hold this task
\r
2807 pending until the scheduler is resumed. */
\r
2808 vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
\r
2811 if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
2813 /* Return true if the task removed from the event list has a higher
\r
2814 priority than the calling task. This allows the calling task to know if
\r
2815 it should force a context switch now. */
\r
2818 /* Mark that a yield is pending in case the user is not using the
\r
2819 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
\r
2820 xYieldPending = pdTRUE;
\r
2824 xReturn = pdFALSE;
\r
2827 #if( configUSE_TICKLESS_IDLE != 0 )
\r
2829 /* If a task is blocked on a kernel object then xNextTaskUnblockTime
\r
2830 might be set to the blocked task's time out time. If the task is
\r
2831 unblocked for a reason other than a timeout xNextTaskUnblockTime is
\r
2832 normally left unchanged, because it is automatically reset to a new
\r
2833 value when the tick count equals xNextTaskUnblockTime. However if
\r
2834 tickless idling is used it might be more important to enter sleep mode
\r
2835 at the earliest possible time - so reset xNextTaskUnblockTime here to
\r
2836 ensure it is updated at the earliest possible time. */
\r
2837 prvResetNextTaskUnblockTime();
\r
2843 /*-----------------------------------------------------------*/
\r
2845 BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )
\r
2847 TCB_t *pxUnblockedTCB;
\r
2848 BaseType_t xReturn;
\r
2850 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
\r
2851 the event flags implementation. */
\r
2852 configASSERT( uxSchedulerSuspended != pdFALSE );
\r
2854 /* Store the new item value in the event list. */
\r
2855 listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
\r
2857 /* Remove the event list form the event flag. Interrupts do not access
\r
2859 pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem );
\r
2860 configASSERT( pxUnblockedTCB );
\r
2861 ( void ) uxListRemove( pxEventListItem );
\r
2863 /* Remove the task from the delayed list and add it to the ready list. The
\r
2864 scheduler is suspended so interrupts will not be accessing the ready
\r
2866 ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
\r
2867 prvAddTaskToReadyList( pxUnblockedTCB );
\r
2869 if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
2871 /* Return true if the task removed from the event list has
\r
2872 a higher priority than the calling task. This allows
\r
2873 the calling task to know if it should force a context
\r
2877 /* Mark that a yield is pending in case the user is not using the
\r
2878 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
\r
2879 xYieldPending = pdTRUE;
\r
2883 xReturn = pdFALSE;
\r
2888 /*-----------------------------------------------------------*/
\r
2890 void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
\r
2892 configASSERT( pxTimeOut );
\r
2893 pxTimeOut->xOverflowCount = xNumOfOverflows;
\r
2894 pxTimeOut->xTimeOnEntering = xTickCount;
\r
2896 /*-----------------------------------------------------------*/
\r
2898 BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait )
\r
2900 BaseType_t xReturn;
\r
2902 configASSERT( pxTimeOut );
\r
2903 configASSERT( pxTicksToWait );
\r
2905 taskENTER_CRITICAL();
\r
2907 /* Minor optimisation. The tick count cannot change in this block. */
\r
2908 const TickType_t xConstTickCount = xTickCount;
\r
2910 #if( INCLUDE_xTaskAbortDelay == 1 )
\r
2911 if( pxCurrentTCB->ucDelayAborted != pdFALSE )
\r
2913 /* The delay was aborted, which is not the same as a time out,
\r
2914 but has the same result. */
\r
2915 pxCurrentTCB->ucDelayAborted = pdFALSE;
\r
2921 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2922 if( *pxTicksToWait == portMAX_DELAY )
\r
2924 /* If INCLUDE_vTaskSuspend is set to 1 and the block time
\r
2925 specified is the maximum block time then the task should block
\r
2926 indefinitely, and therefore never time out. */
\r
2927 xReturn = pdFALSE;
\r
2932 if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
\r
2934 /* The tick count is greater than the time at which
\r
2935 vTaskSetTimeout() was called, but has also overflowed since
\r
2936 vTaskSetTimeOut() was called. It must have wrapped all the way
\r
2937 around and gone past again. This passed since vTaskSetTimeout()
\r
2941 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
2943 /* Not a genuine timeout. Adjust parameters for time remaining. */
\r
2944 *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );
\r
2945 vTaskSetTimeOutState( pxTimeOut );
\r
2946 xReturn = pdFALSE;
\r
2953 taskEXIT_CRITICAL();
\r
2957 /*-----------------------------------------------------------*/
\r
2959 void vTaskMissedYield( void )
\r
2961 xYieldPending = pdTRUE;
\r
2963 /*-----------------------------------------------------------*/
\r
2965 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2967 UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )
\r
2969 UBaseType_t uxReturn;
\r
2972 if( xTask != NULL )
\r
2974 pxTCB = ( TCB_t * ) xTask;
\r
2975 uxReturn = pxTCB->uxTaskNumber;
\r
2985 #endif /* configUSE_TRACE_FACILITY */
\r
2986 /*-----------------------------------------------------------*/
\r
2988 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2990 void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle )
\r
2994 if( xTask != NULL )
\r
2996 pxTCB = ( TCB_t * ) xTask;
\r
2997 pxTCB->uxTaskNumber = uxHandle;
\r
3001 #endif /* configUSE_TRACE_FACILITY */
\r
3004 * -----------------------------------------------------------
\r
3006 * ----------------------------------------------------------
\r
3008 * The portTASK_FUNCTION() macro is used to allow port/compiler specific
\r
3009 * language extensions. The equivalent prototype for this function is:
\r
3011 * void prvIdleTask( void *pvParameters );
\r
3014 static portTASK_FUNCTION( prvIdleTask, pvParameters )
\r
3016 /* Stop warnings. */
\r
3017 ( void ) pvParameters;
\r
3019 /** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
\r
3020 SCHEDULER IS STARTED. **/
\r
3024 /* See if any tasks have deleted themselves - if so then the idle task
\r
3025 is responsible for freeing the deleted task's TCB and stack. */
\r
3026 prvCheckTasksWaitingTermination();
\r
3028 #if ( configUSE_PREEMPTION == 0 )
\r
3030 /* If we are not using preemption we keep forcing a task switch to
\r
3031 see if any other task has become available. If we are using
\r
3032 preemption we don't need to do this as any task becoming available
\r
3033 will automatically get the processor anyway. */
\r
3036 #endif /* configUSE_PREEMPTION */
\r
3038 #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
\r
3040 /* When using preemption tasks of equal priority will be
\r
3041 timesliced. If a task that is sharing the idle priority is ready
\r
3042 to run then the idle task should yield before the end of the
\r
3045 A critical region is not required here as we are just reading from
\r
3046 the list, and an occasional incorrect value will not matter. If
\r
3047 the ready list at the idle priority contains more than one task
\r
3048 then a task other than the idle task is ready to execute. */
\r
3049 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )
\r
3055 mtCOVERAGE_TEST_MARKER();
\r
3058 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
\r
3060 #if ( configUSE_IDLE_HOOK == 1 )
\r
3062 extern void vApplicationIdleHook( void );
\r
3064 /* Call the user defined function from within the idle task. This
\r
3065 allows the application designer to add background functionality
\r
3066 without the overhead of a separate task.
\r
3067 NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
\r
3068 CALL A FUNCTION THAT MIGHT BLOCK. */
\r
3069 vApplicationIdleHook();
\r
3071 #endif /* configUSE_IDLE_HOOK */
\r
3073 /* This conditional compilation should use inequality to 0, not equality
\r
3074 to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
\r
3075 user defined low power mode implementations require
\r
3076 configUSE_TICKLESS_IDLE to be set to a value other than 1. */
\r
3077 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
3079 TickType_t xExpectedIdleTime;
\r
3081 /* It is not desirable to suspend then resume the scheduler on
\r
3082 each iteration of the idle task. Therefore, a preliminary
\r
3083 test of the expected idle time is performed without the
\r
3084 scheduler suspended. The result here is not necessarily
\r
3086 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
3088 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
3090 vTaskSuspendAll();
\r
3092 /* Now the scheduler is suspended, the expected idle
\r
3093 time can be sampled again, and this time its value can
\r
3095 configASSERT( xNextTaskUnblockTime >= xTickCount );
\r
3096 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
3098 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
3100 traceLOW_POWER_IDLE_BEGIN();
\r
3101 portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
\r
3102 traceLOW_POWER_IDLE_END();
\r
3106 mtCOVERAGE_TEST_MARKER();
\r
3109 ( void ) xTaskResumeAll();
\r
3113 mtCOVERAGE_TEST_MARKER();
\r
3116 #endif /* configUSE_TICKLESS_IDLE */
\r
3119 /*-----------------------------------------------------------*/
\r
3121 #if( configUSE_TICKLESS_IDLE != 0 )
\r
3123 eSleepModeStatus eTaskConfirmSleepModeStatus( void )
\r
3125 /* The idle task exists in addition to the application tasks. */
\r
3126 const UBaseType_t uxNonApplicationTasks = 1;
\r
3127 eSleepModeStatus eReturn = eStandardSleep;
\r
3129 if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
\r
3131 /* A task was made ready while the scheduler was suspended. */
\r
3132 eReturn = eAbortSleep;
\r
3134 else if( xYieldPending != pdFALSE )
\r
3136 /* A yield was pended while the scheduler was suspended. */
\r
3137 eReturn = eAbortSleep;
\r
3141 /* If all the tasks are in the suspended list (which might mean they
\r
3142 have an infinite block time rather than actually being suspended)
\r
3143 then it is safe to turn all clocks off and just wait for external
\r
3145 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
\r
3147 eReturn = eNoTasksWaitingTimeout;
\r
3151 mtCOVERAGE_TEST_MARKER();
\r
3158 #endif /* configUSE_TICKLESS_IDLE */
\r
3159 /*-----------------------------------------------------------*/
\r
3161 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
\r
3163 void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue )
\r
3167 if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS )
\r
3169 pxTCB = prvGetTCBFromHandle( xTaskToSet );
\r
3170 pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue;
\r
3174 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
\r
3175 /*-----------------------------------------------------------*/
\r
3177 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
\r
3179 void *pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex )
\r
3181 void *pvReturn = NULL;
\r
3184 if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS )
\r
3186 pxTCB = prvGetTCBFromHandle( xTaskToQuery );
\r
3187 pvReturn = pxTCB->pvThreadLocalStoragePointers[ xIndex ];
\r
3197 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
\r
3198 /*-----------------------------------------------------------*/
\r
3200 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
3202 void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions )
\r
3206 /* If null is passed in here then we are modifying the MPU settings of
\r
3207 the calling task. */
\r
3208 pxTCB = prvGetTCBFromHandle( xTaskToModify );
\r
3210 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
\r
3213 #endif /* portUSING_MPU_WRAPPERS */
\r
3214 /*-----------------------------------------------------------*/
\r
3216 static void prvInitialiseTaskLists( void )
\r
3218 UBaseType_t uxPriority;
\r
3220 for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
\r
3222 vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
\r
3225 vListInitialise( &xDelayedTaskList1 );
\r
3226 vListInitialise( &xDelayedTaskList2 );
\r
3227 vListInitialise( &xPendingReadyList );
\r
3229 #if ( INCLUDE_vTaskDelete == 1 )
\r
3231 vListInitialise( &xTasksWaitingTermination );
\r
3233 #endif /* INCLUDE_vTaskDelete */
\r
3235 #if ( INCLUDE_vTaskSuspend == 1 )
\r
3237 vListInitialise( &xSuspendedTaskList );
\r
3239 #endif /* INCLUDE_vTaskSuspend */
\r
3241 /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
\r
3243 pxDelayedTaskList = &xDelayedTaskList1;
\r
3244 pxOverflowDelayedTaskList = &xDelayedTaskList2;
\r
3246 /*-----------------------------------------------------------*/
\r
3248 static void prvCheckTasksWaitingTermination( void )
\r
3251 /** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/
\r
3253 #if ( INCLUDE_vTaskDelete == 1 )
\r
3255 BaseType_t xListIsEmpty;
\r
3257 /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
\r
3258 too often in the idle task. */
\r
3259 while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
\r
3261 vTaskSuspendAll();
\r
3263 xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
\r
3265 ( void ) xTaskResumeAll();
\r
3267 if( xListIsEmpty == pdFALSE )
\r
3271 taskENTER_CRITICAL();
\r
3273 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
\r
3274 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
3275 --uxCurrentNumberOfTasks;
\r
3276 --uxDeletedTasksWaitingCleanUp;
\r
3278 taskEXIT_CRITICAL();
\r
3280 prvDeleteTCB( pxTCB );
\r
3284 mtCOVERAGE_TEST_MARKER();
\r
3288 #endif /* INCLUDE_vTaskDelete */
\r
3290 /*-----------------------------------------------------------*/
\r
3292 #if( configUSE_TRACE_FACILITY == 1 )
\r
3294 void vTaskGetTaskInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState )
\r
3298 /* xTask is NULL then get the state of the calling task. */
\r
3299 pxTCB = prvGetTCBFromHandle( xTask );
\r
3301 pxTaskStatus->xHandle = ( TaskHandle_t ) pxTCB;
\r
3302 pxTaskStatus->pcTaskName = ( const char * ) &( pxTCB->pcTaskName [ 0 ] );
\r
3303 pxTaskStatus->uxCurrentPriority = pxTCB->uxPriority;
\r
3304 pxTaskStatus->pxStackBase = pxTCB->pxStack;
\r
3305 pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber;
\r
3307 #if ( INCLUDE_vTaskSuspend == 1 )
\r
3309 /* If the task is in the suspended list then there is a chance it is
\r
3310 actually just blocked indefinitely - so really it should be reported as
\r
3311 being in the Blocked state. */
\r
3312 if( pxTaskStatus->eCurrentState == eSuspended )
\r
3314 vTaskSuspendAll();
\r
3316 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
3318 pxTaskStatus->eCurrentState = eBlocked;
\r
3324 #endif /* INCLUDE_vTaskSuspend */
\r
3326 #if ( configUSE_MUTEXES == 1 )
\r
3328 pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;
\r
3332 pxTaskStatus->uxBasePriority = 0;
\r
3336 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
3338 pxTaskStatus->ulRunTimeCounter = pxTCB->ulRunTimeCounter;
\r
3342 pxTaskStatus->ulRunTimeCounter = 0;
\r
3346 /* Obtaining the task state is a little fiddly, so is only done if the value
\r
3347 of eState passed into this function is eInvalid - otherwise the state is
\r
3348 just set to whatever is passed in. */
\r
3349 if( eState != eInvalid )
\r
3351 pxTaskStatus->eCurrentState = eState;
\r
3355 pxTaskStatus->eCurrentState = eTaskGetState( xTask );
\r
3358 /* Obtaining the stack space takes some time, so the xGetFreeStackSpace
\r
3359 parameter is provided to allow it to be skipped. */
\r
3360 if( xGetFreeStackSpace != pdFALSE )
\r
3362 #if ( portSTACK_GROWTH > 0 )
\r
3364 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxEndOfStack );
\r
3368 pxTaskStatus->usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxTCB->pxStack );
\r
3374 pxTaskStatus->usStackHighWaterMark = 0;
\r
3378 #endif /* configUSE_TRACE_FACILITY */
\r
3379 /*-----------------------------------------------------------*/
\r
3381 #if ( configUSE_TRACE_FACILITY == 1 )
\r
3383 static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )
\r
3385 volatile TCB_t *pxNextTCB, *pxFirstTCB;
\r
3386 UBaseType_t uxTask = 0;
\r
3388 if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
\r
3390 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
\r
3392 /* Populate an TaskStatus_t structure within the
\r
3393 pxTaskStatusArray array for each task that is referenced from
\r
3394 pxList. See the definition of TaskStatus_t in task.h for the
\r
3395 meaning of each TaskStatus_t structure member. */
\r
3398 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
\r
3399 vTaskGetTaskInfo( ( TaskHandle_t ) pxNextTCB, &( pxTaskStatusArray[ uxTask ] ), pdTRUE, eState );
\r
3401 } while( pxNextTCB != pxFirstTCB );
\r
3405 mtCOVERAGE_TEST_MARKER();
\r
3411 #endif /* configUSE_TRACE_FACILITY */
\r
3412 /*-----------------------------------------------------------*/
\r
3414 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
3416 static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
\r
3418 uint32_t ulCount = 0U;
\r
3420 while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE )
\r
3422 pucStackByte -= portSTACK_GROWTH;
\r
3426 ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */
\r
3428 return ( uint16_t ) ulCount;
\r
3431 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */
\r
3432 /*-----------------------------------------------------------*/
\r
3434 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
\r
3436 UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
\r
3439 uint8_t *pucEndOfStack;
\r
3440 UBaseType_t uxReturn;
\r
3442 pxTCB = prvGetTCBFromHandle( xTask );
\r
3444 #if portSTACK_GROWTH < 0
\r
3446 pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
\r
3450 pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
\r
3454 uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );
\r
3459 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
\r
3460 /*-----------------------------------------------------------*/
\r
3462 #if ( INCLUDE_vTaskDelete == 1 )
\r
3464 static void prvDeleteTCB( TCB_t *pxTCB )
\r
3466 /* This call is required specifically for the TriCore port. It must be
\r
3467 above the vPortFree() calls. The call is also used by ports/demos that
\r
3468 want to allocate and clean RAM statically. */
\r
3469 portCLEAN_UP_TCB( pxTCB );
\r
3471 /* Free up the memory allocated by the scheduler for the task. It is up
\r
3472 to the task to free any memory allocated at the application level. */
\r
3473 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
3475 _reclaim_reent( &( pxTCB->xNewLib_reent ) );
\r
3477 #endif /* configUSE_NEWLIB_REENTRANT */
\r
3479 #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
\r
3481 /* The task can only have been allocated dynamically - free it
\r
3483 vPortFree( pxTCB->pxStack );
\r
3484 vPortFree( pxTCB );
\r
3486 #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
\r
3488 /* The task could have been allocated statically or dynamically, so
\r
3489 check before attempting to free the memory. */
\r
3490 if( pxTCB->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
\r
3492 vPortFree( pxTCB->pxStack );
\r
3493 vPortFree( pxTCB );
\r
3497 mtCOVERAGE_TEST_MARKER();
\r
3500 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
\r
3503 #endif /* INCLUDE_vTaskDelete */
\r
3504 /*-----------------------------------------------------------*/
\r
3506 static void prvResetNextTaskUnblockTime( void )
\r
3510 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
\r
3512 /* The new current delayed list is empty. Set xNextTaskUnblockTime to
\r
3513 the maximum possible value so it is extremely unlikely that the
\r
3514 if( xTickCount >= xNextTaskUnblockTime ) test will pass until
\r
3515 there is an item in the delayed list. */
\r
3516 xNextTaskUnblockTime = portMAX_DELAY;
\r
3520 /* The new current delayed list is not empty, get the value of
\r
3521 the item at the head of the delayed list. This is the time at
\r
3522 which the task at the head of the delayed list should be removed
\r
3523 from the Blocked state. */
\r
3524 ( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
\r
3525 xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xStateListItem ) );
\r
3528 /*-----------------------------------------------------------*/
\r
3530 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
\r
3532 TaskHandle_t xTaskGetCurrentTaskHandle( void )
\r
3534 TaskHandle_t xReturn;
\r
3536 /* A critical section is not required as this is not called from
\r
3537 an interrupt and the current TCB will always be the same for any
\r
3538 individual execution thread. */
\r
3539 xReturn = pxCurrentTCB;
\r
3544 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
\r
3545 /*-----------------------------------------------------------*/
\r
3547 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
3549 BaseType_t xTaskGetSchedulerState( void )
\r
3551 BaseType_t xReturn;
\r
3553 if( xSchedulerRunning == pdFALSE )
\r
3555 xReturn = taskSCHEDULER_NOT_STARTED;
\r
3559 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
3561 xReturn = taskSCHEDULER_RUNNING;
\r
3565 xReturn = taskSCHEDULER_SUSPENDED;
\r
3572 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
\r
3573 /*-----------------------------------------------------------*/
\r
3575 #if ( configUSE_MUTEXES == 1 )
\r
3577 void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
\r
3579 TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
\r
3581 /* If the mutex was given back by an interrupt while the queue was
\r
3582 locked then the mutex holder might now be NULL. */
\r
3583 if( pxMutexHolder != NULL )
\r
3585 /* If the holder of the mutex has a priority below the priority of
\r
3586 the task attempting to obtain the mutex then it will temporarily
\r
3587 inherit the priority of the task attempting to obtain the mutex. */
\r
3588 if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
\r
3590 /* Adjust the mutex holder state to account for its new
\r
3591 priority. Only reset the event list item value if the value is
\r
3592 not being used for anything else. */
\r
3593 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
\r
3595 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
3599 mtCOVERAGE_TEST_MARKER();
\r
3602 /* If the task being modified is in the ready state it will need
\r
3603 to be moved into a new list. */
\r
3604 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
\r
3606 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
3608 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
3612 mtCOVERAGE_TEST_MARKER();
\r
3615 /* Inherit the priority before being moved into the new list. */
\r
3616 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
3617 prvAddTaskToReadyList( pxTCB );
\r
3621 /* Just inherit the priority. */
\r
3622 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
3625 traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );
\r
3629 mtCOVERAGE_TEST_MARKER();
\r
3634 mtCOVERAGE_TEST_MARKER();
\r
3638 #endif /* configUSE_MUTEXES */
\r
3639 /*-----------------------------------------------------------*/
\r
3641 #if ( configUSE_MUTEXES == 1 )
\r
3643 BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )
\r
3645 TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
\r
3646 BaseType_t xReturn = pdFALSE;
\r
3648 if( pxMutexHolder != NULL )
\r
3650 /* A task can only have an inherited priority if it holds the mutex.
\r
3651 If the mutex is held by a task then it cannot be given from an
\r
3652 interrupt, and if a mutex is given by the holding task then it must
\r
3653 be the running state task. */
\r
3654 configASSERT( pxTCB == pxCurrentTCB );
\r
3656 configASSERT( pxTCB->uxMutexesHeld );
\r
3657 ( pxTCB->uxMutexesHeld )--;
\r
3659 /* Has the holder of the mutex inherited the priority of another
\r
3661 if( pxTCB->uxPriority != pxTCB->uxBasePriority )
\r
3663 /* Only disinherit if no other mutexes are held. */
\r
3664 if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
\r
3666 /* A task can only have an inherited priority if it holds
\r
3667 the mutex. If the mutex is held by a task then it cannot be
\r
3668 given from an interrupt, and if a mutex is given by the
\r
3669 holding task then it must be the running state task. Remove
\r
3670 the holding task from the ready list. */
\r
3671 if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
3673 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
3677 mtCOVERAGE_TEST_MARKER();
\r
3680 /* Disinherit the priority before adding the task into the
\r
3681 new ready list. */
\r
3682 traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
\r
3683 pxTCB->uxPriority = pxTCB->uxBasePriority;
\r
3685 /* Reset the event list item value. It cannot be in use for
\r
3686 any other purpose if this task is running, and it must be
\r
3687 running to give back the mutex. */
\r
3688 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
3689 prvAddTaskToReadyList( pxTCB );
\r
3691 /* Return true to indicate that a context switch is required.
\r
3692 This is only actually required in the corner case whereby
\r
3693 multiple mutexes were held and the mutexes were given back
\r
3694 in an order different to that in which they were taken.
\r
3695 If a context switch did not occur when the first mutex was
\r
3696 returned, even if a task was waiting on it, then a context
\r
3697 switch should occur when the last mutex is returned whether
\r
3698 a task is waiting on it or not. */
\r
3703 mtCOVERAGE_TEST_MARKER();
\r
3708 mtCOVERAGE_TEST_MARKER();
\r
3713 mtCOVERAGE_TEST_MARKER();
\r
3719 #endif /* configUSE_MUTEXES */
\r
3720 /*-----------------------------------------------------------*/
\r
3722 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
3724 void vTaskEnterCritical( void )
\r
3726 portDISABLE_INTERRUPTS();
\r
3728 if( xSchedulerRunning != pdFALSE )
\r
3730 ( pxCurrentTCB->uxCriticalNesting )++;
\r
3732 /* This is not the interrupt safe version of the enter critical
\r
3733 function so assert() if it is being called from an interrupt
\r
3734 context. Only API functions that end in "FromISR" can be used in an
\r
3735 interrupt. Only assert if the critical nesting count is 1 to
\r
3736 protect against recursive calls if the assert function also uses a
\r
3737 critical section. */
\r
3738 if( pxCurrentTCB->uxCriticalNesting == 1 )
\r
3740 portASSERT_IF_IN_ISR();
\r
3745 mtCOVERAGE_TEST_MARKER();
\r
3749 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
3750 /*-----------------------------------------------------------*/
\r
3752 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
3754 void vTaskExitCritical( void )
\r
3756 if( xSchedulerRunning != pdFALSE )
\r
3758 if( pxCurrentTCB->uxCriticalNesting > 0U )
\r
3760 ( pxCurrentTCB->uxCriticalNesting )--;
\r
3762 if( pxCurrentTCB->uxCriticalNesting == 0U )
\r
3764 portENABLE_INTERRUPTS();
\r
3768 mtCOVERAGE_TEST_MARKER();
\r
3773 mtCOVERAGE_TEST_MARKER();
\r
3778 mtCOVERAGE_TEST_MARKER();
\r
3782 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
3783 /*-----------------------------------------------------------*/
\r
3785 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
3787 static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName )
\r
3791 /* Start by copying the entire string. */
\r
3792 strcpy( pcBuffer, pcTaskName );
\r
3794 /* Pad the end of the string with spaces to ensure columns line up when
\r
3796 for( x = strlen( pcBuffer ); x < ( size_t ) ( configMAX_TASK_NAME_LEN - 1 ); x++ )
\r
3798 pcBuffer[ x ] = ' ';
\r
3802 pcBuffer[ x ] = 0x00;
\r
3804 /* Return the new end of string. */
\r
3805 return &( pcBuffer[ x ] );
\r
3808 #endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
\r
3809 /*-----------------------------------------------------------*/
\r
3811 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
3813 void vTaskList( char * pcWriteBuffer )
\r
3815 TaskStatus_t *pxTaskStatusArray;
\r
3816 volatile UBaseType_t uxArraySize, x;
\r
3822 * This function is provided for convenience only, and is used by many
\r
3823 * of the demo applications. Do not consider it to be part of the
\r
3826 * vTaskList() calls uxTaskGetSystemState(), then formats part of the
\r
3827 * uxTaskGetSystemState() output into a human readable table that
\r
3828 * displays task names, states and stack usage.
\r
3830 * vTaskList() has a dependency on the sprintf() C library function that
\r
3831 * might bloat the code size, use a lot of stack, and provide different
\r
3832 * results on different platforms. An alternative, tiny, third party,
\r
3833 * and limited functionality implementation of sprintf() is provided in
\r
3834 * many of the FreeRTOS/Demo sub-directories in a file called
\r
3835 * printf-stdarg.c (note printf-stdarg.c does not provide a full
\r
3836 * snprintf() implementation!).
\r
3838 * It is recommended that production systems call uxTaskGetSystemState()
\r
3839 * directly to get access to raw stats data, rather than indirectly
\r
3840 * through a call to vTaskList().
\r
3844 /* Make sure the write buffer does not contain a string. */
\r
3845 *pcWriteBuffer = 0x00;
\r
3847 /* Take a snapshot of the number of tasks in case it changes while this
\r
3848 function is executing. */
\r
3849 uxArraySize = uxCurrentNumberOfTasks;
\r
3851 /* Allocate an array index for each task. NOTE! if
\r
3852 configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
\r
3853 equate to NULL. */
\r
3854 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
\r
3856 if( pxTaskStatusArray != NULL )
\r
3858 /* Generate the (binary) data. */
\r
3859 uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
\r
3861 /* Create a human readable table from the binary data. */
\r
3862 for( x = 0; x < uxArraySize; x++ )
\r
3864 switch( pxTaskStatusArray[ x ].eCurrentState )
\r
3866 case eReady: cStatus = tskREADY_CHAR;
\r
3869 case eBlocked: cStatus = tskBLOCKED_CHAR;
\r
3872 case eSuspended: cStatus = tskSUSPENDED_CHAR;
\r
3875 case eDeleted: cStatus = tskDELETED_CHAR;
\r
3878 default: /* Should not get here, but it is included
\r
3879 to prevent static checking errors. */
\r
3884 /* Write the task name to the string, padding with spaces so it
\r
3885 can be printed in tabular form more easily. */
\r
3886 pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
\r
3888 /* Write the rest of the string. */
\r
3889 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
3890 pcWriteBuffer += strlen( pcWriteBuffer );
\r
3893 /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
\r
3894 is 0 then vPortFree() will be #defined to nothing. */
\r
3895 vPortFree( pxTaskStatusArray );
\r
3899 mtCOVERAGE_TEST_MARKER();
\r
3903 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
\r
3904 /*----------------------------------------------------------*/
\r
3906 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
3908 void vTaskGetRunTimeStats( char *pcWriteBuffer )
\r
3910 TaskStatus_t *pxTaskStatusArray;
\r
3911 volatile UBaseType_t uxArraySize, x;
\r
3912 uint32_t ulTotalTime, ulStatsAsPercentage;
\r
3914 #if( configUSE_TRACE_FACILITY != 1 )
\r
3916 #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats().
\r
3923 * This function is provided for convenience only, and is used by many
\r
3924 * of the demo applications. Do not consider it to be part of the
\r
3927 * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part
\r
3928 * of the uxTaskGetSystemState() output into a human readable table that
\r
3929 * displays the amount of time each task has spent in the Running state
\r
3930 * in both absolute and percentage terms.
\r
3932 * vTaskGetRunTimeStats() has a dependency on the sprintf() C library
\r
3933 * function that might bloat the code size, use a lot of stack, and
\r
3934 * provide different results on different platforms. An alternative,
\r
3935 * tiny, third party, and limited functionality implementation of
\r
3936 * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in
\r
3937 * a file called printf-stdarg.c (note printf-stdarg.c does not provide
\r
3938 * a full snprintf() implementation!).
\r
3940 * It is recommended that production systems call uxTaskGetSystemState()
\r
3941 * directly to get access to raw stats data, rather than indirectly
\r
3942 * through a call to vTaskGetRunTimeStats().
\r
3945 /* Make sure the write buffer does not contain a string. */
\r
3946 *pcWriteBuffer = 0x00;
\r
3948 /* Take a snapshot of the number of tasks in case it changes while this
\r
3949 function is executing. */
\r
3950 uxArraySize = uxCurrentNumberOfTasks;
\r
3952 /* Allocate an array index for each task. NOTE! If
\r
3953 configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
\r
3954 equate to NULL. */
\r
3955 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
\r
3957 if( pxTaskStatusArray != NULL )
\r
3959 /* Generate the (binary) data. */
\r
3960 uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
\r
3962 /* For percentage calculations. */
\r
3963 ulTotalTime /= 100UL;
\r
3965 /* Avoid divide by zero errors. */
\r
3966 if( ulTotalTime > 0 )
\r
3968 /* Create a human readable table from the binary data. */
\r
3969 for( x = 0; x < uxArraySize; x++ )
\r
3971 /* What percentage of the total run time has the task used?
\r
3972 This will always be rounded down to the nearest integer.
\r
3973 ulTotalRunTimeDiv100 has already been divided by 100. */
\r
3974 ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
\r
3976 /* Write the task name to the string, padding with
\r
3977 spaces so it can be printed in tabular form more
\r
3979 pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
\r
3981 if( ulStatsAsPercentage > 0UL )
\r
3983 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
3985 sprintf( pcWriteBuffer, "\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
\r
3989 /* sizeof( int ) == sizeof( long ) so a smaller
\r
3990 printf() library can be used. */
\r
3991 sprintf( pcWriteBuffer, "\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );
\r
3997 /* If the percentage is zero here then the task has
\r
3998 consumed less than 1% of the total run time. */
\r
3999 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
4001 sprintf( pcWriteBuffer, "\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter );
\r
4005 /* sizeof( int ) == sizeof( long ) so a smaller
\r
4006 printf() library can be used. */
\r
4007 sprintf( pcWriteBuffer, "\t%u\t\t<1%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter );
\r
4012 pcWriteBuffer += strlen( pcWriteBuffer );
\r
4017 mtCOVERAGE_TEST_MARKER();
\r
4020 /* Free the array again. NOTE! If configSUPPORT_DYNAMIC_ALLOCATION
\r
4021 is 0 then vPortFree() will be #defined to nothing. */
\r
4022 vPortFree( pxTaskStatusArray );
\r
4026 mtCOVERAGE_TEST_MARKER();
\r
4030 #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
\r
4031 /*-----------------------------------------------------------*/
\r
4033 TickType_t uxTaskResetEventItemValue( void )
\r
4035 TickType_t uxReturn;
\r
4037 uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );
\r
4039 /* Reset the event list item to its normal value - so it can be used with
\r
4040 queues and semaphores. */
\r
4041 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
4045 /*-----------------------------------------------------------*/
\r
4047 #if ( configUSE_MUTEXES == 1 )
\r
4049 void *pvTaskIncrementMutexHeldCount( void )
\r
4051 /* If xSemaphoreCreateMutex() is called before any tasks have been created
\r
4052 then pxCurrentTCB will be NULL. */
\r
4053 if( pxCurrentTCB != NULL )
\r
4055 ( pxCurrentTCB->uxMutexesHeld )++;
\r
4058 return pxCurrentTCB;
\r
4061 #endif /* configUSE_MUTEXES */
\r
4062 /*-----------------------------------------------------------*/
\r
4064 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4066 uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )
\r
4068 uint32_t ulReturn;
\r
4070 taskENTER_CRITICAL();
\r
4072 /* Only block if the notification count is not already non-zero. */
\r
4073 if( pxCurrentTCB->ulNotifiedValue == 0UL )
\r
4075 /* Mark this task as waiting for a notification. */
\r
4076 pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;
\r
4078 if( xTicksToWait > ( TickType_t ) 0 )
\r
4080 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
\r
4081 traceTASK_NOTIFY_TAKE_BLOCK();
\r
4083 /* All ports are written to allow a yield in a critical
\r
4084 section (some will yield immediately, others wait until the
\r
4085 critical section exits) - but it is not something that
\r
4086 application code should ever do. */
\r
4087 portYIELD_WITHIN_API();
\r
4091 mtCOVERAGE_TEST_MARKER();
\r
4096 mtCOVERAGE_TEST_MARKER();
\r
4099 taskEXIT_CRITICAL();
\r
4101 taskENTER_CRITICAL();
\r
4103 traceTASK_NOTIFY_TAKE();
\r
4104 ulReturn = pxCurrentTCB->ulNotifiedValue;
\r
4106 if( ulReturn != 0UL )
\r
4108 if( xClearCountOnExit != pdFALSE )
\r
4110 pxCurrentTCB->ulNotifiedValue = 0UL;
\r
4114 ( pxCurrentTCB->ulNotifiedValue )--;
\r
4119 mtCOVERAGE_TEST_MARKER();
\r
4122 pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
\r
4124 taskEXIT_CRITICAL();
\r
4129 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4130 /*-----------------------------------------------------------*/
\r
4132 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4134 BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait )
\r
4136 BaseType_t xReturn;
\r
4138 taskENTER_CRITICAL();
\r
4140 /* Only block if a notification is not already pending. */
\r
4141 if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED )
\r
4143 /* Clear bits in the task's notification value as bits may get
\r
4144 set by the notifying task or interrupt. This can be used to
\r
4145 clear the value to zero. */
\r
4146 pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry;
\r
4148 /* Mark this task as waiting for a notification. */
\r
4149 pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;
\r
4151 if( xTicksToWait > ( TickType_t ) 0 )
\r
4153 prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
\r
4154 traceTASK_NOTIFY_WAIT_BLOCK();
\r
4156 /* All ports are written to allow a yield in a critical
\r
4157 section (some will yield immediately, others wait until the
\r
4158 critical section exits) - but it is not something that
\r
4159 application code should ever do. */
\r
4160 portYIELD_WITHIN_API();
\r
4164 mtCOVERAGE_TEST_MARKER();
\r
4169 mtCOVERAGE_TEST_MARKER();
\r
4172 taskEXIT_CRITICAL();
\r
4174 taskENTER_CRITICAL();
\r
4176 traceTASK_NOTIFY_WAIT();
\r
4178 if( pulNotificationValue != NULL )
\r
4180 /* Output the current notification value, which may or may not
\r
4182 *pulNotificationValue = pxCurrentTCB->ulNotifiedValue;
\r
4185 /* If ucNotifyValue is set then either the task never entered the
\r
4186 blocked state (because a notification was already pending) or the
\r
4187 task unblocked because of a notification. Otherwise the task
\r
4188 unblocked because of a timeout. */
\r
4189 if( pxCurrentTCB->ucNotifyState == taskWAITING_NOTIFICATION )
\r
4191 /* A notification was not received. */
\r
4192 xReturn = pdFALSE;
\r
4196 /* A notification was already pending or a notification was
\r
4197 received while the task was waiting. */
\r
4198 pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnExit;
\r
4202 pxCurrentTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
\r
4204 taskEXIT_CRITICAL();
\r
4209 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4210 /*-----------------------------------------------------------*/
\r
4212 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4214 BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue )
\r
4217 BaseType_t xReturn = pdPASS;
\r
4218 uint8_t ucOriginalNotifyState;
\r
4220 configASSERT( xTaskToNotify );
\r
4221 pxTCB = ( TCB_t * ) xTaskToNotify;
\r
4223 taskENTER_CRITICAL();
\r
4225 if( pulPreviousNotificationValue != NULL )
\r
4227 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
\r
4230 ucOriginalNotifyState = pxTCB->ucNotifyState;
\r
4232 pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
\r
4237 pxTCB->ulNotifiedValue |= ulValue;
\r
4241 ( pxTCB->ulNotifiedValue )++;
\r
4244 case eSetValueWithOverwrite :
\r
4245 pxTCB->ulNotifiedValue = ulValue;
\r
4248 case eSetValueWithoutOverwrite :
\r
4249 if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
\r
4251 pxTCB->ulNotifiedValue = ulValue;
\r
4255 /* The value could not be written to the task. */
\r
4261 /* The task is being notified without its notify value being
\r
4266 traceTASK_NOTIFY();
\r
4268 /* If the task is in the blocked state specifically to wait for a
\r
4269 notification then unblock it now. */
\r
4270 if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
\r
4272 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
4273 prvAddTaskToReadyList( pxTCB );
\r
4275 /* The task should not have been on an event list. */
\r
4276 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
\r
4278 #if( configUSE_TICKLESS_IDLE != 0 )
\r
4280 /* If a task is blocked waiting for a notification then
\r
4281 xNextTaskUnblockTime might be set to the blocked task's time
\r
4282 out time. If the task is unblocked for a reason other than
\r
4283 a timeout xNextTaskUnblockTime is normally left unchanged,
\r
4284 because it will automatically get reset to a new value when
\r
4285 the tick count equals xNextTaskUnblockTime. However if
\r
4286 tickless idling is used it might be more important to enter
\r
4287 sleep mode at the earliest possible time - so reset
\r
4288 xNextTaskUnblockTime here to ensure it is updated at the
\r
4289 earliest possible time. */
\r
4290 prvResetNextTaskUnblockTime();
\r
4294 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
4296 /* The notified task has a priority above the currently
\r
4297 executing task so a yield is required. */
\r
4298 taskYIELD_IF_USING_PREEMPTION();
\r
4302 mtCOVERAGE_TEST_MARKER();
\r
4307 mtCOVERAGE_TEST_MARKER();
\r
4310 taskEXIT_CRITICAL();
\r
4315 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4316 /*-----------------------------------------------------------*/
\r
4318 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4320 BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken )
\r
4323 uint8_t ucOriginalNotifyState;
\r
4324 BaseType_t xReturn = pdPASS;
\r
4325 UBaseType_t uxSavedInterruptStatus;
\r
4327 configASSERT( xTaskToNotify );
\r
4329 /* RTOS ports that support interrupt nesting have the concept of a
\r
4330 maximum system call (or maximum API call) interrupt priority.
\r
4331 Interrupts that are above the maximum system call priority are keep
\r
4332 permanently enabled, even when the RTOS kernel is in a critical section,
\r
4333 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
4334 is defined in FreeRTOSConfig.h then
\r
4335 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
4336 failure if a FreeRTOS API function is called from an interrupt that has
\r
4337 been assigned a priority above the configured maximum system call
\r
4338 priority. Only FreeRTOS functions that end in FromISR can be called
\r
4339 from interrupts that have been assigned a priority at or (logically)
\r
4340 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
4341 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
4342 simple as possible. More information (albeit Cortex-M specific) is
\r
4343 provided on the following link:
\r
4344 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
4345 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
4347 pxTCB = ( TCB_t * ) xTaskToNotify;
\r
4349 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
4351 if( pulPreviousNotificationValue != NULL )
\r
4353 *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;
\r
4356 ucOriginalNotifyState = pxTCB->ucNotifyState;
\r
4357 pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
\r
4362 pxTCB->ulNotifiedValue |= ulValue;
\r
4366 ( pxTCB->ulNotifiedValue )++;
\r
4369 case eSetValueWithOverwrite :
\r
4370 pxTCB->ulNotifiedValue = ulValue;
\r
4373 case eSetValueWithoutOverwrite :
\r
4374 if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
\r
4376 pxTCB->ulNotifiedValue = ulValue;
\r
4380 /* The value could not be written to the task. */
\r
4386 /* The task is being notified without its notify value being
\r
4391 traceTASK_NOTIFY_FROM_ISR();
\r
4393 /* If the task is in the blocked state specifically to wait for a
\r
4394 notification then unblock it now. */
\r
4395 if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
\r
4397 /* The task should not have been on an event list. */
\r
4398 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
\r
4400 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
4402 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
4403 prvAddTaskToReadyList( pxTCB );
\r
4407 /* The delayed and ready lists cannot be accessed, so hold
\r
4408 this task pending until the scheduler is resumed. */
\r
4409 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
4412 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
4414 /* The notified task has a priority above the currently
\r
4415 executing task so a yield is required. */
\r
4416 if( pxHigherPriorityTaskWoken != NULL )
\r
4418 *pxHigherPriorityTaskWoken = pdTRUE;
\r
4422 /* Mark that a yield is pending in case the user is not
\r
4423 using the "xHigherPriorityTaskWoken" parameter to an ISR
\r
4424 safe FreeRTOS function. */
\r
4425 xYieldPending = pdTRUE;
\r
4430 mtCOVERAGE_TEST_MARKER();
\r
4434 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
4439 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4440 /*-----------------------------------------------------------*/
\r
4442 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4444 void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken )
\r
4447 uint8_t ucOriginalNotifyState;
\r
4448 UBaseType_t uxSavedInterruptStatus;
\r
4450 configASSERT( xTaskToNotify );
\r
4452 /* RTOS ports that support interrupt nesting have the concept of a
\r
4453 maximum system call (or maximum API call) interrupt priority.
\r
4454 Interrupts that are above the maximum system call priority are keep
\r
4455 permanently enabled, even when the RTOS kernel is in a critical section,
\r
4456 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
4457 is defined in FreeRTOSConfig.h then
\r
4458 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
4459 failure if a FreeRTOS API function is called from an interrupt that has
\r
4460 been assigned a priority above the configured maximum system call
\r
4461 priority. Only FreeRTOS functions that end in FromISR can be called
\r
4462 from interrupts that have been assigned a priority at or (logically)
\r
4463 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
4464 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
4465 simple as possible. More information (albeit Cortex-M specific) is
\r
4466 provided on the following link:
\r
4467 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
4468 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
4470 pxTCB = ( TCB_t * ) xTaskToNotify;
\r
4472 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
4474 ucOriginalNotifyState = pxTCB->ucNotifyState;
\r
4475 pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED;
\r
4477 /* 'Giving' is equivalent to incrementing a count in a counting
\r
4479 ( pxTCB->ulNotifiedValue )++;
\r
4481 traceTASK_NOTIFY_GIVE_FROM_ISR();
\r
4483 /* If the task is in the blocked state specifically to wait for a
\r
4484 notification then unblock it now. */
\r
4485 if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
\r
4487 /* The task should not have been on an event list. */
\r
4488 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
\r
4490 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
4492 ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
\r
4493 prvAddTaskToReadyList( pxTCB );
\r
4497 /* The delayed and ready lists cannot be accessed, so hold
\r
4498 this task pending until the scheduler is resumed. */
\r
4499 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
4502 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
4504 /* The notified task has a priority above the currently
\r
4505 executing task so a yield is required. */
\r
4506 if( pxHigherPriorityTaskWoken != NULL )
\r
4508 *pxHigherPriorityTaskWoken = pdTRUE;
\r
4512 /* Mark that a yield is pending in case the user is not
\r
4513 using the "xHigherPriorityTaskWoken" parameter in an ISR
\r
4514 safe FreeRTOS function. */
\r
4515 xYieldPending = pdTRUE;
\r
4520 mtCOVERAGE_TEST_MARKER();
\r
4524 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
4527 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4529 /*-----------------------------------------------------------*/
\r
4531 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4533 BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask )
\r
4536 BaseType_t xReturn;
\r
4538 /* If null is passed in here then it is the calling task that is having
\r
4539 its notification state cleared. */
\r
4540 pxTCB = prvGetTCBFromHandle( xTask );
\r
4542 taskENTER_CRITICAL();
\r
4544 if( pxTCB->ucNotifyState == taskNOTIFICATION_RECEIVED )
\r
4546 pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
\r
4554 taskEXIT_CRITICAL();
\r
4559 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4560 /*-----------------------------------------------------------*/
\r
4563 static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, const BaseType_t xCanBlockIndefinitely )
\r
4565 TickType_t xTimeToWake;
\r
4567 #if( INCLUDE_xTaskAbortDelay == 1 )
\r
4569 /* About to enter a delayed list, so ensure the ucDelayAborted flag is
\r
4570 reset to pdFALSE so it can be detected as having been set to pdTRUE
\r
4571 when the task leaves the Blocked state. */
\r
4572 pxCurrentTCB->ucDelayAborted = pdFALSE;
\r
4576 /* Remove the task from the ready list before adding it to the blocked list
\r
4577 as the same list item is used for both lists. */
\r
4578 if( uxListRemove( &( pxCurrentTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
\r
4580 /* The current task must be in a ready list, so there is no need to
\r
4581 check, and the port reset macro can be called directly. */
\r
4582 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
4586 mtCOVERAGE_TEST_MARKER();
\r
4590 #if ( INCLUDE_vTaskSuspend == 1 )
\r
4592 if( ( xTicksToWait == portMAX_DELAY ) && ( xCanBlockIndefinitely != pdFALSE ) )
\r
4594 /* Add the task to the suspended task list instead of a delayed task
\r
4595 list to ensure it is not woken by a timing event. It will block
\r
4597 vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
4601 /* Calculate the time at which the task should be woken if the event
\r
4602 does not occur. This may overflow but this doesn't matter, the
\r
4603 kernel will manage it correctly. */
\r
4604 xTimeToWake = xTickCount + xTicksToWait;
\r
4606 /* The list item will be inserted in wake time order. */
\r
4607 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
\r
4609 if( xTimeToWake < xTickCount )
\r
4611 /* Wake time has overflowed. Place this item in the overflow
\r
4613 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
4617 /* The wake time has not overflowed, so the current block list
\r
4619 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
4621 /* If the task entering the blocked state was placed at the
\r
4622 head of the list of blocked tasks then xNextTaskUnblockTime
\r
4623 needs to be updated too. */
\r
4624 if( xTimeToWake < xNextTaskUnblockTime )
\r
4626 xNextTaskUnblockTime = xTimeToWake;
\r
4630 mtCOVERAGE_TEST_MARKER();
\r
4635 #else /* INCLUDE_vTaskSuspend */
\r
4637 /* Calculate the time at which the task should be woken if the event
\r
4638 does not occur. This may overflow but this doesn't matter, the kernel
\r
4639 will manage it correctly. */
\r
4640 xTimeToWake = xTickCount + xTicksToWait;
\r
4642 /* The list item will be inserted in wake time order. */
\r
4643 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );
\r
4645 if( xTimeToWake < xTickCount )
\r
4647 /* Wake time has overflowed. Place this item in the overflow list. */
\r
4648 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
4652 /* The wake time has not overflowed, so the current block list is used. */
\r
4653 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
\r
4655 /* If the task entering the blocked state was placed at the head of the
\r
4656 list of blocked tasks then xNextTaskUnblockTime needs to be updated
\r
4658 if( xTimeToWake < xNextTaskUnblockTime )
\r
4660 xNextTaskUnblockTime = xTimeToWake;
\r
4664 mtCOVERAGE_TEST_MARKER();
\r
4668 /* Avoid compiler warning when INCLUDE_vTaskSuspend is not 1. */
\r
4669 ( void ) xCanBlockIndefinitely;
\r
4671 #endif /* INCLUDE_vTaskSuspend */
\r
4675 #ifdef FREERTOS_MODULE_TEST
\r
4676 #include "tasks_test_access_functions.h"
\r