FreeRTOS_任务管理_任务优先级与状态_学习笔记

上一篇文章

3.4 优先级与tick

3.4.1 优先级

优先级的取值范围是 0 ~ configMAX_PRIORITIES - 1,越大优先级越高
FreeRTOS会确保最高优先级的任务马上执行,对于同级的轮流执行。

3.4.2 tick和延迟函数

FreeRTOS使用定时器产生固定间隔中断,叫tick。假设t1、t2、t3三个时刻发生中断,则称两次中断之间的实践为time slice(时间片)。
常用的延时函数有两种,mdelay(time)和vTaskDelay(tick_period),前者用延时时间作为输入,后者用几个tick作为输入,也可以用vTaskDelay(pdMS_TO_TICKS(time))实现输入延时时间。

  1. mdelay(t)通过CPU执行无意义指令空耗时间,会阻塞其他任务执行
  2. vTaskDelay(n)是FreeRTOS提供的,调用后任务会立即放弃CPU控制权,进入阻塞状态,延时结束后会被任务调度器唤醒并变得可运行。
  3. 但是vTaskDelay(n)所延迟的时间并不是完全精准的,可以用vTaskDelayUntil(&Pre, n)等待到指定的绝对时刻任务才进入就绪状态。&Pre是上一次被唤醒的时间,n是要等待的tick数。常用做法为:
pretime = xTaskGetTickCount();
while(1)
{
	func();
	vTaskDelayUntil(&pretime, 15);
}

为什么xTaskGetTickCount写在while外面也能起作用呢,因为调用vTaskDelayUntil(&pretime, 15)时,pretime会自动更新上一次的唤醒时间

3.5 任务状态

3.5.1 阻塞状态(Block)

在日常生活的例子中,母亲在电脑前跟同事沟通时,如果同事一直没回复,那么母亲的
工作就被卡住了、被堵住了、处于阻塞状态(Blocked)。重点在于:母亲在等待

在实际产品中,我们不会让一个任务一直运行,而是使用"事件驱动"的方法让它运行:
任务要等待某个事件,事件发生后它才能运行;在等待事件过程中,它不消耗 CPU 资源,这个任务就处于阻塞状态。
阻塞状态下的任务可以等待两种类型的事件:

  1. 时间:固定的时长或特定的时刻
  2. 同步事件:别的事件传来的信号

3.5.2 暂停状态(Suspended)

可以通过任务句柄暂停任务

void vTaskSuspend( TaskHandle_t xTaskToSuspend );
// 输入别的任务句柄可以暂停别人
//输入NULL可以暂停自己

退出暂停状态只能让别人干

vTaskResume( TaskHandle_t xTaskToSuspend );

3.5.3 就绪状态(Ready)

可以跑了就等一声令下
在这里插入图片描述

3.6 空闲任务

空闲任务的作用:给删除的任务释放内存。
此外,
调度器必须能找到一个可以运行的任务,当使用vTaskStartScheduler()函数来创建、启动调度器时,这个函数内部会创建空闲任务。(像默认构造函数?)
空闲任务优先级为0,永远不会阻塞。
添加一个空闲任务的钩子函数(空闲函数的循环每执行一次,就调用一次钩子函数)可以达到以下目的:

  1. 执行低优先级,后台的,需要连续执行的函数
  2. 测量系统空闲时间
  3. 进入省电模式

示例:让LED闪烁任务挂起和继续

任务描述:初始时,遥控器按play键创建任务,以后再按play键则在挂起和继续任务中切换,按power键删除任务:

osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
  .name = "defaultTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
void StartDefaultTask(void *argument);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
}
void StartDefaultTask(void *argument)
{
	ColorLED_Set(0);
	LCD_Init();
    LCD_Clear();
    IRReceiver_Init();
	TaskHandle_t xColorLedHandle=NULL;
	LCD_PrintString(0,0,"waiting control");
    int running;

  for(;;)
  { 
		uint8_t dev,data;
		//读取红外遥控器
		if (!IRReceiver_Read(&dev, &data))
        {
            
			if(data == 0xa8) //按下play
			{
				if(xColorLedHandle == NULL){

					LCD_ClearLine(0, 0);
					LCD_PrintString(0, 0, "running Task");
                    vTaskDelay(2);
					xTaskCreate(ColorLED_Test, "cled", 128, NULL, osPriorityNormal, &xColorLedHandle);
                    running = 1;                
				}
                else{
                    if(running) // 如果正在运行,则让其挂起
                    {
                        LCD_ClearLine(0, 0);
                        LCD_PrintString(0, 0, "Task Suspended");
                        vTaskSuspend(xColorLedHandle);
                        ColorLED_Set(0);
                        running = 0;
                    }
                    else{ // 如果没在运行,则让其继续
                        LCD_ClearLine(0, 0);
                        LCD_PrintString(0, 0, "Task Resume");
                        vTaskResume(xColorLedHandle);
                        running = 1;
                    }
                }
			}
			else if(data == 0xa2) //按下power
			{
				if(xColorLedHandle != NULL){
					LCD_ClearLine(0, 0);
					LCD_PrintString(0, 0, "Task deleted");
					vTaskDelete(xColorLedHandle);
					ColorLED_Set(0);
					xColorLedHandle = NULL;
				}
			}
		}
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值