任务状态
freertos中的任务分为四个状态:就绪状态(ready)、运行状态(running)、阻塞状态(blocked)、暂停状态(suspended)
完整的任务状态转换图:
在使用vTaskDelay函数后任务就会转换为阻塞态,阻塞态下需要等待某个时间或某个事件才可以进入准备态随时被调用。
任务在除了暂停状态以外的任何状态都可以通过调用vTaskSuspend函数使得任务进入暂停状态,任务在运行中自行调用,非运行态则可以通过别的运行中的任务调用来令其进入暂停态。在暂停状态下可以调用vTaskResume函数恢复
任务管理与调度
关于优先级:
A.高优先级的任务未运行结束低优先级任务无法运行
B.一旦高优先级的任务就绪就立刻运行
C.同优先级的任务轮流运行
在代码中通过链表的方式进行任务管理,在代码宏定义中:
pxReadyTaskLists数组中存放56个链表,而本程序中的最高优先级为56,而这其中每一个链表放置的就是同优先级处于就绪态或运行态的任务TCB结构体
在创建任务的同时还会创建一个pxCurrentTCB指针指向最高优先级的任务,假设有ABC三个同优先级任务按顺序创建,A创建时指向A,B创建时指向B,C创建时指向C,在开启任务调度器后就会从指针处开始运行,因此同优先级最后一个创建的任务最先运行
在FREERTOS中定义一个1000hz的时钟频率作为tick中断依据,在运行1ms后产生tick中断,中断中设置cnt++作为时钟基准并发起调度,调度的过程就是从上到下遍历pxReadyTaskLists数组中的56个链表,找到第一个非空的链表,使得pxCurrentTCB指针指向下一个任务,每次tick中断就会触发一次调度
高优先级任务可以无需tick调度直接在低优先级任务运行过程中进行抢占,例如,有AB两个任务,B任务优先级高于A任务,那么如果A任务在运行过程中B任务被置于就绪态则B任务会直接抢占开始运行,无需等待tick中断调度,然后在高优先级任务运行中使用DELAY函数则会将其从pxReadyTaskLists中的链表中取出放入xDelayedTaskList1进入阻塞态,并寻找立即下一个运行的任务,在低优先级的任务被抢占时会记录一个index指针指向被抢占的任务,此时就调用此任务。
存放在xDelayedTaskList1链表中的任务的TCB结构体中都会保存有需要等待的时间,而在tick中断时还会判断一下xDelayedTaskList1中的任务是否可恢复,如果可恢复则将其放入pxReadyTaskLists中的链表里,然后再发起调度。
在对任务调用vTaskSuspend函数后将其放入xSuspendedTaskList链表中,在暂停态下无法通过tick中断的判断重新进入就绪态,只能通过调用vTaskResume函数使其回归就绪态
调度总结:
调度本质上就是链表管理,任务在不同状态下存入不同链表
rtos中设置tick中断,而tick中断时进行的操作为:
a.设置cnt++
b.判断一下xDelayedTaskList1中的任务是否可恢复,如果可恢复则将其放入 pxReadyTaskLists中的链表里
c.发起调度