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

背景
大多数嵌入式RTOS在-M3/M4上的移植都需要,比如uCOS、RT-、等,本文就对的功能作用,以及为什么需要进行详细的分析 。
是什么?
我们先引用《-M3权威指南》对的介绍:
(可悬起的系统调用),它是一种CPU系统级别的异常,它可以像普通外设中断一样被悬起,而不会像SVC服务那样,因为没有及时响应处理,而触发Fault 。
个人理解的英文全称应该是:PendCall,简称.
所以的最大特点就是,它是系统级别的异常,但它又天生支持【缓期执行】 。
使用场景
由于的特点就是支持【缓期执行】,所以嵌入式OS可以利用它这个特点,进行任务调度过程的上下文切换 。而为什么要使用【缓期执行】的特点来进行上下文切换呢?简单的说就是任何嵌入式RTOS,都需要尽量不打断外设中断 。
我们来举例说明,假如一个系统中有2个就绪的任务,上下文切换被切换的场合有:
【2RTOS系列文章:PendSV功能,为什么需要PendSV】执行了一个系统调用SVC 。系统滴答定时器中断,触发了任务的调度 。没有外部中断,OS直接切换任务
假如我们在中断服务程序中,启动上下文切换,流程图如下:
上图中,似乎一切都正常,任务调度很流畅,但现实总是很骨感的,不可能这么简单,假如在产生异常时,CPU正在响应另一个中断ISR1,而的优先级又大于ISR1,在这种情况下,就会抢占ISR1,获取CPU使用权,但是在中不能进行上下文切换,因为这将导致中断ISR1被延迟,这在实时要求的系统中是不能容忍的,但是这个说辞只是为了方便理解,更重要的是:
在-M3中,如果OS在某个中断活跃时,抢占了该中断,而且又发生了任务调度,并执行了任务,切换到了线程运行模式,将直接触发Fault异常 。
优先级高于外部中断,OS抢占IRQ进行任务调度触发Fault
如下图所示:
为了解决这个问题,早起的OS大多会检测当前是否有中断在活跃中,只有在无任何中断需要响应时,才进行上下文切换,切换期间无法响应中断 。
这个时候,可能会有人想,既然有上面的原因限制,我能不能将的优先级设置为最低,然后在中进行上下文切换,然后任务调度呢? 答案是:可以 。这一点在-M3权威指南中没有解释,反而影响了很多读者对于的理解 。按照上面的思路,我们分析一下整体流程:
中断优先级低与IRQ,任务调度流程
在上图中我们可以看到,当OS的中断级别低于外部中断时,确实不会触发Fault,但是这带来了一个问题:
一般OS在调度任务时,会关闭中断,也就是进入临界区,而OS任务调度是要耗时的,这就会出现一种情况:
在任务调度期间,如果新的外部IRQ发生,CPU将不能够快速响应处理 。
将的优先级调低,避免了触发Fault的问题,但是会影响外部中断IRQ的处理速度,那有没有进一步优化的方法呢?答案就是PenSV 。因为有【缓期执行】的特点,所以可以将上图中的OS拆分,分成2段:
滴答定时器中断,制作业务调度前的判断工作,不做任务切换 。触发,并不会立即执行,因为的优先级最低,如果此时正好有IRQ请求,那么先响应IRQ,最后等到所有优先级高于的IRQ都执行完毕,再执行,进行任务调度 。、优先级低,只在中进行上线文切换,任务调度
上述的流程就是目前常见的嵌入式RTOS的任务调度流程,uC/OS和都会将和的优先级设置为最低 。
到这里,可能会有人又有疑问,这样做是不是也有缺点:
的优先级最低,那如果外部IRQ比较频繁,是不是会导致经常被挂起,然后滞后,导致的节拍延长,进而导致不准啊?因为1的原因,导致任务的执行调度就不够快了?