基于STM32结合CubeMX学习Free-RT-OS的源码之任务调度

本文深入探讨了FreeRTOS的任务调度机制,包括抢占式调度、任务的三种状态(就绪、阻塞、挂起)、任务优先级管理以及调度触发条件。在抢占式FreeRTOS中,高优先级任务能够中断低优先级任务执行。调度主要发生在tick中断和任务主动yield时,中断回调中可以唤醒任务。此外,还介绍了非抢占模式下的行为及tick中断回调函数xTaskIncrementTick的角色。
摘要由CSDN通过智能技术生成

目录

 任务调度

任务的三种状态

在抢占式的FREE RT OS中,调度器如何选择它需要执行的任务?

什么时候会产生任务的调度?

什么时候高优先级的任务进行抢占?

不抢占,不礼让的Free RT OS会发生什么?

xTaskIncreamentTick(void)  tick中断的回调函数。

常用的在硬件嵌套中断的回调函数中唤醒任务。


 任务调度

目前实时操作系统(RTOS)多数为抢占式的系统。

#define configUSE_PREEMPTION                     1

        Free RT OS使用抢占式的任务调度,高优先级的任务抢占低优先级的任务执行。

         Free rt os 会根据创建任务的优先级建立多个优先级就绪链表。再创建两个个阻塞链表,一个挂起链表。

就绪链表数组。

 阻塞链表

PRIVILEGED_DATA static List_t xDelayedTaskList1 = {0};              //延时的任务

PRIVILEGED_DATA static List_t xDelayedTaskList2 = {0};     用于超出当前tick计数的延迟。

挂起链表

 

任务的三种状态

  •         就绪:等待调度就能得到执行。
  •         阻塞:等待某个条件,常见的有系统延时等待滴答数。
  •         挂起:必须要手动进行唤醒。

         

        默认是0-31个优先级,优先级数字越大则优先级等级越高(这与中断嵌套的优先级数字越大则优先级越小)相反。

          创建任务后,该任务会根据优先级放在不同的就就绪链表中。

         任务可以主动阻塞。在阻塞后,该任务的会从就绪列表中移除并放入阻塞列表中,比如常见的阻塞API函数 OS_Delay(),它会等待tick中断唤醒。唤醒后再次加入它所在优先级的链表中。

在抢占式的FREE RT OS中,调度器如何选择它需要执行的任务?

从高优先级的任务链表中向链表的尾部遍历,若该高优先级链表没有就绪状态的任务,则向下,向低优先级的链表遍历。

 ---------------------------------------->  高优先级链表(同一优先级的任务)先向尾部遍历。

|    (再向下遍历)                                             

|

|

|

|

|

v

在同等优先级的情况下,若该任务的优先级大于0则后创建的任务会先执行。

创建任务的顺序   :任务1->任务2->任务3

执行顺序       :任务3->任务1->任务2

若该优先级的任务和空闲任务IDLE的优先级相同(也就是为0),则按创建任务的顺序执行。

(  创建任务的顺序和执行任务的顺序相同)         空闲任务(IDLE空闲任务会主动礼让给其他任务)->任务1->任务2->任务3  。(每个任务执行完毕则又插到链表尾部如此往复)。

 见源码

什么时候会产生任务的调度?

  • tick中断(这个在free rt os中默认是以systick为滴答时基)。(下文记录这个tick中断回调函数)
  • 主动调用taskYIELD()进行任务切换。
  • 硬件中断,这个有很多种,比如在串口中断回调函数中,或者是其他的中断回调函数中唤醒了某个高线程,则在中断结束后立刻发生调度,无需等待tick中断的调度。 

    

什么时候高优先级的任务进行抢占?

  • 高优先级的任务为就绪状态的情况下,  tick中断产生调度任务进行切换(当前任务压入自己的任务栈,PSP指针指向新任务的函数入口)PSP是进程堆栈指针。(这也是绝大多数情况)
  • 硬件中断产生唤醒高优先级的任务。(在 RTOS里最低优先级的硬件中断也高于最高优先级的任务,硬件中断唤醒了某个高优先级的任务,则离开进行抢占)

不抢占,不礼让的Free RT OS会发生什么?

如果通过宏配置不抢占也不礼让,无论是否是同优先级,那么永远只有当前任务能一直执行。

 

xTaskIncreamentTick(void)  tick中断的回调函数。

/* Called by the portable layer each time a tick interrupt occurs.
    Increments the tick then checks to see if the new tick value will cause any
    tasks to be unblocked. */

翻译: 

每次tick中断发生时由移植层调用。增加tick值,然后检查新的tick值是否会引起任何变化要解除阻塞的任务。

在xTaskIncreamentTick(void)中

 只有配置了可抢占才会发生任务的调度。

在所有任务的优先级相同时,只有配置了可抢占,且配置了使用同优先级下采用时间片轮转的方法,才会使各个任务交替轮流执行一段时间。

 

常用的在硬件嵌套中断的回调函数中唤醒任务。

比如释放一个信号量

static portBASE_TYPE xHigherPriorityTaskWoken;  //发送信号量后切换任务的标记

在中断嵌套中调用 

 xSemaphoreGiveFromISR(myBinarySem01Handle,&xHigherPriorityTaskWoken);   
 portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

通过查看xHigherPriorityTaskWoken的值来判断是否立刻进行任务切换。(PdTRUE立刻切换,否则不切换)

如果最后不调用   portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); 则会在下一次调度时被切换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值