你看的是这个版本的os_cpu_a.asm吗?
- ;********************************************************************************************************
- ; HANDLE PendSV EXCEPTION
- ; void OS_CPU_PendSVHandler(void)
- ;
- ; Note(s) : 1) PendSV is used to cause a context switch. This is a recommended method for performing
- ; context switches with Cortex-M3. This is because the Cortex-M3 auto-saves half of the
- ; processor context on any exception, and restores same on return from exception. So only
- ; saving of R4-R11 is required and fixing up the stack pointers. Using the PendSV exception
- ; this way means that context saving and restoring is identical whether it is initiated from
- ; a thread or occurs due to an interrupt or exception.
- ;
- ; 2) Pseudo-code is:
- ; a) Get the process SP, if 0 then skip (goto d) the saving part (first context switch);
- ; b) Save remaining regs r4-r11 on process stack;
- ; c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP;
- ; d) Call OSTaskSwHook();
- ; e) Get current high priority, OSPrioCur = OSPrioHighRdy;
- ; f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy;
- ; g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr;
- ; h) Restore R4-R11 from new process stack;
- ; i) Perform exception return which will restore remaining context.
- ;
- ; 3) On entry into PendSV handler:
- ; a) The following have been saved on the process stack (by processor):
- ; xPSR, PC, LR, R12, R0-R3
- ; b) Processor mode is switched to Handler mode (from Thread mode)
- ; c) Stack is Main stack (switched from Process stack)
- ; d) OSTCBCur points to the OS_TCB of the task to suspend
- ; OSTCBHighRdy points to the OS_TCB of the task to resume
- ;
- ; 4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we
- ; know that it will only be run when no other exception or interrupt is active, and
- ; therefore safe to assume that context being switched out was using the process stack (PSP).
- ;********************************************************************************************************
-
- OS_CPU_PendSVHandler
- CPSID I ; 上下文切换期间防止中断-关中断
- MRS R0, PSP ; 获得PSP
- CBZ R0, OS_CPU_PendSVHandler_nosave ;PSP为0跳到OS_CPU_PendSVHandler_nosave,即不保存上文,直接进入下文。
- ;问什么呢,因为首次调用,是没有上文的。否则,全部执行
-
- ;接下来是保存上文
- SUBS R0, R0, #0x20 ;因为寄存器是32位的,4字节对齐,自动压栈的寄存器有8个,所以偏移为8*0x04=0x20
- STM R0, {R4-R11} ;除去自动压栈的寄存器外,需手动将R4-R11压栈
-
- LDR R1, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP;保存上文的SP指针 OSTCBCur->OSTCBStkPtr = SP;
- LDR R1, [R1]
- STR R0, [R1] ; R0 is SP of process being switched out
-
- ; At this point, entire context of process has been saved
- OS_CPU_PendSVHandler_nosave ;切换下文
- PUSH {R14} ; Save LR exc_return value, LR压栈,下面要调用C函数
- LDR R0, =OSTaskSwHook ; OSTaskSwHook();
- BLX R0
- POP {R14}
-
- 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] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
- LDM R0, {R4-R11} ; Restore r4-11 from new process stack
- ADDS R0, R0, #0x20
- MSR PSP, R0 ; Load PSP with new process SP ,PSP = 新任务SP
- ORR LR, LR, #0x04 ; Ensure exception return uses process stack,确保异常返回后使用PSP
- CPSIE I
- BX LR ; Exception return will restore remaining context,
- ;退出异常,从PSP弹出xPSR,PC,LR,R0-R3,进入新任务运行
- END
|