任务管理
系统中任务运行调度方式
每个任务都是在独立的堆栈环境运行,运行的任务越多需要的堆栈空间越多。
任务之间的切换是基于抢占优先级的,高优先级抢占低优先级
任务切换的寻找方式
- 基于链表,从高往低查,任务创建时已经完成排序
- 计算前导零指令
CLZ
,直接读出优先级任务(stm32
使用这种方式)
相同优先级任务则采用时间片轮转,无更高优先级任务情况下。
任务状态
创建的任务一般有四种状态
就绪态:新创建的任务处于该状态,等待调度器调度
运行态:正在运行的任务,运行的是最高优先级的就绪态任务
阻塞态:不在就绪态列表中,处于中断或等待
挂起态:
- 挂起态任务调度器不可见
- 使用
vTaskSuspend()
进入挂起态 - 使用
vTaskResume()
或vTaskResumeFromISR()
从挂起态恢复 - 和阻塞态的区别在于:挂起态用于长时间不处理的任务;阻塞态的任务系统需要判断是否
超时
常见任务操作函数
vTaskSuspend()
任务挂起:等效于该任务被“冻结”或者“休眠”vTaskSuspendAll()
全任务挂起vTaskResume()
任务恢复:将被挂起的任务恢复vTaskResumeFromISR()
中断专用任务恢复- 无论使用几次
vTaskSuspend()
,只需要使用一次恢复函数即可恢复 - 需要配置
INCLUDE_vTaskResumeFromISR 1
的宏定义
- 无论使用几次
vTaskResumeAll()
全任务恢复vTaskDelete()
任务删除vTaskDelay()
任务延时,延时时间为Systick
vTaskDelayUntil()
任务绝对延时
设计一个任务管理
通过2个Button
控制一个LED
灯任务的挂起和恢复,需要注意的是:按键检测最好设计成通用函数,保留GPIO
和Pin
让每个按键的检测尽量避免耦合
1 | //按下状态,0为低有效道通,此处根据接线而定 |
建立一个按键检测的任务,根据按键检测来判断是否导通,然后其中一个按键用于挂起任务,另一个按键用于恢复任务。
1 | static void KEY_Task(void *paramter) |