现在再来看任务切换的过程:
HOSPsvHandler:
LDR R3,=gpxTcbRunning
LDR R1,[R3]
LDR R2,=gpxTcbComming
LDR R2,[R2]
CMP R1,R2 //如果gpxTcbComming、gpxTcbRunning相同,就不必要再切换上下文了。
BEQ ExitPendSV
MRS R0, PSP //取出正在运行任务的堆栈PSP,后面的工作就是往PSP里灌数据了,保存16个寄存器。上面提到CPU自动保存了8个,还需要手动保存R4~R11
SUBS R0,R0,#32
STR R0,[R1]
STMIA R0!,{R4-R7} //保存4个寄存器, R4~R7
MOV R4,R8
MOV R5,R9
MOV R6,R10
MOV R7,R11
STMIA R0!,{R4-R7} //保存4个寄存器,R8~R11
STR R2, [R3] //用gpxTcbComming更新替换gpxTcbRunning
LDR R0, [R2] //R0加载的就是gpxTcbRunning这个指针指向的内容了,不过值已经变成了gpxTcbComming的东西
ADDS R0,R0,#16 //从gpxTcbRunning实际上已经是(gpxTcbComming)取输出,恢复各个寄存器,同上。
LDMIA R0!,{R4-R7}
MOV R8,R4
MOV R9,R5
MOV R10,R6
MOV R11,R7
SUBS R0,R0,#32
LDMIA R0!,{R4-R7}
ADDS R0,R0,#16
MSR PSP, R0 //这里取出的是即将运行任务的堆栈数据,恢复PSP
ExitPendSV:
LDR R3,=NVIC_EXIT_TH_PSP //返回。返回是CPU自动退栈,把对应位置的数据压入PC,LR等...
LDR R0, [R3]
BX R0
|