1. 任务状态介绍
FreeRTOS中的任务状态,可以简单的分为运行态(running)和非运行态(not running)。
但是对于非运行态我们还可以继续细分:
- 阻塞状态(Blocked)
- 暂停(挂起)状态(Suspended)
- 就绪状态(Ready)
2. 阻塞状态
上一篇介绍FreeRTOS优先级的博客文章中,所展示的示例代码中,创建的任务是永远都可以执行的,他们一直在不停地执行着自己的任务,而没有去等待其他的任何事件。
但是在实际的产品开发中,我们是不会让一个任务一直在运行的,而是使用“事件驱动”的方法让它运行。就是说任务要等待某个事件发生后它才能运行,这个等待某个事件的过程中就是处于阻塞状态,处于阻塞状态的任务是不会消耗CPU资源的。
在阻塞状态中,任务可以等待两种类型的事件:
- 时间相关的事件。
- 可以是等待一段时间,比如等3秒钟。使用vTaskDelay函数实现,等待的时间到了任务就会变为就绪态
- 也可以是等到某个绝对的时间点。使用vTaskDelayUntil函数实现,等到了某个时间点任务就会进入就绪态
- 同步事件,由其他任务或者中断产生,比如任务A给任务B发送数据,或者任务A等待用户按下按键。同步事件的来源很多,如下:
- 队列(queue)
- 二进制信号量(binary semaphores)
- 互斥量(mutexes)
- 递归互斥量、递归锁(recursive muxtexes)
- 事件组(event groups)
- 任务通知(task notifications)
3.暂停(挂起)状态
FreeRTOS中的任务也可以进入暂停状态,唯一的方法是通过vTaskSuspend函数。函数原型如下:
void vTaskSuspend( TaskHandle_t xTaskToSuspend );
参数xTaskToSuspend表示要暂停的任务,如果为NULL,表示暂停自己。
任务进入暂停态后,想要退出暂停状态,那只能由别的任务来操作:
- 其他任务调用vTaskResume
- 中断程序调用xTaskResumeFromISR
其他任务或中断调用上面这两个函数,才能使得进入暂停态的任务退出暂停状态。
但是在实际开发中,暂停状态很少用。
4. 就绪状态
就绪状态比较简单,就是这个任务既没有阻塞也没有,也没有挂起,那么这个任务就是处于就绪状态的。处于就绪状态的任务是随时都可以被运行的,只是当前还没有运行。
一般任务创建后,就是处于就绪状态的。
5. 状态转换图
如下图,完整的展示了一个任务的各种状态转换。