阅读本文请参考《都江堰操作系统与嵌入式系统设计》第15章,该书可在www.djyos.com下载。
本篇先讲一下cm3移植版本中断系统的总体设计,代码还在调试中,等调试完了再帖。
回忆一下《stm32移植日志之一》,那里说道,djyos移植有一个重要的工作就是中断系统的决策,djyos允许在中断服务中执行系统调用,可能会使比被中断线程更高优先级的线程就绪,中断返回时将直接返回到高优先级的线程,这就需要有一个被中断线程的栈、高优先级线程栈、中断栈直接的数据交换过程,因此,中断系统的决策往往跟设计线程上下文栈同时进行。
1、
中断和线程上下文的栈设计
我们知道,djyos把中断分为异步信号和实时中断,实时中断是不允许调用可能导致发生调度的api的,其栈结构与线程调度无关,可以自由设计,这里要讲的是异步信号的栈。我们先看看在中断里面使最高优先级的事件发生变化的执行过程:
a) 正在执行低优先级事件A,该事件由线程A处理,发生中断。
b) 把xpsr、pc、lr、r12,r3~r0依次压入线程A的栈,硬件执行。
c) 取中断向量,并切换成使用msp做栈指针。
d) ISR执行过程中,使高优先级的事件B就绪,该事件由线程B处理。
e) 中断返回线程状态,因线程B的优先级高,直接返回线程B。
大家注意到了,被中断的是线程A,返回的是线程B,一般来说,中断是从哪里中断,ISR执行后,就返回哪里继续执行。要实现返回线程B,我们要在中断函数返回前做两个工作:
a) 要保存线程A的完整上下文,中断自动入栈的只有8个寄存器,但线程上下文要求保存全部寄存器。
b) 制造被中断线程是线程B的假象,欺骗CPU,使中断返回的时候,把线程B上下文中的由硬件自动执行xpsr、pc、lr、r12,r3~r0恢复到对应的寄存器中外,还要手工恢复如4~r7。
栈结构设计如图 1
所示
图 1
中断和线程统一的上下文设计
djyos for cm3的上下文栈结构与arm的不同,cm3中,因为中断有自动入栈操作,线程上下文模拟中断上下文,使两者寄存器排列做成一致的话,可以使中断里的上下文切换操作变得非常简单,保存线程A的上下文,实际上只需要把当前psp值保存到线程上下文中即可;模拟线程B被中断的假象,也只需要把线程B的当前栈指针从上下文中copy到psp寄存器中。但这样做的代价是,非中断的上下文切换将变得复杂得多。而在arm7中,线程上下文完全按照寄存器编号由高到低排列,保存上下文只要一条stmfd指令,恢复上下文只要一条ldmfd指令。当然,cm3中还要微调上下文中的PC值,调整方法尚在验证中,暂且不表。
2、
系统中断结构设计
图 2
来自《都江堰操作系统与嵌入式系统设计》,是djyos中断系统的总图,所有djyos移植都要实现这个图,也就是使硬件平台的中断管理功能与图中结构匹配。
图 2
中断结构总图
先把图中各开关和cm3的硬件对好入座吧:
中断线使能开关:用NVIC寄存器中的SETENA和CLRENA寄存器组。
异步信号使能开关:所有异步信号的优先级均被设置为最低优先级,因此只要把BASEPRI寄存器值设为255,就相当于禁止了所有异步信号中断,设为0则允许所有异步信号(因总中断有单独开关,无须担心)。
总中断使能开关:置位PRIMASK则禁止所有中断,包括实时中断和异步信号。大家注意,PRIMASK寄存器禁止的,除了中断以外,系统异常也被禁止了,只留下NMI和硬fault。这是合理的,系统中,还有什么比实时中断还紧急的事情吗?没有了,既然连实时中断都禁止了,系统异常自然不能捣乱,是必须禁止的。
中断类型选择器:这是一个软开关,设置一个中断为实时中断还是异步信号,并没有改变该中断相关的硬件寄存器,仅仅该了一下内存中的标志为,以及中断向量表中的指针。
|