Cortex-M3PendSV 中断系统调用说明

参考 -M3权威指南中文版
异常是和系统调用有些类似,cpu 需要手动将往NVIC 的 悬起寄存器中写1,然后产生中断,系统调用(SVC)是-M3 CPU执行 SVC指令之后产生中断(arm中一般是SWI 指令),都是软件的方式产生的中断,称其为内中断 。
和SVC 两个内中断的不同之处在于:
SVC指令执行之后,必须立即响应(保证能够立即硬件入栈r0-r3等寄存器,这是因为SVC中断需要传递参数到中断模式,所以必须立即响应,保证寄存器中存储的参数不被破坏,另一个原因是用户态程序,即线程模式的程序有的时候必须得到SVC中断响应函数的返回值才能继续执行,否则强行继续执行,将会出错),SVC的中断服务程序(ISR)立即执行,如果此时有别的ISR正在执行,且此中断的优先级比SVC的优先级高,将会产生硬fault,
(注:SVC通常在用户级线程模式下运行,但可以在特权级线程模式或者模式下运行,详见《 m3 权威指南》第12章,非基级的线程模式 一节,如果在一个中断的ISR中调用 SVC,而且此ISR的优先级比SVC的优先级高,那么会产生硬fault,这是合理的,SVC必须立即得到响应,但是响应过程中允许被其他中断打断 例如在svc中断触发后,开始硬件入栈,但svc的ISR还没有开始执行,此时来了个优先级比SVC优先级更高的中断,那么优先级高的中断将以 晚到中断 的形式执行,执行完毕后 SVC的ISR再以 咬尾中断 的形式执行)
SVC中断 和 其他中断还有不同之处,其他中断一般都是 不需要参数和返回值的,所以中断触发之后的 硬件入栈 之后 和 执行出栈序列 之前,中断的ISR一般是不修改 保存在栈的R0-R3、xpsr、PC 和 LR 寄存器的,(也有特殊情况,例如 上述提到过的 《 m3 权威指南》第12章,非基级的线程模式 一节),但是SVC中断是可能需要 参数或者 返回值的,参数和返回值要借助 R0-R3寄存器来传递,考虑到-m3的晚到中断、咬尾中断等硬件机制,SVC触发后,SVC的ISR执行过程中不能直接读取R0-R3寄存器获取参数,而是要到栈中读取 保存的R0-R3寄存器的值,来获取参数,SVC的ISR 返回 返回值的时候,也不能直接 向R0寄存器中写入返回值,出栈序列执行后,R0的值会被栈中保存的R0的值覆盖,正确的做法是,修改栈中保存的R0的值,修改为要返回的值
注:这里说的 线程模式 模式 特权级 用户级的关系如下:
SVC一般在用户线程模式下执行 。它设计的本意就是让用户模式完成到普通模式的切换 。
中断,一般在特权模式下 往 NVIC 的 悬起寄存器中写1,来触发,一般在中断的ISR中执行,也就是模式下并且,的优先级一般设置成最低,的ISR一般等到其他中断全部响应完成后,再响应,(悬起异常)设计的理念就是可以将此异常悬起,这样就可以完美应用在 上下文切换的场景中 。上下文切换可以再SVC和的ISR中完成,这里只说(系统滴答时钟中断),如果发生时,程序执行在用户级的线程模式,则没有问题,如下图:
但是如果,发生时,是在其他中断的ISR中,则系统是不允许系统调用发生的,如果允许将会产生如下效果:
我们可以看到,IRQ中间被中断了,并且中断的时间 包含上下文切换以及任务B的一个时间片,这个时间是不确定的,IRQ的没有得到及时的响应,这在实时系统中是坚决不允许的 。所以 就引入了 ,如果在来临的时候,检测到有IRQ在执行,就延缓上下文切换,在的ISR中 使用悬起一个异常,等之前的IRQ执行完之后,在执行上下文切换,如下图:
事件的流水账记录如下:
1. 任务 A 呼叫SVC 来请求任务切换(例如,等待某些工作完成)