官方的例子不太好,不能中断嵌套,所有中断必须在同一优先级别,官方例子都是0,主要是在双堆栈指针使用上有问题 用下面两段代码替换就没问题了,也不存在原来有人说使用不同优化级别编译会死机的问题
OSStartHighRdy LDR R0, =NVIC_SYSPRI2 ; Set the PendSV exception priority LDR R1, =NVIC_PENDSV_PRI STRB R1, [R0]
;MOVS R0, #0 ; Set the PSP to 0 for initial context switch call ;MSR PSP, R0 MRS R0, MSP MSR PSP, R0 MRS R0, CONTROL ORR R0, R0, #0x02 MSR CONTROL, R0 LDR R1, __OS_TCBCur MRS R0, PSP SUBS R0, R0, #0x24 STR R0, [R1] LDR R0, __OS_Running ; OSRunning = TRUE MOVS R1, #1 STRB R1, [R0]
LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch) LDR R1, =NVIC_PENDSVSET STR R1, [R0] CPSIE I ; Enable interrupts at processor level
OSStartHang NOP B OSStartHang ;Should never get here
OSPendSV MRS R0, PSP ; PSP is process stack pointer ;CBZ R0, OSPendSV_nosave ; skip register save the first time
SUBS R0, R0, #0x20 ; save remaining regs r4-11 on process stack STM R0, {R4-R11}
LDR R1, __OS_TCBCur ; 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 OSPendSV_nosave PUSH {R14} ; need to save LR exc_return value LDR R0, __OS_TaskSwHook ; OSTaskSwHook(); BLX R0 POP {R14}
LDR R0, __OS_PrioCur ; OSPrioCur = OSPrioHighRdy; LDR R1, __OS_PrioHighRdy LDRB R2, [R1] STRB R2, [R0]
LDR R0, __OS_TCBCur ; OSTCBCur = OSTCBHighRdy; LDR R1, __OS_TCBHighRdy 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 ;ORR LR, LR, #0x04 ; ensure exception return uses process stack BX LR |