深入理解Cortex-M7 SVC和PendSV

12 篇文章 1 订阅
本文探讨了在ARMV7架构的Cortex-M7中,PendSV和SVC异常在RTOS中的角色,如何利用它们在不关闭中断的情况下进行上下文切换,以及SVC的同步性和优先级设置的重要性,以优化中断管理和任务调度效率。
摘要由CSDN通过智能技术生成

1前言

1.1 PendSV

        在ARM V7上,PendSV用来作为RTOS调度器的御用通道,上下文切换,任务调度都是在其ISR中实现的。所谓pend,字面意思即有悬起等待的意思,ARM官方也明确说明,PendSV应该在其他异常处理完毕后执行。

        具体来说,ICSR(Interrupt Control and State Register)专为为PendSV设置了相关控制位段:

        ① 悬起设置位(PENDSVSET,PendSV set-pending bit),该位写0无效,置1则将PendSV设置为pending状态(这也是悬起PendSV的唯一方式);

        ② 悬起清除位(PENDSVCLR,PendSV clear-pending bit,该位写0无效,置1则解除PendSV的悬起状态;

        注意,如果同时向这两个控制位写1,将导致无法预测的行为。在Cortex-M7中,ICSR的物理地址为0xE000ED04,复位后默认值为0x00000000,在特权级下支持读写。

1.2 SVC

        复位后,处理器默认进入线程模式(Thread mode),特权极访问。 在特权级下的程序可以为所欲为,程序可以访问所有范围的存储器(如果有 MPU,还要在 MPU 规定的禁地之外),并且可以执行所有指令。
      一旦进入用户级,再想回来就得走“法律程序”了——用户级的程序不能简简单单地试图改写 CONTROL 寄存器就回到特权级(control寄存器只能在特权级模式下修改),它必须先“申诉”:执行一条系统调用指令(SVC)。这会触发 SVC 异常,然后由异常服务例程(通常是操作系统的一部分,Handler mode)接管,如果批准了进入,则异常服务例程修改 CONTROL 寄存器,才能在用户级线程模式下重新进入特权级
        事实上,从用户级到特权级的唯一途径就是异常:如果在程序执行过程中触发了一个异常,处理器总是先切换入特权级, 并且在异常服务例程执行完毕退出时,返回先前的状态。

 图1 SVC调用示意图

        注意,SVC属于同步异常,没有专门的pending状态位,这就意味着一旦无法被关中断屏蔽掉,系统后续忙完再开中断时,可能就忘记了之前的SVC请求。因此,如果系统的异常可执行优先级(execution priority)小于HardFault(优先级固定为-1)时,如果发生了SVC或fault类型的同步异常,而当前系统的异常可执行优先级较高(或与同步异常相同),无法进行抢占,则会直接触发HardFault异常。

        也就是说,SVC 异常是必须在执行 SVC 指令后立即得到响应的(对于 SVC 异常来说,若因优先级不比异常可执行优先级高,例如PRIMASK被置1,异常可执行优先级位0,则将上访成硬 fault),应用程序执行 SVC 时都是希望所需的请求立即得到响应。这也就意味着,如果在关中断的情况下(同时屏蔽掉了SVC所在优先级),应用程序如果在此情况下调用SVC指令,将会直接酿成一个HardFault异常。        

2 Cortex-M7中断的抢断行为

图2 中断抢占行为分析

3  SVCall和PendSV组合使用实现上下文切换

           通常来说,在进行上下文切换(Context switching)时,RTOS都是通过关中断来进行临界区保护的。关中断会降低中断响应的实时性,严重时甚至会丢失中断请求。

        Armv7-M提供了一种机制,可以在不必关中断的情况下,进行上下文切换:

        ① 将SVCall和PendSV都配置成最低优先级

        ② 在线程中使用SVC进行系统调用,包括上下文切换(比如线程主动让出CPU),也通过SVC进行请求;

        ③ 通过PendSV来执行上下文切换需要临界区保护的代码,包括SVC在内的所有异常都不要染指该临界区,它们最多只能悬起PendSV,并最终通过PendSV来执行上下文切换;

        如此一来,SVC和PendSV优先级相同,无法互相抢占,而这两个异常又是始终处于使能状态的;由于只在线程中调用SVC悬起PendSV,所以SVC的同步性可以得以保证,而具体的上下文切换的代码在PendSV的ISR来执行。上下文切换完成后,程序从PendSV返回线程继续执行。

 4 总结

        将PendSV优先级设为最低,还有一点考虑,如果其优先级比较高,有可能出现以下情况:

        PendSV会抢断其他中断的执行,随后进行上下文切换,而其他中断以尾链机制继续执行,并请求进行上下文切换,这就导致多次重复的上下文切换,而在此过程中,无辜的任务只能眼巴巴的等着,啥都做不了,而内核在忙着来回切换上下文,浪费了很多CPU时间。

        此外,SVC指令要求SVC异常的优先级高于异常可执行优先级,否则将触发错误异常。因此,在NMl或HardFault等优先级高于SVC的异常处理程序中,不能使用SVC。这也意味着,应尽量只在线程中使用SVC指令进行系统调用。

  • 36
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值