[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-M. This is because the Cortex-M auto-saves half of the
; processor context on any exception, and restores same on return from exception. So only
; saving of R4-R11 & R14 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
; b) Save remaining regs r4-r11 & r14 on process stack;
; c) Save the process SP in its TCB, OSTCBCurPtr->OSTCBStkPtr = SP;
; d) Call OSTaskSwHook();
; e) Get current high priority, OSPrioCur = OSPrioHighRdy;
; f) Get current ready thread TCB, OSTCBCurPtr = OSTCBHighRdyPtr;
; g) Get new process SP from TCB, SP = OSTCBHighRdyPtr->OSTCBStkPtr;
; h) Restore R4-R11 and R14 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) OSTCBCurPtr points to the OS_TCB of the task to suspend
; OSTCBHighRdyPtr 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).
;
; 5) Increasing priority using a write to BASEPRI does not take effect immediately.
; (a) IMPLICATION This erratum means that the instruction after an MSR to boost BASEPRI
; might incorrectly be preempted by an insufficient high priority exception.
;
; (b) WORKAROUND The MSR to boost BASEPRI can be replaced by the following code sequence:
;
; CPSID i
; MSR to BASEPRI
; DSB
; ISB
; CPSIE i
;********************************************************************************************************
OS_CPU_PendSVHandler
CPSID I ; Cortex-M7 errata notice. See Note #5
MOV32 R2, OS_KA_BASEPRI_Boundary ; Set BASEPRI priority level required for exception preemption
LDR R1, [R2]
MSR BASEPRI, R1
DSB
ISB
CPSIE I
MRS R0, PSP ; PSP is process stack pointer
IF {FPU} != "SoftVFP"
; Push high vfp registers if the task is using the FPU context
TST R14, #0x10
IT EQ
VSTMDBEQ R0!, {S16-S31}
ENDIF
STMFD R0!, {R4-R11, R14} ; Save remaining regs r4-11, R14 on process stack
MOV32 R5, OSTCBCurPtr ; OSTCBCurPtr->StkPtr = SP;
LDR R1, [R5]
STR R0, [R1] ; 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
BL OSTaskSwHook ; Call OSTaskSwHook() for FPU Push & Pop
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, #0x04 ; Ensure exception return uses process stack
LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
LDMFD R0!, {R4-R11, R14} ; Restore r4-11, R14 from new process stack
IF {FPU} != "SoftVFP"
; Pop the high vfp registers if the next task is using the FPU context
TST R14, #0x10
IT EQ
VLDMIAEQ R0!, {S16-S31}
ENDIF
MSR PSP, R0 ; Load PSP with new process SP
MOV32 R2, #0 ; Restore BASEPRI priority level to 0
CPSID I ; Cortex-M7 errata notice. See Note #5
MSR BASEPRI, R2
DSB
ISB
CPSIE I
BX LR ; Exception return will restore remaining context
ALIGN ; Removes warning[A1581W]: added <no_padbytes> of padding at <address>
END