• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

RTOS系列文章2PendSV功能,为什么需要PendSV

武飞扬头像
猪哥-嵌入式
帮助1

背景

大多数嵌入式RTOS在Cortex-M3/M4上的移植都需要PendSV,比如uCOS、RT-Thread、FreeRTOS等,本文就对PendSV的功能作用,以及为什么需要PendSV进行详细的分析。

PendSV是什么?

我们先引用《Cortex-M3权威指南》对PendSV的介绍:

PendSV(可悬起的系统调用),它是一种CPU系统级别的异常,它可以像普通外设中断一样被悬起,而不会像SVC服务那样,因为没有及时响应处理,而触发Fault。

个人理解PendSV的英文全称应该是:Pend System Service Call,简称PendSV.
所以PendSV的最大特点就是,它是系统级别的异常,但它又天生支持【缓期执行】。

PendSV使用场景

由于PendSV的特点就是支持【缓期执行】,所以嵌入式OS可以利用它这个特点,进行任务调度过程的上下文切换。而为什么要使用【缓期执行】的特点来进行上下文切换呢?简单的说就是任何嵌入式RTOS,都需要尽量不打断外设中断。
我们来举例说明,假如一个系统中有2个就绪的任务,上下文切换被切换的场合有:

  1. 执行了一个系统调用SVC。
  2. 系统滴答定时器SYSTICK中断,触发了任务的调度。

没有外部中断,OS直接切换任务

假如我们在Systick中断服务程序中,启动上下文切换,流程图如下:
学新通

上图中,似乎一切都正常,任务调度很流畅,但现实总是很骨感的,不可能这么简单,假如在产生异常时,CPU正在响应另一个中断ISR1,而SysTick的优先级又大于ISR1,在这种情况下,SysTick就会抢占ISR1,获取CPU使用权,但是在SysTick中不能进行上下文切换,因为这将导致中断ISR1被延迟,这在实时要求的系统中是不能容忍的,但是这个说辞只是为了方便理解,更重要的是:

在Cortex-M3中,如果OS在某个中断活跃时,抢占了该中断,而且又发生了任务调度,并执行了任务,切换到了线程运行模式,将直接触发Fault异常。

SysTick优先级高于外部中断,OS抢占IRQ进行任务调度触发Fault

如下图所示:
学新通
为了解决这个问题,早起的OS大多会检测当前是否有中断在活跃中,只有在无任何中断需要响应时,才进行上下文切换,切换期间无法响应中断。
这个时候,可能会有人想,既然有上面的原因限制,我能不能将SysTick的优先级设置为最低,然后在SysTick中进行上下文切换,然后任务调度呢? 答案是:可以。这一点在Cortex-M3权威指南中没有解释,反而影响了很多读者对于PendSV的理解。按照上面的思路,我们分析一下整体流程:

Systick中断优先级低与IRQ,任务调度流程 学新通

在上图中我们可以看到,当OS的Systick中断级别低于外部中断时,确实不会触发Fault,但是这带来了一个问题:

一般OS在调度任务时,会关闭中断,也就是进入临界区,而OS任务调度是要耗时的,这就会出现一种情况:
在任务调度期间,如果新的外部IRQ发生,CPU将不能够快速响应处理。

将SysTick的优先级调低,避免了触发Fault的问题,但是会影响外部中断IRQ的处理速度,那有没有进一步优化的方法呢?答案就是PenSV。因为PendSV有【缓期执行】的特点,所以可以将上图中的OS拆分,分成2段:

  1. 滴答定时器中断,制作业务调度前的判断工作,不做任务切换。
  2. 触发PendSV,PendSV并不会立即执行,因为PendSV的优先级最低,如果此时正好有IRQ请求,那么先响应IRQ,最后等到所有优先级高于PendSV的IRQ都执行完毕,再执行PendSV,进行任务调度。

Systick、PendSV优先级低,只在PendSV中进行上线文切换,任务调度

学新通
上述的流程就是目前常见的嵌入式RTOS的任务调度流程,uC/OS和FreeRTOS都会将Systick和PendSV的优先级设置为最低。
到这里,可能会有人又有疑问,这样做是不是也有缺点:

  1. SysTick的优先级最低,那如果外部IRQ比较频繁,是不是会导致SysTick经常被挂起,然后滞后,导致Systick的节拍延长,进而导致不准啊?
  2. 因为1的原因,导致任务的执行调度就不够快了?

答案:确实存在这些问题,但是这些问题影响面已经很小了。我们能不能将SysTick的优先级设置成最高,将PendSV的优先级设置为低,就能完美的解决上述问题,我们不妨分析下这种情况:
学新通
这样似乎解决了问题,但是又带来了一个问题,因为SysTick的优先级最高,而且又是周期性的触发,会导致经常抢占外部IRQ,这就会导致外部IRQ响应变慢,这在一些对实时性要求高的,比如按键、断电中断等待,是不能接受的,你肯定不希望你的按键扫描体验卡顿。
所以,没有十全十美的解决方案,关键是要看我们更关注什么?对于CPU来说,嵌入式OS也是一个程序,跟普通的裸机程序是一样的,无非就是复杂一些,涉及到了手动切换堆栈、PC等高级操作而已,OS的优先级天生就没有外部中断的优先级高。

小结

  1. PendSV是可悬起系统中断,具有【缓期执行】特征。
  2. PendSV一般被嵌入式OS用于 任务调度的上下文切换。
  3. 使用PendSV时,一般会将PendSV的优先级设置为最低,让外部IRQ先执行,等到没有外部中断后,在执行上下文切换。
  4. 嵌入式实时操作系统的【实时】概念,并不仅仅指应用程序、任务的调度实时,而是指整个系统的实时性高,具备【可剥夺】特点,当有高优先级的中断、任务具备执行条件时,立刻中断当前正在运行的任务,去执行高优先级的IRQ和高优先级任务。
  5. 嵌入式OS一般会将SysTick的优先级也设置为最低,保证外部中断IRQ优先,详细的分析,我们下一篇文章讨论。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgcjhhf
系列文章
更多 icon
同类精品
更多 icon
继续加载