Cortex-M3体系结构学习笔记-“异常“之SVC与PendSV

标签:
svcpendsvcm3结构异常 |
进栈指令PUSH,出栈指令POP
SVC作为操作系统函数门户示意图
SVC(系统服务调用,亦简称系统调用)和
PendSV(可悬起系统调用),它们多用于在操作系统之上的软件开发中。 SVC
用于产生系统函数的调用请求。例如,操作系统不让用户程序直接访问硬件,而是通过提供一些系统服务函数,用户程序使用 SVC
发出对系统服务函数的呼叫请求,以这种方法调用它们来间接访问硬件。因此,当用户程序想要控制特定的硬件时,它就会产生一个 SVC
异常,然后操作系统提供的 SVC 异常服务例程得到执行,它再调用相关的操作系统函数,后者完成用户程序请求的服务。
另一个相关的异常是 PendSV(可悬起的系统调用),它和 SVC 协同使用。一方面,
SVC异常是必须立即得到响应的(若因优先级不比当前正处理的高, 或是其它原因使之无法立即响应, 将上访成硬
fault——译者注),应用程序执行 SVC 时都是希望所需的请求立即得到响应。另一方面, PendSV
则不同,它是可以像普通的中断一样被悬起的(不像 SVC 那样会上访)。 OS 可以利用它“缓期执行”
一个异常——直到其它重要的任务完成后才执行动作。 悬起 PendSV 的方法是:手工往 NVIC 的 PendSV 悬起寄存器中写
1。 悬起后, 如果优先级不够高,则将缓期等待执行。
PendSV
的典型使用场合是在上下文切换时(在不同任务之间切换)。例如,一个系统中有两个就绪的任务,上下文切换被触发的场合可以是:
• 执行一个系统调用
• 系统滴答定时器(SYSTICK)中断,(轮转调度中需要)
让我们举个简单的例子来辅助理解。假设有这么一个系统,里面有两个就绪的任务,并且通过 SysTick 异常启动上下文切换。 如图
7.15 所示。
上图是两个任务轮转调度的示意图。但若在产生 SysTick
异常时正在响应一个中断,则SysTick 异常会抢占其 ISR。在这种情况下, OS
不得执行上下文切换,否则将使中断请求被延迟,而且在真实系统中延迟时间还往往不可预知——任何有一丁点实时要求的系统都决不能容忍这种事。因此,在
CM3 中也是严禁没商量—如果 OS 在某中断活跃时尝试切入线程模式,将触犯用法 fault 异常。
为解决此问题,早期的 OS
大多会检测当前是否有中断在活跃中,只有没有任何中断需要响应时,才执行上下文切换(切换期间无法响应中断)。然而,这种方法的弊端在于,它可以把任务切换动作拖延很久(因为如果抢占了
IRQ,则本次 SysTick 在执行后不得作上下文切换,只能等待下一次 SysTick 异常),尤其是当某中断源的频率和
SysTick 异常的频率比较接近时,会发生“共振”。现在好了,PendSV可以用来完美解决这个问题了,PendSV
异常会自动延迟上下文切换的请求,直到其它的 ISR 都完成了处理后才放行。为实现这个机器制,需要PendSV
编程为最低优先级的异常。如果 OS 检测到某 IRQ 正在活动并且被 SysTick 抢占,它将悬起一个 PendSV
异常,以便缓期执行上下文切换。如图 7.17 所示 。
个中事件的流水账记录如下:
1. 任务 A 呼叫 SVC
来请求任务切换(例如,等待某些工作完成)
2. OS 接收到请求,做好上下文切换的准备,并且 pend 一个
PendSV 异常。
3. 当 CPU 退出 SVC 后,它立即进入
PendSV,从而执行上下文切换。
4. 当 PendSV 执行完毕后,将返回到任务
B,同时进入线程模式。
5. 发生了一个中断,并且中断服务程序开始执行
6. 在 ISR 执行过程中,发生 SysTick 异常,并且抢占了该
ISR。
7. OS 执行必要的操作,然后 pend 起 PendSV
异常以作好上下文切换的准备。
8. 当 SysTick 退出后,回到先前被抢占的 ISR 中, ISR
继续执行
9. ISR 执行完毕并退出后, PendSV
服务例程开始执行,并且在里面执行上下文切换
10. 当 PendSV 执行完毕后,回到任务
A,同时系统再次进入线程模式。
附录:CM3体系结构“异常”常用缩写
SVC-系统服务调用(System Service Call)
SYSTICK-系统滴答定时器(System Tick Timer)
ISR-中断服务例程(Interrupt Service Routine)
IRQ-中断请求(Interrupt ReQuest)