接下来我们再了解一下STM32的中断机制。
Cortex内核发生中断时,硬件会自动将XPSR、PC、LR、R12、R3、R2、R1和R0这8个寄存器压入栈(详细介绍可以参考《底》2.1、2.3和5.1节),其余的R4~R11、LR、XPSR寄存器的备份则需要由C编译器去做。硬件为啥只将这8个寄存器入栈呢,因为AAPCS——Procedure Call Standard for the ARM Architecture对传递函数值所使用的寄存器做了规定,其中R0~R3和R12是接口寄存器,父函数可以通过这5个寄存器向其调用的子函数传递函数参数,子函数可以直接使用这5个寄存器,而子函数若需要使用其它的寄存器则需要由子函数先备份,以免破坏父函数保存在这些寄存器中的数值,然后才能使用。C编译器需要遵守这个规定,以保证不同的编译器编译出的二进制代码是兼容的。中断的产生具有随机性,中断服务程序无法知道被其打断的函数在哪些寄存器中保存了有用的数值,因此为了不破坏寄存器中的数据,C编译器需要在中断服务程序里对所有的寄存器进行备份,然后才能使用这些寄存器。LR寄存器保存了子函数/中断服务程序的返回地址,因此也需要C编译器来备份。PC寄存器保存的是发生子函数/中断服务程序调用那一时刻的程序指针,我认为没有备份的必要,但备份下来会看的更直观些。XPSR寄存器中保存的是子函数/中断服务程序调用那一时刻的芯片状态,因此这个需要备份。
Cortex内核在中断发生时硬件会自动入栈上述8个寄存器,因此C编译器就不需要再做重复的工作了,下面我们对比一下ARM7内核与cortex内核C编译器在子函数/中断服务程序调用时需要对寄存器做的备份工作,其中ARM7内核在中断发生时硬件不会自动将寄存器压入堆栈的: