FreeRTOS笔记(五)任务状态

FreeRTOS笔记(五)任务状态

文章目录

01 - 任务的状态02 - tick时钟和调度器03 - 任务状态测试04 - 总结

上一文链接:FreeRTOS笔记(四)初识任务

01 - 任务的状态

任务被创建后,它可能正在运行,可能暂停运行,任务有状态之分是由于调度器的存在,调度器需要决定哪些任务可以去运行,于是在FreeRTOS中任务具有4种状态,分别是就绪态、运行态、阻塞态和挂起态,它们之间的转化关系如下:

4个状态的含义如下: 就绪态:已经可以运行,等待调度器的切入 运行态:正在占用CPU运行 阻塞态:等待某个事件的到来,定时或者同步 挂起态:退出调度系统,调度器不可见,只能使用vTaskSuspend()挂起和vTaskResume()唤醒后进入就绪态

虽然官方文档只描述4个状态,但小白认为应该是5种状态,第5种是僵尸态,指在任务被删除后,其TCB控制块扔保留一段时间,等待内核检查和回收资源,在内核没有处理之前,任务其实并没有被完全删除,但是再也不能被调度器调度,这称为僵尸态,在Linux下的进程是存在僵尸态的,而从FreeRTOS的API中就可以看出,FreeRTOS的任务也存在僵尸态。

要使用eTaskGetState()函数,就要在FreeRTOSConfig.h中配置INCLUDE_eTaskGetState宏为1

#define INCLUDE_eTaskGetState 1

02 - tick时钟和调度器

调度器本身也是一段程序,任务需要调度器安排执行顺序,那么调度器本身就需要被执行,这个执行由一个称为心跳时钟(tick)的中断触发,tick时钟的频率需要在FreeRTOSConfig.h文件中配置,单位是HZ,比如本例程中配置configTICK_RATE_HZ为1000,那么中断频时间是1000/1000 = 1ms,每隔1ms,FreeRTOS就会进入tick中断,触发调度器进行工作。

#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )

调度器被触发后,会根据事先设定好的调度算法进行工作,FreeRTOS使用的调度算法有优先级抢占式调度和协作式调度: 优先级抢占式调度算法,给每一个任务分配一个优先级,调度器每次都选择优先级最高的任务执行,如果优先级相同,就采用时间片轮流执行,每个任务执行一个时间片后切出,再切入下一个任务。 协作式调度算法,只可能在运行态任务进入阻塞态或是运行态任务显式调用taskYIELD()主动让出CPU时,才会进行上下文切换。 调度算法的配置也是在FreeRTOSConfig.h中进行。

#define configUSE_PREEMPTION 1 //0-协作调度,1-抢占式调度

03 - 任务状态测试

下面用优先级抢占式调度算法来测试一下任务的各种状态,其中挂起和唤醒的API如下:

项目ValuevTaskSuspend()挂起一个任务vTaskResume()唤醒一个任务

测试内容:一共有5个任务,分别是start和ABCD,start优先级最高,其余优先级递增,任务的工作如下: start:负责创建另外4个任务,输出所有任务的状态,然后删除自己 A:输出所有任务的状态,打开LED B:输出所有任务的状态,关闭LED,使用vTaskDelay()阻塞自己 C:输出所有任务的状态使用vTaskDelay()阻塞自己,然后间隔使用vTaskResume唤醒D D:输出所有任务的状态,使用vTaskSuspend()挂起自己

/* start 任务 */

void start_task(void *pParam)

{

//进入临界区

taskENTER_CRITICAL();

xTaskCreate( (TaskFunction_t)a_task,

(const char*)"a_task",

(uint16_t)A_STACK_SIZE,

(void*)NULL,

(UBaseType_t)A_TASK_PRIO,

(TaskHandle_t*)&aTask_Handler

);

xTaskCreate( (TaskFunction_t)b_task,

(const char*)"b_task",

(uint16_t)B_STACK_SIZE,

(void*)NULL,

(UBaseType_t)B_TASK_PRIO,

(TaskHandle_t*)&bTask_Handler

);

xTaskCreate( (TaskFunction_t)c_task,

(const char*)"c_task",

(uint16_t)C_STACK_SIZE,

(void*)NULL,

(UBaseType_t)C_TASK_PRIO,

(TaskHandle_t*)&cTask_Handler

);

xTaskCreate( (TaskFunction_t)d_task,

(const char*)"d_task",

(uint16_t)D_STACK_SIZE,

(void*)NULL,

(UBaseType_t)D_TASK_PRIO,

(TaskHandle_t*)&dTask_Handler

);

print_state("start",eTaskGetState(StartTask_Handler));

print_state("A",eTaskGetState(aTask_Handler));

print_state("B",eTaskGetState(bTask_Handler));

print_state("C",eTaskGetState(cTask_Handler));

print_state("D",eTaskGetState(dTask_Handler));

printf("\r\n");

//退出临界区

taskEXIT_CRITICAL();

//删除自己

vTaskDelete(NULL);

}

/* A 任务 */

void a_task(void *pParam)

{

for(;;)

{

print_all_state("A");

//打开LED

GPIO_ResetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);

}

}

/* B 任务 */

void b_task(void *pParam)

{

for(;;)

{

//输出

print_all_state("B");

//关闭LED

GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);

//阻塞自己

vTaskDelay(10);

}

}

/* C 任务 */

void c_task(void *pParam)

{

for(;;)

{

//输出

print_all_state("C");

//阻塞自己

vTaskDelay(10);

//唤醒D

vTaskResume(dTask_Handler);

}

}

/* D 任务 */

void d_task(void *pParam)

{

for(;;)

{

//输出

print_all_state("D");

//挂起自己

vTaskSuspend(NULL);

}

}

其中print_all_state()和print_state()是为了方便输出状态,代码如下:

static void print_state(char *msg,eTaskState state)

{

printf("%s-",msg);

switch(state)

{

case eRunning: printf("run");break;

case eReady: printf("ready");break;

case eBlocked: printf("block");break;

case eSuspended:printf("suspend");break;

case eDeleted: printf("delete");break;

default: printf("5");break;

}

printf(" ");

}

static void print_all_state(char *msg)

{

taskENTER_CRITICAL();

printf("%s:",msg);

print_state("start",eTaskGetState(StartTask_Handler));

print_state("A",eTaskGetState(aTask_Handler));

print_state("B",eTaskGetState(bTask_Handler));

print_state("C",eTaskGetState(cTask_Handler));

print_state("D",eTaskGetState(dTask_Handler));

printf("\r\n");

taskEXIT_CRITICAL();

}

运行结果

因为延迟太短,看不到LED的闪烁,但是从串口可以看出,各个任务有序运行,每个状态都出现了,状态之间的转换几乎在一瞬间,运行时序图可以简述如下:

04 - 总结

任务有4种(5种)状态,分别为就绪态、运行态、阻塞态、挂起态(僵尸态)调度器程序在每个tick时钟中断里被执行FreeRTOS调度器有两种调度算法,抢占式和协作式

相关推荐