FreeRTOS学习(8)-pendsv和systick优先级分析以及任务切换场景

前文提要
FreeRTOS学习(1)—为什么使用RTOS
FreeRTOS学习(2)-链表和节点之结构体分析
FreeRTOS学习(3)-链表和节点程序分析
FreeRTOS学习(4)-什么是任务?
FreeRTOS学习(5)-任务之静态创建函数解析
FreeRTOS学习(6)-任务之静态创建函数解析2(重点)
FreeRTOS学习(7)-任务切换理论分析(重点)

我们对pendsv和systick使用场景做一下具体分析,看看不同优先级带来的影响,以及为什么我们要选择将这两个优先级都设置最低

假设这个系统有两个任务,任务1和任务2,并且通过 SysTick 异常启动上下文切换。
在这里插入图片描述

1、假设SysTick优先级高于外部中断

在这里插入图片描述

    若在产生 SysTick 异常时正在响应一个中断,则SysTick 异常会抢占其IRQ(中断服务程序)。在这种情况下,OS(操作系统) 是不能执行上下文切换的,否则将使中断请求被延迟,而且在真实系统中延迟时间还往往不可预知——任何有一丁点实时要求的系统都决不能容忍这种事。因此,在 CM3 中被严禁——如果OS在某中断活跃时尝试切入线程模式,将触犯用法 fault 异常。
    为了解决此问题,早期的 OS 大多会检测当前是否有中断在活跃中,只有在无任何中断需要响应时,才执行上下文切换(切换期间无法响应中断)。然而,这种方法的弊端在于,它可以把任务切换动作拖延很久(因为如果抢占了 IRQ,则本次 SysTick 在执行后不可以上下文切换,只能等待下一次 SysTick 异常),尤其是当某中断源的频率和 SysTick 异常的频率比较接近时,会发生“共振”,使上下文切换迟迟不能进行。

2、将SysTick的优先级设置为最低,然后在SysTick中进行上下文切换

在这里插入图片描述

    当OS的Systick中断级别低于外部中断时,确实不会触发Fault。但是这带来了另外的问题:
    一般OS在调度任务时,会关闭中断,也就是进入临界区,而OS任务调度是要耗时的,这就会出现一种情况:在任务调度期间,如果新的外部IRQ发生,CPU将不能够快速响应处理。这也带来了实时性问题。

3、将SysTick的优先级调低,会影响外部中断IRQ的处理速度,那有没有进一步优化的方法呢?

答案就是PendSV。 因为PendSV有 【缓期执行】 的特点,所以可以将上图中的OS拆分,分成2段:

(1)滴答定时器中断,仅进行任务调度判断,如果需要任务切换,则设置 PendSV 中断挂起。

(2)触发PendSV,PendSV并不会立即执行,因为PendSV的优先级最低,如果此时正好有IRQ请求,那么先响应IRQ,最后等到所有优先级高于PendSV的IRQ都执行完毕,再执行PendSV,进行任务调度。

在这里插入图片描述

细心地读者相信也发现了问题:
SysTick的优先级最低,那如果外部IRQ比较频繁,会导致SysTick经常被挂起,然后滞后,导致Systick的节拍延长,从而导致任务的执行调度就不够快

(3)补充:图上的两种调动方式-SVC调动pendsv和systick触发pendsv区别

· SVC调动PendSV用于任务主动请求上下文切换,由任务执行的SVC指令触发。
· systick直接触发PendSV用于操作系统定期调度,由定时器中断机制触发。

4、将SysTick的优先级设置最高,将PendSV的优先级设置为低,这样是不是既能保证任务切换的频率和外部中断的响应?

在这里插入图片描述

保证任务切换的频率同时也带来的问题:因为SysTick的优先级最高,而且又是周期性的触发,会导致经常抢占外部IRQ,这就会导致外部IRQ响应变慢。所以没有完美的方案。一般为了保持外部中断,SysTick也会设置为最低优先级

5、在这里我对上一篇博客补充下任务切换的流程:

①SVC调动PendSV

1)触发方式:

SVC中断是通过软件触发的,可以由应用程序代码中执行SVC指令来触发。例如,任务A执行某个系统调用,触发了SVC中断。

2)使用场景:

SVC中断常用于请求特权操作,如系统调用、内核服务调用等。当任务需要进行某些需要特权级别的操作时,会触发SVC中断。
SVC中断触发PendSV的场景通常是任务主动请求上下文切换,例如任务完成了当前工作,主动放弃CPU。

3)流程:

任务A触发SVC中断。
SVC中断服务程序决定需要进行上下文切换,设置PendSV中断挂起。
PendSV中断被挂起,等待当前中断处理完成后执行。
PendSV中断开始执行,处理上下文切换,将任务A切换到任务B。

②操作系统(OS)直接触发PendSV

1)触发方式:

操作系统可以直接通过编程设置PendSV中断挂起标志来触发PendSV中断,而不需要经过SVC中断。

2)使用场景:

操作系统通常使用定时器中断(如SysTick)来定期触发上下文切换。例如,任务B执行过程中,SysTick中断发生,表示任务的时间片到期,需要进行任务调度。操作系统在处理SysTick中断时,可以决定挂起PendSV中断,以进行上下文切换。

3)流程:

操作系统通过定时器中断(如SysTick)检测到任务B的时间片到期。
在SysTick中断服务程序中,操作系统决定挂起PendSV中断。
PendSV中断被挂起,等待当前中断处理完成后执行。
PendSV中断开始执行,处理上下文切换,将任务B切换到另一个任务(如任务A)。

③关键区别

1)触发方式:

SVC调动PendSV:通过任务代码中的SVC指令触发,通常用于任务主动请求上下文切换。
OS直接触发PendSV:通过操作系统定时器中断(如SysTick)或其他机制触发,通常用于定期调度任务。

2)触发时机:

SVC调动PendSV:在任务主动请求时触发,例如任务完成工作或请求系统服务。
OS直接触发PendSV:在操作系统检测到需要调度时触发,例如时间片到期或其他调度条件满足时。

下一章我们对任务切换代码做具体分析。
个人学习文档,有问题欢迎大家评论交流,如果感到有用的话点个赞吧。ヽ(。◕‿◕。)ノ゚

  • 25
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值