FreeRTOS xTaskCreate函数讲解(窥探系统任务管理)

一.函数讲解

        函数原型:

        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 )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值