FreeRTOS-任务创建和删除

一、任务创建及删除介绍

  • 任务的创建删除本质就是调用FreeRTOS的API函数(指可供用户调用的函数,用于管理和控制操作系统的各种功能)
  • 下面是任务创建和删除的API函数和描述
xTaskCreat();//动态方式创建任务
xTaskCreateStatic();//静态方式创建任务
vTaskDelete();//删除任务

1.1 动态创建任务

  • 动态创建任务是指任务的控制块以及栈空间所需的内存,均由FreeRTOS自动从FreeRTOS管理的堆中分配
//xTaskCreate();//动态方式创建任务,返回值为pdPASS任务创建成功,err创建失败
BaseType_t xTaskCreate
( 
		TaskFunction_t 						pxTaskCode,//指向任务函数的指针
		const char *const 					pcName,//任务名字
		const configSTACK_DEPTH_TYPE 		usStackDepth,//任务堆栈大小,字为单位
		void *const 						pvParameters,//传递给任务函数的参数
		UBaseType_t 						uxPriority,//任务优先级
		TaskHandle_t *const 				pxCreatedTask//任务句柄:指向一个任务控制块TCB的指针
)
  • 实现动态创建任务流程:将宏configSUPPORT_DYNAMIC_ALLOCATION配置成1 — 定义6个函数入口参数编写任务函数
  • 此函数创建的任务会立刻进入就绪态,由任务调度器运行

1.2 静态创建任务

  • 静态创建任务是指任务的控制块以及栈空间所需的内存,需要用户分配提供
//xTaskCreateStatic();//静态方式创建任务,返回指为NULL表示用户没有提供内存创建失败,其他值创建成功
TaskHandle_t xTaskCreateStatic
( 
		TaskFunction_t 						pxTaskCode,//指向任务函数的指针
		const char *const 					pcName,//任务名字
		const uint32_t                      usStackDepth,//任务堆栈大小,字为单位
		void *const 						pvParameters,//传递给任务函数的参数
		UBaseType_t 						uxPriority,//任务优先级
		StackType_t *const      			puxStackBuffer,//任务堆栈,一般为数组
		StackTask_t *const 				    pxTaskBuffer//任务控制块,由用户分配
)
  • 实现静态创建任务流程:将宏configSUPPORT_STATIC_ALLOCATION配置成1 — 定义空闲任务&定时器任务的任务堆栈TCB — 实现两个接口函数(Getldle和GetTimer) — 定义函数入口参数编写任务函数
  • 此函数创建的任务会立刻进入就绪态,由任务调度器运行

1.3 任务删除

  • 当删除任务函数的传入的参数为NULL时,表示删除任务自身(当前正在运行的任务)
  • 空闲任务负责释放被删除任务中由系统分配(动态任务创建)的内存
  • 由用户自己申请的内存(静态任务创建),则由用户在任务被删除前提前释放,否则会导致内存泄露
void vTaskDelete(TaskHandle_t xTaskToDelete);//删除已被创建的任务
//形参xTaskToDelete表示待删除的任务句柄
  • 实现任务删除流程:将宏INCLUDE_vTaskDelete配置成1 — 入口参数输入需要删除的任务句柄(NULL代表删除任务本身)
  • 此函数创建的任务会立刻进入就绪态,由任务调度器运行

二、实战编程

2.1 任务创建和删除(动态方法)

  • 创建四个任务,Start_task(用来创建其他三个任务)、task1(LED0每500ms闪烁一次)、task2(LED1每500ms闪烁一次)、task3(判断按键按下,按下则删除task1)
  • 此处Start_task只需要执行一次就要删除,否则动态创建任务,会导致自动分配堆栈不够
  • 动态创建任务步骤:宏configSUPPORT_DYNAMIC_ALLOCATION配置成1 — 定义6个函数入口参数编写任务函数
#define configSUPPORT_DYNAMIC_ALLOCATION					1//宏定义配置

//start_task参数宏定义
#define	START_TASK_STACK_SIZE 								128//堆栈大小
#define	START_TASK_PRIO										1//任务优先级
TaskHandle_t	start_task_handle;							//任务句柄
//task1参数宏定义
#define	TASK1_STACK_SIZE 									128//堆栈大小
#define	TASK1_PRIO											2//任务优先级
TaskHandle_t	task1_handle;								//任务句柄
//task2参数宏定义
#define	TASK2_STACK_SIZE 									128//堆栈大小
#define	TASK2_PRIO											3//任务优先级
TaskHandle_t	task2_handle;								//任务句柄
//task3参数宏定义
#define	TASK3_STACK_SIZE 									128//堆栈大小
#define	TASK3_PRIO											4//任务优先级
TaskHandle_t	task3_handle;								//任务句柄


//task1任务函数:LED0每500ms闪烁一次
void task1( void * pvParameters )
{
		while(1)
		{
			LED0_Turn();//LED0反转
			vTaskDelay(500);//自带延时函数
		}
}
//task2任务函数:LED1每500ms闪烁一次
void task2( void * pvParameters )
{
		while(1)
		{
			LED0_Turn();//LED1反转
			vTaskDelay(500);//自带延时函数
		}
}
//task3任务函数:判断按键按下,按下则删除task1
void task3( void * pvParameters )
{
		uint8_t KeyNum = 0;
		while(1)
		{
			KeyNum = Key_GetNum();//获取按键键码
			if(KeyNum == 1)
			{
				vTaskDelete(task1_handle);//按键按下删除task1,参数为task1句柄
			}
			vTaskDelay(10);//延时10ms,给了task1和task2机会
		}
}
//Start_task任务函数
void Start_task( void * pvParameters )
{
		//创建任务1
		xTaskCreate(task1,//任务函数
					"task1",//任务名称
					TASK1_STACK_SIZE,//堆栈大小/字
					NULL,//入口参数没有
					TASK1_PRIO,//优先级
					&task1_handle//任务句柄
					);
		//创建任务2
		xTaskCreate(task2,//任务函数
					"task2",//任务名称
					TASK2_STACK_SIZE,//堆栈大小/字
					NULL,//入口参数没有
					TASK2_PRIO,//优先级
					&task2_handle//句柄
					);
		//创建任务3
		xTaskCreate(task3,//任务函数
					"task3",//任务名称
					TASK3_STACK_SIZE,//堆栈大小/字
					NULL,//入口参数没有
					TASK3_PRIO,//优先级
					&task3_handle//句柄
					);
		vTaskDelete(start_task_handle);
		//删除自身任务Start_task,start_task_handle或NULL都可以
}

//FreeRTOS入口函数,程序从此处开始执行
void freertos_demo()
{
		xTaskCreate(Start_task,//任务函数
					"Start_task",//任务名称
					START_TASK_STACK_SIZE,//堆栈大小/字
					NULL,//入口参数没有
					START_TASK_PRIO,//优先级
					&start_task_handle//句柄
					);//创建Start任务
		vTaskStartScheduler();//开启任务调度器,开启执行Start任务,创建task123
}
  • 主函数main.c就不需要while循环函数了,只需要初始化外设、调用FreeRTOS入口函数即可
int main()
{
		//外设初始化
		freertos_demo();
}
  • 进入入口函数,一创建Start_task任务,任务调度器就开启,然后才开始执行Start_task任务
  • 按顺序首先创建task1,task1优先级>Start_task,在最开始运行task1阻塞500ms将cpu交给其他任务执行。然后创建task2,task2优先级>task1,运行task2,阻塞500ms释放,最后创建task3,优先级最高,运行task3,阻塞10ms,当全部阻塞时,删除Start_task任务
  • 如果想首先运行优先级最高的task3,可以在创建task123前,进入临界区,即关闭中断,还必须退出临界区后才会开始任务调度
  • 加上临界区时,整个任务流程应该是task3 task2 task1 task3…task3…task2 …task3…task3…task3… task1
  • 运行流程以task3居多,由于task3只阻塞10ms,当task3阻塞时,task2运行,task3和task2阻塞都阻塞时,task1运行
//Start_task任务函数
void Start_task( void * pvParameters )
{
		taskENTER_CRITICAL();//进入临界区
		//创建任务1
		xTaskCreate(task1,//任务函数
					"task1",//任务名称
					TASK1_STACK_SIZE,//堆栈大小/字
					NULL,//入口参数没有
					TASK1_PRIO,
					&task1_handle
					);
		//创建任务2
		xTaskCreate(task2,//任务函数
					"task2",//任务名称
					TASK2_STACK_SIZE,//堆栈大小/字
					NULL,//入口参数没有
					TASK2_PRIO,
					&task2_handle
					);
		//创建任务3
		xTaskCreate(task3,//任务函数
					"task3",//任务名称
					TASK3_STACK_SIZE,//堆栈大小/字
					NULL,//入口参数没有
					TASK3_PRIO,
					&task3_handle
					);
		vTaskDelete(start_task_handle);
		//删除自身任务Start_task,start_task_handle或NULL都可以
		taskEXIT_CRITICAL();//退出临界区
}

2.2 任务创建和删除(静态方法)

  • 创建四个任务,Start_task(用来创建其他三个任务)、task1(LED0每500ms闪烁一次)、task2(LED1每500ms闪烁一次)、task3(判断按键按下,按下则删除task1)
  • 实现静态创建任务流程宏configSUPPORT_STATIC_ALLOCATION配置成1 — 定义空闲任务定时器任务任务堆栈TCB(Getldle空闲任务和GetTimer定时器任务) — 定义函数入口参数编写任务函数
#define configSUPPORT_STATIC_ALLOCATION					1//宏定义配置

//start_task参数宏定义
#define			START_TASK_STACK_SIZE 								128//堆栈大小
#define			START_TASK_PRIO										1//任务优先级
StackType_t 	start_task_stack[START_TASK_STACK_SIZE] //任务堆栈
StackTask_t 	start_task_tcb;//任务控制块tcb
TaskHandle_t	start_task_handle;							//任务句柄
//task1参数宏定义
#define			TASK1_STACK_SIZE 									128//堆栈大小
#define			TASK1_PRIO											2//任务优先级
StackType_t 	task1_stack[TASK1_STACK_SIZE]		//任务堆栈
StackTask_t 	task1_tcb;//任务控制块tcb
TaskHandle_t	task1_handle;								//任务句柄
//task2参数宏定义
#define			TASK2_STACK_SIZE 									128//堆栈大小
#define			TASK2_PRIO											3//任务优先级
StackType_t	 	task2_stack[TASK2_STACK_SIZE]		//任务堆栈
StackTask_t		task2_tcb;//任务控制块tcb
TaskHandle_t	task2_handle;								//任务句柄
//task3参数宏定义
#define			TASK3_STACK_SIZE 									128//堆栈大小
#define			TASK3_PRIO											4//任务优先级
StackType_t 	task3_stack[TASK3_STACK_SIZE]		//任务堆栈
StackTask_t 	task3_tcb;//任务控制块tcb
TaskHandle_t	task3_handle;								//任务句柄


//task1任务函数:LED0每500ms闪烁一次
void task1( void * pvParameters )
{
		while(1)
		{
			LED0_Turn();//LED0反转
			vTaskDelay(500);//自带延时函数
		}
}
//task2任务函数:LED1每500ms闪烁一次
void task2( void * pvParameters )
{
		while(1)
		{
			LED0_Turn();//LED1反转
			vTaskDelay(500);//自带延时函数
		}
}
//task3任务函数:判断按键按下,按下则删除task1
void task3( void * pvParameters )
{
		uint8_t KeyNum = 0;
		while(1)
		{
			KeyNum = Key_GetNum();//获取按键键码
			if(KeyNum == 1)
			{
				vTaskDelete(task1_handle);//按键按下删除task1,参数为task1句柄
			}
			vTaskDelay(10);//延时10ms,给了task1和task2机会
		}
}
//Start_task任务函数
void Start_task( void * pvParameters )
{
		taskENTER_CRITICAL();//进入临界区
		//创建任务1,创建成功返回句柄
		task1_handle = xTaskCreateStatic(task1,//任务函数
						"task1",//任务名字
						TASK1_STACK_SIZE,//任务堆栈大小字
						NULL,//传递给任务函数的参数
						TASK1_PRIO,//任务优先级
						task1_stack,//任务堆栈
						&task1_tcb//任务控制块tcb
						);
		//创建任务2
		task2_handle = xTaskCreateStatic(task2,//任务函数
						"task2",//任务名字
						TASK2_STACK_SIZE,//任务堆栈大小字
						NULL,//传递给任务函数的参数
						TASK2_PRIO,//任务优先级
						task2_stack,//任务堆栈
						&task2_tcb//任务控制块tcb
						);
		//创建任务3
		task3_handle = xTaskCreateStatic(task3,//任务函数
						"task3",//任务名字
						TASK3_STACK_SIZE,//任务堆栈大小字
						NULL,//传递给任务函数的参数
						TASK3_PRIO,//任务优先级
						task3_stack,//任务堆栈
						&task3_tcb//任务控制块tcb
						);
		vTaskDelete(start_task_handle);
		//删除自身任务Start_task,start_task_handle或NULL都可以
		taskEXIT_CRITICAL();//退出临界区
}

//空闲任务配置
#define 		configMINIMAL_STACK_SIZE					128//空闲任务堆栈大小
StaticTask_t	idle_task_tcb;//定义任务控制块
StackType_t 	idle_task_stack[configMINIMAL_STACK_SIZE];//定义空闲任务堆栈
//空闲任务内存分配和TCB配置
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
                                     StackType_t ** ppxIdleTaskStackBuffer,
                                     uint32_t * pulIdleTaskStackSize )
{
		* ppxIdleTaskTCBBuffer = &idle_task_tcb;//任务控制块TCB
		* ppxIdleTaskStackBuffer = idle_task_stack;//分配空闲任务堆栈
		* pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;//空闲任务堆栈大小
} 
                                 
//定时器任务配置
#define 		configUSE_TIMERS			1//使能软件定时器宏
#define			configTIMER_TASK_STACK_DEPTH		(configMINIMAL_STACK_SIZE*2)//软件定时器任务堆栈大小
StaticTask_t	timer_task_tcb;//定义定时器任务控制块
StackType_t 	timer_task_stack[configMINIMAL_STACK_SIZE];//定义定时器任务堆栈
//定时器任务内存分配和TCB配置
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
 										StackType_t ** ppxTimerTaskStackBuffer, 
										uint32_t *pulTimerTaskStackSize )
{
		* ppxTimerTaskTCBBuffer = &timer_task_tcb;//定时器任务控制块TCB
		* ppxTimerTaskStackBuffer = timer_task_stack;//分配定时器任务堆栈
		* pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;//定时器任务堆栈大小
}

//FreeRTOS入口函数,程序从此处开始执行
void freertos_demo()
{
		//创建Start任务
		start_task_handle = xTaskCreateStatic(start_task,//任务函数
							"start_task",//任务名字
							START_TASK_STACK_SIZE,//任务堆栈大小字
							NULL,//传递给任务函数的参数
							START_TASK_PRIO,//任务优先级
							start_task_stack,//任务堆栈
							&start_task_tcb//任务控制块tcb
						)
		vTaskStartScheduler();//开启任务调度器,开启执行Start任务,创建task123
}
  • 动态任务创建不需要返回句柄,在创建时已经定义句柄
  • 静态任务创建和动态任务创建不同之处空闲任务分配内存并配置TCB定时器任务分配内存并配置TCB返回任务句柄任务堆栈和TCB需要手动配置
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值