一、任务
1、中断服务函数
中断服务函数尽量精简,运行时间不允许过长
中断服务函数不允许被挂起,不允许调用任何会阻塞任务的API接口函数
2、普通任务
普通任务需要注意的是:高优先级任务必须在合适的时间,交出cpu的控制权(即阻塞该任务,使用vTaskDelay() 函数就是一种阻塞 ),否则低优先级任务将无法执行
3、空闲任务
因为FreeRTOS无论何时都要有任务在运行,所以当其他任务都被挂起时,就会执行空闲任务,这就是为什么需要空闲任务的原因。
空闲任务不允许被挂起,不允许删除,优先级最低。
4、任务执行时间
任务的执行时间一般是指两个方面,一是任务从开始到结束的时间,二是任务的周期。
在系统设计的时候这两个时间候我们都需要考虑,例如,对于事件 A 对应的服务任务Ta,系统要求的实时响应指标是 10ms,而 Ta 的最大运行时间是 1ms,那么 10ms 就是任务Ta 的周期了, 1ms 则是任务的运行时间,简单来说任务 Ta 在 10ms 内完成对事件 A 的响应即可。此时,系统中还存在着以 50ms 为周期的另一任务 Tb,它每次运行的最大时间长度是 100us。在这种情况下,即使把任务 Tb 的优先级抬到比 Ta 更高的位置,对系统的实时性指标也没什么影响,因为即使在 Ta 的运行过程中, Tb 抢占了 Ta 的资源,等到 Tb 执行完毕,消耗的时间也只不过是 100us,还是在事件 A 规定的响应时间内(10ms), Ta 能够安全完成对事件 A 的响应。但是假如系统中还存在任务 Tc,其运行时间为 20ms,假如将 Tc的优先级设置比 Ta 更高,那么在 Ta 运行的时候,突然间被 Tc 打断,等到 Tc 执行完毕,那 Ta 已经错过对事件 A(10ms)的响应了,这是不允许的。所以在我们设计的时候,必须考虑任务的时间,一般来说处理时间更短的任务优先级应设置更高一些。
二、任务管理
1、任务管理介绍 (野火FreeRTOS教程第16章)
FreeRTOS中,任务的执行一般有俩种方式:抢占式调度和时间片调度,可以通过更改 FreeRTOSConfig.h 文件中的 configUSE_PREEMPTION 与 configUSE_TIME_SLICING(一般将俩个宏都置1)
抢占式调度:高优先级的任务可以打断低优先级任务的执行,优先级高的任务优先执行。
例:优先级分别为 1、2、3、4的任务,则会先执行按照优先级从高到低的顺序执行
时间片调度:优先级相同的任务,每个任务都会依次执行一个时间片然后释放cpu资源执行下一个任务。
例:四个任务(A、B、C、D)优先级相同,则会任务A现执行一个时间片然后释放cpu资源,然后任务B执行一个时间片然后释放cpu资源.....(如此循环)
2、任务状态
分为 就绪、运行、阻塞、挂起 四种状态
就绪:即具有可执行能力的任务。处于就绪态的任务会存在于就序列表中。当任务被初始化完成后,该任务会被加入到就序列表中去。
运行:即正在运行的任务。
阻塞:即正在等待外部时序或外部中断的任务。包含:任务被挂起、 任务被延时、任务正在等待信号量、读写队列或者等待读写事件等。处于阻塞态的任务会从就绪列表中移除
挂起:处于挂起态的任务对调度器而言是不可见的, 让一个任务进入挂起状态的唯一办法就是调用 vTaskSuspend()函数;而把一个挂起状态的任务恢复的唯一途径就是调用 vTaskResume() 或 vTaskResumeFromISR()函数(前一个函数不可以在中断中调用,后一个函数是在中断中唤醒被挂起的任务)
我们可以这么理解挂起态与阻塞态的区别,当任务有较长的时间不允许运行的时候,我们可以挂起任务,这样子调度器就不会管这个任务的任何信息,直到我们调用恢复任务的 API 函数;而任务处于阻塞态的时候,系统还需要判断阻塞态的任务是否超时,是否可以解除阻塞。