【FreeRTOS】任务状态

目录

  1. 任务状态理论
  2. 任务的状态切换图
  3. 任务状态实验

1.任务状态理论

根据上一篇文章任务创建的基础,在原始的任务创建的基础上加上任务状态的判断,程序如下:

//main.c

//定义任务句柄
TaskHandle_t xHandleTask1;

//定义任务标识符
static int task1flag=0;
static int task2flag=0;
static int task3flag=0;

//创建任务
void Task1Function(void *param)
{
	while(1)
	{
		task1flag=1;
		task2flag=0;
		task3flag=0;
		printf("1");
	}
}
void Task2Function(void *param)
{
	while(1)
	{
		task1flag=0;
		task2flag=1;
		task3flag=0;
		printf("2");
	}
}
void Task3Function(void *param)
{
	while(1)
	{
		task1flag=0;
		task2flag=0;
		task3flag=1;
		printf("3");
	}
}

StackType_t xTask3Stack[100];
StaticTask_t xTask3TCB;
StackType_t xIdleTaskStack[100];;
StaticTask_t xIdleTaskTCB;

void vApplicationGetIdleTaskMemory(StaticTask_t ** ppxIdleTaskTCBBuffer,
									StackType_t ** ppxIdleTaskStackBuffer,
									uint32_t * pulIdleTaskStackSize)
{
	*ppxIdleTaskTCBBuffer=&xIdelTaskTCB; 
	*ppxIdleTaskStackBuffer=xIdleTaskStack;
	*pulIdleTaskStackSize=100;
}

int main(void)
{
	printf("Hello World!");
	xTaskCreat(Task1Function,
				"Task1",
				100,
				NULL,
				1,
				&xHandleTask1
			);
	xTaskCreat(Task2Function,
				"Task2",
				100,
				NULL,
				1,
				NULL
			);
	xTaskCreatStatic(Task3Function,
					"Task3",
					100,
					NULL,
					1,
					xTask3Stack,
					&xTask3TCB
				);	
	vTaskStartScheduler();	
}

打开魔法棒->Debug->进行勾选
在这里插入图片描述
然后将程序进入到Debug,将task1flag,task2flag,task3flag三个变量add xxx to Logic Analyzer
在这里插入图片描述
从上面的图可以看出,task3、task1、task2是交替执行的,他们的执行时间大致为1ms,执行的顺序为task3、task1、task2。任务切换的基础为tick中断,打开FreeRTOSConfig.h可以查看到,FreeRTOS基准的Tick为1ms,也就对应了他们的执行时间大致为1ms。
在这里插入图片描述

FreeRTOS的每个任务都有单独的堆栈空间,当任务切出的时候它的执行环境会被保存在该任务的栈空间中,这样当任务再次运行时,就能从堆栈中正确的恢复上次的运行环境,任务越多,需要的堆栈空间就越大,而一个系统能运行多少个任务,取决于系统的可用的 SRAM
FreeRTOS的任务执行可以是抢占式调度机制,优先级高的任务可以打断优先级低的任务的执行,优先级低的任务必须在优先级高的任务阻塞或者结束后得到调度。
FreeRTOS的任务执行也可以进行时间片流转调度方式,时间片流转的方式不允许抢占任务的CPU使用权。 任务通常运行在死循环里。

2.任务的状态切换图

在这里插入图片描述
任务一共有四个状态:
1.Running(运行)
2.Ready(就绪)
3.Blocked(阻塞):等待某些事情发生,例如vTaskDelay()函数
4.Suspened(暂停):主动或者被动休息,例如vTaskSuspended/vTaskResume
如何来管理不同状态的任务:将它们放在不同的链表里

3.任务状态实验

TickType_t xTaskGetTickCount( void )函数:获取系统当前运行的时钟节拍数
void vTaskDelay( const TickType_t xTicksToDelay )函数:用于任务的延时,至少等待指定个数的tick才能变成就绪状态
void vTaskSuspend( TaskHandle_t xTaskToSuspend )函数:任务进入暂停状态
void vTaskResume( TaskHandle_t xTaskToResume )函数:任务恢复就绪状态

1.任务状态暂停和恢复函数

//任务句柄
TaskHandle_t xHandleTask1;
TaskHandle_t xHandleTask3;

