μC/OS-II在80x86上的移植
过程中,变量
OSTCBCur始终包含一个指向当前运行任务OS_TCB的指针。程序清单L9.4为OSCtxSw()的代码。
图F9.4是任务被挂起或被唤醒时的堆栈结构。在80x86处理器上,任务调用OS_TASK_SW()执
行软中断指令后[图F9.4/程序清单L9.4(1)],先向堆栈中压入返回地址(段地址和偏移量),
然后是状态字寄存器SW。紧接着用PUSHA[图F9.4/程序清单L9.4(2)],PUSHES[图F9.4/程序
清单L9.4(3)],和PUSHDS[图F9.4/程序清单L9.4(4)]保存任务运行环境。最后用OSCtxSw()在
任务OS_TCB中保存SS和SP寄存器。
任务环境保存完后,将调用用户定义的对外接口函数OSTaskSwHook()[程序清单L9.4(6)]。
请注意,此时OSTCBCur指向当前任务OS_TCB,OSTCBHighRdy指向新任务的OS_TCB。在
OSTaskSwHook()中,用户可以访问这两个任务的OS_TCB。如果不使用对外接口函数,请在头文
件中把相应的开关选项关闭,加快任务切换的速度。
程序清单L9.4 OSCtxSw().
_OSCtxSwPROCFAR(1)
;
PUSHA; 保存当前任务环境 (2)
PUSHES (3)
PUSHDS (4)
;
MOVAX,SEG_OSTCBCur; 载入DS
MOVDS,AX
;
LESBX,DWORDPTRDS:_OSTCBCur;OSTCBCur->OSTCBStkPtr=SS:S(5)
MOVES:[BX+2],SS
MOVES:[BX+0],SP
;
CALLFARPTR_OSTaskSwHook(6)
;
MOVAX,WORDPTRDS:_OSTCBHighRdy+2;OSTCBCur=OSTCBHighRdy(7)
MOVDX,WORDPTRDS:_OSTCBHighRdy
MOVWORDPTRDS:_OSTCBCur+2,AX
MOVWORDPTRDS:_OSTCBCur,DX
;
MOVAL,BYTEPTRDS:_OSPrioHighRdy;OSPrioCur=OSPrioHighRdy(8)
MOVBYTEPTRDS:_OSPrioCur,AL
;
LESBX,DWORDPTRDS:_OSTCBHighRdy;SS:SP=OSTCBHighRdy-
>OSTCBStkPtr (9)
MOVSS,ES:[BX+2]
MOVSP,ES:[BX]
;
POPDS; 载入新任务的CPU环境 (10)
POPES (11)
POPA (12)
;
IRET; 返回新任务 (13)
;
_OSCtxSwENDP
从对外接口函数OSTaskSwHook()返回后,由于任务的更替,变量OSTCBHighRdy被拷贝到
OSTCBCur中[程序清单L9.4(7)],同样,OSPrioHighRdy被拷贝到OSPrioCur中[程序清单
L9.4(8)]。OSCtxSw()将载入新任务的CPU环境,首先从新任务OS_TCB中取出SS和SP寄存器的值
[图F9.4(6)/程序清单L9.4(9)],然后运行POPDS[图F9.4(7)/程序清单L9.4(10)],POPES
[图F9.4(8)/程序清单L9.4(11)],POPA[图F9.4(9)/程序清单L9.4(12)]取出其他寄存器的值,
最后用中断返回指令IRET[图F9.4(10)/L9.4(13)]完成任务切换。
需要注意的是在运行OSCtxSw()和OSTaskSwHook()函数期间,中断是禁止的。
9.04.03 OSIntCtxSw()
在μC/OS-II中,由于中断的产生可能会引起任务切换,在中断服务程序的最后会调用
OSIntExit()函数检查任务就绪状态,如果需要进行任务切换,将调用OSIntCtxSw()。所以
OSIntCtxSw()又称为中断级的任务切换函数。由于在调用OSIntCtxSw()之前已经发生了中断,
OSIntCtxSw()将默认CPU寄存器已经保存在被中断任务的堆栈中了。

图F 9.4 任务级任务切换时的80x86堆栈结构.
程序清单L9.5给出的代码大部分与OSCtxSw()的代码相同,不同之处是,第一,由于中断已
经发生, 此处不需要再保存CPU寄存器 (没有PUSHA,PUSHES,或PUSHDS) ; 第二, OSIntCtxSw()需要调整堆栈指针,去掉堆栈中一些不需要的内容,以使堆栈中只包含任务的运行环境。图F9.5可以帮助读者理解这一过程。
程序清单L 9.5 OSIntCtxSw().
_OSIntCtxSwPROCFAR
;;IgnorecallstoOSIntExitandOSIntCtxSw
;ADDSP,8;(UncommentifOS_CRITICAL_METHODis1,seeOS_CPU.H)(1)
ADDSP,10;(UncommentifOS_CRITICAL_METHODis2,seeOS_CPU.H)
;
MOVAX,SEG_OSTCBCur; 载入DS
MOVDS,AX
;
LESBX,DWORDPTRDS:_OSTCBCur;OSTCBCur->OSTCBStkPtr=SS:SP(2)
MOVES:[BX+2],SS
MOVES:[BX+0],SP
;
CALLFARPTR_OSTaskSwHook(3)
;
MOVAX,WORDPTRDS:_OSTCBHighRdy+2;OSTCBCur=OSTCBHighRdy(4)
MOVDX,WORDPTRDS:_OSTCBHighRdy
MOVWORDPTRDS:_OSTCBCur+2,AX
MOVWORDPTRDS:_OSTCBCur,DX
;
MOVAL,BYTEPTRDS:_OSPrioHighRdy;OSPrioCur=OSPrioHighRdy(5)
MOVBYTEPTRDS:_OSPrioCur,AL
;
LESBX,DWORDPTRDS:_OSTCBHighRdy;SS:SP=OSTCBHighRdy-
>OSTCBStkPtr (6)
MOVSS,ES:[BX+2]
MOVSP,ES:[BX]
;
POPDS; 载入新任务的CPU环境 (7)
POPES (8)
POPA (9)
;
IRET; 返回新任务 (10)
;
_OSIntCtxSwENDP
图F 9.5 中断级任务切换时的80x86堆栈结构

当中断发生后,CPU在完成当前指令后,进入中断处理过程。首先是保存现场,将返回地址
压入当前任务堆栈,然后保存状态寄存器的内容。接下来CPU从中断向量处找到中断服务程序的
入口地址,运行中断服务程序。在μC/OS-II中,要求用户的中断服务程序在开头保存CPU其他寄
存器的内容[图F9.5(
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)
