Cortex-M3 PendSV中断入栈出栈情况
Cortex-M3 在触发PendSV中断后的入栈情况
当前系统触发PendSV中断后,内核会自动做入栈操作(这里不考虑局部变量的入栈)
详细的步骤如下
1、 根据R13(SP)的地址找到当前栈首地址
2、 将当前R13(SP)首地址减4,跳到下一个栈地址
3 、将xPSR寄存器的值写入当前R13(SP)所在的栈地址中
4、 将当前R13(SP)首地址减4,跳到下一个栈地址
5、 将R15(PC)寄存器的值写入当前R13(SP)所在的栈地址中
6、 以此类推,依次将系统特殊寄存器压入栈中。
下表是内核自动压入的特殊寄存器的顺序
序号 | 寄存器 |
---|---|
1 | xPSR |
2 | R15(PC) |
3 | R14(LR) |
4 | R12(SP) |
5 | R3 |
6 | R2 |
7 | R1 |
8 | R0 |
Cortex-M3 在触发BX LR的出栈情况
当系统执行BX LR指令后,内核会自动做出栈操作
具体步骤如下:
1、首先判断R14(LR)的值,如果是0xFFFFFFF9,那么要获取MSP的值,如果是0xFFFFFFFD的值,那么要获取PSP的值。
2、获取PSP或者MSP的值后,根据其中的值恢复寄存器的值,恢复的顺序与入栈顺序相反。
3、根据恢复后的特殊寄存器信息,继续从PC位置执行代码。
下面是我验证使用的代码,使用环境是KEIL5,编译器选中5版本
//PendSV中断入口函数
__asm void PendSV_Handler(void)
{
NOP
BX LR
}
//触发PendSV中断
__asm void TriggerOS()
{
LDR R0, =0xE000ED04
LDR R1, =0x10000000
STR R1, [R0]
BX LR
}
int main(void)
{
TriggerOS();
while(1)
{
}
}
下图是调试时,入栈的结果对照。
实验结果表明,内核会为我们的中断前自动做一些特殊寄存器的入栈操作
当前执行BX LR指令时又会执行自动出栈操作。
这对我们以后写RTOS时立即任务的切换非常重要,特单独研究,以加深印象。