一.函数讲解
函数原型:
BaseType_t ICACHE_ATTR xTaskCreate(
TaskFunction_t pxTaskCode,
const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
作用:创建任务
二.代码解析(创建任务)
任务控制块TCB:
typedef struct tskTaskControlBlock
{
//任务栈栈顶,必须要TCB的第一个成员
volatile StackType_t *pxTopOfStack;
//任务状态列表项
ListItem_t xStateListItem;
//任务时间列表项
ListItem_t xEventListItem;
//任务优先级
UBaseType_t uxPriority;
//指向任务栈首地址的指针
StackType_t *pxStack;
//任务名字
char pcTaskName[ configMAX_TASK_NAME_LEN ];
//任务栈栈底
#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
StackType_t *pxEndOfStack;
#endif
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
UBaseType_t uxCriticalNesting;
#endif
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxTCBNumber;
UBaseType_t uxTaskNumber;
#endif
//互斥信号量变量
#if ( configUSE_MUTEXES == 1 )
UBaseType_t uxBasePriority;
UBaseType_t uxMutexesHeld;
#endif
#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
#endif
#if( configGENERATE_RUN_TIME_STATS == 1 )
uint32_t ulRunTimeCounter;
#endif
//任务通知模块变量
#if( configUSE_TASK_NOTIFICATIONS == 1 )
volatile uint32_t ulNotifiedValue;
volatile uint8_t ucNotifyState;
#endif
} tskTCB;
BaseType_t ICACHE_ATTR xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
{
//创建任务控制块
TCB_t *pxNewTCB;
BaseType_t xReturn;
/* If the stack grows down then allocate the stack then the TCB so the stack
does not grow into the TCB. Likewise if the stack grows up then allocate
the TCB then the stack. */
//判断栈的地址是向上增长还是向下增长。也就是地址存储是从低地址往高地址增长还是高往低
#if( portSTACK_GROWTH > 0 )
{
/* Allocate space for the TCB. Where the memory comes from depends on
the implementation of the port malloc function and whether or not static
allocation is being used. */
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
if( pxNewTCB != NULL )
{
/* Allocate space for the stack used by the task being created.
The base of the stack memory stored in the TCB so the task can
be deleted later if required. */
pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
if( pxNewTCB->pxStack == NULL )
{
/* Could not allocate the stack. Delete the allocated TCB. */
vPortFree( pxNewTCB );
pxNewTCB = NULL;
}
}
}
#else /* portSTACK_GROWTH */
{
//定义任务堆栈
StackType_t *pxStack;
/* Allocate space for the stack used by the task being created. */
//动态任务堆栈空间申请,以字为单位
pxStack = pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */
if( pxStack != NULL )
{
/* Allocate space for the TCB. */
//申请任务控制块的空间
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */
if( pxNewTCB != NULL )
{
//保存堆栈地址到任务控制块中
/* Store the stack location in the TCB. */
pxNewTCB->pxStack = pxStack;
}
else
{
/* The stack cannot be used as the TCB was not created. Free
it again. */
vPortFree( pxStack );
}
}
else
{
pxNewTCB = NULL;
}
}
#endif /* portSTACK_GROWTH */
if( pxNewTCB != NULL )
{
#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e9029 !e731 Macro has been consolidated for readability reasons. */
{
/* Tasks can be created statically or dynamically, so note this
task was created dynamically in case it is later deleted. */
pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
}
#endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
//初始化任务控制块的成员
prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL );
//把新创建的任务添加到就绪列表中
prvAddNewTaskToReadyList( pxNewTCB );
xReturn = pdPASS;
}
else
{
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
}
return xReturn;
}
prvInitialiseNewTask()函数:
//把堆栈空间全部赋值成tskSTACK_FILL_BYTE,方便检测剩余堆栈大小,判断是否为tskSTACK_FILL_BYTE
( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );
//把栈顶地址赋值给pxTopOfStack,注意是栈顶地址(栈末尾地址),不是栈起始地址
pxTopOfStack = &( pxNewTCB->pxStack[ ulStackDepth - ( uint32_t ) 1 ] );
//8字节对其
pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
//赋值名字
pxNewTCB->pcTaskName[ x ] = pcName[ x ];
//任务优先级赋值
pxNewTCB->uxPriority = uxPriority;
//互斥量优先级初始化,用于互斥信号量场景使用,防止优先级翻转问题
#if ( configUSE_MUTEXES == 1 )
{
pxNewTCB->uxBasePriority = uxPriority;
pxNewTCB->uxMutexesHeld = 0;
}
//初始化状态列表项以及事件列表项
vListInitialiseItem( &( pxNewTCB->xStateListItem ) );
vListInitialiseItem( &( pxNewTCB->xEventListItem ) );
listSET_LIST_ITEM_OWNER( &( pxNewTCB->xStateListItem ), pxNewTCB );
//初始化事件列表项数值
listSET_LIST_ITEM_VALUE( &( pxNewTCB->xEventListItem ), ( TickType_t )configMAX_PRIORITIES - ( TickType_t ) uxPriority );
listSET_LIST_ITEM_OWNER( &( pxNewTCB->xEventListItem ), pxNewTCB );
//对任务栈进行赋值
pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters );
//任务句柄赋值
*pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
prvAddNewTaskToReadyList()函数
static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
{
/* Ensure interrupts don't access the task lists while the lists are being
updated. */
//临界区
taskENTER_CRITICAL();
{
//任务数量++
uxCurrentNumberOfTasks++;
//pxCurrentTCB 指向当前优先级最高的任务,这里判断的意思是是否为第一个任务
if( pxCurrentTCB == NULL )
{
/* There are no other tasks, or all the other tasks are in
the suspended state - make this the current task. */
//赋值任务控制块
pxCurrentTCB = pxNewTCB;
//如果是第一个任务
if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 )
{
//初始化列表
/* This is the first task to be created so do the preliminary
initialisation required. We will not recover if this call
fails, but we will report the failure. */
prvInitialiseTaskLists();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
/* If the scheduler is not already running, make this task the
current task if it is the highest priority task to be created
so far. */
//判断调度器是否启动
if( xSchedulerRunning == pdFALSE )
{
//如果已经启动,并且新创建的任务优先级比当前任务优先级高
if( pxCurrentTCB->uxPriority <= pxNewTCB->uxPriority )
{
pxCurrentTCB = pxNewTCB;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
//任务标号,第几个创建的任务
uxTaskNumber++;
#if ( configUSE_TRACE_FACILITY == 1 )
{
/* Add a counter into the TCB for tracing only. */
pxNewTCB->uxTCBNumber = uxTaskNumber;
}
#endif /* configUSE_TRACE_FACILITY */
traceTASK_CREATE( pxNewTCB );
//添加到就绪列表
prvAddTaskToReadyList( pxNewTCB );
portSETUP_TCB( pxNewTCB );
}
taskEXIT_CRITICAL();
if( xSchedulerRunning != pdFALSE )
{
/* If the created task is of a higher priority than the current task
then it should run now. */
//调度器已启动,如果新创建的任务优先级比当前执行任务高,则进行一次任务调度,切换任务
if( pxCurrentTCB->uxPriority < pxNewTCB->uxPriority )
{
taskYIELD_IF_USING_PREEMPTION();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
prvInitialiseTaskLists()
static void prvInitialiseTaskLists( void )
{
UBaseType_t uxPriority;
//初始化就绪列表
for( uxPriority = ( UBaseType_t ) 0U; uxPriority < ( UBaseType_t ) configMAX_PRIORITIES; uxPriority++ )
{
vListInitialise( &( pxReadyTasksLists[ uxPriority ] ) );
}
//初始化两个延时列表,为什么是两个?为了防止溢出
vListInitialise( &xDelayedTaskList1 );
vListInitialise( &xDelayedTaskList2 );
//初始化等待就绪列表
vListInitialise( &xPendingReadyList );
//初始化等待删除列表
#if ( INCLUDE_vTaskDelete == 1 )
{
vListInitialise( &xTasksWaitingTermination );
}
#endif /* INCLUDE_vTaskDelete */
//初始化挂起列表
#if ( INCLUDE_vTaskSuspend == 1 )
{
vListInitialise( &xSuspendedTaskList );
}
#endif /* INCLUDE_vTaskSuspend */
/* Start with pxDelayedTaskList using list1 and the pxOverflowDelayedTaskList
using list2. */
pxDelayedTaskList = &xDelayedTaskList1;
pxOverflowDelayedTaskList = &xDelayedTaskList2;
}
#define prvAddTaskToReadyList( pxTCB )
#define prvAddTaskToReadyList( pxTCB ) \
//
traceMOVED_TASK_TO_READY_STATE( pxTCB ); \
//如果新pxTCB的优先级比当前就绪列表中任务最高优先级大,则赋值给uxTopReadyPriority
taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority ); \
//尾部插入到就绪列表中
vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \
tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )