CORTEX-M3中断的现场保护问题

在《Cortex-M3 Devices Generic User Guide.pdf》中介绍了异常入栈和出栈的状况,详见2.3 Exception model。Cortex-M3内核的寄存器以下。 

异常发生时,入栈的寄存器是R0~R3+R12+PC+LR+SP。为啥袒护R0‐R3以及R12呢, R4‐R11就是下等公民?(摘自《Cortex-M3权威指南 》第9章) 
原来,在ARM上,有一套的C函数调用标准约定(《 C/C++ rocedure Call Standard for the ARM Architecture》,AAPCS, Ref5)。个中缘由就在它上面:它使得中断服务例程能用C语言编写,编译器优先使用被入栈的寄存器来保存中间结果(固然,若是程序过大也可能要用到R4‐R11,此时编译器负责生成代码来push它们。可是, ISR应该短小精悍,不要让系统如此操心——译者注)。若是读者再仔细看,会发现R0‐R3, R12是最后被压进去的。这里也有一番良苦用心:为的是能够更容易地使用SP基址来索引寻址,( 以及为了LDM等多重加载指令,由于LDM必须加载地址连续的一串数据)。参数的传递也是受益者:使之能够方便地经过压入栈的R0‐R3取出( 主要为系统软件所利用,多见于SVC与PendSV中的参数传递)。 
这就是说,C编译器中断(异常)服务函数封装的这样的需求:当R0~R3+R12不够用时会使用R4‐R11,在使用R4‐R11以前会进行入栈保护;在使用完以后进行出栈恢复现场。 
这也为开发人员使用汇编语言编写中断服务函数提供了借鉴。好比,在uC/OS-III移植过程当中使用汇编编写任务级/中断级调度器。调度器须要触发Cortex-M3的滴答定时器中断来达到现场保护和任务切换的目的。而这个滴答定时器中断就须要使用汇编编写(详见已经移植好了的os_cpu_a.s)。 
对uC/OS-III其余中断便可使用C编译器提供的模板便可: 
void xxxxx_xxxHandler(void) ? 

OSIntEnter(); 
…… //中断服务函数代码 
OSIntExit();   

分析一下其过程 
响应xxxxx_xxxHandler以后,保存现场R0~R3+R12+PC+LR+SP,执行OSIntEnter()和中断服务函数代码(若这期间若是通用寄存器不够用时会使用R4‐R11,使用前会先进行入栈保护,使用后出栈恢复现场),而后会在中断级调度器OSIntExit()中断定是否须要进行任务切换,若是须要则定位好待切换的任务,最后挂起由汇编编写的滴答定时器中断。这会引入“咬尾机制”直接转而去执行滴答定时器中断服务函数。 

经过对C编译器封装的中断服务函数模型进行的“背地儿里”的操做,能够预见C编译器对普通函数模型封装的额外操做。至少不会比这个复杂吧....ide

 

 

 

 

 

 

 

----函数

相关文章
相关标签/搜索