📄 tasks.c
字号:
/*
FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
***************************************************************************
* *
* If you are: *
* *
* + New to FreeRTOS, *
* + Wanting to learn FreeRTOS or multitasking in general quickly *
* + Looking for basic training, *
* + Wanting to improve your FreeRTOS skills and productivity *
* *
* then take a look at the FreeRTOS eBook *
* *
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
* http://www.FreeRTOS.org/Documentation *
* *
* A pdf reference manual is also available. Both are usually delivered *
* to your inbox within 20 minutes to two hours when purchased between 8am *
* and 8pm GMT (although please allow up to 24 hours in case of *
* exceptional circumstances). Thank you for your support! *
* *
***************************************************************************
This file is part of the FreeRTOS distribution.
FreeRTOS is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License (version 2) as published by the
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
***NOTE*** The exception to the GPL is included to allow you to distribute
a combined work that includes FreeRTOS without being obliged to provide the
source code for proprietary components outside of the FreeRTOS kernel.
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details. You should have received a copy of the GNU General Public
License and the FreeRTOS license exception along with FreeRTOS; if not it
can be viewed here: http://www.freertos.org/a00114.html and also obtained
by writing to Richard Barry, contact details for whom are available on the
FreeRTOS WEB site.
1 tab == 4 spaces!
http://www.FreeRTOS.org - Documentation, latest information, license and
contact details.
http://www.SafeRTOS.com - A version that is certified for use in safety
critical systems.
http://www.OpenRTOS.com - Commercial support, development, porting,
licensing and training services.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
all the API functions to use the MPU wrappers. That should only be done when
task.h is included from an application file. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#include "FreeRTOS.h"
#include "task.h"
#include "StackMacros.h"
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/*
* Macro to define the amount of stack available to the idle task.
*/
#define tskIDLE_STACK_SIZE configMINIMAL_STACK_SIZE
/*
* Task control block. A task control block (TCB) is allocated to each task,
* and stores the context of the task.
*/
typedef struct tskTaskControlBlock
{
volatile portSTACK_TYPE *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */
#if ( portUSING_MPU_WRAPPERS == 1 )
xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE STRUCT. */
#endif
xListItem xGenericListItem; /*< List item used to place the TCB in ready and blocked queues. */
xListItem xEventListItem; /*< List item used to place the TCB in event lists. */
unsigned portBASE_TYPE uxPriority; /*< The priority of the task where 0 is the lowest priority. */
portSTACK_TYPE *pxStack; /*< Points to the start of the stack. */
signed char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */
#if ( portSTACK_GROWTH > 0 )
portSTACK_TYPE *pxEndOfStack; /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */
#endif
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
unsigned portBASE_TYPE uxCriticalNesting;
#endif
#if ( configUSE_TRACE_FACILITY == 1 )
unsigned portBASE_TYPE uxTCBNumber; /*< This is used for tracing the scheduler and making debugging easier only. */
#endif
#if ( configUSE_MUTEXES == 1 )
unsigned portBASE_TYPE uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
#endif
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
pdTASK_HOOK_CODE pxTaskTag;
#endif
#if ( configGENERATE_RUN_TIME_STATS == 1 )
unsigned long ulRunTimeCounter; /*< Used for calculating how much CPU time each task is utilising. */
#endif
} tskTCB;
/*
* Some kernel aware debuggers require data to be viewed to be global, rather
* than file scope.
*/
#ifdef portREMOVE_STATIC_QUALIFIER
#define static
#endif
/*lint -e956 */
PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL;
/* Lists for ready and blocked tasks. --------------------*/
PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< Prioritised ready tasks. */
PRIVILEGED_DATA static xList xDelayedTaskList1; /*< Delayed tasks. */
PRIVILEGED_DATA static xList xDelayedTaskList2; /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
PRIVILEGED_DATA static xList * volatile pxDelayedTaskList ; /*< Points to the delayed task list currently being used. */
PRIVILEGED_DATA static xList * volatile pxOverflowDelayedTaskList; /*< Points to the delayed task list currently being used to hold tasks that have overflowed the current tick count. */
PRIVILEGED_DATA static xList xPendingReadyList; /*< Tasks that have been readied while the scheduler was suspended. They will be moved to the ready queue when the scheduler is resumed. */
#if ( INCLUDE_vTaskDelete == 1 )
PRIVILEGED_DATA static volatile xList xTasksWaitingTermination; /*< Tasks that have been deleted - but the their memory not yet freed. */
PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTasksDeleted = ( unsigned portBASE_TYPE ) 0;
#endif
#if ( INCLUDE_vTaskSuspend == 1 )
PRIVILEGED_DATA static xList xSuspendedTaskList; /*< Tasks that are currently suspended. */
#endif
/* File private variables. --------------------------------*/
PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxCurrentNumberOfTasks = ( unsigned portBASE_TYPE ) 0;
PRIVILEGED_DATA static volatile portTickType xTickCount = ( portTickType ) 0;
PRIVILEGED_DATA static unsigned portBASE_TYPE uxTopUsedPriority = tskIDLE_PRIORITY;
PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxTopReadyPriority = tskIDLE_PRIORITY;
PRIVILEGED_DATA static volatile signed portBASE_TYPE xSchedulerRunning = pdFALSE;
PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxSchedulerSuspended = ( unsigned portBASE_TYPE ) pdFALSE;
PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxMissedTicks = ( unsigned portBASE_TYPE ) 0;
PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield = ( portBASE_TYPE ) pdFALSE;
PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows = ( portBASE_TYPE ) 0;
PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber = ( unsigned portBASE_TYPE ) 0;
#if ( configGENERATE_RUN_TIME_STATS == 1 )
PRIVILEGED_DATA static char pcStatsString[ 50 ] ;
PRIVILEGED_DATA static unsigned long ulTaskSwitchedInTime = 0UL; /*< Holds the value of a timer/counter the last time a task was switched in. */
static void prvGenerateRunTimeStatsForTasksInList( const signed char *pcWriteBuffer, xList *pxList, unsigned long ulTotalRunTime ) PRIVILEGED_FUNCTION;
#endif
/* Debugging and trace facilities private variables and macros. ------------*/
/*
* The value used to fill the stack of a task when the task is created. This
* is used purely for checking the high water mark for tasks.
*/
#define tskSTACK_FILL_BYTE ( 0xa5 )
/*
* Macros used by vListTask to indicate which state a task is in.
*/
#define tskBLOCKED_CHAR ( ( signed char ) 'B' )
#define tskREADY_CHAR ( ( signed char ) 'R' )
#define tskDELETED_CHAR ( ( signed char ) 'D' )
#define tskSUSPENDED_CHAR ( ( signed char ) 'S' )
/*
* Macros and private variables used by the trace facility.
*/
#if ( configUSE_TRACE_FACILITY == 1 )
#define tskSIZE_OF_EACH_TRACE_LINE ( ( unsigned long ) ( sizeof( unsigned long ) + sizeof( unsigned long ) ) )
PRIVILEGED_DATA static volatile signed char * volatile pcTraceBuffer;
PRIVILEGED_DATA static signed char *pcTraceBufferStart;
PRIVILEGED_DATA static signed char *pcTraceBufferEnd;
PRIVILEGED_DATA static signed portBASE_TYPE xTracing = pdFALSE;
static unsigned portBASE_TYPE uxPreviousTask = 255;
PRIVILEGED_DATA static char pcStatusString[ 50 ];
#endif
/*-----------------------------------------------------------*/
/*
* Macro that writes a trace of scheduler activity to a buffer. This trace
* shows which task is running when and is very useful as a debugging tool.
* As this macro is called each context switch it is a good idea to undefine
* it if not using the facility.
*/
#if ( configUSE_TRACE_FACILITY == 1 )
#define vWriteTraceToBuffer() \
{ \
if( xTracing ) \
{ \
if( uxPreviousTask != pxCurrentTCB->uxTCBNumber ) \
{ \
if( ( pcTraceBuffer + tskSIZE_OF_EACH_TRACE_LINE ) < pcTraceBufferEnd ) \
{ \
uxPreviousTask = pxCurrentTCB->uxTCBNumber; \
*( unsigned long * ) pcTraceBuffer = ( unsigned long ) xTickCount; \
pcTraceBuffer += sizeof( unsigned long ); \
*( unsigned long * ) pcTraceBuffer = ( unsigned long ) uxPreviousTask; \
pcTraceBuffer += sizeof( unsigned long ); \
} \
else \
{ \
xTracing = pdFALSE; \
} \
} \
} \
}
#else
#define vWriteTraceToBuffer()
#endif
/*-----------------------------------------------------------*/
/*
* Place the task represented by pxTCB into the appropriate ready queue for
* the task. It is inserted at the end of the list. One quirk of this is
* that if the task being inserted is at the same priority as the currently
* executing task, then it will only be rescheduled after the currently
* executing task has been rescheduled.
*/
#define prvAddTaskToReadyQueue( pxTCB ) \
{ \
if( pxTCB->uxPriority > uxTopReadyPriority ) \
{ \
uxTopReadyPriority = pxTCB->uxPriority; \
} \
vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ); \
}
/*-----------------------------------------------------------*/
/*
* Macro that looks at the list of tasks that are currently delayed to see if
* any require waking.
*
* Tasks are stored in the queue in the order of their wake time - meaning
* once one tasks has been found whose timer has not expired we need not look
* any further down the list.
*/
#define prvCheckDelayedTasks() \
{ \
register tskTCB *pxTCB; \
\
while( ( pxTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ) ) != NULL ) \
{ \
if( xTickCount < listGET_LIST_ITEM_VALUE( &( pxTCB->xGenericListItem ) ) ) \
{ \
break; \
} \
vListRemove( &( pxTCB->xGenericListItem ) ); \
/* Is the task waiting on an event also? */ \
if( pxTCB->xEventListItem.pvContainer ) \
{ \
vListRemove( &( pxTCB->xEventListItem ) ); \
} \
prvAddTaskToReadyQueue( pxTCB ); \
} \
}
/*-----------------------------------------------------------*/
/*
* Several functions take an xTaskHandle parameter that can optionally be NULL,
* where NULL is used to indicate that the handle of the currently executing
* task should be used in place of the parameter. This macro simply checks to
* see if the parameter is NULL and returns a pointer to the appropriate TCB.
*/
#define prvGetTCBFromHandle( pxHandle ) ( ( pxHandle == NULL ) ? ( tskTCB * ) pxCurrentTCB : ( tskTCB * ) pxHandle )
/* File private functions. --------------------------------*/
/*
* Utility to ready a TCB for a given task. Mainly just copies the parameters
* into the TCB structure.
*/
static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const pcName, unsigned portBASE_TYPE uxPriority, const xMemoryRegion * const xRegions, unsigned short usStackDepth ) PRIVILEGED_FUNCTION;
/*
* Utility to ready all the lists used by the scheduler. This is called
* automatically upon the creation of the first task.
*/
static void prvInitialiseTaskLists( void ) PRIVILEGED_FUNCTION;
/*
* The idle task, which as all tasks is implemented as a never ending loop.
* The idle task is automatically created and added to the ready lists upon
* creation of the first user task.
*
* The portTASK_FUNCTION_PROTO() macro is used to allow port/compiler specific
* language extensions. The equivalent prototype for this function is:
*
* void prvIdleTask( void *pvParameters );
*
*/
static portTASK_FUNCTION_PROTO( prvIdleTask, pvParameters );
/*
* Utility to free all memory allocated by the scheduler to hold a TCB,
* including the stack pointed to by the TCB.
*
* This does not free memory allocated by the task itself (i.e. memory
* allocated by calls to pvPortMalloc from within the tasks application code).
*/
#if ( ( INCLUDE_vTaskDelete == 1 ) || ( INCLUDE_vTaskCleanUpResources == 1 ) )
static void prvDeleteTCB( tskTCB *pxTCB ) PRIVILEGED_FUNCTION;
#endif
/*
* Used only by the idle task. This checks to see if anything has been placed
* in the list of tasks waiting to be deleted. If so the task is cleaned up
* and its TCB deleted.
*/
static void prvCheckTasksWaitingTermination( void ) PRIVILEGED_FUNCTION;
/*
* Allocates memory from the heap for a TCB and associated stack. Checks the
* allocation was successful.
*/
static tskTCB *prvAllocateTCBAndStack( unsigned short usStackDepth, portSTACK_TYPE *puxStackBuffer ) PRIVILEGED_FUNCTION;
/*
* Called from vTaskList. vListTasks details all the tasks currently under
* control of the scheduler. The tasks may be in one of a number of lists.
* prvListTaskWithinSingleList accepts a list and details the tasks from
* within just that list.
*
* THIS FUNCTION IS INTENDED FOR DEBUGGING ONLY, AND SHOULD NOT BE CALLED FROM
* NORMAL APPLICATION CODE.
*/
#if ( configUSE_TRACE_FACILITY == 1 )
static void prvListTaskWithinSingleList( const signed char *pcWriteBuffer, xList *pxList, signed char cStatus ) PRIVILEGED_FUNCTION;
#endif
/*
* When a task is created, the stack of the task is filled with a known value.
* This function determines the 'high water mark' of the task stack by
* determining how much of the stack remains at the original preset value.
*/
#if ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
static unsigned short usTaskCheckFreeStackSpace( const unsigned char * pucStackByte ) PRIVILEGED_FUNCTION;
#endif
/*lint +e956 */
/*-----------------------------------------------------------
* TASK CREATION API documented in task.h
*----------------------------------------------------------*/
signed portBASE_TYPE xTaskGenericCreate( pdTASK_CODE pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, xTaskHandle *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const xMemoryRegion * const xRegions )
{
signed portBASE_TYPE xReturn;
tskTCB * pxNewTCB;
/* Allocate the memory required by the TCB and stack for the new task,
checking that the allocation was successful. */
pxNewTCB = prvAllocateTCBAndStack( usStackDepth, puxStackBuffer );
if( pxNewTCB != NULL )
{
portSTACK_TYPE *pxTopOfStack;
#if( portUSING_MPU_WRAPPERS == 1 )
/* Should the task be created in privileged mode? */
portBASE_TYPE xRunPrivileged;
if( ( uxPriority & portPRIVILEGE_BIT ) != 0x00 )
{
xRunPrivileged = pdTRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -