FreeRTOS—动态创建与删除任务实战;静态创建与删除任务实战

注意:任务优先级与中断优先级不一样

  • 任务优先级:数值越大,越先被执行
  • 中断优先级:数值越小,越先被执行

一、动态创建任务

1.1.实验设计

创建四个任务,任务名字分别是 start_task、task1、task2、task3:

  1. start_task:用来创建其他三个任务
  2. task1:实现 LED0 每500ms闪烁一次
  3. task2:实现 LED1 每500ms闪烁一次
  4. task3:判断按键 KEY0 是否按下,按下则删除 task1

1.2.软件设计

以下代码设计在 freertos_demo.c 文件里实现:

  1. 首先在 FreeRTOSConfig.h 文件,将宏configSUPPORT_DYNAMIC_ALLOCATION配置为1,支持动态申请内存
  2. 定义入口函数参数,并在上面声明该函数、进行堆栈大小和任务优先级的宏定义,记得在主函数里面调用freertos_demo( );,以下代码实现:
void freertos_demo(void)
{
    xTaskCreate((TaskFunction_t)    start_task,
                (char*)             "start_task",
                (uint16_t)          START_TASK_STACK_SIZE,
                (void*)             NULL,
                (UBaseType_t)       START_TASK_PRIO,
                (TaskHandle_t*)     &start_task_handler);
    vTaskStartScheduler();  		//开启任务调度器
}
  1. 声明每个任务的配置包括:任务句柄、任务优先级、堆栈大小、创建任务
//start_task的任务配置
#define START_TASK_PRIO           1
#define START_TASK_STACK_SIZE     128
TaskHandle_t start_task_handler;
void start_task(void *pvParameters);

//task1的任务配置
#define TASK1_PRIO           2
#define TASK1_STACK_SIZE     128
TaskHandle_t task1_handler;
void task1(void *pvParameters);

//task2的任务配置
#define TASK2_PRIO           3
#define TASK2_STACK_SIZE     128
TaskHandle_t task2_handler;
void task2(void *pvParameters);

//task3的任务配置
#define TASK3_PRIO           4
#define TASK3_STACK_SIZE     128
TaskHandle_t task3_handler;
void task3(void *pvParameters);
  1. 编写任务函数
//编写start_task的任务函数,它的里面又定义task1、task2、task3
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区,为什么要进入临界区
    								//因为在定义入口函数参数的时候开启了任务调度器,当任务调度器开启的时候,任务立刻创建,立刻与第一个任务进行优先级比较,优先级的作用在开始的时候就发挥不出来,所以需要进去临界区,等待全部任务创建完成,就进行调度,优先级高的先进性
    xTaskCreate((TaskFunction_t)    task1,
                (char*)             "task1",
                (uint16_t)          TASK1_STACK_SIZE,
                (void*)             NULL,
                (UBaseType_t)       TASK1_PRIO,
                (TaskHandle_t*)     &task1_handler);

    xTaskCreate((TaskFunction_t)    task2,
                (char*)             "task2",
                (uint16_t)          TASK2_STACK_SIZE,
                (void*)             NULL,
                (UBaseType_t)       TASK2_PRIO,
                (TaskHandle_t*)     &task2_handler);

    xTaskCreate((TaskFunction_t)    task3,
                (char*)             "task3",
                (uint16_t)          TASK3_STACK_SIZE,
                (void*)             NULL,
                (UBaseType_t)       TASK3_PRIO,
                (TaskHandle_t*)     &task3_handler);
                
    vTaskDelete(start_task_handler);//删除start_task任务,释放空间	
    taskEXIT_CRITICAL();            //退出临界区
}

编写 task1、task2、task3 代码:

void task1(void *pvParameters)
{
	while(1)
	{
		printf("task1正在运行");
		LED0_TOGGLE();
		vTaskDelay(500);
	}
}

void task2(void *pvParameters)
{
	while(1)
	{
		printf("task2正在运行");
		LED1_TOGGLE();
		vTaskDelay(500);
	}
}

void task3(void *pvParameters)
{
	uint8_t key = 0;
	while(1)
	{
		printf("task3正在运行");
		key = key_scan(0);
		if(key == KEY0)
		{
			vTaskDelete(task1_handler);
			printf("删除成功");
			task1_handler = NULL;	//避免空指针的出现
		}
		vTaskDelay(10);
	}
}

