FreeRTOS原理剖析:任务的创建

1. 任务创建API函数

任务的最基本功能是任务管理,任务管理中最基本操作是任务的创建和删除。对于任务的创建和删除,由于篇幅有点长,分两篇分别讲解。在FreeRTOS中任务的创建函数如下:

函数 描述
xTaskCreate() 使用动态方法创建一个任务
xTaskCreateStatic() 使用静态方法创建一个任务
xTaskCreateRestricted() 创建一个使用MPU进行限制的任务,使用动态内存分配,要求对应的MCU有MPU功能(内存保护单元)

其它内部调用函数:

函数 描述
prvInitialiseNewTask() 初始化任务
pxPortInitialiseStack() 初始化堆栈
prvAddNewTaskToReadyList() 若第一次创建任务,将调函数prvInitialiseTaskLists(),初始化各个系统列表,最后调用函数prvAddTaskToReadyList(),将新创建的任务挂接到任务就绪表中
prvInitialiseTaskLists() 初始化任务列表
prvAddTaskToReadyList() 将新创建的任务挂接到任务就绪表中

2. 任务的动态创建

2.1 任务动态创建函数xTaskCreate()

该函数是使用动态方法创建一个任务,每个任务需要RAM来保存任务的状态信息,在FreeRTOS中称为任务控制块。该函数会自动给任务申请任务控制块空间、申请任务的堆栈空间,不需要用户自己定义堆栈和任务控制块储存空间。另外也会将任务添加到任务就绪表中,使创建的任务处于就绪态,供任务调度器调用。使用此函数,必须将configSUPPORT_DYNAMIC_ALLOCATION设置为1,此宏定义在FreeRTOSConfig.h文件中。

函数原型如下:

BaseType_t xTaskCreate(	TaskFunction_t 		 pxTaskCode,
					    const char * const 	 pcName,
						const uint16_t 		 usStackDepth,
						void * const 		 pvParameters,
					    UBaseType_t 		 uxPriority,
					    TaskHandle_t * const pxCreatedTask )

函数参数说明:

  • pxTaskCode: 任务函数指针,指向任务函数入口。该参数是新定义的类型typedef void ( * TaskFunction_t )(void * ),该类型在projdefs.h中定义,表示一个指向函数的指针,其无返回值(void)和参数是 void * 类型。
    通常 void* 用在函数参数值(或者返回值)中是为了兼容不同指针类型的传递。可以将别的类型指针无需强制类型转换,就能赋值给 void* 类型,也可以将 void* 强制类型转换成任何别的指针类型。
  • pcName: 任务的描述性名字,主要用于追踪和调试。字符串最大长度不超过configMAX_TASK_NAME_LEN,在FreeRTOSConfig.h中定义。
  • usStackDepth: 任务堆栈的大小。当MCU为STM32时,实际为字节数为:usStackDepth * 4。内存申请函数参数为size_t类型,即堆栈能分配的最大字节数为类型size_t能表示的最大数字。
  • pvParameters: 函数的参数。当任务创建时,作为一个参数传递给任务,当不需要参数时,设为NULL。
  • uxPriority: 任务的优先级。最大不能超过configMAX_PRIORITIES - 1,在FreeRTOSConfig中定义。
  • pxCreatedTask: 任务的句柄。创建一个任务时,会保存任务一个句柄(TCB的入口地址),可以使用这个句柄引用任务,如改变任务的优先级或删除任务等,如果程序中不需要句柄,可将该参数设为NULL。

返回值:

  • pdPASS: 任务创建成功
  • errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY: 任务创建失败,栈内存不足。

函数代码如下:

BaseType_t xTaskCreate(	TaskFunction_t       pxTaskCode,
						const char * const   pcName,
						const uint16_t       usStackDepth,
						void * const         pvParameters,
						UBaseType_t          uxPriority,
						TaskHandle_t * const pxCreatedTask ) 
{
	TCB_t *pxNewTCB;
	BaseType_t xReturn;

	/* 
	 * portSTACK_GROWTH > 0时,表示堆栈向上增长
	 * portSTACK_GROWTH <=0时,表示堆栈向下增长
	 * portSTACK_GROWTH 表示栈的生长方向,对于ARM CM4是向下增长的
	 * portSTACK_GROWTH在portmacro.h中定义,默认为 -1
	 */
	#if( portSTACK_GROWTH > 0 )
	{
		/* 堆栈向上增长,为防止堆栈增长到任务控制块,则先为任务控制块申请内存 */
		pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );

		/* 任务控制块申请内存成功 */
		if( pxNewTCB != NULL )
		{
			/* 
			 * 堆栈申请内存,堆栈的实际内存空间等于(usStackDepth  * sizeof( StackType_t ) )
			 * 其中,StackType_t 为uint32_t类型,即堆栈实际字节数为:usStackDepth  *  4
			 * 直接让任务控制块中堆栈指针指向申请的堆栈入口地址
			 */
			pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); 
			
			/* 如果堆栈内存申请失败 */
			if( pxNewTCB->pxStack == NULL )
			{
				vPortFree( pxNewTCB );	/* 堆栈内存申请失败,释放掉刚刚申请的任务控制块内存 */
				pxNewTCB = NULL;		/* pxNewTCB 指针指向空地址,因为释放掉了刚刚申请的任务控制块内存 */
			}
		}
	}
	#else /* portSTACK_GROWTH */
	{
		StackType_t *pxStack;

		/* 
		 * 堆栈申请内存,堆栈的实际内存空间等于(usStackDepth  * sizeof( StackType_t ) )
		 * 其中,StackType_t 为uint32_t类型,即堆栈实际字节数为:usStackDepth  *  4
		 */
		pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) );

		/* 堆栈申请成功 */
		if( pxStack != NULL )
		{
			/* 任务控制块申请内存 */
			pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值