中级会员
 
- 积分
- 388
- 金钱
- 388
- 注册时间
- 2017-3-2
- 在线时间
- 156 小时
|

楼主 |
发表于 2017-6-20 16:23:38
|
显示全部楼层
本帖最后由 kokoromi 于 2017-6-20 20:41 编辑
最后还是自己搞明白了,说一下吧:
之所以不能采用上述调用的方式是因为链接寄存器 LR的问题,进入系统异常 PendSV_Handler后,LR的值为 EXC_RETURN,但在调用 OS_CPU_PendSVHandler后,LR的值变为这个函数的返回地址,即进入OS_CPU_PendSVHandler后的 LR的值已经不是 EXC_RETURN,而是 OS_CPU_PendSVHandler的返回地址,所以在 OS_CPU_PendSVHandler中对 LR的操作(ORR LR, R4, #0xF4)会导致最后执行 BX LR后程序可能跑飞(取决于 ORR操作是否修改了返回地址 LR的值),综上,中断处理函数 OS_CPU_PendSVHandler必须直接放到中断向量表中,不能被其他函数调用。
OS_CPU_PendSVHandler
CPSID I ; Prevent interruption during context switch
MRS R0, PSP ; PSP is process stack pointer
STMFD R0!, {R4-R11} ; Save remaining regs r4-11 on process stack
MOV32 R5, OSTCBCurPtr ; OSTCBCurPtr->OSTCBStkPtr = SP;
LDR R6, [R5]
STR R0, [R6] ; R0 is SP of process being switched out
; At this point, entire context of process has been saved
MOV R4, LR ; Save LR exc_return value (此处保存的已经不是 exc_return了,而是这个函数的返回地址)
BL OSTaskSwHook ; OSTaskSwHook();
MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy;
MOV32 R1, OSPrioHighRdy
LDRB R2, [R1]
STRB R2, [R0]
MOV32 R1, OSTCBHighRdyPtr ; OSTCBCurPtr = OSTCBHighRdyPtr;
LDR R2, [R1]
STR R2, [R5]
ORR LR, R4, #0xF4 ; Ensure exception return uses process stack
LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
LDMFD R0!, {R4-R11} ; Restore r4-11 from new process stack
MSR PSP, R0 ; Load PSP with new process SP
CPSIE I
BX LR ; Exception return will restore remaining context
END
|
|