//任务状态标志
static int task1flag=0;
static int task2flag=0;
static int task3flag=0;
//Task1函数
void Task1Function(void *param)
{
	TickType_t tstart=xTaskGetTickCount();//获取当前任务的时钟节拍
	TickType_t t;
	int flag=0;
	while(1)
	{
		t=xTaskGetTickCount();//获取当前任务的时钟节拍
		task1flag=1;
		task2flag=0;
		task3flag=0;
		printf("1");

		if(!flag && (t-tstart>10))
		{
			//task3进入到suspended状态
			vTaskSuspend( xHandleTask3 );
			falg=1;
		}
		if((t-start>20))
		{
			//任务3恢复就绪态
			 vTaskResume( xHandleTask3 );
		}
	}
}
//Task2函数
void Task2Function(void *param)
{
	while(1)
	{
		task2flag=1;
		task1flag=0;
		task3flag=0;
		printf("2");
		
		//task2进入阻塞状态
		vTaskDelay(10);//用于任务延时,每执行10个tick才能从阻塞状态变为就绪状态
	}
}
//Task3
void Task3Function(void *param)
{
	while(1)
	{
		task1flag=0;
		task2flag=0;
		task3flag=1;
		printf("3");
	}
}

StackType_t xTask3Stack[100];
StaticTask_t xTask3TCB;

StackType_t xIdleTaskStack[100];
StaticTask_t xIdelTaskTCB;

void	vApplicationGetIdleTaskMemory(StaticTask_t ** ppxIdleTaskTCBBuffer,
										StackType_t ** ppxIdleTaskStackBuffer,
										uint32_t * pulIdleTaskStackSize)
{
	*ppxIdleTaskTCBBuffer=&xIdelTaskTCB; 
	*ppxIdleTaskStackBuffer=xIdleTaskStack;
	*pulIdleTaskStackSize=100;
}

int main( void )
{
	printf("Hello World!\r\n");
	
	xTaskCreate(Task1Function,"Task1",100,NULL,1,&xHandleTask1);
	xTaskCreate(Task2Function,"Task2",100,NULL,1,NULL);
	xHandleTask3=xTaskCreateStatic(Task3Function,"Task3",100,NULL,1,xTask3Stack,&xTask3TCB);

	vTaskStartScheduler();
}

开始时task3进入到running状态,执行1ms后进入ready状态->task1进入running状态执行1ms后进入ready状态->task2进入running状态,然后开始blocked,需要阻塞10ms->task1和task3交替执行,直到task1执行10个tick,task3进入suspended状态,等task1再执行10个tick,task3恢复ready状态->之后task1和task3可以交替执行,但是task2依然会进入blocked状态

程序执行的结果如下:
在这里插入图片描述

2.vTaskDelay和vTaskDelayUtil函数

void vTaskDelay( const TickType_t xTicksToDelay ):至少等待指定的tick数才能进入到就绪状态,能保证休眠的时间一样,但不能保证从启动到下一次启动的时间一样
void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ):等待到指定的绝对时刻变为就绪态,能保证这一次启动到下一次启动的时间一样,但不能保证休眠的时间一样

程序如下:

TaskHandle_t xHandleTask1;
TaskHandle_t xHandleTask3;

static int task1flag=0;
static int task2flag=0;
static int task3flag=0;

static int rands[]={3,56,12,37,96,45};


void Task1Function(void *param)
{
	TickType_t start = xTaskGetTickCount();
	int i=0;
	int j=0;
	
	while(1)
	{
		task1flag=1;
		task2flag=0;
		task3flag=0;
		
		for(i=0;i<rands[j];i++)
			printf("1");
		j++;
		if(j == 6)
			j=0;

#if 0		
		vTaskDelay(20);
#else 1
		vTaskDelayUntil(&start,20);
#endif
		
	}
//接下来在main函数中,将task1的优先级设置为2,其余不变
xTaskCreate(Task1Function,"Task1",100,NULL,2,&xHandleTask1);

vTaskDelay()函数的运行结果,可以看出,任务执行的时间间隔是一样的,也就是休眠时间是一样的.
请添加图片描述
vTaskDelayUntil()函数可以看出这一次启动到下一次启动的时间间隔是一样的,但是休眠时间是不一定的。请添加图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值