2 FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
\r
5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
7 ***************************************************************************
\r
9 * FreeRTOS provides completely free yet professionally developed, *
\r
10 * robust, strictly quality controlled, supported, and cross *
\r
11 * platform software that has become a de facto standard. *
\r
13 * Help yourself get started quickly and support the FreeRTOS *
\r
14 * project by purchasing a FreeRTOS tutorial book, reference *
\r
15 * manual, or both from: http://www.FreeRTOS.org/Documentation *
\r
19 ***************************************************************************
\r
21 This file is part of the FreeRTOS distribution.
\r
23 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
24 the terms of the GNU General Public License (version 2) as published by the
\r
25 Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
\r
27 >>! NOTE: The modification to the GPL is included to allow you to !<<
\r
28 >>! distribute a combined work that includes FreeRTOS without being !<<
\r
29 >>! obliged to provide the source code for proprietary components !<<
\r
30 >>! outside of the FreeRTOS kernel. !<<
\r
32 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
33 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
34 FOR A PARTICULAR PURPOSE. Full license text is available from the following
\r
35 link: http://www.freertos.org/a00114.html
\r
39 ***************************************************************************
\r
41 * Having a problem? Start by reading the FAQ "My application does *
\r
42 * not run, what could be wrong?" *
\r
44 * http://www.FreeRTOS.org/FAQHelp.html *
\r
46 ***************************************************************************
\r
48 http://www.FreeRTOS.org - Documentation, books, training, latest versions,
\r
49 license and Real Time Engineers Ltd. contact details.
\r
51 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
52 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
\r
53 compatible FAT file system, and our tiny thread aware UDP/IP stack.
\r
55 http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
\r
56 Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
\r
57 licenses offer ticketed support, indemnification and middleware.
\r
59 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
60 engineered and independently SIL3 certified version for use in safety and
\r
61 mission critical applications that require provable dependability.
\r
66 /* Standard includes. */
\r
70 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
\r
71 all the API functions to use the MPU wrappers. That should only be done when
\r
72 task.h is included from an application file. */
\r
73 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
\r
75 /* FreeRTOS includes. */
\r
76 #include "FreeRTOS.h"
\r
79 #include "StackMacros.h"
\r
81 /* Lint e961 and e750 are suppressed as a MISRA exception justified because the
\r
82 MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
\r
83 header files above, but not in this file, in order to generate the correct
\r
84 privileged Vs unprivileged linkage and placement. */
\r
85 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
\r
87 /* Set configUSE_STATS_FORMATTING_FUNCTIONS to 2 to include the stats formatting
\r
88 functions but without including stdio.h here. */
\r
89 #if ( configUSE_STATS_FORMATTING_FUNCTIONS == 1 )
\r
90 /* At the bottom of this file are two optional functions that can be used
\r
91 to generate human readable text from the raw data generated by the
\r
92 uxTaskGetSystemState() function. Note the formatting functions are provided
\r
93 for convenience only, and are NOT considered part of the kernel. */
\r
95 #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
\r
97 /* Sanity check the configuration. */
\r
98 #if configUSE_TICKLESS_IDLE != 0
\r
99 #if INCLUDE_vTaskSuspend != 1
\r
100 #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0
\r
101 #endif /* INCLUDE_vTaskSuspend */
\r
102 #endif /* configUSE_TICKLESS_IDLE */
\r
105 * Defines the size, in words, of the stack allocated to the idle task.
\r
107 #define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE
\r
109 #if( configUSE_PREEMPTION == 0 )
\r
110 /* If the cooperative scheduler is being used then a yield should not be
\r
111 performed just because a higher priority task has been woken. */
\r
112 #define taskYIELD_IF_USING_PREEMPTION()
\r
114 #define taskYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
\r
117 /* Value that can be assigned to the eNotifyState member of the TCB. */
\r
120 eNotWaitingNotification,
\r
121 eWaitingNotification,
\r
126 * Task control block. A task control block (TCB) is allocated for each task,
\r
127 * and stores task state information, including a pointer to the task's context
\r
128 * (the task's run time environment, including register values)
\r
130 typedef struct tskTaskControlBlock
\r
132 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
134 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
135 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
138 ListItem_t xGenericListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
\r
139 ListItem_t xEventListItem; /*< Used to reference a task from an event list. */
\r
140 UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */
\r
141 StackType_t *pxStack; /*< Points to the start of the stack. */
\r
142 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
144 #if ( portSTACK_GROWTH > 0 )
\r
145 StackType_t *pxEndOfStack; /*< Points to the end of the stack on architectures where the stack grows up from low memory. */
\r
148 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
149 UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
\r
152 #if ( configUSE_TRACE_FACILITY == 1 )
\r
153 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
154 UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
\r
157 #if ( configUSE_MUTEXES == 1 )
\r
158 UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
\r
159 UBaseType_t uxMutexesHeld;
\r
162 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
163 TaskHookFunction_t pxTaskTag;
\r
166 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
167 uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
\r
170 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
171 /* Allocate a Newlib reent structure that is specific to this task.
\r
172 Note Newlib support has been included by popular demand, but is not
\r
173 used by the FreeRTOS maintainers themselves. FreeRTOS is not
\r
174 responsible for resulting newlib operation. User must be familiar with
\r
175 newlib and must provide system-wide implementations of the necessary
\r
176 stubs. Be warned that (at the time of writing) the current newlib design
\r
177 implements a system-wide malloc() that must be provided with locks. */
\r
178 struct _reent xNewLib_reent;
\r
181 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
\r
182 uint32_t ulNotifiedValue;
\r
183 eNotifyValue eNotifyState;
\r
188 /* The old tskTCB name is maintained above then typedefed to the new TCB_t name
\r
189 below to enable the use of older kernel aware debuggers. */
\r
190 typedef tskTCB TCB_t;
\r
193 * Some kernel aware debuggers require the data the debugger needs access to to
\r
194 * be global, rather than file scope.
\r
196 #ifdef portREMOVE_STATIC_QUALIFIER
\r
200 /*lint -e956 A manual analysis and inspection has been used to determine which
\r
201 static variables must be declared volatile. */
\r
203 PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
\r
205 /* Lists for ready and blocked tasks. --------------------*/
\r
206 PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ];/*< Prioritised ready tasks. */
\r
207 PRIVILEGED_DATA static List_t xDelayedTaskList1; /*< Delayed tasks. */
\r
208 PRIVILEGED_DATA static List_t xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
\r
209 PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList; /*< Points to the delayed task list currently being used. */
\r
210 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
211 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
213 #if ( INCLUDE_vTaskDelete == 1 )
\r
215 PRIVILEGED_DATA static List_t xTasksWaitingTermination; /*< Tasks that have been deleted - but their memory not yet freed. */
\r
216 PRIVILEGED_DATA static volatile UBaseType_t uxTasksDeleted = ( UBaseType_t ) 0U;
\r
220 #if ( INCLUDE_vTaskSuspend == 1 )
\r
222 PRIVILEGED_DATA static List_t xSuspendedTaskList; /*< Tasks that are currently suspended. */
\r
226 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
228 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
232 /* Other file private variables. --------------------------------*/
\r
233 PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks = ( UBaseType_t ) 0U;
\r
234 PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) 0U;
\r
235 PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority = tskIDLE_PRIORITY;
\r
236 PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning = pdFALSE;
\r
237 PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks = ( UBaseType_t ) 0U;
\r
238 PRIVILEGED_DATA static volatile BaseType_t xYieldPending = pdFALSE;
\r
239 PRIVILEGED_DATA static volatile BaseType_t xNumOfOverflows = ( BaseType_t ) 0;
\r
240 PRIVILEGED_DATA static UBaseType_t uxTaskNumber = ( UBaseType_t ) 0U;
\r
241 PRIVILEGED_DATA static volatile TickType_t xNextTaskUnblockTime = portMAX_DELAY;
\r
243 /* Context switches are held pending while the scheduler is suspended. Also,
\r
244 interrupts must not manipulate the xGenericListItem of a TCB, or any of the
\r
245 lists the xGenericListItem can be referenced from, if the scheduler is suspended.
\r
246 If an interrupt needs to unblock a task while the scheduler is suspended then it
\r
247 moves the task's event list item into the xPendingReadyList, ready for the
\r
248 kernel to move the task from the pending ready list into the real ready list
\r
249 when the scheduler is unsuspended. The pending ready list itself can only be
\r
250 accessed from a critical section. */
\r
251 PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE;
\r
253 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
255 PRIVILEGED_DATA static uint32_t ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
\r
256 PRIVILEGED_DATA static uint32_t ulTotalRunTime = 0UL; /*< Holds the total amount of execution time as defined by the run time counter clock. */
\r
262 /* Debugging and trace facilities private variables and macros. ------------*/
\r
265 * The value used to fill the stack of a task when the task is created. This
\r
266 * is used purely for checking the high water mark for tasks.
\r
268 #define tskSTACK_FILL_BYTE ( 0xa5U )
\r
271 * Macros used by vListTask to indicate which state a task is in.
\r
273 #define tskBLOCKED_CHAR ( 'B' )
\r
274 #define tskREADY_CHAR ( 'R' )
\r
275 #define tskDELETED_CHAR ( 'D' )
\r
276 #define tskSUSPENDED_CHAR ( 'S' )
\r
278 /*-----------------------------------------------------------*/
\r
280 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
\r
282 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
\r
283 performed in a generic way that is not optimised to any particular
\r
284 microcontroller architecture. */
\r
286 /* uxTopReadyPriority holds the priority of the highest priority ready
\r
288 #define taskRECORD_READY_PRIORITY( uxPriority ) \
\r
290 if( ( uxPriority ) > uxTopReadyPriority ) \
\r
292 uxTopReadyPriority = ( uxPriority ); \
\r
294 } /* taskRECORD_READY_PRIORITY */
\r
296 /*-----------------------------------------------------------*/
\r
298 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
300 /* Find the highest priority queue that contains ready tasks. */ \
\r
301 while( listLIST_IS_EMPTY( &( pxReadyTasksLists[ uxTopReadyPriority ] ) ) ) \
\r
303 configASSERT( uxTopReadyPriority ); \
\r
304 --uxTopReadyPriority; \
\r
307 /* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
\r
308 the same priority get an equal share of the processor time. */ \
\r
309 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \
\r
310 } /* taskSELECT_HIGHEST_PRIORITY_TASK */
\r
312 /*-----------------------------------------------------------*/
\r
314 /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as
\r
315 they are only required when a port optimised method of task selection is
\r
317 #define taskRESET_READY_PRIORITY( uxPriority )
\r
318 #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
320 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
322 /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is
\r
323 performed in a way that is tailored to the particular microcontroller
\r
324 architecture being used. */
\r
326 /* A port optimised version is provided. Call the port defined macros. */
\r
327 #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )
\r
329 /*-----------------------------------------------------------*/
\r
331 #define taskSELECT_HIGHEST_PRIORITY_TASK() \
\r
333 UBaseType_t uxTopPriority; \
\r
335 /* Find the highest priority queue that contains ready tasks. */ \
\r
336 portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
\r
337 configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
\r
338 listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \
\r
339 } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
\r
341 /*-----------------------------------------------------------*/
\r
343 /* A port optimised version is provided, call it only if the TCB being reset
\r
344 is being referenced from a ready list. If it is referenced from a delayed
\r
345 or suspended list then it won't be in a ready list. */
\r
346 #define taskRESET_READY_PRIORITY( uxPriority ) \
\r
348 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \
\r
350 portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \
\r
354 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
\r
356 /*-----------------------------------------------------------*/
\r
358 /* pxDelayedTaskList and pxOverflowDelayedTaskList are switched when the tick
\r
359 count overflows. */
\r
360 #define taskSWITCH_DELAYED_LISTS() \
\r
364 /* The delayed tasks list should be empty when the lists are switched. */ \
\r
365 configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) ); \
\r
367 pxTemp = pxDelayedTaskList; \
\r
368 pxDelayedTaskList = pxOverflowDelayedTaskList; \
\r
369 pxOverflowDelayedTaskList = pxTemp; \
\r
370 xNumOfOverflows++; \
\r
371 prvResetNextTaskUnblockTime(); \
\r
374 /*-----------------------------------------------------------*/
\r
377 * Place the task represented by pxTCB into the appropriate ready list for
\r
378 * the task. It is inserted at the end of the list.
\r
380 #define prvAddTaskToReadyList( pxTCB ) \
\r
381 traceMOVED_TASK_TO_READY_STATE( pxTCB ) \
\r
382 taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
\r
383 vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) )
\r
384 /*-----------------------------------------------------------*/
\r
387 * Several functions take an TaskHandle_t parameter that can optionally be NULL,
\r
388 * where NULL is used to indicate that the handle of the currently executing
\r
389 * task should be used in place of the parameter. This macro simply checks to
\r
390 * see if the parameter is NULL and returns a pointer to the appropriate TCB.
\r
392 #define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TCB_t * ) pxCurrentTCB : ( TCB_t * ) ( pxHandle ) )
\r
394 /* The item value of the event list item is normally used to hold the priority
\r
395 of the task to which it belongs (coded to allow it to be held in reverse
\r
396 priority order). However, it is occasionally borrowed for other purposes. It
\r
397 is important its value is not updated due to a task priority change while it is
\r
398 being used for another purpose. The following bit definition is used to inform
\r
399 the scheduler that the value should not be changed - in which case it is the
\r
400 responsibility of whichever module is using the value to ensure it gets set back
\r
401 to its original value when it is released. */
\r
402 #if configUSE_16_BIT_TICKS == 1
\r
403 #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x8000U
\r
405 #define taskEVENT_LIST_ITEM_VALUE_IN_USE 0x80000000UL
\r
408 /* Callback function prototypes. --------------------------*/
\r
409 #if configCHECK_FOR_STACK_OVERFLOW > 0
\r
410 extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName );
\r
413 #if configUSE_TICK_HOOK > 0
\r
414 extern void vApplicationTickHook( void );
\r
417 /* File private functions. --------------------------------*/
\r
420 * Utility to ready a TCB for a given task. Mainly just copies the parameters
\r
421 * into the TCB structure.
\r
423 static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
426 * Utility task that simply returns pdTRUE if the task referenced by xTask is
\r
427 * currently in the Suspended state, or pdFALSE if the task referenced by xTask
\r
428 * is in any other state.
\r
430 #if ( INCLUDE_vTaskSuspend == 1 )
\r
431 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
\r
432 #endif /* INCLUDE_vTaskSuspend */
\r
435 * Utility to ready all the lists used by the scheduler. This is called
\r
436 * automatically upon the creation of the first task.
\r
438 static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
\r
441 * The idle task, which as all tasks is implemented as a never ending loop.
\r
442 * The idle task is automatically created and added to the ready lists upon
\r
443 * creation of the first user task.
\r
445 * The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
\r
446 * language extensions. The equivalent prototype for this function is:
\r
448 * void prvIdleTask( void *pvParameters );
\r
451 static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
\r
454 * Utility to free all memory allocated by the scheduler to hold a TCB,
\r
455 * including the stack pointed to by the TCB.
\r
457 * This does not free memory allocated by the task itself (i.e. memory
\r
458 * allocated by calls to pvPortMalloc from within the tasks application code).
\r
460 #if ( INCLUDE_vTaskDelete == 1 )
\r
462 static void prvDeleteTCB( TCB_t *pxTCB ) PRIVILEGED_FUNCTION;
\r
467 * Used only by the idle task. This checks to see if anything has been placed
\r
468 * in the list of tasks waiting to be deleted. If so the task is cleaned up
\r
469 * and its TCB deleted.
\r
471 static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
\r
474 * The currently executing task is entering the Blocked state. Add the task to
\r
475 * either the current or the overflow delayed task list.
\r
477 static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake ) PRIVILEGED_FUNCTION;
\r
480 * Allocates memory from the heap for a TCB and associated stack. Checks the
\r
481 * allocation was successful.
\r
483 static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer ) PRIVILEGED_FUNCTION;
\r
486 * Fills an TaskStatus_t structure with information on each task that is
\r
487 * referenced from the pxList list (which may be a ready list, a delayed list,
\r
488 * a suspended list, etc.).
\r
490 * THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
\r
491 * NORMAL APPLICATION CODE.
\r
493 #if ( configUSE_TRACE_FACILITY == 1 )
\r
495 static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState ) PRIVILEGED_FUNCTION;
\r
500 * When a task is created, the stack of the task is filled with a known value.
\r
501 * This function determines the 'high water mark' of the task stack by
\r
502 * determining how much of the stack remains at the original preset value.
\r
504 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
506 static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte ) PRIVILEGED_FUNCTION;
\r
511 * Return the amount of time, in ticks, that will pass before the kernel will
\r
512 * next move a task from the Blocked state to the Running state.
\r
514 * This conditional compilation should use inequality to 0, not equality to 1.
\r
515 * This is to ensure portSUPPRESS_TICKS_AND_SLEEP() can be called when user
\r
516 * defined low power mode implementations require configUSE_TICKLESS_IDLE to be
\r
517 * set to a value other than 1.
\r
519 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
521 static TickType_t prvGetExpectedIdleTime( void ) PRIVILEGED_FUNCTION;
\r
526 * Set xNextTaskUnblockTime to the time at which the next Blocked state task
\r
527 * will exit the Blocked state.
\r
529 static void prvResetNextTaskUnblockTime( void );
\r
531 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
534 * Helper function used to pad task names with spaces when printing out
\r
535 * human readable tables of task information.
\r
537 static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName );
\r
540 /*-----------------------------------------------------------*/
\r
542 BaseType_t xTaskGenericCreate( 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, const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
544 BaseType_t xReturn;
\r
547 configASSERT( pxTaskCode );
\r
548 configASSERT( ( ( uxPriority & ( ~portPRIVILEGE_BIT ) ) < configMAX_PRIORITIES ) );
\r
550 /* Allocate the memory required by the TCB and stack for the new task,
\r
551 checking that the allocation was successful. */
\r
552 pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer );
\r
554 if( pxNewTCB != NULL )
\r
556 StackType_t *pxTopOfStack;
\r
558 #if( portUSING_MPU_WRAPPERS == 1 )
\r
559 /* Should the task be created in privileged mode? */
\r
560 BaseType_t xRunPrivileged;
\r
561 if( ( uxPriority & portPRIVILEGE_BIT ) != 0U )
\r
563 xRunPrivileged = pdTRUE;
\r
567 xRunPrivileged = pdFALSE;
\r
569 uxPriority &= ~portPRIVILEGE_BIT;
\r
570 #endif /* portUSING_MPU_WRAPPERS == 1 */
\r
572 /* Calculate the top of stack address. This depends on whether the
\r
573 stack grows from high memory to low (as per the 80x86) or vice versa.
\r
574 portSTACK_GROWTH is used to make the result positive or negative as
\r
575 required by the port. */
\r
576 #if( portSTACK_GROWTH < 0 )
\r
578 pxTopOfStack = pxNewTCB->pxStack + ( usStackDepth - ( uint16_t ) 1 );
\r
579 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
581 /* Check the alignment of the calculated top of stack is correct. */
\r
582 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
584 #else /* portSTACK_GROWTH */
\r
586 pxTopOfStack = pxNewTCB->pxStack;
\r
588 /* Check the alignment of the stack buffer is correct. */
\r
589 configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
\r
591 /* If we want to use stack checking on architectures that use
\r
592 a positive stack growth direction then we also need to store the
\r
593 other extreme of the stack space. */
\r
594 pxNewTCB->pxEndOfStack = pxNewTCB->pxStack + ( usStackDepth - 1 );
\r
596 #endif /* portSTACK_GROWTH */
\r
598 /* Setup the newly allocated TCB with the initial state of the task. */
\r
599 prvInitialiseTCBVariables( pxNewTCB, pcName, uxPriority, xRegions, usStackDepth );
\r
601 /* Initialize the TCB stack to look as if the task was already running,
\r
602 but had been interrupted by the scheduler. The return address is set
\r
603 to the start of the task function. Once the stack has been initialised
\r
604 the top of stack variable is updated. */
\r
605 #if( portUSING_MPU_WRAPPERS == 1 )
\r
607 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
\r
609 #else /* portUSING_MPU_WRAPPERS */
\r
611 pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
\r
613 #endif /* portUSING_MPU_WRAPPERS */
\r
615 if( ( void * ) pxCreatedTask != NULL )
\r
617 /* Pass the TCB out - in an anonymous way. The calling function/
\r
618 task can use this as a handle to delete the task later if
\r
620 *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
\r
624 mtCOVERAGE_TEST_MARKER();
\r
627 /* Ensure interrupts don't access the task lists while they are being
\r
629 taskENTER_CRITICAL();
\r
631 uxCurrentNumberOfTasks++;
\r
632 if( pxCurrentTCB == NULL )
\r
634 /* There are no other tasks, or all the other tasks are in
\r
635 the suspended state - make this the current task. */
\r
636 pxCurrentTCB = pxNewTCB;
\r
638 if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
\r
640 /* This is the first task to be created so do the preliminary
\r
641 initialisation required. We will not recover if this call
\r
642 fails, but we will report the failure. */
\r
643 prvInitialiseTaskLists();
\r
647 mtCOVERAGE_TEST_MARKER();
\r
652 /* If the scheduler is not already running, make this task the
\r
653 current task if it is the highest priority task to be created
\r
655 if( xSchedulerRunning == pdFALSE )
\r
657 if( pxCurrentTCB->uxPriority <= uxPriority )
\r
659 pxCurrentTCB = pxNewTCB;
\r
663 mtCOVERAGE_TEST_MARKER();
\r
668 mtCOVERAGE_TEST_MARKER();
\r
674 #if ( configUSE_TRACE_FACILITY == 1 )
\r
676 /* Add a counter into the TCB for tracing only. */
\r
677 pxNewTCB->uxTCBNumber = uxTaskNumber;
\r
679 #endif /* configUSE_TRACE_FACILITY */
\r
680 traceTASK_CREATE( pxNewTCB );
\r
682 prvAddTaskToReadyList( pxNewTCB );
\r
685 portSETUP_TCB( pxNewTCB );
\r
687 taskEXIT_CRITICAL();
\r
691 xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
\r
692 traceTASK_CREATE_FAILED();
\r
695 if( xReturn == pdPASS )
\r
697 if( xSchedulerRunning != pdFALSE )
\r
699 /* If the created task is of a higher priority than the current task
\r
700 then it should run now. */
\r
701 if( pxCurrentTCB->uxPriority < uxPriority )
\r
703 taskYIELD_IF_USING_PREEMPTION();
\r
707 mtCOVERAGE_TEST_MARKER();
\r
712 mtCOVERAGE_TEST_MARKER();
\r
718 /*-----------------------------------------------------------*/
\r
720 #if ( INCLUDE_vTaskDelete == 1 )
\r
722 void vTaskDelete( TaskHandle_t xTaskToDelete )
\r
726 taskENTER_CRITICAL();
\r
728 /* If null is passed in here then it is the calling task that is
\r
730 pxTCB = prvGetTCBFromHandle( xTaskToDelete );
\r
732 /* Remove task from the ready list and place in the termination list.
\r
733 This will stop the task from be scheduled. The idle task will check
\r
734 the termination list and free up any memory allocated by the
\r
735 scheduler for the TCB and stack. */
\r
736 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
738 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
742 mtCOVERAGE_TEST_MARKER();
\r
745 /* Is the task waiting on an event also? */
\r
746 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
748 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
752 mtCOVERAGE_TEST_MARKER();
\r
755 vListInsertEnd( &xTasksWaitingTermination, &( pxTCB->xGenericListItem ) );
\r
757 /* Increment the ucTasksDeleted variable so the idle task knows
\r
758 there is a task that has been deleted and that it should therefore
\r
759 check the xTasksWaitingTermination list. */
\r
762 /* Increment the uxTaskNumberVariable also so kernel aware debuggers
\r
763 can detect that the task lists need re-generating. */
\r
766 traceTASK_DELETE( pxTCB );
\r
768 taskEXIT_CRITICAL();
\r
770 /* Force a reschedule if it is the currently running task that has just
\r
772 if( xSchedulerRunning != pdFALSE )
\r
774 if( pxTCB == pxCurrentTCB )
\r
776 configASSERT( uxSchedulerSuspended == 0 );
\r
778 /* The pre-delete hook is primarily for the Windows simulator,
\r
779 in which Windows specific clean up operations are performed,
\r
780 after which it is not possible to yield away from this task -
\r
781 hence xYieldPending is used to latch that a context switch is
\r
783 portPRE_TASK_DELETE_HOOK( pxTCB, &xYieldPending );
\r
784 portYIELD_WITHIN_API();
\r
788 /* Reset the next expected unblock time in case it referred to
\r
789 the task that has just been deleted. */
\r
790 taskENTER_CRITICAL();
\r
792 prvResetNextTaskUnblockTime();
\r
794 taskEXIT_CRITICAL();
\r
799 #endif /* INCLUDE_vTaskDelete */
\r
800 /*-----------------------------------------------------------*/
\r
802 #if ( INCLUDE_vTaskDelayUntil == 1 )
\r
804 void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
\r
806 TickType_t xTimeToWake;
\r
807 BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;
\r
809 configASSERT( pxPreviousWakeTime );
\r
810 configASSERT( ( xTimeIncrement > 0U ) );
\r
811 configASSERT( uxSchedulerSuspended == 0 );
\r
815 /* Minor optimisation. The tick count cannot change in this
\r
817 const TickType_t xConstTickCount = xTickCount;
\r
819 /* Generate the tick time at which the task wants to wake. */
\r
820 xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;
\r
822 if( xConstTickCount < *pxPreviousWakeTime )
\r
824 /* The tick count has overflowed since this function was
\r
825 lasted called. In this case the only time we should ever
\r
826 actually delay is if the wake time has also overflowed,
\r
827 and the wake time is greater than the tick time. When this
\r
828 is the case it is as if neither time had overflowed. */
\r
829 if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )
\r
831 xShouldDelay = pdTRUE;
\r
835 mtCOVERAGE_TEST_MARKER();
\r
840 /* The tick time has not overflowed. In this case we will
\r
841 delay if either the wake time has overflowed, and/or the
\r
842 tick time is less than the wake time. */
\r
843 if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )
\r
845 xShouldDelay = pdTRUE;
\r
849 mtCOVERAGE_TEST_MARKER();
\r
853 /* Update the wake time ready for the next call. */
\r
854 *pxPreviousWakeTime = xTimeToWake;
\r
856 if( xShouldDelay != pdFALSE )
\r
858 traceTASK_DELAY_UNTIL();
\r
860 /* Remove the task from the ready list before adding it to the
\r
861 blocked list as the same list item is used for both lists. */
\r
862 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
864 /* The current task must be in a ready list, so there is
\r
865 no need to check, and the port reset macro can be called
\r
867 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
871 mtCOVERAGE_TEST_MARKER();
\r
874 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
878 mtCOVERAGE_TEST_MARKER();
\r
881 xAlreadyYielded = xTaskResumeAll();
\r
883 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
884 have put ourselves to sleep. */
\r
885 if( xAlreadyYielded == pdFALSE )
\r
887 portYIELD_WITHIN_API();
\r
891 mtCOVERAGE_TEST_MARKER();
\r
895 #endif /* INCLUDE_vTaskDelayUntil */
\r
896 /*-----------------------------------------------------------*/
\r
898 #if ( INCLUDE_vTaskDelay == 1 )
\r
900 void vTaskDelay( const TickType_t xTicksToDelay )
\r
902 TickType_t xTimeToWake;
\r
903 BaseType_t xAlreadyYielded = pdFALSE;
\r
906 /* A delay time of zero just forces a reschedule. */
\r
907 if( xTicksToDelay > ( TickType_t ) 0U )
\r
909 configASSERT( uxSchedulerSuspended == 0 );
\r
914 /* A task that is removed from the event list while the
\r
915 scheduler is suspended will not get placed in the ready
\r
916 list or removed from the blocked list until the scheduler
\r
919 This task cannot be in an event list as it is the currently
\r
922 /* Calculate the time to wake - this may overflow but this is
\r
924 xTimeToWake = xTickCount + xTicksToDelay;
\r
926 /* We must remove ourselves from the ready list before adding
\r
927 ourselves to the blocked list as the same list item is used for
\r
929 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
931 /* The current task must be in a ready list, so there is
\r
932 no need to check, and the port reset macro can be called
\r
934 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
938 mtCOVERAGE_TEST_MARKER();
\r
940 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
942 xAlreadyYielded = xTaskResumeAll();
\r
946 mtCOVERAGE_TEST_MARKER();
\r
949 /* Force a reschedule if xTaskResumeAll has not already done so, we may
\r
950 have put ourselves to sleep. */
\r
951 if( xAlreadyYielded == pdFALSE )
\r
953 portYIELD_WITHIN_API();
\r
957 mtCOVERAGE_TEST_MARKER();
\r
961 #endif /* INCLUDE_vTaskDelay */
\r
962 /*-----------------------------------------------------------*/
\r
964 #if ( INCLUDE_eTaskGetState == 1 )
\r
966 eTaskState eTaskGetState( TaskHandle_t xTask )
\r
968 eTaskState eReturn;
\r
969 List_t *pxStateList;
\r
970 const TCB_t * const pxTCB = ( TCB_t * ) xTask;
\r
972 configASSERT( pxTCB );
\r
974 if( pxTCB == pxCurrentTCB )
\r
976 /* The task calling this function is querying its own state. */
\r
977 eReturn = eRunning;
\r
981 taskENTER_CRITICAL();
\r
983 pxStateList = ( List_t * ) listLIST_ITEM_CONTAINER( &( pxTCB->xGenericListItem ) );
\r
985 taskEXIT_CRITICAL();
\r
987 if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) )
\r
989 /* The task being queried is referenced from one of the Blocked
\r
991 eReturn = eBlocked;
\r
994 #if ( INCLUDE_vTaskSuspend == 1 )
\r
995 else if( pxStateList == &xSuspendedTaskList )
\r
997 /* The task being queried is referenced from the suspended
\r
998 list. Is it genuinely suspended or is it block
\r
1000 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
\r
1002 eReturn = eSuspended;
\r
1006 eReturn = eBlocked;
\r
1011 #if ( INCLUDE_vTaskDelete == 1 )
\r
1012 else if( pxStateList == &xTasksWaitingTermination )
\r
1014 /* The task being queried is referenced from the deleted
\r
1016 eReturn = eDeleted;
\r
1020 else /*lint !e525 Negative indentation is intended to make use of pre-processor clearer. */
\r
1022 /* If the task is not in any other state, it must be in the
\r
1023 Ready (including pending ready) state. */
\r
1029 } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
\r
1031 #endif /* INCLUDE_eTaskGetState */
\r
1032 /*-----------------------------------------------------------*/
\r
1034 #if ( INCLUDE_uxTaskPriorityGet == 1 )
\r
1036 UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask )
\r
1039 UBaseType_t uxReturn;
\r
1041 taskENTER_CRITICAL();
\r
1043 /* If null is passed in here then we are changing the
\r
1044 priority of the calling function. */
\r
1045 pxTCB = prvGetTCBFromHandle( xTask );
\r
1046 uxReturn = pxTCB->uxPriority;
\r
1048 taskEXIT_CRITICAL();
\r
1053 #endif /* INCLUDE_uxTaskPriorityGet */
\r
1054 /*-----------------------------------------------------------*/
\r
1056 #if ( INCLUDE_uxTaskPriorityGet == 1 )
\r
1058 UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask )
\r
1061 UBaseType_t uxReturn, uxSavedInterruptState;
\r
1063 /* RTOS ports that support interrupt nesting have the concept of a
\r
1064 maximum system call (or maximum API call) interrupt priority.
\r
1065 Interrupts that are above the maximum system call priority are keep
\r
1066 permanently enabled, even when the RTOS kernel is in a critical section,
\r
1067 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
1068 is defined in FreeRTOSConfig.h then
\r
1069 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1070 failure if a FreeRTOS API function is called from an interrupt that has
\r
1071 been assigned a priority above the configured maximum system call
\r
1072 priority. Only FreeRTOS functions that end in FromISR can be called
\r
1073 from interrupts that have been assigned a priority at or (logically)
\r
1074 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
1075 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
1076 simple as possible. More information (albeit Cortex-M specific) is
\r
1077 provided on the following link:
\r
1078 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1079 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1081 uxSavedInterruptState = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1083 /* If null is passed in here then we are changing the
\r
1084 priority of the calling function. */
\r
1085 pxTCB = prvGetTCBFromHandle( xTask );
\r
1086 uxReturn = pxTCB->uxPriority;
\r
1088 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptState );
\r
1093 #endif /* INCLUDE_uxTaskPriorityGet */
\r
1094 /*-----------------------------------------------------------*/
\r
1096 #if ( INCLUDE_vTaskPrioritySet == 1 )
\r
1098 void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )
\r
1101 UBaseType_t uxCurrentBasePriority, uxPriorityUsedOnEntry;
\r
1102 BaseType_t xYieldRequired = pdFALSE;
\r
1104 configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
\r
1106 /* Ensure the new priority is valid. */
\r
1107 if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
\r
1109 uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
\r
1113 mtCOVERAGE_TEST_MARKER();
\r
1116 taskENTER_CRITICAL();
\r
1118 /* If null is passed in here then it is the priority of the calling
\r
1119 task that is being changed. */
\r
1120 pxTCB = prvGetTCBFromHandle( xTask );
\r
1122 traceTASK_PRIORITY_SET( pxTCB, uxNewPriority );
\r
1124 #if ( configUSE_MUTEXES == 1 )
\r
1126 uxCurrentBasePriority = pxTCB->uxBasePriority;
\r
1130 uxCurrentBasePriority = pxTCB->uxPriority;
\r
1134 if( uxCurrentBasePriority != uxNewPriority )
\r
1136 /* The priority change may have readied a task of higher
\r
1137 priority than the calling task. */
\r
1138 if( uxNewPriority > uxCurrentBasePriority )
\r
1140 if( pxTCB != pxCurrentTCB )
\r
1142 /* The priority of a task other than the currently
\r
1143 running task is being raised. Is the priority being
\r
1144 raised above that of the running task? */
\r
1145 if( uxNewPriority >= pxCurrentTCB->uxPriority )
\r
1147 xYieldRequired = pdTRUE;
\r
1151 mtCOVERAGE_TEST_MARKER();
\r
1156 /* The priority of the running task is being raised,
\r
1157 but the running task must already be the highest
\r
1158 priority task able to run so no yield is required. */
\r
1161 else if( pxTCB == pxCurrentTCB )
\r
1163 /* Setting the priority of the running task down means
\r
1164 there may now be another task of higher priority that
\r
1165 is ready to execute. */
\r
1166 xYieldRequired = pdTRUE;
\r
1170 /* Setting the priority of any other task down does not
\r
1171 require a yield as the running task must be above the
\r
1172 new priority of the task being modified. */
\r
1175 /* Remember the ready list the task might be referenced from
\r
1176 before its uxPriority member is changed so the
\r
1177 taskRESET_READY_PRIORITY() macro can function correctly. */
\r
1178 uxPriorityUsedOnEntry = pxTCB->uxPriority;
\r
1180 #if ( configUSE_MUTEXES == 1 )
\r
1182 /* Only change the priority being used if the task is not
\r
1183 currently using an inherited priority. */
\r
1184 if( pxTCB->uxBasePriority == pxTCB->uxPriority )
\r
1186 pxTCB->uxPriority = uxNewPriority;
\r
1190 mtCOVERAGE_TEST_MARKER();
\r
1193 /* The base priority gets set whatever. */
\r
1194 pxTCB->uxBasePriority = uxNewPriority;
\r
1198 pxTCB->uxPriority = uxNewPriority;
\r
1202 /* Only reset the event list item value if the value is not
\r
1203 being used for anything else. */
\r
1204 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
\r
1206 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
1210 mtCOVERAGE_TEST_MARKER();
\r
1213 /* If the task is in the blocked or suspended list we need do
\r
1214 nothing more than change it's priority variable. However, if
\r
1215 the task is in a ready list it needs to be removed and placed
\r
1216 in the list appropriate to its new priority. */
\r
1217 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
\r
1219 /* The task is currently in its ready list - remove before adding
\r
1220 it to it's new ready list. As we are in a critical section we
\r
1221 can do this even if the scheduler is suspended. */
\r
1222 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
1224 /* It is known that the task is in its ready list so
\r
1225 there is no need to check again and the port level
\r
1226 reset macro can be called directly. */
\r
1227 portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
\r
1231 mtCOVERAGE_TEST_MARKER();
\r
1233 prvAddTaskToReadyList( pxTCB );
\r
1237 mtCOVERAGE_TEST_MARKER();
\r
1240 if( xYieldRequired == pdTRUE )
\r
1242 taskYIELD_IF_USING_PREEMPTION();
\r
1246 mtCOVERAGE_TEST_MARKER();
\r
1249 /* Remove compiler warning about unused variables when the port
\r
1250 optimised task selection is not being used. */
\r
1251 ( void ) uxPriorityUsedOnEntry;
\r
1254 taskEXIT_CRITICAL();
\r
1257 #endif /* INCLUDE_vTaskPrioritySet */
\r
1258 /*-----------------------------------------------------------*/
\r
1260 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1262 void vTaskSuspend( TaskHandle_t xTaskToSuspend )
\r
1266 taskENTER_CRITICAL();
\r
1268 /* If null is passed in here then it is the running task that is
\r
1269 being suspended. */
\r
1270 pxTCB = prvGetTCBFromHandle( xTaskToSuspend );
\r
1272 traceTASK_SUSPEND( pxTCB );
\r
1274 /* Remove task from the ready/delayed list and place in the
\r
1275 suspended list. */
\r
1276 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
1278 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
1282 mtCOVERAGE_TEST_MARKER();
\r
1285 /* Is the task waiting on an event also? */
\r
1286 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
1288 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1292 mtCOVERAGE_TEST_MARKER();
\r
1295 vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) );
\r
1297 taskEXIT_CRITICAL();
\r
1299 if( pxTCB == pxCurrentTCB )
\r
1301 if( xSchedulerRunning != pdFALSE )
\r
1303 /* The current task has just been suspended. */
\r
1304 configASSERT( uxSchedulerSuspended == 0 );
\r
1305 portYIELD_WITHIN_API();
\r
1309 /* The scheduler is not running, but the task that was pointed
\r
1310 to by pxCurrentTCB has just been suspended and pxCurrentTCB
\r
1311 must be adjusted to point to a different task. */
\r
1312 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == uxCurrentNumberOfTasks )
\r
1314 /* No other tasks are ready, so set pxCurrentTCB back to
\r
1315 NULL so when the next task is created pxCurrentTCB will
\r
1316 be set to point to it no matter what its relative priority
\r
1318 pxCurrentTCB = NULL;
\r
1322 vTaskSwitchContext();
\r
1328 if( xSchedulerRunning != pdFALSE )
\r
1330 /* A task other than the currently running task was suspended,
\r
1331 reset the next expected unblock time in case it referred to the
\r
1332 task that is now in the Suspended state. */
\r
1333 taskENTER_CRITICAL();
\r
1335 prvResetNextTaskUnblockTime();
\r
1337 taskEXIT_CRITICAL();
\r
1341 mtCOVERAGE_TEST_MARKER();
\r
1346 #endif /* INCLUDE_vTaskSuspend */
\r
1347 /*-----------------------------------------------------------*/
\r
1349 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1351 static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask )
\r
1353 BaseType_t xReturn = pdFALSE;
\r
1354 const TCB_t * const pxTCB = ( TCB_t * ) xTask;
\r
1356 /* Accesses xPendingReadyList so must be called from a critical
\r
1359 /* It does not make sense to check if the calling task is suspended. */
\r
1360 configASSERT( xTask );
\r
1362 /* Is the task being resumed actually in the suspended list? */
\r
1363 if( listIS_CONTAINED_WITHIN( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) ) != pdFALSE )
\r
1365 /* Has the task already been resumed from within an ISR? */
\r
1366 if( listIS_CONTAINED_WITHIN( &xPendingReadyList, &( pxTCB->xEventListItem ) ) == pdFALSE )
\r
1368 /* Is it in the suspended list because it is in the Suspended
\r
1369 state, or because is is blocked with no timeout? */
\r
1370 if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )
\r
1376 mtCOVERAGE_TEST_MARKER();
\r
1381 mtCOVERAGE_TEST_MARKER();
\r
1386 mtCOVERAGE_TEST_MARKER();
\r
1390 } /*lint !e818 xTask cannot be a pointer to const because it is a typedef. */
\r
1392 #endif /* INCLUDE_vTaskSuspend */
\r
1393 /*-----------------------------------------------------------*/
\r
1395 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1397 void vTaskResume( TaskHandle_t xTaskToResume )
\r
1399 TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
\r
1401 /* It does not make sense to resume the calling task. */
\r
1402 configASSERT( xTaskToResume );
\r
1404 /* The parameter cannot be NULL as it is impossible to resume the
\r
1405 currently executing task. */
\r
1406 if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
\r
1408 taskENTER_CRITICAL();
\r
1410 if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE )
\r
1412 traceTASK_RESUME( pxTCB );
\r
1414 /* As we are in a critical section we can access the ready
\r
1415 lists even if the scheduler is suspended. */
\r
1416 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1417 prvAddTaskToReadyList( pxTCB );
\r
1419 /* We may have just resumed a higher priority task. */
\r
1420 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1422 /* This yield may not cause the task just resumed to run,
\r
1423 but will leave the lists in the correct state for the
\r
1425 taskYIELD_IF_USING_PREEMPTION();
\r
1429 mtCOVERAGE_TEST_MARKER();
\r
1434 mtCOVERAGE_TEST_MARKER();
\r
1437 taskEXIT_CRITICAL();
\r
1441 mtCOVERAGE_TEST_MARKER();
\r
1445 #endif /* INCLUDE_vTaskSuspend */
\r
1447 /*-----------------------------------------------------------*/
\r
1449 #if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) )
\r
1451 BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume )
\r
1453 BaseType_t xYieldRequired = pdFALSE;
\r
1454 TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
\r
1455 UBaseType_t uxSavedInterruptStatus;
\r
1457 configASSERT( xTaskToResume );
\r
1459 /* RTOS ports that support interrupt nesting have the concept of a
\r
1460 maximum system call (or maximum API call) interrupt priority.
\r
1461 Interrupts that are above the maximum system call priority are keep
\r
1462 permanently enabled, even when the RTOS kernel is in a critical section,
\r
1463 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
1464 is defined in FreeRTOSConfig.h then
\r
1465 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1466 failure if a FreeRTOS API function is called from an interrupt that has
\r
1467 been assigned a priority above the configured maximum system call
\r
1468 priority. Only FreeRTOS functions that end in FromISR can be called
\r
1469 from interrupts that have been assigned a priority at or (logically)
\r
1470 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
1471 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
1472 simple as possible. More information (albeit Cortex-M specific) is
\r
1473 provided on the following link:
\r
1474 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1475 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1477 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1479 if( prvTaskIsTaskSuspended( pxTCB ) == pdTRUE )
\r
1481 traceTASK_RESUME_FROM_ISR( pxTCB );
\r
1483 /* Check the ready lists can be accessed. */
\r
1484 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
1486 /* Ready lists can be accessed so move the task from the
\r
1487 suspended list to the ready list directly. */
\r
1488 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1490 xYieldRequired = pdTRUE;
\r
1494 mtCOVERAGE_TEST_MARKER();
\r
1497 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1498 prvAddTaskToReadyList( pxTCB );
\r
1502 /* The delayed or ready lists cannot be accessed so the task
\r
1503 is held in the pending ready list until the scheduler is
\r
1505 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
1510 mtCOVERAGE_TEST_MARKER();
\r
1513 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1515 return xYieldRequired;
\r
1518 #endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */
\r
1519 /*-----------------------------------------------------------*/
\r
1521 void vTaskStartScheduler( void )
\r
1523 BaseType_t xReturn;
\r
1525 /* Add the idle task at the lowest priority. */
\r
1526 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
1528 /* Create the idle task, storing its handle in xIdleTaskHandle so it can
\r
1529 be returned by the xTaskGetIdleTaskHandle() function. */
\r
1530 xReturn = xTaskCreate( prvIdleTask, "IDLE", tskIDLE_STACK_SIZE, ( 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
1534 /* Create the idle task without storing its handle. */
\r
1535 xReturn = xTaskCreate( prvIdleTask, "IDLE", tskIDLE_STACK_SIZE, ( void * ) NULL, ( tskIDLE_PRIORITY | portPRIVILEGE_BIT ), NULL ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
\r
1537 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
\r
1539 #if ( configUSE_TIMERS == 1 )
\r
1541 if( xReturn == pdPASS )
\r
1543 xReturn = xTimerCreateTimerTask();
\r
1547 mtCOVERAGE_TEST_MARKER();
\r
1550 #endif /* configUSE_TIMERS */
\r
1552 if( xReturn == pdPASS )
\r
1554 /* Interrupts are turned off here, to ensure a tick does not occur
\r
1555 before or during the call to xPortStartScheduler(). The stacks of
\r
1556 the created tasks contain a status word with interrupts switched on
\r
1557 so interrupts will automatically get re-enabled when the first task
\r
1559 portDISABLE_INTERRUPTS();
\r
1561 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
1563 /* Switch Newlib's _impure_ptr variable to point to the _reent
\r
1564 structure specific to the task that will run first. */
\r
1565 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
\r
1567 #endif /* configUSE_NEWLIB_REENTRANT */
\r
1569 xSchedulerRunning = pdTRUE;
\r
1570 xTickCount = ( TickType_t ) 0U;
\r
1572 /* If configGENERATE_RUN_TIME_STATS is defined then the following
\r
1573 macro must be defined to configure the timer/counter used to generate
\r
1574 the run time counter time base. */
\r
1575 portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
\r
1577 /* Setting up the timer tick is hardware specific and thus in the
\r
1578 portable interface. */
\r
1579 if( xPortStartScheduler() != pdFALSE )
\r
1581 /* Should not reach here as if the scheduler is running the
\r
1582 function will not return. */
\r
1586 /* Should only reach here if a task calls xTaskEndScheduler(). */
\r
1591 /* This line will only be reached if the kernel could not be started,
\r
1592 because there was not enough FreeRTOS heap to create the idle task
\r
1593 or the timer task. */
\r
1594 configASSERT( xReturn );
\r
1597 /*-----------------------------------------------------------*/
\r
1599 void vTaskEndScheduler( void )
\r
1601 /* Stop the scheduler interrupts and call the portable scheduler end
\r
1602 routine so the original ISRs can be restored if necessary. The port
\r
1603 layer must ensure interrupts enable bit is left in the correct state. */
\r
1604 portDISABLE_INTERRUPTS();
\r
1605 xSchedulerRunning = pdFALSE;
\r
1606 vPortEndScheduler();
\r
1608 /*----------------------------------------------------------*/
\r
1610 void vTaskSuspendAll( void )
\r
1612 /* A critical section is not required as the variable is of type
\r
1613 BaseType_t. Please read Richard Barry's reply in the following link to a
\r
1614 post in the FreeRTOS support forum before reporting this as a bug! -
\r
1615 http://goo.gl/wu4acr */
\r
1616 ++uxSchedulerSuspended;
\r
1618 /*----------------------------------------------------------*/
\r
1620 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
1622 static TickType_t prvGetExpectedIdleTime( void )
\r
1624 TickType_t xReturn;
\r
1626 if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
\r
1630 else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
\r
1632 /* There are other idle priority tasks in the ready state. If
\r
1633 time slicing is used then the very next tick interrupt must be
\r
1639 xReturn = xNextTaskUnblockTime - xTickCount;
\r
1645 #endif /* configUSE_TICKLESS_IDLE */
\r
1646 /*----------------------------------------------------------*/
\r
1648 BaseType_t xTaskResumeAll( void )
\r
1651 BaseType_t xAlreadyYielded = pdFALSE;
\r
1653 /* If uxSchedulerSuspended is zero then this function does not match a
\r
1654 previous call to vTaskSuspendAll(). */
\r
1655 configASSERT( uxSchedulerSuspended );
\r
1657 /* It is possible that an ISR caused a task to be removed from an event
\r
1658 list while the scheduler was suspended. If this was the case then the
\r
1659 removed task will have been added to the xPendingReadyList. Once the
\r
1660 scheduler has been resumed it is safe to move all the pending ready
\r
1661 tasks from this list into their appropriate ready list. */
\r
1662 taskENTER_CRITICAL();
\r
1664 --uxSchedulerSuspended;
\r
1666 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
1668 if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )
\r
1670 /* Move any readied tasks from the pending list into the
\r
1671 appropriate ready list. */
\r
1672 while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
\r
1674 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );
\r
1675 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1676 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1677 prvAddTaskToReadyList( pxTCB );
\r
1679 /* If the moved task has a priority higher than the current
\r
1680 task then a yield must be performed. */
\r
1681 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
1683 xYieldPending = pdTRUE;
\r
1687 mtCOVERAGE_TEST_MARKER();
\r
1691 /* If any ticks occurred while the scheduler was suspended then
\r
1692 they should be processed now. This ensures the tick count does
\r
1693 not slip, and that any delayed tasks are resumed at the correct
\r
1695 if( uxPendedTicks > ( UBaseType_t ) 0U )
\r
1697 while( uxPendedTicks > ( UBaseType_t ) 0U )
\r
1699 if( xTaskIncrementTick() != pdFALSE )
\r
1701 xYieldPending = pdTRUE;
\r
1705 mtCOVERAGE_TEST_MARKER();
\r
1712 mtCOVERAGE_TEST_MARKER();
\r
1715 if( xYieldPending == pdTRUE )
\r
1717 #if( configUSE_PREEMPTION != 0 )
\r
1719 xAlreadyYielded = pdTRUE;
\r
1722 taskYIELD_IF_USING_PREEMPTION();
\r
1726 mtCOVERAGE_TEST_MARKER();
\r
1732 mtCOVERAGE_TEST_MARKER();
\r
1735 taskEXIT_CRITICAL();
\r
1737 return xAlreadyYielded;
\r
1739 /*-----------------------------------------------------------*/
\r
1741 TickType_t xTaskGetTickCount( void )
\r
1743 TickType_t xTicks;
\r
1745 /* Critical section required if running on a 16 bit processor. */
\r
1746 taskENTER_CRITICAL();
\r
1748 xTicks = xTickCount;
\r
1750 taskEXIT_CRITICAL();
\r
1754 /*-----------------------------------------------------------*/
\r
1756 TickType_t xTaskGetTickCountFromISR( void )
\r
1758 TickType_t xReturn;
\r
1759 UBaseType_t uxSavedInterruptStatus;
\r
1761 /* RTOS ports that support interrupt nesting have the concept of a maximum
\r
1762 system call (or maximum API call) interrupt priority. Interrupts that are
\r
1763 above the maximum system call priority are kept permanently enabled, even
\r
1764 when the RTOS kernel is in a critical section, but cannot make any calls to
\r
1765 FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
\r
1766 then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
1767 failure if a FreeRTOS API function is called from an interrupt that has been
\r
1768 assigned a priority above the configured maximum system call priority.
\r
1769 Only FreeRTOS functions that end in FromISR can be called from interrupts
\r
1770 that have been assigned a priority at or (logically) below the maximum
\r
1771 system call interrupt priority. FreeRTOS maintains a separate interrupt
\r
1772 safe API to ensure interrupt entry is as fast and as simple as possible.
\r
1773 More information (albeit Cortex-M specific) is provided on the following
\r
1774 link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
1775 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
1777 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
1779 xReturn = xTickCount;
\r
1781 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
1785 /*-----------------------------------------------------------*/
\r
1787 UBaseType_t uxTaskGetNumberOfTasks( void )
\r
1789 /* A critical section is not required because the variables are of type
\r
1791 return uxCurrentNumberOfTasks;
\r
1793 /*-----------------------------------------------------------*/
\r
1795 #if ( INCLUDE_pcTaskGetTaskName == 1 )
\r
1797 char *pcTaskGetTaskName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
1801 /* If null is passed in here then the name of the calling task is being queried. */
\r
1802 pxTCB = prvGetTCBFromHandle( xTaskToQuery );
\r
1803 configASSERT( pxTCB );
\r
1804 return &( pxTCB->pcTaskName[ 0 ] );
\r
1807 #endif /* INCLUDE_pcTaskGetTaskName */
\r
1808 /*-----------------------------------------------------------*/
\r
1810 #if ( configUSE_TRACE_FACILITY == 1 )
\r
1812 UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime )
\r
1814 UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
\r
1816 vTaskSuspendAll();
\r
1818 /* Is there a space in the array for each task in the system? */
\r
1819 if( uxArraySize >= uxCurrentNumberOfTasks )
\r
1821 /* Fill in an TaskStatus_t structure with information on each
\r
1822 task in the Ready state. */
\r
1826 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady );
\r
1828 } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
1830 /* Fill in an TaskStatus_t structure with information on each
\r
1831 task in the Blocked state. */
\r
1832 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked );
\r
1833 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked );
\r
1835 #if( INCLUDE_vTaskDelete == 1 )
\r
1837 /* Fill in an TaskStatus_t structure with information on
\r
1838 each task that has been deleted but not yet cleaned up. */
\r
1839 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted );
\r
1843 #if ( INCLUDE_vTaskSuspend == 1 )
\r
1845 /* Fill in an TaskStatus_t structure with information on
\r
1846 each task in the Suspended state. */
\r
1847 uxTask += prvListTaskWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended );
\r
1851 #if ( configGENERATE_RUN_TIME_STATS == 1)
\r
1853 if( pulTotalRunTime != NULL )
\r
1855 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
1856 portALT_GET_RUN_TIME_COUNTER_VALUE( ( *pulTotalRunTime ) );
\r
1858 *pulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
1864 if( pulTotalRunTime != NULL )
\r
1866 *pulTotalRunTime = 0;
\r
1873 mtCOVERAGE_TEST_MARKER();
\r
1876 ( void ) xTaskResumeAll();
\r
1881 #endif /* configUSE_TRACE_FACILITY */
\r
1882 /*----------------------------------------------------------*/
\r
1884 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
\r
1886 TaskHandle_t xTaskGetIdleTaskHandle( void )
\r
1888 /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
\r
1889 started, then xIdleTaskHandle will be NULL. */
\r
1890 configASSERT( ( xIdleTaskHandle != NULL ) );
\r
1891 return xIdleTaskHandle;
\r
1894 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
\r
1895 /*----------------------------------------------------------*/
\r
1897 /* This conditional compilation should use inequality to 0, not equality to 1.
\r
1898 This is to ensure vTaskStepTick() is available when user defined low power mode
\r
1899 implementations require configUSE_TICKLESS_IDLE to be set to a value other than
\r
1901 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
1903 void vTaskStepTick( const TickType_t xTicksToJump )
\r
1905 /* Correct the tick count value after a period during which the tick
\r
1906 was suppressed. Note this does *not* call the tick hook function for
\r
1907 each stepped tick. */
\r
1908 configASSERT( ( xTickCount + xTicksToJump ) <= xNextTaskUnblockTime );
\r
1909 xTickCount += xTicksToJump;
\r
1910 traceINCREASE_TICK_COUNT( xTicksToJump );
\r
1913 #endif /* configUSE_TICKLESS_IDLE */
\r
1914 /*----------------------------------------------------------*/
\r
1916 BaseType_t xTaskIncrementTick( void )
\r
1919 TickType_t xItemValue;
\r
1920 BaseType_t xSwitchRequired = pdFALSE;
\r
1922 /* Called by the portable layer each time a tick interrupt occurs.
\r
1923 Increments the tick then checks to see if the new tick value will cause any
\r
1924 tasks to be unblocked. */
\r
1925 traceTASK_INCREMENT_TICK( xTickCount );
\r
1926 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
1928 /* Increment the RTOS tick, switching the delayed and overflowed
\r
1929 delayed lists if it wraps to 0. */
\r
1933 /* Minor optimisation. The tick count cannot change in this
\r
1935 const TickType_t xConstTickCount = xTickCount;
\r
1937 if( xConstTickCount == ( TickType_t ) 0U )
\r
1939 taskSWITCH_DELAYED_LISTS();
\r
1943 mtCOVERAGE_TEST_MARKER();
\r
1946 /* See if this tick has made a timeout expire. Tasks are stored in
\r
1947 the queue in the order of their wake time - meaning once one task
\r
1948 has been found whose block time has not expired there is no need to
\r
1949 look any further down the list. */
\r
1950 if( xConstTickCount >= xNextTaskUnblockTime )
\r
1954 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
\r
1956 /* The delayed list is empty. Set xNextTaskUnblockTime
\r
1957 to the maximum possible value so it is extremely
\r
1959 if( xTickCount >= xNextTaskUnblockTime ) test will pass
\r
1960 next time through. */
\r
1961 xNextTaskUnblockTime = portMAX_DELAY;
\r
1966 /* The delayed list is not empty, get the value of the
\r
1967 item at the head of the delayed list. This is the time
\r
1968 at which the task at the head of the delayed list must
\r
1969 be removed from the Blocked state. */
\r
1970 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
\r
1971 xItemValue = listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) );
\r
1973 if( xConstTickCount < xItemValue )
\r
1975 /* It is not time to unblock this item yet, but the
\r
1976 item value is the time at which the task at the head
\r
1977 of the blocked list must be removed from the Blocked
\r
1978 state - so record the item value in
\r
1979 xNextTaskUnblockTime. */
\r
1980 xNextTaskUnblockTime = xItemValue;
\r
1985 mtCOVERAGE_TEST_MARKER();
\r
1988 /* It is time to remove the item from the Blocked state. */
\r
1989 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
1991 /* Is the task waiting on an event also? If so remove
\r
1992 it from the event list. */
\r
1993 if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
\r
1995 ( void ) uxListRemove( &( pxTCB->xEventListItem ) );
\r
1999 mtCOVERAGE_TEST_MARKER();
\r
2002 /* Place the unblocked task into the appropriate ready
\r
2004 prvAddTaskToReadyList( pxTCB );
\r
2006 /* A task being unblocked cannot cause an immediate
\r
2007 context switch if preemption is turned off. */
\r
2008 #if ( configUSE_PREEMPTION == 1 )
\r
2010 /* Preemption is on, but a context switch should
\r
2011 only be performed if the unblocked task has a
\r
2012 priority that is equal to or higher than the
\r
2013 currently executing task. */
\r
2014 if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
\r
2016 xSwitchRequired = pdTRUE;
\r
2020 mtCOVERAGE_TEST_MARKER();
\r
2023 #endif /* configUSE_PREEMPTION */
\r
2029 /* Tasks of equal priority to the currently running task will share
\r
2030 processing time (time slice) if preemption is on, and the application
\r
2031 writer has not explicitly turned time slicing off. */
\r
2032 #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
\r
2034 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 )
\r
2036 xSwitchRequired = pdTRUE;
\r
2040 mtCOVERAGE_TEST_MARKER();
\r
2043 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
\r
2045 #if ( configUSE_TICK_HOOK == 1 )
\r
2047 /* Guard against the tick hook being called when the pended tick
\r
2048 count is being unwound (when the scheduler is being unlocked). */
\r
2049 if( uxPendedTicks == ( UBaseType_t ) 0U )
\r
2051 vApplicationTickHook();
\r
2055 mtCOVERAGE_TEST_MARKER();
\r
2058 #endif /* configUSE_TICK_HOOK */
\r
2064 /* The tick hook gets called at regular intervals, even if the
\r
2065 scheduler is locked. */
\r
2066 #if ( configUSE_TICK_HOOK == 1 )
\r
2068 vApplicationTickHook();
\r
2073 #if ( configUSE_PREEMPTION == 1 )
\r
2075 if( xYieldPending != pdFALSE )
\r
2077 xSwitchRequired = pdTRUE;
\r
2081 mtCOVERAGE_TEST_MARKER();
\r
2084 #endif /* configUSE_PREEMPTION */
\r
2086 return xSwitchRequired;
\r
2088 /*-----------------------------------------------------------*/
\r
2090 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2092 void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction )
\r
2096 /* If xTask is NULL then it is the task hook of the calling task that is
\r
2098 if( xTask == NULL )
\r
2100 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2104 xTCB = ( TCB_t * ) xTask;
\r
2107 /* Save the hook function in the TCB. A critical section is required as
\r
2108 the value can be accessed from an interrupt. */
\r
2109 taskENTER_CRITICAL();
\r
2110 xTCB->pxTaskTag = pxHookFunction;
\r
2111 taskEXIT_CRITICAL();
\r
2114 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2115 /*-----------------------------------------------------------*/
\r
2117 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2119 TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask )
\r
2122 TaskHookFunction_t xReturn;
\r
2124 /* If xTask is NULL then we are setting our own task hook. */
\r
2125 if( xTask == NULL )
\r
2127 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2131 xTCB = ( TCB_t * ) xTask;
\r
2134 /* Save the hook function in the TCB. A critical section is required as
\r
2135 the value can be accessed from an interrupt. */
\r
2136 taskENTER_CRITICAL();
\r
2138 xReturn = xTCB->pxTaskTag;
\r
2140 taskEXIT_CRITICAL();
\r
2145 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2146 /*-----------------------------------------------------------*/
\r
2148 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2150 BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter )
\r
2153 BaseType_t xReturn;
\r
2155 /* If xTask is NULL then we are calling our own task hook. */
\r
2156 if( xTask == NULL )
\r
2158 xTCB = ( TCB_t * ) pxCurrentTCB;
\r
2162 xTCB = ( TCB_t * ) xTask;
\r
2165 if( xTCB->pxTaskTag != NULL )
\r
2167 xReturn = xTCB->pxTaskTag( pvParameter );
\r
2177 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2178 /*-----------------------------------------------------------*/
\r
2180 void vTaskSwitchContext( void )
\r
2182 if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )
\r
2184 /* The scheduler is currently suspended - do not allow a context
\r
2186 xYieldPending = pdTRUE;
\r
2190 xYieldPending = pdFALSE;
\r
2191 traceTASK_SWITCHED_OUT();
\r
2193 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
2195 #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
\r
2196 portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
\r
2198 ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
\r
2201 /* Add the amount of time the task has been running to the
\r
2202 accumulated time so far. The time the task started running was
\r
2203 stored in ulTaskSwitchedInTime. Note that there is no overflow
\r
2204 protection here so count values are only valid until the timer
\r
2205 overflows. The guard against negative values is to protect
\r
2206 against suspect run time stat counter implementations - which
\r
2207 are provided by the application, not the kernel. */
\r
2208 if( ulTotalRunTime > ulTaskSwitchedInTime )
\r
2210 pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
\r
2214 mtCOVERAGE_TEST_MARKER();
\r
2216 ulTaskSwitchedInTime = ulTotalRunTime;
\r
2218 #endif /* configGENERATE_RUN_TIME_STATS */
\r
2220 /* Check for stack overflow, if configured. */
\r
2221 taskFIRST_CHECK_FOR_STACK_OVERFLOW();
\r
2222 taskSECOND_CHECK_FOR_STACK_OVERFLOW();
\r
2224 /* Select a new task to run using either the generic C or port
\r
2225 optimised asm code. */
\r
2226 taskSELECT_HIGHEST_PRIORITY_TASK();
\r
2227 traceTASK_SWITCHED_IN();
\r
2229 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
2231 /* Switch Newlib's _impure_ptr variable to point to the _reent
\r
2232 structure specific to this task. */
\r
2233 _impure_ptr = &( pxCurrentTCB->xNewLib_reent );
\r
2235 #endif /* configUSE_NEWLIB_REENTRANT */
\r
2238 /*-----------------------------------------------------------*/
\r
2240 void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait )
\r
2242 TickType_t xTimeToWake;
\r
2244 configASSERT( pxEventList );
\r
2246 /* THIS FUNCTION MUST BE CALLED WITH EITHER INTERRUPTS DISABLED OR THE
\r
2247 SCHEDULER SUSPENDED AND THE QUEUE BEING ACCESSED LOCKED. */
\r
2249 /* Place the event list item of the TCB in the appropriate event list.
\r
2250 This is placed in the list in priority order so the highest priority task
\r
2251 is the first to be woken by the event. The queue that contains the event
\r
2252 list is locked, preventing simultaneous access from interrupts. */
\r
2253 vListInsert( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2255 /* The task must be removed from from the ready list before it is added to
\r
2256 the blocked list as the same list item is used for both lists. Exclusive
\r
2257 access to the ready lists guaranteed because the scheduler is locked. */
\r
2258 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
2260 /* The current task must be in a ready list, so there is no need to
\r
2261 check, and the port reset macro can be called directly. */
\r
2262 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
2266 mtCOVERAGE_TEST_MARKER();
\r
2269 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2271 if( xTicksToWait == portMAX_DELAY )
\r
2273 /* Add the task to the suspended task list instead of a delayed task
\r
2274 list to ensure the task is not woken by a timing event. It will
\r
2275 block indefinitely. */
\r
2276 vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
\r
2280 /* Calculate the time at which the task should be woken if the event
\r
2281 does not occur. This may overflow but this doesn't matter, the
\r
2282 scheduler will handle it. */
\r
2283 xTimeToWake = xTickCount + xTicksToWait;
\r
2284 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
2287 #else /* INCLUDE_vTaskSuspend */
\r
2289 /* Calculate the time at which the task should be woken if the event does
\r
2290 not occur. This may overflow but this doesn't matter, the scheduler
\r
2291 will handle it. */
\r
2292 xTimeToWake = xTickCount + xTicksToWait;
\r
2293 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
2295 #endif /* INCLUDE_vTaskSuspend */
\r
2297 /*-----------------------------------------------------------*/
\r
2299 void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait )
\r
2301 TickType_t xTimeToWake;
\r
2303 configASSERT( pxEventList );
\r
2305 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
\r
2306 the event groups implementation. */
\r
2307 configASSERT( uxSchedulerSuspended != 0 );
\r
2309 /* Store the item value in the event list item. It is safe to access the
\r
2310 event list item here as interrupts won't access the event list item of a
\r
2311 task that is not in the Blocked state. */
\r
2312 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ), xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
\r
2314 /* Place the event list item of the TCB at the end of the appropriate event
\r
2315 list. It is safe to access the event list here because it is part of an
\r
2316 event group implementation - and interrupts don't access event groups
\r
2317 directly (instead they access them indirectly by pending function calls to
\r
2318 the task level). */
\r
2319 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2321 /* The task must be removed from the ready list before it is added to the
\r
2322 blocked list. Exclusive access can be assured to the ready list as the
\r
2323 scheduler is locked. */
\r
2324 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
2326 /* The current task must be in a ready list, so there is no need to
\r
2327 check, and the port reset macro can be called directly. */
\r
2328 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
2332 mtCOVERAGE_TEST_MARKER();
\r
2335 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2337 if( xTicksToWait == portMAX_DELAY )
\r
2339 /* Add the task to the suspended task list instead of a delayed task
\r
2340 list to ensure it is not woken by a timing event. It will block
\r
2342 vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
\r
2346 /* Calculate the time at which the task should be woken if the event
\r
2347 does not occur. This may overflow but this doesn't matter, the
\r
2348 kernel will manage it correctly. */
\r
2349 xTimeToWake = xTickCount + xTicksToWait;
\r
2350 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
2353 #else /* INCLUDE_vTaskSuspend */
\r
2355 /* Calculate the time at which the task should be woken if the event does
\r
2356 not occur. This may overflow but this doesn't matter, the kernel
\r
2357 will manage it correctly. */
\r
2358 xTimeToWake = xTickCount + xTicksToWait;
\r
2359 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
2361 #endif /* INCLUDE_vTaskSuspend */
\r
2363 /*-----------------------------------------------------------*/
\r
2365 #if configUSE_TIMERS == 1
\r
2367 void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait )
\r
2369 TickType_t xTimeToWake;
\r
2371 configASSERT( pxEventList );
\r
2373 /* This function should not be called by application code hence the
\r
2374 'Restricted' in its name. It is not part of the public API. It is
\r
2375 designed for use by kernel code, and has special calling requirements -
\r
2376 it should be called from a critical section. */
\r
2379 /* Place the event list item of the TCB in the appropriate event list.
\r
2380 In this case it is assume that this is the only task that is going to
\r
2381 be waiting on this event list, so the faster vListInsertEnd() function
\r
2382 can be used in place of vListInsert. */
\r
2383 vListInsertEnd( pxEventList, &( pxCurrentTCB->xEventListItem ) );
\r
2385 /* We must remove this task from the ready list before adding it to the
\r
2386 blocked list as the same list item is used for both lists. This
\r
2387 function is called form a critical section. */
\r
2388 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
2390 /* The current task must be in a ready list, so there is no need to
\r
2391 check, and the port reset macro can be called directly. */
\r
2392 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
2396 mtCOVERAGE_TEST_MARKER();
\r
2399 /* Calculate the time at which the task should be woken if the event does
\r
2400 not occur. This may overflow but this doesn't matter. */
\r
2401 xTimeToWake = xTickCount + xTicksToWait;
\r
2403 traceTASK_DELAY_UNTIL();
\r
2404 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
2407 #endif /* configUSE_TIMERS */
\r
2408 /*-----------------------------------------------------------*/
\r
2410 BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
\r
2412 TCB_t *pxUnblockedTCB;
\r
2413 BaseType_t xReturn;
\r
2415 /* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be
\r
2416 called from a critical section within an ISR. */
\r
2418 /* The event list is sorted in priority order, so the first in the list can
\r
2419 be removed as it is known to be the highest priority. Remove the TCB from
\r
2420 the delayed list, and add it to the ready list.
\r
2422 If an event is for a queue that is locked then this function will never
\r
2423 get called - the lock count on the queue will get modified instead. This
\r
2424 means exclusive access to the event list is guaranteed here.
\r
2426 This function assumes that a check has already been made to ensure that
\r
2427 pxEventList is not empty. */
\r
2428 pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
\r
2429 configASSERT( pxUnblockedTCB );
\r
2430 ( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );
\r
2432 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
2434 ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
\r
2435 prvAddTaskToReadyList( pxUnblockedTCB );
\r
2439 /* The delayed and ready lists cannot be accessed, so hold this task
\r
2440 pending until the scheduler is resumed. */
\r
2441 vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );
\r
2444 if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
2446 /* Return true if the task removed from the event list has a higher
\r
2447 priority than the calling task. This allows the calling task to know if
\r
2448 it should force a context switch now. */
\r
2451 /* Mark that a yield is pending in case the user is not using the
\r
2452 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
\r
2453 xYieldPending = pdTRUE;
\r
2457 xReturn = pdFALSE;
\r
2460 #if( configUSE_TICKLESS_IDLE == 1 )
\r
2462 /* If a task is blocked on a kernel object then xNextTaskUnblockTime
\r
2463 might be set to the blocked task's time out time. If the task is
\r
2464 unblocked for a reason other than a timeout xNextTaskUnblockTime is
\r
2465 normally left unchanged, because it is automatically get reset to a new
\r
2466 value when the tick count equals xNextTaskUnblockTime. However if
\r
2467 tickless idling is used it might be more important to enter sleep mode
\r
2468 at the earliest possible time - so reset xNextTaskUnblockTime here to
\r
2469 ensure it is updated at the earliest possible time. */
\r
2470 prvResetNextTaskUnblockTime();
\r
2476 /*-----------------------------------------------------------*/
\r
2478 BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )
\r
2480 TCB_t *pxUnblockedTCB;
\r
2481 BaseType_t xReturn;
\r
2483 /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by
\r
2484 the event flags implementation. */
\r
2485 configASSERT( uxSchedulerSuspended != pdFALSE );
\r
2487 /* Store the new item value in the event list. */
\r
2488 listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE );
\r
2490 /* Remove the event list form the event flag. Interrupts do not access
\r
2492 pxUnblockedTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxEventListItem );
\r
2493 configASSERT( pxUnblockedTCB );
\r
2494 ( void ) uxListRemove( pxEventListItem );
\r
2496 /* Remove the task from the delayed list and add it to the ready list. The
\r
2497 scheduler is suspended so interrupts will not be accessing the ready
\r
2499 ( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
\r
2500 prvAddTaskToReadyList( pxUnblockedTCB );
\r
2502 if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
2504 /* Return true if the task removed from the event list has
\r
2505 a higher priority than the calling task. This allows
\r
2506 the calling task to know if it should force a context
\r
2510 /* Mark that a yield is pending in case the user is not using the
\r
2511 "xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
\r
2512 xYieldPending = pdTRUE;
\r
2516 xReturn = pdFALSE;
\r
2521 /*-----------------------------------------------------------*/
\r
2523 void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
\r
2525 configASSERT( pxTimeOut );
\r
2526 pxTimeOut->xOverflowCount = xNumOfOverflows;
\r
2527 pxTimeOut->xTimeOnEntering = xTickCount;
\r
2529 /*-----------------------------------------------------------*/
\r
2531 BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait )
\r
2533 BaseType_t xReturn;
\r
2535 configASSERT( pxTimeOut );
\r
2536 configASSERT( pxTicksToWait );
\r
2538 taskENTER_CRITICAL();
\r
2540 /* Minor optimisation. The tick count cannot change in this block. */
\r
2541 const TickType_t xConstTickCount = xTickCount;
\r
2543 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2544 /* If INCLUDE_vTaskSuspend is set to 1 and the block time specified is
\r
2545 the maximum block time then the task should block indefinitely, and
\r
2546 therefore never time out. */
\r
2547 if( *pxTicksToWait == portMAX_DELAY )
\r
2549 xReturn = pdFALSE;
\r
2551 else /* We are not blocking indefinitely, perform the checks below. */
\r
2554 if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */
\r
2556 /* The tick count is greater than the time at which vTaskSetTimeout()
\r
2557 was called, but has also overflowed since vTaskSetTimeOut() was called.
\r
2558 It must have wrapped all the way around and gone past us again. This
\r
2559 passed since vTaskSetTimeout() was called. */
\r
2562 else if( ( xConstTickCount - pxTimeOut->xTimeOnEntering ) < *pxTicksToWait )
\r
2564 /* Not a genuine timeout. Adjust parameters for time remaining. */
\r
2565 *pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );
\r
2566 vTaskSetTimeOutState( pxTimeOut );
\r
2567 xReturn = pdFALSE;
\r
2574 taskEXIT_CRITICAL();
\r
2578 /*-----------------------------------------------------------*/
\r
2580 void vTaskMissedYield( void )
\r
2582 xYieldPending = pdTRUE;
\r
2584 /*-----------------------------------------------------------*/
\r
2586 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2588 UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask )
\r
2590 UBaseType_t uxReturn;
\r
2593 if( xTask != NULL )
\r
2595 pxTCB = ( TCB_t * ) xTask;
\r
2596 uxReturn = pxTCB->uxTaskNumber;
\r
2606 #endif /* configUSE_TRACE_FACILITY */
\r
2607 /*-----------------------------------------------------------*/
\r
2609 #if ( configUSE_TRACE_FACILITY == 1 )
\r
2611 void vTaskSetTaskNumber( TaskHandle_t xTask, const UBaseType_t uxHandle )
\r
2615 if( xTask != NULL )
\r
2617 pxTCB = ( TCB_t * ) xTask;
\r
2618 pxTCB->uxTaskNumber = uxHandle;
\r
2622 #endif /* configUSE_TRACE_FACILITY */
\r
2625 * -----------------------------------------------------------
\r
2627 * ----------------------------------------------------------
\r
2629 * The portTASK_FUNCTION() macro is used to allow port/compiler specific
\r
2630 * language extensions. The equivalent prototype for this function is:
\r
2632 * void prvIdleTask( void *pvParameters );
\r
2635 static portTASK_FUNCTION( prvIdleTask, pvParameters )
\r
2637 /* Stop warnings. */
\r
2638 ( void ) pvParameters;
\r
2642 /* See if any tasks have been deleted. */
\r
2643 prvCheckTasksWaitingTermination();
\r
2645 #if ( configUSE_PREEMPTION == 0 )
\r
2647 /* If we are not using preemption we keep forcing a task switch to
\r
2648 see if any other task has become available. If we are using
\r
2649 preemption we don't need to do this as any task becoming available
\r
2650 will automatically get the processor anyway. */
\r
2653 #endif /* configUSE_PREEMPTION */
\r
2655 #if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
\r
2657 /* When using preemption tasks of equal priority will be
\r
2658 timesliced. If a task that is sharing the idle priority is ready
\r
2659 to run then the idle task should yield before the end of the
\r
2662 A critical region is not required here as we are just reading from
\r
2663 the list, and an occasional incorrect value will not matter. If
\r
2664 the ready list at the idle priority contains more than one task
\r
2665 then a task other than the idle task is ready to execute. */
\r
2666 if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )
\r
2672 mtCOVERAGE_TEST_MARKER();
\r
2675 #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
\r
2677 #if ( configUSE_IDLE_HOOK == 1 )
\r
2679 extern void vApplicationIdleHook( void );
\r
2681 /* Call the user defined function from within the idle task. This
\r
2682 allows the application designer to add background functionality
\r
2683 without the overhead of a separate task.
\r
2684 NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
\r
2685 CALL A FUNCTION THAT MIGHT BLOCK. */
\r
2686 vApplicationIdleHook();
\r
2688 #endif /* configUSE_IDLE_HOOK */
\r
2690 /* This conditional compilation should use inequality to 0, not equality
\r
2691 to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
\r
2692 user defined low power mode implementations require
\r
2693 configUSE_TICKLESS_IDLE to be set to a value other than 1. */
\r
2694 #if ( configUSE_TICKLESS_IDLE != 0 )
\r
2696 TickType_t xExpectedIdleTime;
\r
2698 /* It is not desirable to suspend then resume the scheduler on
\r
2699 each iteration of the idle task. Therefore, a preliminary
\r
2700 test of the expected idle time is performed without the
\r
2701 scheduler suspended. The result here is not necessarily
\r
2703 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
2705 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
2707 vTaskSuspendAll();
\r
2709 /* Now the scheduler is suspended, the expected idle
\r
2710 time can be sampled again, and this time its value can
\r
2712 configASSERT( xNextTaskUnblockTime >= xTickCount );
\r
2713 xExpectedIdleTime = prvGetExpectedIdleTime();
\r
2715 if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
\r
2717 traceLOW_POWER_IDLE_BEGIN();
\r
2718 portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
\r
2719 traceLOW_POWER_IDLE_END();
\r
2723 mtCOVERAGE_TEST_MARKER();
\r
2726 ( void ) xTaskResumeAll();
\r
2730 mtCOVERAGE_TEST_MARKER();
\r
2733 #endif /* configUSE_TICKLESS_IDLE */
\r
2736 /*-----------------------------------------------------------*/
\r
2738 #if configUSE_TICKLESS_IDLE != 0
\r
2740 eSleepModeStatus eTaskConfirmSleepModeStatus( void )
\r
2742 eSleepModeStatus eReturn = eStandardSleep;
\r
2744 if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
\r
2746 /* A task was made ready while the scheduler was suspended. */
\r
2747 eReturn = eAbortSleep;
\r
2749 else if( xYieldPending != pdFALSE )
\r
2751 /* A yield was pended while the scheduler was suspended. */
\r
2752 eReturn = eAbortSleep;
\r
2756 #if configUSE_TIMERS == 0
\r
2758 /* The idle task exists in addition to the application tasks. */
\r
2759 const UBaseType_t uxNonApplicationTasks = 1;
\r
2761 /* If timers are not being used and all the tasks are in the
\r
2762 suspended list (which might mean they have an infinite block
\r
2763 time rather than actually being suspended) then it is safe to
\r
2764 turn all clocks off and just wait for external interrupts. */
\r
2765 if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
\r
2767 eReturn = eNoTasksWaitingTimeout;
\r
2771 mtCOVERAGE_TEST_MARKER();
\r
2774 #endif /* configUSE_TIMERS */
\r
2779 #endif /* configUSE_TICKLESS_IDLE */
\r
2780 /*-----------------------------------------------------------*/
\r
2782 static void prvInitialiseTCBVariables( TCB_t * const pxTCB, const char * const pcName, UBaseType_t uxPriority, const MemoryRegion_t * const xRegions, const uint16_t usStackDepth ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
\r
2786 /* Store the task name in the TCB. */
\r
2787 for( x = ( UBaseType_t ) 0; x < ( UBaseType_t ) configMAX_TASK_NAME_LEN; x++ )
\r
2789 pxTCB->pcTaskName[ x ] = pcName[ x ];
\r
2791 /* Don't copy all configMAX_TASK_NAME_LEN if the string is shorter than
\r
2792 configMAX_TASK_NAME_LEN characters just in case the memory after the
\r
2793 string is not accessible (extremely unlikely). */
\r
2794 if( pcName[ x ] == 0x00 )
\r
2800 mtCOVERAGE_TEST_MARKER();
\r
2804 /* Ensure the name string is terminated in the case that the string length
\r
2805 was greater or equal to configMAX_TASK_NAME_LEN. */
\r
2806 pxTCB->pcTaskName[ configMAX_TASK_NAME_LEN - 1 ] = '\0';
\r
2808 /* This is used as an array index so must ensure it's not too large. First
\r
2809 remove the privilege bit if one is present. */
\r
2810 if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
\r
2812 uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
\r
2816 mtCOVERAGE_TEST_MARKER();
\r
2819 pxTCB->uxPriority = uxPriority;
\r
2820 #if ( configUSE_MUTEXES == 1 )
\r
2822 pxTCB->uxBasePriority = uxPriority;
\r
2823 pxTCB->uxMutexesHeld = 0;
\r
2825 #endif /* configUSE_MUTEXES */
\r
2827 vListInitialiseItem( &( pxTCB->xGenericListItem ) );
\r
2828 vListInitialiseItem( &( pxTCB->xEventListItem ) );
\r
2830 /* Set the pxTCB as a link back from the ListItem_t. This is so we can get
\r
2831 back to the containing TCB from a generic item in a list. */
\r
2832 listSET_LIST_ITEM_OWNER( &( pxTCB->xGenericListItem ), pxTCB );
\r
2834 /* Event lists are always in priority order. */
\r
2835 listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
2836 listSET_LIST_ITEM_OWNER( &( pxTCB->xEventListItem ), pxTCB );
\r
2838 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
2840 pxTCB->uxCriticalNesting = ( UBaseType_t ) 0U;
\r
2842 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
2844 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
\r
2846 pxTCB->pxTaskTag = NULL;
\r
2848 #endif /* configUSE_APPLICATION_TASK_TAG */
\r
2850 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
2852 pxTCB->ulRunTimeCounter = 0UL;
\r
2854 #endif /* configGENERATE_RUN_TIME_STATS */
\r
2856 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
2858 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, pxTCB->pxStack, usStackDepth );
\r
2860 #else /* portUSING_MPU_WRAPPERS */
\r
2862 ( void ) xRegions;
\r
2863 ( void ) usStackDepth;
\r
2865 #endif /* portUSING_MPU_WRAPPERS */
\r
2867 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
\r
2869 pxTCB->ulNotifiedValue = 0;
\r
2870 pxTCB->eNotifyState = eNotWaitingNotification;
\r
2874 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
2876 /* Initialise this task's Newlib reent structure. */
\r
2877 _REENT_INIT_PTR( ( &( pxTCB->xNewLib_reent ) ) );
\r
2879 #endif /* configUSE_NEWLIB_REENTRANT */
\r
2881 /*-----------------------------------------------------------*/
\r
2883 #if ( portUSING_MPU_WRAPPERS == 1 )
\r
2885 void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions )
\r
2889 /* If null is passed in here then we are deleting ourselves. */
\r
2890 pxTCB = prvGetTCBFromHandle( xTaskToModify );
\r
2892 vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
\r
2895 #endif /* portUSING_MPU_WRAPPERS */
\r
2896 /*-----------------------------------------------------------*/
\r
2898 static void prvInitialiseTaskLists( void )
\r
2900 UBaseType_t uxPriority;
\r
2902 for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
\r
2904 vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
\r
2907 vListInitialise( &xDelayedTaskList1 );
\r
2908 vListInitialise( &xDelayedTaskList2 );
\r
2909 vListInitialise( &xPendingReadyList );
\r
2911 #if ( INCLUDE_vTaskDelete == 1 )
\r
2913 vListInitialise( &xTasksWaitingTermination );
\r
2915 #endif /* INCLUDE_vTaskDelete */
\r
2917 #if ( INCLUDE_vTaskSuspend == 1 )
\r
2919 vListInitialise( &xSuspendedTaskList );
\r
2921 #endif /* INCLUDE_vTaskSuspend */
\r
2923 /* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
\r
2925 pxDelayedTaskList = &xDelayedTaskList1;
\r
2926 pxOverflowDelayedTaskList = &xDelayedTaskList2;
\r
2928 /*-----------------------------------------------------------*/
\r
2930 static void prvCheckTasksWaitingTermination( void )
\r
2932 #if ( INCLUDE_vTaskDelete == 1 )
\r
2934 BaseType_t xListIsEmpty;
\r
2936 /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
\r
2937 too often in the idle task. */
\r
2938 while( uxTasksDeleted > ( UBaseType_t ) 0U )
\r
2940 vTaskSuspendAll();
\r
2942 xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
\r
2944 ( void ) xTaskResumeAll();
\r
2946 if( xListIsEmpty == pdFALSE )
\r
2950 taskENTER_CRITICAL();
\r
2952 pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
\r
2953 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
2954 --uxCurrentNumberOfTasks;
\r
2957 taskEXIT_CRITICAL();
\r
2959 prvDeleteTCB( pxTCB );
\r
2963 mtCOVERAGE_TEST_MARKER();
\r
2967 #endif /* vTaskDelete */
\r
2969 /*-----------------------------------------------------------*/
\r
2971 static void prvAddCurrentTaskToDelayedList( const TickType_t xTimeToWake )
\r
2973 /* The list item will be inserted in wake time order. */
\r
2974 listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xGenericListItem ), xTimeToWake );
\r
2976 if( xTimeToWake < xTickCount )
\r
2978 /* Wake time has overflowed. Place this item in the overflow list. */
\r
2979 vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
\r
2983 /* The wake time has not overflowed, so the current block list is used. */
\r
2984 vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xGenericListItem ) );
\r
2986 /* If the task entering the blocked state was placed at the head of the
\r
2987 list of blocked tasks then xNextTaskUnblockTime needs to be updated
\r
2989 if( xTimeToWake < xNextTaskUnblockTime )
\r
2991 xNextTaskUnblockTime = xTimeToWake;
\r
2995 mtCOVERAGE_TEST_MARKER();
\r
2999 /*-----------------------------------------------------------*/
\r
3001 static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer )
\r
3005 /* If the stack grows down then allocate the stack then the TCB so the stack
\r
3006 does not grow into the TCB. Likewise if the stack grows up then allocate
\r
3007 the TCB then the stack. */
\r
3008 #if( portSTACK_GROWTH > 0 )
\r
3010 /* Allocate space for the TCB. Where the memory comes from depends on
\r
3011 the implementation of the port malloc function. */
\r
3012 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
\r
3014 if( pxNewTCB != NULL )
\r
3016 /* Allocate space for the stack used by the task being created.
\r
3017 The base of the stack memory stored in the TCB so the task can
\r
3018 be deleted later if required. */
\r
3019 pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
3021 if( pxNewTCB->pxStack == NULL )
\r
3023 /* Could not allocate the stack. Delete the allocated TCB. */
\r
3024 vPortFree( pxNewTCB );
\r
3029 #else /* portSTACK_GROWTH */
\r
3031 StackType_t *pxStack;
\r
3033 /* Allocate space for the stack used by the task being created. */
\r
3034 pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
\r
3036 if( pxStack != NULL )
\r
3038 /* Allocate space for the TCB. Where the memory comes from depends
\r
3039 on the implementation of the port malloc function. */
\r
3040 pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
\r
3042 if( pxNewTCB != NULL )
\r
3044 /* Store the stack location in the TCB. */
\r
3045 pxNewTCB->pxStack = pxStack;
\r
3049 /* The stack cannot be used as the TCB was not created. Free it
\r
3051 vPortFree( pxStack );
\r
3059 #endif /* portSTACK_GROWTH */
\r
3061 if( pxNewTCB != NULL )
\r
3063 /* Avoid dependency on memset() if it is not required. */
\r
3064 #if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
3066 /* Just to help debugging. */
\r
3067 ( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( StackType_t ) );
\r
3069 #endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */
\r
3074 /*-----------------------------------------------------------*/
\r
3076 #if ( configUSE_TRACE_FACILITY == 1 )
\r
3078 static UBaseType_t prvListTaskWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )
\r
3080 volatile TCB_t *pxNextTCB, *pxFirstTCB;
\r
3081 UBaseType_t uxTask = 0;
\r
3083 if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
\r
3085 listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
\r
3087 /* Populate an TaskStatus_t structure within the
\r
3088 pxTaskStatusArray array for each task that is referenced from
\r
3089 pxList. See the definition of TaskStatus_t in task.h for the
\r
3090 meaning of each TaskStatus_t structure member. */
\r
3093 listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
\r
3095 pxTaskStatusArray[ uxTask ].xHandle = ( TaskHandle_t ) pxNextTCB;
\r
3096 pxTaskStatusArray[ uxTask ].pcTaskName = ( const char * ) &( pxNextTCB->pcTaskName [ 0 ] );
\r
3097 pxTaskStatusArray[ uxTask ].xTaskNumber = pxNextTCB->uxTCBNumber;
\r
3098 pxTaskStatusArray[ uxTask ].eCurrentState = eState;
\r
3099 pxTaskStatusArray[ uxTask ].uxCurrentPriority = pxNextTCB->uxPriority;
\r
3101 #if ( INCLUDE_vTaskSuspend == 1 )
\r
3103 /* If the task is in the suspended list then there is a chance
\r
3104 it is actually just blocked indefinitely - so really it should
\r
3105 be reported as being in the Blocked state. */
\r
3106 if( eState == eSuspended )
\r
3108 if( listLIST_ITEM_CONTAINER( &( pxNextTCB->xEventListItem ) ) != NULL )
\r
3110 pxTaskStatusArray[ uxTask ].eCurrentState = eBlocked;
\r
3114 #endif /* INCLUDE_vTaskSuspend */
\r
3116 #if ( configUSE_MUTEXES == 1 )
\r
3118 pxTaskStatusArray[ uxTask ].uxBasePriority = pxNextTCB->uxBasePriority;
\r
3122 pxTaskStatusArray[ uxTask ].uxBasePriority = 0;
\r
3126 #if ( configGENERATE_RUN_TIME_STATS == 1 )
\r
3128 pxTaskStatusArray[ uxTask ].ulRunTimeCounter = pxNextTCB->ulRunTimeCounter;
\r
3132 pxTaskStatusArray[ uxTask ].ulRunTimeCounter = 0;
\r
3136 #if ( portSTACK_GROWTH > 0 )
\r
3138 pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxEndOfStack );
\r
3142 pxTaskStatusArray[ uxTask ].usStackHighWaterMark = prvTaskCheckFreeStackSpace( ( uint8_t * ) pxNextTCB->pxStack );
\r
3148 } while( pxNextTCB != pxFirstTCB );
\r
3152 mtCOVERAGE_TEST_MARKER();
\r
3158 #endif /* configUSE_TRACE_FACILITY */
\r
3159 /*-----------------------------------------------------------*/
\r
3161 #if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
\r
3163 static uint16_t prvTaskCheckFreeStackSpace( const uint8_t * pucStackByte )
\r
3165 uint32_t ulCount = 0U;
\r
3167 while( *pucStackByte == ( uint8_t ) tskSTACK_FILL_BYTE )
\r
3169 pucStackByte -= portSTACK_GROWTH;
\r
3173 ulCount /= ( uint32_t ) sizeof( StackType_t ); /*lint !e961 Casting is not redundant on smaller architectures. */
\r
3175 return ( uint16_t ) ulCount;
\r
3178 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) */
\r
3179 /*-----------------------------------------------------------*/
\r
3181 #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
\r
3183 UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
\r
3186 uint8_t *pucEndOfStack;
\r
3187 UBaseType_t uxReturn;
\r
3189 pxTCB = prvGetTCBFromHandle( xTask );
\r
3191 #if portSTACK_GROWTH < 0
\r
3193 pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
\r
3197 pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
\r
3201 uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );
\r
3206 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
\r
3207 /*-----------------------------------------------------------*/
\r
3209 #if ( INCLUDE_vTaskDelete == 1 )
\r
3211 static void prvDeleteTCB( TCB_t *pxTCB )
\r
3213 /* This call is required specifically for the TriCore port. It must be
\r
3214 above the vPortFree() calls. The call is also used by ports/demos that
\r
3215 want to allocate and clean RAM statically. */
\r
3216 portCLEAN_UP_TCB( pxTCB );
\r
3218 /* Free up the memory allocated by the scheduler for the task. It is up
\r
3219 to the task to free any memory allocated at the application level. */
\r
3220 #if ( configUSE_NEWLIB_REENTRANT == 1 )
\r
3222 _reclaim_reent( &( pxTCB->xNewLib_reent ) );
\r
3224 #endif /* configUSE_NEWLIB_REENTRANT */
\r
3225 vPortFreeAligned( pxTCB->pxStack );
\r
3226 vPortFree( pxTCB );
\r
3229 #endif /* INCLUDE_vTaskDelete */
\r
3230 /*-----------------------------------------------------------*/
\r
3232 static void prvResetNextTaskUnblockTime( void )
\r
3236 if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
\r
3238 /* The new current delayed list is empty. Set
\r
3239 xNextTaskUnblockTime to the maximum possible value so it is
\r
3240 extremely unlikely that the
\r
3241 if( xTickCount >= xNextTaskUnblockTime ) test will pass until
\r
3242 there is an item in the delayed list. */
\r
3243 xNextTaskUnblockTime = portMAX_DELAY;
\r
3247 /* The new current delayed list is not empty, get the value of
\r
3248 the item at the head of the delayed list. This is the time at
\r
3249 which the task at the head of the delayed list should be removed
\r
3250 from the Blocked state. */
\r
3251 ( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );
\r
3252 xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xGenericListItem ) );
\r
3255 /*-----------------------------------------------------------*/
\r
3257 #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
\r
3259 TaskHandle_t xTaskGetCurrentTaskHandle( void )
\r
3261 TaskHandle_t xReturn;
\r
3263 /* A critical section is not required as this is not called from
\r
3264 an interrupt and the current TCB will always be the same for any
\r
3265 individual execution thread. */
\r
3266 xReturn = pxCurrentTCB;
\r
3271 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
\r
3272 /*-----------------------------------------------------------*/
\r
3274 #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
\r
3276 BaseType_t xTaskGetSchedulerState( void )
\r
3278 BaseType_t xReturn;
\r
3280 if( xSchedulerRunning == pdFALSE )
\r
3282 xReturn = taskSCHEDULER_NOT_STARTED;
\r
3286 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
3288 xReturn = taskSCHEDULER_RUNNING;
\r
3292 xReturn = taskSCHEDULER_SUSPENDED;
\r
3299 #endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) */
\r
3300 /*-----------------------------------------------------------*/
\r
3302 #if ( configUSE_MUTEXES == 1 )
\r
3304 void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
\r
3306 TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
\r
3308 /* If the mutex was given back by an interrupt while the queue was
\r
3309 locked then the mutex holder might now be NULL. */
\r
3310 if( pxMutexHolder != NULL )
\r
3312 if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
\r
3314 /* Adjust the mutex holder state to account for its new
\r
3315 priority. Only reset the event list item value if the value is
\r
3316 not being used for anything else. */
\r
3317 if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
\r
3319 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
3323 mtCOVERAGE_TEST_MARKER();
\r
3326 /* If the task being modified is in the ready state it will need to
\r
3327 be moved into a new list. */
\r
3328 if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )
\r
3330 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
3332 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
3336 mtCOVERAGE_TEST_MARKER();
\r
3339 /* Inherit the priority before being moved into the new list. */
\r
3340 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
3341 prvAddTaskToReadyList( pxTCB );
\r
3345 /* Just inherit the priority. */
\r
3346 pxTCB->uxPriority = pxCurrentTCB->uxPriority;
\r
3349 traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );
\r
3353 mtCOVERAGE_TEST_MARKER();
\r
3358 mtCOVERAGE_TEST_MARKER();
\r
3362 #endif /* configUSE_MUTEXES */
\r
3363 /*-----------------------------------------------------------*/
\r
3365 #if ( configUSE_MUTEXES == 1 )
\r
3367 BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder )
\r
3369 TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
\r
3370 BaseType_t xReturn = pdFALSE;
\r
3372 if( pxMutexHolder != NULL )
\r
3374 configASSERT( pxTCB->uxMutexesHeld );
\r
3375 ( pxTCB->uxMutexesHeld )--;
\r
3377 if( pxTCB->uxPriority != pxTCB->uxBasePriority )
\r
3379 /* Only disinherit if no other mutexes are held. */
\r
3380 if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
\r
3382 /* A task can only have an inhertied priority if it holds
\r
3383 the mutex. If the mutex is held by a task then it cannot be
\r
3384 given from an interrupt, and if a mutex is given by the
\r
3385 holding task then it must be the running state task. Remove
\r
3386 the holding task from the ready list. */
\r
3387 if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
3389 taskRESET_READY_PRIORITY( pxTCB->uxPriority );
\r
3393 mtCOVERAGE_TEST_MARKER();
\r
3396 /* Disinherit the priority before adding the task into the
\r
3397 new ready list. */
\r
3398 traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
\r
3399 pxTCB->uxPriority = pxTCB->uxBasePriority;
\r
3401 /* Reset the event list item value. It cannot be in use for
\r
3402 any other purpose if this task is running, and it must be
\r
3403 running to give back the mutex. */
\r
3404 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
3405 prvAddTaskToReadyList( pxTCB );
\r
3407 /* Return true to indicate that a context switch is required.
\r
3408 This is only actually required in the corner case whereby
\r
3409 multiple mutexes were held and the mutexes were given back
\r
3410 in an order different to that in which they were taken.
\r
3411 If a context switch did not occur when the first mutex was
\r
3412 returned, even if a task was waiting on it, then a context
\r
3413 switch should occur when the last mutex is returned whether
\r
3414 a task is waiting on it or not. */
\r
3419 mtCOVERAGE_TEST_MARKER();
\r
3424 mtCOVERAGE_TEST_MARKER();
\r
3429 mtCOVERAGE_TEST_MARKER();
\r
3435 #endif /* configUSE_MUTEXES */
\r
3436 /*-----------------------------------------------------------*/
\r
3438 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
3440 void vTaskEnterCritical( void )
\r
3442 portDISABLE_INTERRUPTS();
\r
3444 if( xSchedulerRunning != pdFALSE )
\r
3446 ( pxCurrentTCB->uxCriticalNesting )++;
\r
3448 /* This is not the interrupt safe version of the enter critical
\r
3449 function so assert() if it is being called from an interrupt
\r
3450 context. Only API functions that end in "FromISR" can be used in an
\r
3451 interrupt. Only assert if the critical nesting count is 1 to
\r
3452 protect against recursive calls if the assert function also uses a
\r
3453 critical section. */
\r
3454 if( pxCurrentTCB->uxCriticalNesting == 1 )
\r
3456 portASSERT_IF_IN_ISR();
\r
3462 mtCOVERAGE_TEST_MARKER();
\r
3466 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
3467 /*-----------------------------------------------------------*/
\r
3469 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
\r
3471 void vTaskExitCritical( void )
\r
3473 if( xSchedulerRunning != pdFALSE )
\r
3475 if( pxCurrentTCB->uxCriticalNesting > 0U )
\r
3477 ( pxCurrentTCB->uxCriticalNesting )--;
\r
3479 if( pxCurrentTCB->uxCriticalNesting == 0U )
\r
3481 portENABLE_INTERRUPTS();
\r
3485 mtCOVERAGE_TEST_MARKER();
\r
3490 mtCOVERAGE_TEST_MARKER();
\r
3495 mtCOVERAGE_TEST_MARKER();
\r
3499 #endif /* portCRITICAL_NESTING_IN_TCB */
\r
3500 /*-----------------------------------------------------------*/
\r
3502 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
3504 static char *prvWriteNameToBuffer( char *pcBuffer, const char *pcTaskName )
\r
3508 /* Start by copying the entire string. */
\r
3509 strcpy( pcBuffer, pcTaskName );
\r
3511 /* Pad the end of the string with spaces to ensure columns line up when
\r
3513 for( x = strlen( pcBuffer ); x < configMAX_TASK_NAME_LEN; x++ )
\r
3515 pcBuffer[ x ] = ' ';
\r
3519 pcBuffer[ x ] = 0x00;
\r
3521 /* Return the new end of string. */
\r
3522 return &( pcBuffer[ x ] );
\r
3525 #endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
\r
3526 /*-----------------------------------------------------------*/
\r
3528 #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
3530 void vTaskList( char * pcWriteBuffer )
\r
3532 TaskStatus_t *pxTaskStatusArray;
\r
3533 volatile UBaseType_t uxArraySize, x;
\r
3539 * This function is provided for convenience only, and is used by many
\r
3540 * of the demo applications. Do not consider it to be part of the
\r
3543 * vTaskList() calls uxTaskGetSystemState(), then formats part of the
\r
3544 * uxTaskGetSystemState() output into a human readable table that
\r
3545 * displays task names, states and stack usage.
\r
3547 * vTaskList() has a dependency on the sprintf() C library function that
\r
3548 * might bloat the code size, use a lot of stack, and provide different
\r
3549 * results on different platforms. An alternative, tiny, third party,
\r
3550 * and limited functionality implementation of sprintf() is provided in
\r
3551 * many of the FreeRTOS/Demo sub-directories in a file called
\r
3552 * printf-stdarg.c (note printf-stdarg.c does not provide a full
\r
3553 * snprintf() implementation!).
\r
3555 * It is recommended that production systems call uxTaskGetSystemState()
\r
3556 * directly to get access to raw stats data, rather than indirectly
\r
3557 * through a call to vTaskList().
\r
3561 /* Make sure the write buffer does not contain a string. */
\r
3562 *pcWriteBuffer = 0x00;
\r
3564 /* Take a snapshot of the number of tasks in case it changes while this
\r
3565 function is executing. */
\r
3566 uxArraySize = uxCurrentNumberOfTasks;
\r
3568 /* Allocate an array index for each task. */
\r
3569 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
\r
3571 if( pxTaskStatusArray != NULL )
\r
3573 /* Generate the (binary) data. */
\r
3574 uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, NULL );
\r
3576 /* Create a human readable table from the binary data. */
\r
3577 for( x = 0; x < uxArraySize; x++ )
\r
3579 switch( pxTaskStatusArray[ x ].eCurrentState )
\r
3581 case eReady: cStatus = tskREADY_CHAR;
\r
3584 case eBlocked: cStatus = tskBLOCKED_CHAR;
\r
3587 case eSuspended: cStatus = tskSUSPENDED_CHAR;
\r
3590 case eDeleted: cStatus = tskDELETED_CHAR;
\r
3593 default: /* Should not get here, but it is included
\r
3594 to prevent static checking errors. */
\r
3599 /* Write the task name to the string, padding with spaces so it
\r
3600 can be printed in tabular form more easily. */
\r
3601 pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
\r
3603 /* Write the rest of the string. */
\r
3604 sprintf( pcWriteBuffer, "\t\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
3605 pcWriteBuffer += strlen( pcWriteBuffer );
\r
3608 /* Free the array again. */
\r
3609 vPortFree( pxTaskStatusArray );
\r
3613 mtCOVERAGE_TEST_MARKER();
\r
3617 #endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
\r
3618 /*----------------------------------------------------------*/
\r
3620 #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
\r
3622 void vTaskGetRunTimeStats( char *pcWriteBuffer )
\r
3624 TaskStatus_t *pxTaskStatusArray;
\r
3625 volatile UBaseType_t uxArraySize, x;
\r
3626 uint32_t ulTotalTime, ulStatsAsPercentage;
\r
3628 #if( configUSE_TRACE_FACILITY != 1 )
\r
3630 #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats().
\r
3637 * This function is provided for convenience only, and is used by many
\r
3638 * of the demo applications. Do not consider it to be part of the
\r
3641 * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part
\r
3642 * of the uxTaskGetSystemState() output into a human readable table that
\r
3643 * displays the amount of time each task has spent in the Running state
\r
3644 * in both absolute and percentage terms.
\r
3646 * vTaskGetRunTimeStats() has a dependency on the sprintf() C library
\r
3647 * function that might bloat the code size, use a lot of stack, and
\r
3648 * provide different results on different platforms. An alternative,
\r
3649 * tiny, third party, and limited functionality implementation of
\r
3650 * sprintf() is provided in many of the FreeRTOS/Demo sub-directories in
\r
3651 * a file called printf-stdarg.c (note printf-stdarg.c does not provide
\r
3652 * a full snprintf() implementation!).
\r
3654 * It is recommended that production systems call uxTaskGetSystemState()
\r
3655 * directly to get access to raw stats data, rather than indirectly
\r
3656 * through a call to vTaskGetRunTimeStats().
\r
3659 /* Make sure the write buffer does not contain a string. */
\r
3660 *pcWriteBuffer = 0x00;
\r
3662 /* Take a snapshot of the number of tasks in case it changes while this
\r
3663 function is executing. */
\r
3664 uxArraySize = uxCurrentNumberOfTasks;
\r
3666 /* Allocate an array index for each task. */
\r
3667 pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) );
\r
3669 if( pxTaskStatusArray != NULL )
\r
3671 /* Generate the (binary) data. */
\r
3672 uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalTime );
\r
3674 /* For percentage calculations. */
\r
3675 ulTotalTime /= 100UL;
\r
3677 /* Avoid divide by zero errors. */
\r
3678 if( ulTotalTime > 0 )
\r
3680 /* Create a human readable table from the binary data. */
\r
3681 for( x = 0; x < uxArraySize; x++ )
\r
3683 /* What percentage of the total run time has the task used?
\r
3684 This will always be rounded down to the nearest integer.
\r
3685 ulTotalRunTimeDiv100 has already been divided by 100. */
\r
3686 ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalTime;
\r
3688 if( ulStatsAsPercentage > 0UL )
\r
3690 /* Write the task name to the string, padding with
\r
3691 spaces so it can be printed in tabular form more
\r
3693 pcWriteBuffer = prvWriteNameToBuffer( pcWriteBuffer, pxTaskStatusArray[ x ].pcTaskName );
\r
3695 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
3697 sprintf( pcWriteBuffer, "\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
\r
3701 /* sizeof( int ) == sizeof( long ) so a smaller
\r
3702 printf() library can be used. */
\r
3703 sprintf( pcWriteBuffer, "\t\t%u\t\t%u%%\r\n", ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter, ( unsigned int ) ulStatsAsPercentage );
\r
3709 /* If the percentage is zero here then the task has
\r
3710 consumed less than 1% of the total run time. */
\r
3711 #ifdef portLU_PRINTF_SPECIFIER_REQUIRED
\r
3713 sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );
\r
3717 /* sizeof( int ) == sizeof( long ) so a smaller
\r
3718 printf() library can be used. */
\r
3719 sprintf( pcWriteBuffer, "%s\t\t%u\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, ( unsigned int ) pxTaskStatusArray[ x ].ulRunTimeCounter );
\r
3724 pcWriteBuffer += strlen( pcWriteBuffer );
\r
3729 mtCOVERAGE_TEST_MARKER();
\r
3732 /* Free the array again. */
\r
3733 vPortFree( pxTaskStatusArray );
\r
3737 mtCOVERAGE_TEST_MARKER();
\r
3741 #endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
\r
3742 /*-----------------------------------------------------------*/
\r
3744 TickType_t uxTaskResetEventItemValue( void )
\r
3746 TickType_t uxReturn;
\r
3748 uxReturn = listGET_LIST_ITEM_VALUE( &( pxCurrentTCB->xEventListItem ) );
\r
3750 /* Reset the event list item to its normal value - so it can be used with
\r
3751 queues and semaphores. */
\r
3752 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
3756 /*-----------------------------------------------------------*/
\r
3758 #if ( configUSE_MUTEXES == 1 )
\r
3760 void *pvTaskIncrementMutexHeldCount( void )
\r
3762 /* If xSemaphoreCreateMutex() is called before any tasks have been created
\r
3763 then pxCurrentTCB will be NULL. */
\r
3764 if( pxCurrentTCB != NULL )
\r
3766 ( pxCurrentTCB->uxMutexesHeld )++;
\r
3769 return pxCurrentTCB;
\r
3772 #endif /* configUSE_MUTEXES */
\r
3773 /*-----------------------------------------------------------*/
\r
3775 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
3777 uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )
\r
3779 TickType_t xTimeToWake;
\r
3780 uint32_t ulReturn;
\r
3782 taskENTER_CRITICAL();
\r
3784 /* Only block if the notification count is not already non-zero. */
\r
3785 if( pxCurrentTCB->ulNotifiedValue == 0UL )
\r
3787 /* Mark this task as waiting for a notification. */
\r
3788 pxCurrentTCB->eNotifyState = eWaitingNotification;
\r
3790 if( xTicksToWait > 0 )
\r
3792 /* The task is going to block. First it must be removed
\r
3793 from the ready list. */
\r
3794 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
3796 /* The current task must be in a ready list, so there is
\r
3797 no need to check, and the port reset macro can be called
\r
3799 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
3803 mtCOVERAGE_TEST_MARKER();
\r
3806 #if ( INCLUDE_vTaskSuspend == 1 )
\r
3808 if( xTicksToWait == portMAX_DELAY )
\r
3810 /* Add the task to the suspended task list instead
\r
3811 of a delayed task list to ensure the task is not
\r
3812 woken by a timing event. It will block
\r
3814 vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
\r
3818 /* Calculate the time at which the task should be
\r
3819 woken if no notification events occur. This may
\r
3820 overflow but this doesn't matter, the scheduler will
\r
3822 xTimeToWake = xTickCount + xTicksToWait;
\r
3823 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
3826 #else /* INCLUDE_vTaskSuspend */
\r
3828 /* Calculate the time at which the task should be
\r
3829 woken if the event does not occur. This may
\r
3830 overflow but this doesn't matter, the scheduler will
\r
3832 xTimeToWake = xTickCount + xTicksToWait;
\r
3833 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
3835 #endif /* INCLUDE_vTaskSuspend */
\r
3837 /* All ports are written to allow a yield in a critical
\r
3838 section (some will yield immediately, others wait until the
\r
3839 critical section exits) - but it is not something that
\r
3840 application code should ever do. */
\r
3841 portYIELD_WITHIN_API();
\r
3845 mtCOVERAGE_TEST_MARKER();
\r
3850 mtCOVERAGE_TEST_MARKER();
\r
3853 taskEXIT_CRITICAL();
\r
3855 taskENTER_CRITICAL();
\r
3857 ulReturn = pxCurrentTCB->ulNotifiedValue;
\r
3859 if( ulReturn != 0 )
\r
3861 if( xClearCountOnExit != pdFALSE )
\r
3863 pxCurrentTCB->ulNotifiedValue = 0UL;
\r
3867 ( pxCurrentTCB->ulNotifiedValue )--;
\r
3872 mtCOVERAGE_TEST_MARKER();
\r
3875 pxCurrentTCB->eNotifyState = eNotWaitingNotification;
\r
3877 taskEXIT_CRITICAL();
\r
3882 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
3883 /*-----------------------------------------------------------*/
\r
3885 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
3887 BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, BaseType_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait )
\r
3889 TickType_t xTimeToWake;
\r
3890 BaseType_t xReturn;
\r
3892 taskENTER_CRITICAL();
\r
3894 /* Only block if a notification is not already pending. */
\r
3895 if( pxCurrentTCB->eNotifyState != eNotified )
\r
3897 /* Clear bits in the task's notification value as bits may get
\r
3898 set by the notifying task or interrupt. This can be used to
\r
3899 clear the value to zero. */
\r
3900 pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry;
\r
3902 /* Mark this task as waiting for a notification. */
\r
3903 pxCurrentTCB->eNotifyState = eWaitingNotification;
\r
3905 if( xTicksToWait > 0 )
\r
3907 /* The task is going to block. First it must be removed
\r
3908 from the ready list. */
\r
3909 if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
\r
3911 /* The current task must be in a ready list, so there is
\r
3912 no need to check, and the port reset macro can be called
\r
3914 portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );
\r
3918 mtCOVERAGE_TEST_MARKER();
\r
3921 #if ( INCLUDE_vTaskSuspend == 1 )
\r
3923 if( xTicksToWait == portMAX_DELAY )
\r
3925 /* Add the task to the suspended task list instead
\r
3926 of a delayed task list to ensure the task is not
\r
3927 woken by a timing event. It will block
\r
3929 vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
\r
3933 /* Calculate the time at which the task should be
\r
3934 woken if no notification events occur. This may
\r
3935 overflow but this doesn't matter, the scheduler will
\r
3937 xTimeToWake = xTickCount + xTicksToWait;
\r
3938 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
3941 #else /* INCLUDE_vTaskSuspend */
\r
3943 /* Calculate the time at which the task should be
\r
3944 woken if the event does not occur. This may
\r
3945 overflow but this doesn't matter, the scheduler will
\r
3947 xTimeToWake = xTickCount + xTicksToWait;
\r
3948 prvAddCurrentTaskToDelayedList( xTimeToWake );
\r
3950 #endif /* INCLUDE_vTaskSuspend */
\r
3952 /* All ports are written to allow a yield in a critical
\r
3953 section (some will yield immediately, others wait until the
\r
3954 critical section exits) - but it is not something that
\r
3955 application code should ever do. */
\r
3956 portYIELD_WITHIN_API();
\r
3960 mtCOVERAGE_TEST_MARKER();
\r
3965 mtCOVERAGE_TEST_MARKER();
\r
3968 taskEXIT_CRITICAL();
\r
3970 taskENTER_CRITICAL();
\r
3972 if( pulNotificationValue != NULL )
\r
3974 /* Output the current notification value, which may or may not
\r
3976 *pulNotificationValue = pxCurrentTCB->ulNotifiedValue;
\r
3979 /* If eNotifyValue is set then either the task never entered the
\r
3980 blocked state (because a notification was already pending) or the
\r
3981 task unblocked because of a notification. Otherwise the task
\r
3982 unblocked because of a timeout. */
\r
3983 if( pxCurrentTCB->eNotifyState == eWaitingNotification )
\r
3985 /* A notification was not received. */
\r
3986 xReturn = pdFALSE;
\r
3990 /* A notification was already pending or a notification was
\r
3991 received while the task was waiting. */
\r
3992 pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnExit;
\r
3996 pxCurrentTCB->eNotifyState = eNotWaitingNotification;
\r
3998 taskEXIT_CRITICAL();
\r
4003 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4004 /*-----------------------------------------------------------*/
\r
4006 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4008 BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction )
\r
4011 eNotifyValue eOriginalNotifyState;
\r
4012 BaseType_t xReturn = pdPASS;
\r
4014 configASSERT( xTaskToNotify );
\r
4015 pxTCB = ( TCB_t * ) xTaskToNotify;
\r
4017 taskENTER_CRITICAL();
\r
4019 eOriginalNotifyState = pxTCB->eNotifyState;
\r
4021 pxTCB->eNotifyState = eNotified;
\r
4026 pxTCB->ulNotifiedValue |= ulValue;
\r
4030 ( pxTCB->ulNotifiedValue )++;
\r
4033 case eSetValueWithOverwrite :
\r
4034 pxTCB->ulNotifiedValue = ulValue;
\r
4037 case eSetValueWithoutOverwrite :
\r
4038 if( eOriginalNotifyState != eNotified )
\r
4040 pxTCB->ulNotifiedValue = ulValue;
\r
4044 /* The value could not be written to the task. */
\r
4050 /* The task is being notified without its notify value being
\r
4056 /* If the task is in the blocked state specifically to wait for a
\r
4057 notification then unblock it now. */
\r
4058 if( eOriginalNotifyState == eWaitingNotification )
\r
4060 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
4061 prvAddTaskToReadyList( pxTCB );
\r
4063 /* The task should not have been on an event list. */
\r
4064 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
\r
4066 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
4068 /* The notified task has a priority above the currently
\r
4069 executing task so a yield is required. */
\r
4070 portYIELD_WITHIN_API();
\r
4074 mtCOVERAGE_TEST_MARKER();
\r
4079 mtCOVERAGE_TEST_MARKER();
\r
4082 taskEXIT_CRITICAL();
\r
4087 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4088 /*-----------------------------------------------------------*/
\r
4090 #if( configUSE_TASK_NOTIFICATIONS == 1 )
\r
4092 BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken )
\r
4095 eNotifyValue eOriginalNotifyState;
\r
4096 BaseType_t xReturn = pdPASS;
\r
4097 UBaseType_t uxSavedInterruptStatus;
\r
4099 configASSERT( xTaskToNotify );
\r
4101 /* RTOS ports that support interrupt nesting have the concept of a
\r
4102 maximum system call (or maximum API call) interrupt priority.
\r
4103 Interrupts that are above the maximum system call priority are keep
\r
4104 permanently enabled, even when the RTOS kernel is in a critical section,
\r
4105 but cannot make any calls to FreeRTOS API functions. If configASSERT()
\r
4106 is defined in FreeRTOSConfig.h then
\r
4107 portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
\r
4108 failure if a FreeRTOS API function is called from an interrupt that has
\r
4109 been assigned a priority above the configured maximum system call
\r
4110 priority. Only FreeRTOS functions that end in FromISR can be called
\r
4111 from interrupts that have been assigned a priority at or (logically)
\r
4112 below the maximum system call interrupt priority. FreeRTOS maintains a
\r
4113 separate interrupt safe API to ensure interrupt entry is as fast and as
\r
4114 simple as possible. More information (albeit Cortex-M specific) is
\r
4115 provided on the following link:
\r
4116 http://www.freertos.org/RTOS-Cortex-M3-M4.html */
\r
4117 portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
\r
4119 pxTCB = ( TCB_t * ) xTaskToNotify;
\r
4121 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
4123 eOriginalNotifyState = pxTCB->eNotifyState;
\r
4125 pxTCB->eNotifyState = eNotified;
\r
4130 pxTCB->ulNotifiedValue |= ulValue;
\r
4134 ( pxTCB->ulNotifiedValue )++;
\r
4137 case eSetValueWithOverwrite :
\r
4138 pxTCB->ulNotifiedValue = ulValue;
\r
4141 case eSetValueWithoutOverwrite :
\r
4142 if( eOriginalNotifyState != eNotified )
\r
4144 pxTCB->ulNotifiedValue = ulValue;
\r
4148 /* The value could not be written to the task. */
\r
4154 /* The task is being notified without its notify value being
\r
4160 /* If the task is in the blocked state specifically to wait for a
\r
4161 notification then unblock it now. */
\r
4162 if( eOriginalNotifyState == eWaitingNotification )
\r
4164 /* The task should not have been on an event list. */
\r
4165 configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
\r
4167 if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
\r
4169 ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
\r
4170 prvAddTaskToReadyList( pxTCB );
\r
4174 /* The delayed and ready lists cannot be accessed, so hold
\r
4175 this task pending until the scheduler is resumed. */
\r
4176 vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );
\r
4179 if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
\r
4181 /* The notified task has a priority above the currently
\r
4182 executing task so a yield is required. */
\r
4183 if( pxHigherPriorityTaskWoken != NULL )
\r
4185 *pxHigherPriorityTaskWoken = pdTRUE;
\r
4190 mtCOVERAGE_TEST_MARKER();
\r
4194 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
4199 #endif /* configUSE_TASK_NOTIFICATIONS */
\r
4200 /*-----------------------------------------------------------*/
\r
4202 #ifdef FREERTOS_MODULE_TEST
\r
4203 #include "tasks_test_access_functions.h"
\r