PendSV_Handler
CPSID I
MRS R0, PSP
CBZ R0, PendSV_Handler_Nosave ;compare and branch if zero.
SUBS R0, R0, #0x20
STM R0, {R4-R11}
LDR R1, =OSTCBCur
LDR R1, [R1]
STR R0, [R1]
PendSV_Handler_Nosave
PUSH {R14}
LDR R0, =OSTaskSwHook
BLX R0
POP {R14}
LDR R0, =OSPrioCur
LDR R1, =OSPrioHighRdy
LDRB R2, [R1]
STRB R2, [R0]
LDR R0, =OSTCBCur
LDR R1, =OSTCBHighRdy
LDR R2, [R1]
STR R2, [R0]
LDR R0, [R2]
LDM R0, {R4-R11}
ADDS R0, R0, #0x20
MSR PSP, R0
ORR LR, LR, #0x04
CPSIE I
BX LR
这是将 uc/OS-II 移植到 STM32F103,os_cpu_a.asm 中的一段
第4行如果PSP==0,那么就会跳转到 PendSV_Handler_Nosave
我想知道,PendSV_Handler_Nosave 完了之后会返回到第5行继续吗?
它末尾不是有一个 BX LR 么?不理解这个 BX LR 是什么意思
谢谢~
还有,末尾有条注释,
ORR LR, LR, #0x04 ;将 0xFFFFFF(E/F)(9/D) 变成 0xFFFFFF(E/F)D,返回线程模式,并使用线程堆栈
LR 是什么时候变成 0xFFFFFF(E/F)(9/D) 的,它不应该保存返回的偏移地址吗?
线程堆栈,以及 0xFFFFFF(E/F)(9/D) 代表什么我是知道的,但是 LR 是什么时候变的?自动完成的吗?
啊我明白了。有些复杂。
简单回答是:不会返回到第5行,而是退出中断,变为线程模式(只有中断的时候才是 Handler 模式),并使用线程堆栈;LR 是进到中断的时候自动改变的,变成了一个比较特殊的值 EXC_RETURN,而不是某个具体的地址。
https://blog.csdn.net/weixin_45217215/article/details/128661187
PendSV_Handler
CPSID I
MRS R0, PSP
;跳转后就与 PendSV_Handler 无关了
;B 是无条件跳转,不会保存返回地址 LR
;CBZ 只是多了个条件,同样不会保存返回地址 LR
CBZ R0, PendSV_Handler_Nosave ;compare and branch if zero
SUBS R0, R0, #0x20
STM R0, {R4-R11}
LDR R1, =OSTCBCur
LDR R1, [R1]
STR R0, [R1]
PendSV_Handler_Nosave
PUSH {R14}
LDR R0, =OSTaskSwHook
BLX R0
POP {R14}
LDR R0, =OSPrioCur
LDR R1, =OSPrioHighRdy
LDRB R2, [R1]
STRB R2, [R0]
LDR R0, =OSTCBCur
LDR R1, =OSTCBHighRdy
LDR R2, [R1]
STR R2, [R0]
;是STRB,不是STR,因为 OSPrioCur 和 OSPrioHighRdy 都是字节类型
LDR R0, =OSPrioCur ;OSPrioCur = OSPrioHighRdy;
LDR R1, =OSPrioHighRdy
LDRB R2, [R1]
STRB R2, [R0]
LDR R0, =OSTCBCur ;OSTCBCur = OSTCBHighRdy;
LDR R1, =OSTCBHighRdy
LDR R2, [R1]
STR R2, [R0]
LDR R0, [R2] ;R2 = OSTCBHighRdy;R0 = *OSTCBHighRdy = OSTCBHighRdy->OSTCBStkPtr
LDM R0, {R4-R11} ;Restore r4-11 from new process stack; R0不变
ADDS R0, R0, #0x20 ;出栈后,栈指针增加32;32字节 = 8个要“出栈”的寄存器 * 每个寄存器4字节
MSR PSP, R0 ;Load PSP with new process SP
;0xFFFFFF(E/F)9 变成 0xFFFFFF(E/F)D,原来是 0xFFFFFF(E/F)D 就不变。返回线程模式,并使用线程堆栈(SP=PSP)
;参考权威指南 表9.3、表9.4
ORR LR, LR, #0x04 ;Ensure exception return uses process stack
CPSIE I ;开中断
;返回。由于 PendSV 是最低优先级别的,所以肯定不是返回到另一个中断,而是到线程模式
;就像上面说的,是 0xFFFFFF(E/F)9 或 0xFFFFFF(E/F)D,不可能是 0xFFFFFF(E/F)1
;反正知道有这么回事,知道这个函数大概是干什么的,就行了
BX LR
BX LR 指令表示将程序控制权返回到存储在LR寄存器中的地址处,同时会清除当前的中断标志。用于退出子程序或中断服务例程。