FreeRTOS第四节——任务的挂起与恢复

1、函数介绍

函数描述
xTaskSuspend()挂起一个任务
xTaskResume()恢复一个任务的运行
xTaskResumeFromISR()恢复一个任务的运行从中断服务函数中

我们要知道,当我们对一个任务进行挂起和恢复的时候,任务的数据是不会被删除的,方便应用程序接着操作之前的数据上下文继续运行。

1.xTaskSuspend()
我们来简单看一下挂起函数的定义中的解释:
把里面的英文翻译了一下,大概就是:要使得这个函数有效,在FreeRTOSConfig.h中INCLUDE_vTaskSuspend 必须定位为1。无论一个任务是什么优先级,当被挂起的时候,处理器都不会再运行这个函数,Suspend这个函数不能连续的调用,挂起一个任务只需要调用一次vTaskSuspend()就够了,调用vTaskResume () 让一个任务进入就绪态,参数为NULL的时候将会挂起本身, 参数为句柄是将会挂起句柄所代表的函数

/**
 * task. h
 * INCLUDE_vTaskSuspend 必须定位为1,当这个函数有效的时候
 *当一个任务被挂起的时候,无论它是什么优先级,都不会再去占用系统处理时间
 *不能连续的调用Suspend这个函数
 * 挂起一个任务只需要调用一次vTaskSuspend()就够了
 * 调用vTaskResume () 让一个任务进入就绪态
 * 参数为NULL的时候将会挂起本身
 * 参数为句柄是将会挂起句柄所代表的函数
 * 示例用法:
 void vAFunction( void )
 {
 TaskHandle_t xHandle;
	 // 创建任务
	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
	 // ...
	 // 挂起任务
	 vTaskSuspend( xHandle );
	 // ...
	 //这个被挂起的任务将不会再运行,直到另外一个调用vTaskResume(xHandle)
	 //...
	 // 挂起任务本身
	 vTaskSuspend( NULL );
	 // 程序不会运行到这里除非有一个任务调用了vTaskResume并且把当前任务的句柄当作参数传递进去
 }
 */
 //这里是函数的定义
void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION;

2.xTaskResume()
再看一下resume函数的源码:

/**
 * task. h
 * 要使得这个函数有效在FreeRTOSConfig.h中INCLUDE_vTaskSuspend 必须定位为1
 *恢复一个任务调用一次vTaskSuspend ()就行了,不用疯狂调用,试验了一下下,疯狂调用会怎么样,和想象中系统奔溃,地球毁灭的场景不一样,想反系统正常运行中
 * 参数xTaskToResume 要进入准备态的任务的任务句柄
 void vAFunction( void )
 {
 	TaskHandle_t xHandle;
	 // 创建一个任务,存储句柄
	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
	 // ...
	 // 使用句柄去挂起任务
	 vTaskSuspend( xHandle );
	 // ...
	 //这个被挂起的任务将不会再运行,直到另外一个调用vTaskResume(xHandle)
	 //...
	 //自行恢复暂停的任务
	 vTaskResume( xHandle );
	 // 这个任务将会再一次得到系统处理
	 // 在系统的优先级里将会一致
 }
 //函数声明
void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION;

3.xTaskResumeFromISR()
这个是从一个中断服务函数(ISR)中恢复暂停的任务,我们来看一下函数的定义,这个函数有一个返回值,pdTRUE或者pdFALSE,如果是TRUE就意味着唤醒的任务的优先级高于当前任务的优先级,此时的中断服务函数就会被打断。

/**
 * 要使得这个函数有效在FreeRTOSConfig.h中INCLUDE_xTaskResumeFromISR 必须定位为1
 * xTaskResumeFromISR()这个函数可以在ISR中调用.
 * 一个任务被挂起通过xTaskSuspend() 函数后,通过xTaskResumeFromISR ()函数能够再次的运行。
*不应使用xtaskresumefromisr()将任务与如果中断可能在运行,此时任务被挂起会导致错过中断。使用同步机制的信号量可以避免这种可能性。
 * @param xTaskToResume 需要进入就绪态的任务句柄
 * @return pdTRUE 任务的结果应该是一个可以切换的上下文
 * otherwise pdFALSE. ISR使用它来确定ISR之后是否需要上下文切换。
 */
 函数声明
BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION;

测试代码

第一步初始化按键,中断服务函数,LED等:

	uart_init(115200);    
	LED_Init();		  
	KEY_Init();
	EXTIX_Init();	

第二步声明定义并创建任务:


//任务优先级
#define KEY0_TASK_PRIO		2
//堆栈大小
#define KEY0_STK_SIZE 		50  
//句柄 handler
TaskHandle_t KEY0Task_Handler;
//函数
void key0_task(void *pvParameters);

//优先级
#define KEY1_TASK_PRIO		3
//大小
#define KEY1_STK_SIZE 		50  
//句柄
TaskHandle_t KEY1Task_Handler;
//函数
void key1_task(void *pvParameters);

//优先级
#define FLOAT_TASK_PRIO		4
//?堆栈大小
#define FLOAT_STK_SIZE 		128
//处理句柄
TaskHandle_t FLOATTask_Handler;
//函数
void float_task(void *pvParameters);

 //KEY任务
    xTaskCreate((TaskFunction_t )key0_task,     	
                (const char*    )"key0_task",   	
                (uint16_t       )KEY0_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )KEY0_TASK_PRIO,	
                (TaskHandle_t*  )&KEY0Task_Handler);   
    //KEY1任务
    xTaskCreate((TaskFunction_t )key1_task,     
                (const char*    )"key1_task",   
                (uint16_t       )KEY1_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )KEY1_TASK_PRIO,
                (TaskHandle_t*  )&KEY1Task_Handler);   
                

第三步编写服务函数:


//KEY0任务函数
void key0_task(void *pvParameters)
{
		u8 key;
		u16 num = 0;
    while(1)
    {
			key = KEY_Scan(0);	//扫描按键
			switch(key){
				case KEY1_PRES:
					vTaskSuspend(KEY1Task_Handler);
					printf("suspend the task2");
					break;
				case KEY2_PRES:
					vTaskResume(KEY1Task_Handler);
					printf("resume the task1");
					break;
			}
			vTaskDelay(10);
			num++;
			if(num>100){
				printf("TASK1\n");
				num = 0;
			}
    }
}   

//KEY1任务函数
void key1_task(void *pvParameters)
{

    while(1)
    {
			printf("TASK2\n");
			vTaskDelay(1000);
		}
}

第四步开启任务调度:

	vTaskStartScheduler();          //开启任务调度

总结

对于任务的挂起与恢复这个不算难点,就三个函数,其中值得注意的是第三个函数xTaskResumeFromISR(),从中断中唤起任务,是从中断中唤醒的哦,其存在的一个问题就是,既然是从中断中唤醒任务,任务的优先级就是一个问题,如果任务的优先级比中断函数的要低倒是没多大是事情,唤醒你之后我继续干我自己的事情去呗,但是一旦唤醒的这个任务比自己要牛逼,这个时候自己就不得不让出地方,让这个任务运行,尴尬的就在这里,中断服务被硬生生的打断了,后续的动作无法执行了,RTOS给出了解决方案,就是切换上下文,具体是什么意思,怎么做还不清楚,我们继续往后学习~

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值