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時立即任務的切換非常重要,特單獨研究,以加深印象。

浙公網安備 33010602011771號