0 参考资料&工具
Cortex M3权威指南(中文).pdf
1 ARM处理器中断/异常入/出栈(保护/恢复现场)过程分析:以Cortex-M3为例
1.1 中断服务函数格式
所有的中断服务函数都是不带返回、不带参数的。以void SysTick_Handler(void)为例:
/**
* @brief This function handles SysTick Handler.
* @param None
* @retval None
*/
void SysTick_Handler(void)
{
HAL_IncTick();
}
了解中断服务函数的格式对于理解后面的保护、恢复现场的操作非常重要。
1.2 中断/异常入/出栈(保护/恢复现场)过程
当Cortex-M3开始响应中断时,会按照顺序执行以下操作:
(1)入栈(保护现场):将8个关键寄存器值压栈
(2)取向量:将中断对应的中断服务函数的地址从向量表中取出,然后执行中断服务函数
(3)更新寄存器:选择堆栈指针MSP(裸机)/PSP(RTOS),更新堆栈指针SP,更新链接寄存器LR,更新程序计数器PC
(4)出栈(恢复现场):将压栈的8个寄存器值出栈,更新NVIC寄存器将中断激活位被硬件清除
1.2.1 入栈(保护现场)
处理器会依次将xPSR、PC、LR、R12、R3、R2、R1、R0寄存器通过硬件方式(产生中断进入中断服务函数不是使用诸如BL指令跳转到中断服务函数,因此LR的值没有被正确设置为跳转指令的下一条指令地址。为了保证压入栈区的LR值正确,处理器会通过硬件方式将LR等寄存器入栈)自动压入栈区。如果响应异常时,当前的代码正在使用PSP,则压入PSP,即使用线程堆栈;否则压入MSP,使用主堆栈。一旦进入了服务例程,就将一直使用主堆栈。
1.2.2 取向量
1.2.3 更新寄存器
1.2.4 出栈(恢复现场)
这里需要留意,编译器生成的指令实际上进入中断服务函数和退出中断服务函数时也进行了压栈和出栈操作,压栈时LR的值被硬件设置为EXC_RETURN,出栈完成后,会执行诸如BX指令将LR的值写入到PC指针,处理器识别到EXC_RETURN被写入PC指针就会将之前硬件保存在栈内的寄存器值一并恢复,PC指针会指向中断打断位置的下一条指令。这样一套操作下来,就完成了编译器生成的出栈指令出栈和硬件出栈。