Cortex‐M3内核学习笔记(三):SVC和PendSV

一、SVC

SVC(系统服务调用,亦简称系统调用)用于产生系统函数的调用请求。例如,操作系统不让用户程序直接访问硬件,而是通过提供一些系统服务函数,用户程序使用 SVC 发出对系统服务函数的呼叫请求,以这种方法调用它们来间接访问硬件。

因此,当用户程序想要控制特定的硬件时,它就会产生一个 SVC 异常,然后操作系统提供的 SVC 异常服务例程得到执行,它再调用相关的操作系统函数,后者完成用户程序请求的服务。

SVC这种工作模式优点有以下几点

● 它使用户程序从控制硬件的繁文缛节中解脱出来,而是由 OS 负责控制具体的硬件;

● OS 的代码可以经过充分的测试,从而能使系统更加健壮和可靠;

● 它使用户程序无需在特权级下执行,用户程序无需承担因误操作而瘫痪整个系统的风险;

● 通过 SVC 的机制,还让用户程序变得与硬件无关,因此在开发应用程序时无需了解硬件的操作细节,从而简化了开发的难度和繁琐度,并且使应用程序跨硬件平台移植成为可能。

Cortex‐M3内核学习笔记(三):SVC和PendSV_第1张图片

SVC 异常通过执行”SVC”指令来产生。 该指令需要一个立即数, 充当系统调用代号。 SVC异常服务例程稍后会提取出此代号,从而解释本次调用的具体要求,再调用相应的服务函数。例如:

SVC 0x3 ; 调用 3 号系统服务

在 SVC 服务例程执行后,上次执行的 SVC 指令地址可以根据自动入栈的返回地址计算出。找到了 SVC 指令后,就可以读取该 SVC 指令的机器码,从机器码中萃取出立即数,就获知了请求执行的功能代号。

不能在 SVC 服务例程中嵌套使用 SVC 指令(事实上这样做也没意义), 因为同优先级的异常不能抢占自身。 这种作法会产生一个用法 fault。同理,在 NMI 服务例程中也不得使用 SVC,否则将触发硬 fault。

二、PendSV

PendSV(可悬起的系统调用),它和SVC协同使用

SVC异常是必须立即得到响应的(若因优先级不比当前正处理的高, 或是其它原因使之无法立即响应, 将上访成硬 fault——译者注), 应用程序执行SVC 时都是希望所需的请求立即得到响应。

PendSV则不同,它是可以像普通的中断一样被悬起的。 OS 可以利用它“延时执行” 一个异常——直到其它重要的任务完成后才执行动作。 悬起 PendSV 的方法是: 手工往 NVIC 的 PendSV 悬起寄存器中写 1。 悬起后, 如果优先级不够高,则将缓期等待执行。

PendSV 的典型使用场合是在上下文切换时(在不同任务之间切换)。 例如,一个系统中有两个就绪的任务,上下文切换被触发的场合可以是:

● 执行一个系统调用;

● 系统滴答定时器(SYSTICK)中断,(轮转调度中需要)。

让我们举个简单的例子来辅助理解。假设有这么一个系统,里面有两个就绪的任务,并且通过 SysTick 异常启动上下文切换。如下图:

Cortex‐M3内核学习笔记(三):SVC和PendSV_第2张图片

但若在产生 SysTick 异常时正在响应一个ISR中断,则SysTick 异常会抢占其ISR。在这种情况下,OS 不得执行上下文切换,ISR中断请求被延迟,而且在真实系统中延迟时间还往往不可预知——实时要求的系统都决不能容忍这种事。

Cortex‐M3内核学习笔记(三):SVC和PendSV_第3张图片

PendSV 来完美解决上面的问题。PendSV 异常会自动延迟上下文切换的请求,直到其它的 ISR 都完成了处理后才放行。为实现这个机制,需要把 PendSV 编程为最低优先级的异常。如果 OS 检测到某 IRQ 正在活动并且被 SysTick 抢占,它将悬起一个 PendSV 异常,以便缓期执行上下文切换。

Cortex‐M3内核学习笔记(三):SVC和PendSV_第4张图片

上图工作流程如下:

  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,同时系统再次进入线程模式。

参考文献

Cortex-M3权威指南

你可能感兴趣的:(Cortex‐M3内核学习笔记(三):SVC和PendSV)