回去看了下《权威指南》,根据理解,我自己来解答这个问题吧!大家有什么见解可以讨论交流。
__asmvoidPendSV_Handler(void)/*由于用户没有对控制寄存器CONTROL进行设置SP类型,系统与用户程序默认公用一个MSP*/
{
IMPORT__GuiOsEnterSum/*声明全局变量*/
IMPORTOSTCBCur
IMPORTOSTCBHighRdy
IMPORTOSPrioCur
IMPORTOSPrioHighRdy
IMPORTOSTaskSwHook
preserve8
CPSIDI/*baninterrupt*/
/*任务切换目的1:保存旧任务现场*/
/*由于进入异常前,硬件自动把被打断任务的8个特殊的寄存器压入栈中,下面只需要手动压入通用寄存器*/
PUSH{R4-R7}/*进入异常后,将使用一直是用MSP*/
MOVR0,R8
MOVR1,R9
MOVR2,R10
MOVR3,R11
PUSH{R0-R3}
MOVR4,LR/*LR在进入异常的时候被重新解释,在进入handler前,他的值被更新成EXC_RETURN,他的值不同,决定不同含义,详见《权威指南》*/
BLOSTaskSwHook
MOVLR,R4
LDRR1,=__GuiOsEnterSum
LDRR0,[R1]
PUSH{R0}
LDRR2,=OSTCBCur/*savestkpointerinOSTCBCur->OSTCBStkPtr*/
LDRR2,[R2]
MOVR0,SP
STRR0,[R2]
LDRR4,=OSPrioCur/*changetheOSPrioCurtoOSPrioHighRdy*/
LDRR5,=OSPrioHighRdy
LDRBR6,[R5]
STRBR6,[R4]
LDRR6,=OSTCBHighRdy/*changetheOSTCBCurtoOSTCBHighRdy*/
LDRR6,[R6]
LDRR4,=OSTCBCur
STRR6,[R4]
LDRR0,[R6]/*gettheOSTCBHighRdy->OSTCBStkPtr*/
MOVSP,R0
POP{R0}
STRR0,[R1]/*R0=__GuiOsEnterSum*/
CMPR0,#0
BNEOUT
CPSIEI/*enableinterrupt*/
OUT/*任务切换目的2:切换新任务现场*/
POP{R0-R3}/*用新任务的SP把几个通用寄存器出栈,同时SP更新,为接下来硬件自动出栈返回做准备*/
MOVR8,R0
MOVR9,R1
MOVR10,R2
MOVR11,R3
POP{R4-R7}
BXLR/*LR在进入中断时被更新成了EXC_RETURN,把这个值写入PC意味着中断返回,并不是回到LR所指向的地址,
返回的地址PC值硬件自动压入了栈中,系统收到这个返回指令后自动把之前压入栈的寄存器pop出(出栈时继续延用新任务的SP),并按顺序赋给相应的寄存器,包括PC(从而实现跳转),*/
}
|