第3个点设置了各个任务的优先级,其中 task3 的优先级最大,按理来说最先运行,task1 的优先级较为小,在三个任务中最后运行,可通过串口助手证明 task1 反而最先运行;这是因为在入口函数里面调用了任务调度函数vTaskStartScheduler( );start_task函数首先创建 task1 ,所以就先运行 task1,按这样的运行逻辑,task3 成为最后一个运行的任务;为了解决这个问题,就要在start_task函数里调用进入临界区taskENTER_CRITICAL( );和退出临界区taskEXIT_CRITICAL( );,等待所有任务创建完成,再进行优先级排序,这样操作就可以体现优先级的作用了。

在这里插入图片描述

二、静态创建任务

2.2.实验设计

静态创建任务的实验设计与动态创建任务一样,task1、task2、task3 这三个任务内容不变,编写空闲任务内存分配、编写软件定时器内存分配、修改入口函数、start_task函数、各个任务的声明和宏定义即可。

2.3.软件设计

  1. 首先在 FreeRTOSConfig.h 文件,将宏configSUPPORT_STATIC_ALLOCATION配置为1,支持静态申请内存
  2. 定义空闲任务vApplicationGetdleTaskMemory( );(这个是必须的,不要让CUP停下来)、定时器任务的任务堆栈vApplicationGetTimerTaskMemory( );及TCB(软件定时器的宏定义默认是为1的,如果为0就不需要为定时器分配内存)
//空闲任务配置
StaticTask_t idle_task_tcb;
StackType_t  idle_task_stack[configMINIMAL_STACK_SIZE];

//定时器任务配置
StaticTask_t timer_task_tcb;
StackType_t  timer_task_stack[configTIMER_TASK_STACK_DEPTH];

上面的宏定义为下面的函数服务的:

//空闲任务内存分配
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
                                    StackType_t ** ppxIdleTaskStackBuffer,
                                    uint32_t * pulIdleTaskStackSize )
{
	*ppxIdleTaskTCBBuffer = &idle_task_tcb;
	*ppxIdleTaskStackBuffer = idle_task_stack;
	*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}

//软件定时器内存分配
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
                                     StackType_t ** ppxTimerTaskStackBuffer,
                                     uint32_t * pulTimerTaskStackSize )
{
	*ppxTimerTaskTCBBuffer = &timer_task_tcb;
	*ppxTimerTaskStackBuffer = timer_task_stack;
	*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
  1. 定义函数入口参数
//返回一个句柄
void freertos_demo(void)
{
	start_task_handler = xTaskCreateStatic( (TaskFunction_t) start_task,
											(char *)			"start_task",
											(uint32_t) 		START_TASK_STACK_SIZE,
											(void *)			NULL,
											(UBaseType_t) 	START_TASK_PRIO,
											(StackType_t *)	start_task_stack,
											(StaticTask_t *)	&start_task_tcb );
    vTaskStartScheduler();  	//开启任务调度器
}
  1. 编写任务函数
//静态创建任务的函数都需要返回一个句柄
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();    //进入临界值
	
	task1_handler = xTaskCreateStatic( (TaskFunction_t) task1,
									   (char *)			"task1",
									   (uint32_t) 		TASK1_STACK_SIZE,
								       (void *)			NULL,
								       (UBaseType_t) 	TASK1_PRIO,
								       (StackType_t *)	task1_stack,
								       (StaticTask_t *)	&task1_tcb );
					   
	task2_handler = xTaskCreateStatic( (TaskFunction_t) task2,
									   (char *)			"task2",
									   (uint32_t) 		TASK2_STACK_SIZE,
									   (void *)			NULL,
									   (UBaseType_t) 	TASK2_PRIO,
									   (StackType_t *)	task2_stack,
									   (StaticTask_t *)	&task2_tcb );	
					   
	task3_handler = xTaskCreateStatic( (TaskFunction_t) task3,
									   (char *)			"task3",
									   (uint32_t) 		TASK3_STACK_SIZE,
									   (void *)			NULL,
									   (UBaseType_t) 	TASK3_PRIO,
									   (StackType_t *)	task3_stack,
									   (StaticTask_t *)	&task3_tcb );						   
                
    vTaskDelete(start_task_handler);	
    taskEXIT_CRITICAL();          
}

编写 task1、task2、task3 任务函数,与动态创建任务的内容一样。以上就是动态创建和静态创建任务的使用方法,还有删除任务的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值