FreeRTOS任务创建和优先级的抢占及解决方式

FreeRTOS的创建

基于keil5软件:

要包含 #include "FreeRTOS.h"和#include "task.h"这两个头文件,我们在创建一些任务的时候需要这两个头文件。
FreeRTOS要求我们用中断优先级分组4,支持16级的抢占优先级。
FreeRTOS中任务的最高优先级是通过FreeRTOSConfig.h中的configMAX_PRIORITIES 进行配置的,用户实际可以使用的优先级范围是0- configMAX_PRIORITIES -1,也就是说设置的优先级是3,那么我们可以使用的优先级号就是0,1,2不包含3,数字越大优先级越高。

那么我们如何创建任务 ?

这时我们需要用到一个函数xTaskCreate,这个函数和线程函数pthread_create非常相似,功能是差不多的,只不过xTaskCreate里面的参数和pthread_create不一样,接下来让我们看一下如何去写这个函数。
创建任务后我们要开启任务调度
vTaskStartScheduler();

函数代码编写如下:

	/*
		第一个参数表示线程函数
		第二个参数表示任务名字,自定义
		第三个参数表示任务的栈空间,给多少空间
		第四个参数表示参数传递,不传就写空
		第五个参数表示表示优先级
		第六个参数表示句柄等同于线程ID
	*/
	xTaskCreate(app_task1,"app_task1",512,NULL,6,&app_task1_handle);

	//这里我们就顺手写一下根据上面的任务所创建的函数
	void app_task1(void *pvParameters)
	{
		while(1)
		{
			//睡眠延时1000ms
			vTaskDelay(1000);
			printf("[app_task1] runing .....");
		}
	}

注意,RTOS总是运行优先级最高且就绪的任务
如果我们将睡眠延时改成10ms,我们就会发现,低优先级的任务会被抢占,任务被抢占后会从运行态转变为就绪态。如下例子

	//我们创建两个任务
	int main()
	{
		xTaskCreate(app_task1,"app_task1",512,NULL,6,&app_task1_handle);
		xTaskCreate(app_task2,"app_task2",512,NULL,7,&app_task2_handle);
		
		vTaskStartScheduler();
		while(1)
		{
		
		}
	}
	void app_task1(void *pvParameters)
	{
		while(1)
		{
			printf("[app_task1] runing .....");
			//睡眠延时10ms
			vTaskDelay(10);
			
		}
	}
	
	void app_task2(void *pvParameters)
	{
		while(1)
		{
			printf("[app_task2] runing .....");
			//睡眠延时10ms
			vTaskDelay(10);
			
		}
	}

根据上面代码我们可以得知,任务2的优先级比任务1要高,这里的优先级是数字越小优先级越低,这里会先执行任务2,执行后任务2由运行态变为阻塞态,任务1由就绪态变为运行态,此时任务2经过10ms延时之后从阻塞态变为就绪态且任务2的优先级比任务1高,任务1就从运行态变为就绪态,任务2从就绪态变为运行态,后面以此类推,看下图更好理解。
在这里插入图片描述
通过图片我们可以看到第一行任务2是正常运行,第二行开始,任务1在运行时被任务2抢占,此时任务1就变成了就绪状态,第三行也是一样,被任务2抢占,第四行也是同理,这也就导致了任务2完整执行4次,而任务1只完整执行1次,那么我们该如何解决这类问题呢?我们可以通过挂起任务2来让任务1完整运行,如下代码所示

	//我们一样创建两个任务
	int main()
	{
		xTaskCreate(app_task1,"app_task1",512,NULL,6,&app_task1_handle);
		xTaskCreate(app_task2,"app_task2",512,NULL,7,&app_task2_handle);
		
		vTaskStartScheduler();
		while(1)
		{
		
		}
	}
	void app_task1(void *pvParameters)
	{
		while(1)
		{
			vTaskSuspend(app_task2_handle);//挂起任务2
			printf("[app_task1] runing .....");
			vTaskResume(app_task2_handle);//取消挂起
			//睡眠延时10ms
			vTaskDelay(10);
			
		}
	}
	
	void app_task2(void *pvParameters)
	{
		while(1)
		{
			printf("[app_task2] runing .....");
			//睡眠延时10ms
			vTaskDelay(10);
			
		}
	}

可以看到我们用了一个vTaskSuspend()函数,这个函数就是用来挂起某个任务,里面的参数就是你要挂起的任务句柄,句柄就是你创建任务时最后的那个参数,带&符号的那个,当我们挂起这个任务时要记住取消挂起。取消挂起函数vTaskResume(),参数和挂起函数是一样的,此时我们再看下结果。
在这里插入图片描述
此时就是正常的

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值