ucosii在stm32上的移植详解3
R3已自动保存
CPSID I ;任务切换期间需要关中断
MRS R0, PSP ;R0 = PSP
;如果PSP == 0,跳到OS_CPU_PendSVHandler_nosave执行 #1
CBZ R0, OS_CPU_PendSVHandler_nosave
;保存R4-R11到任务堆栈
SUBS R0, R0, #0x20 ;R0 -= 0x20
STM R0, {R4-R11} ;保存R4-R11到任务堆栈
;OSTCBCur->OSTCBStkPtr = SP;
LDR R1, =OSTCBCur ;R1 = &OSTCBCur
LDR R1, [R1] ;R1 = *R1 (R1 = OSTCBCur)
STR R0, [R1] ;*R1 = R0 (*OSTCBCur = SP) #2
OS_CPU_PendSVHandler_nosave
;调用OSTaskSwHook()
PUSH {R14} ;保存R14,因为后面要调用函数
LDR R0, =OSTaskSwHook ;R0 = &OSTaskSwHook
BLX R0 ;调用OSTaskSwHook()
POP {R14} ;恢复R14
;OSPrioCur = OSPrioHighRdy;
LDR R0, =OSPrioCur ;R0 = &OSPrioCur
LDR R1, =OSPrioHighRdy ;R1 = &OSPrioHighRdy
LDRB R2, [R1] ;R2 = *R1 (R2 = OSPrioHighRdy)
STRB R2, [R0] ;*R0 = R2 (OSPrioCur = OSPrioHighRdy)
;OSTCBCur = OSTCBHighRdy;
LDR R0, =OSTCBCur ;R0 = &OSTCBCur
LDR R1, =OSTCBHighRdy ;R1 = &OSTCBHighRdy
LDR R2, [R1] ;R2 = *R1 (R2 = OSTCBHighRdy)
STR R2, [R0] ;*R0 = R2 (OSTCBCur = OSTCBHighRdy)
LDR R0, [R2] ;R0 = *R2 (R0 = OSTCBHighRdy), 此时R0是新任务的SP
;SP = OSTCBHighRdy->OSTCBStkPtr #3
LDM R0, {R4-R11} ;从任务堆栈SP恢复R4-R11
ADDS R0, R0, #0x20 ;R0 += 0x20
MSR PSP, R0 ;PSP = R0,用新任务的SP加载PSP
ORR LR, LR, #0x04 ;确保LR位2为1,返回后使用进程堆栈 #4
CPSIE I ;开中断
BX LR ;中断返回
END
#1 如果PSP == 0,说明OSStartHighRdy()启动后第一次做任务切换,而任务刚创建时R4-R11已经保存在堆栈中了,所以不需要再保存一次了。
#2 OSTCBStkPtr是任务控制块结构体的第一个变量,所以*OSTCBCur = SP(不是很科学)就是OSTCBCur->OSTCBStkPtr = SP;
#3 和#2类似。
#4 因为在中断处理函数中使用的是MSP,所以在返回任务后必须使用PSP,所以LR位2必须为1。
os_dbg.c
用于系统调试,可以不管。
需要修改的代码就介绍到这里,如果还有不明白之处,就再看看AN-1018.pdf,邵老师的书和<>。
ucosiistm32移植详 相关文章:
- ucosii在stm32上的移植详解1(11-09)
- ucosii在stm32上的移植详解5(11-09)
- ucosii在stm32上的移植详解2(11-09)
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)