- ; *-----------------------------------------------------------------------
- ; * void PendSV_Handler(void);
- ; * r0 --> switch from thread stack
- ; * r1 --> switch to thread stack
- ; * psr, pc, lr, r12, r3, r2, r1, r0 are pushed into [from] stack
- ; *-----------------------------------------------------------------------
- PendSV_Handler PROC
- EXPORT PendSV_Handler
- MRS r2, PRIMASK ; 失能中断,为了保护上下文切换不被中断
- CPSID I
-
- LDR r0, =rt_thread_switch_interrupt_flag ;加载rt_thread_switch_interrupt_flag 的地址到r0
- LDR r1, [r0] ; 加载rt_thread_switch_interrupt_flag 的值到r1
- CBZ r1, pendsv_exit ;判断r1 是否为0,为0 则跳转到pendsv_exit
- MOV r1, #0x00 ; r1 不为0 则清0
- STR r1, [r0] ; 将r1 的值存储到rt_thread_switch_interrupt_flag,即清0
- LDR r0, =rt_interrupt_from_thread ; 加载rt_interrupt_from_thread 的地址到r0
- LDR r1, [r0] ; 加载rt_interrupt_from_thread 的值到r1
- CBZ r1, switch_to_thread ; 判断r1 是否为0,为0 则跳转到switch_to_thread ,第一次线程切换时肯定为0,则跳转到switch_to_thread
- ;================================================================================================
- ;上文保存
- ;================================================================================================
- ; 当进入PendSVC Handler 时,上一个线程运行的环境即:
- ; xPSR,PC(线程入口地址),R14,R12,R3,R2,R1,R0(线程的形参)
- ; 这些CPU 寄存器的值会自动保存到线程的栈中,剩下的r4~r11 需要手动保存
- MRS r1, psp ; 获取线程栈指针到r1
- STMFD r1!, {r4 - r11} ; 将CPU 寄存器r4~r11 的值存储到r1 指向的地址(每操作一次地址将递减一次)
- LDR r0, [r0] ; 加载r0 指向值到r0,即r0=rt_interrupt_from_thread
- STR r1, [r0] ; 将r1 的值存储到r0,即更新线程栈sp
- ;========================================================================================================
- ;下文切换
- ;========================================================================================================
- switch_to_thread
- LDR r1, =rt_interrupt_to_thread ; 加载rt_interrupt_to_thread 的地址到r1, 它 是一个全局变量,里面存的是线程栈指针SP 的指针
- LDR r1, [r1] ; 加载rt_interrupt_to_thread 的值到r1,即sp 指针的指针
- LDR r1, [r1] ; 加载rt_interrupt_to_thread 的值到r1,即sp
- LDMFD r1!, {r4 - r11} ; 将线程栈指针r1(操作之前先递减) 指向的内容加载到CPU 寄存器r4~r11
- MSR psp, r1 ; 将线程栈指针更新到PSP
-
- pendsv_exit
- MSR PRIMASK, r2 ; 恢复中断
- ORR lr, lr, #0x04 ; 确保异常返回使用的栈指针是PSP,即LR 寄存器的位2 要为1
- ; 异常返回,这个时候栈中的剩下内容将会自动加载到CPU 寄存器:
- ; xPSR,PC(线程入口地址),R14,R12,R3,R2,R1,R0(线程的形参)
- ; 同时PSP 的值也将更新,即指向线程栈的栈顶
- BX lr
- ENDP ; PendSV_Handler 子程序结束
|