PendSV 中断处理函数实现和注解如下:;Cortex-M3 进入异常服务例程时,自动压栈了 R0-R3,R12,LR(R14,连接寄存器),PSR(程
序状态寄存器)和 PC(R15).
;PSP 不自动压栈,不需要保存到栈中,而是保存到线程结构中;CpuSwitchThread
PendSV_Handler
CPSID I
; 取得线程内容
LDR R0, =uKernelVariable
ADD R1, R0, #4;Nominee
ADD R0, R0, #8;Current
; 如果 uThreadCurrent 和 uThreadNominee 相等则不需要保存寄存器到栈中
LDR R2, [R0]
LDR R3, [R1]
CMP R2, R3
BEQ LOAD_NOMINEE_FILE
; 如果 uThreadCurrent 线程没有被初始化则不需要保存寄存器到栈中
LDR R3, [R2,#0]
AND R3, R3, #0x1
CBZ R3, SWAP_THREAD
STORE_CURRENT_FILE
MRS R3, PSP
SUBS R3, R3, #0x20
STM R3, {R4-R11} ;保存 r4-r11 到 uThreadCurrent 栈中
STR R3, [R2,#4] ;保存 psp 到 uThreadCurrent 线程结构
SWAP_THREAD ; 使得 uThreadCurrent = uThreadNominee;
LDR R3, [R1]
STR R3, [R0]
LOAD_NOMINEE_FILE
LDR R3, [R3,#4] ; 根据 uThreadCurrent 中取得 SP 数值到 R0
LDM R3, {R4-R11} ; 从新线程栈中弹出 r4-11
ADDS R3, R3, #0x20 ; psp 指向中断自动压栈后的栈顶
MSR PSP, R3
; 上电后,处理器处于线程+特权模式+msp。
; 对于第一次 activate 任务,当引发 pendsv 中断后,处理器进入 handler 模式。使
用 msp,
; 返回时,在这里准备使用 psp,从 psp 中弹出 r0...这些寄存器,所以需要修改 LR,
强制使用 psp。
ORR LR, LR, #0x04
CPSIE I;在这里有可能发生中断,而此时新的当前线程的上下文并没有完全恢复。和线程被中断
的情景相似:
;硬件自动保存部分寄存器到线程栈中,其它寄存器还游离在处理器上下文中。
;假如在此时产生的中断 ISR 中调用那些
; (1)会将当前线程从就绪队列中移出的 API,
; (2)或者唤醒了更高优先级的线程,
; (3)调整当前线程或者其它就绪线程的优先级
; (4)系统定时器中断,发生时间片轮转
;那么有可能导致一次新的 PensSv 请求被挂起。
;当下面的语句启动异常返回流程时,会发生前后两个 PendSV 咬尾中断。
;按照 uCM3PendSVHandler 的流程,当前线程的上下文中那些游离的寄存器会再次被
保存到线程栈中,即不继续
;弹栈,也就是说第一次线程上下文切换被强制取消了,转而执行第二次的线程上下文切
换。
; 启动异常返回流程,弹出 r0、 r1、 r2、 r3 寄存器,切换到任务。
BX LR
; 返回后,处理器使用线程+特权模式+psp。线程就在这种环境下运行。
|