【doc】μC/OS-Ⅱ中通过中断返回指令实现任务切换
μC,OS-?中通过中断返回指令实现任务
切换
MicrocomputerApplicationsVo1.22,No.4,2006技术交流微型电脑应用2006年第22卷第4期
文章编号:1007—757X(2006)04--0061—02
l_IC/oS一?中通过中断返回指令实现任务切换
胡蔷
摘要:~C/OS--I是一个源码公开的实时嵌入式操作系统,它的特点在于公开的源代码,很强的移植性,占先式多任务,每
个任务有单独的栈,中断管理及很强的稳定性与可靠性等,目前越来越受到实时嵌入式系统
者的关注,而要使用~C/OS--l
就要针对不同的处理器进行移植,本文通过对在80x86和MCU一51上移植实例的分析,给出了在移植~C/OS--I系统时如何通
过中断指令实现任务切换,解决移植的核心问题.
关键词:~C/OS--I;嵌入式操作系统;移植;任务切换
中圈分类号:TP313文献
码:A
1uC/oS一?的工作原理
~C/OS—I是一个占先式多任务实时嵌入式操作系统,
它的每个任务都有单独的栈,通过时钟中断来控制各个任务
的切换,即时钟节拍是~C/OS--I工作的脉搏,但要这个脉搏
对工作起作用则是通过任务调度函数中的最后一条指令
中断返回指令来实现的.因此要使中断返回指令工作时返回
到正确的任务的入口地址来实现任务切换.
2~c/os-?的移植
2.1要使用uc/os—i正常工作,处理鼍必须满足以下要
求:
(1).处理器的c编译器能产生可重入代码.
(2).用C语言就可以打开和关闭中断.
(3)处理器支持中断,并且能产生定时中断(通常在lO至 lOOHZ之间)
(4)处理器支持能够容纳一定量数据(.--I能是几千字节) 的硬件堆栈.
(5)处理器有堆栈指针和其他CPU寄存器读出和存储到 堆栈或内存中的指令.
2.2需要移檀的文件有:
CPU.H0S—CPU—A.ASMoS—CPU—C.C 0S—
2.3时钟定时鼍的硬件设定
3~c/os-?中中断返回指令实现任务切换
3.1CPU中的中断返回指令的作用是:
从工作堆栈中恢复断点和恢复标志寄存器. 3.2uc/os-i中的任务控制块TCB和任务堆栈(本文只给 作者简介:胡瞢,黄石理工学院,讲师,研究生
出与任务切换有关的TCB结构体定义部分): typedefunsignedint0S—STK;//任务堆栈的栈单元宽 度与编译相关
typedefstructos——tcb{
0S—STK*OSTCBStkptr;//任务堆栈指针
?
………………
)OS--TCB;//任务控制块
OS--TCB*OSTCBCur;指向任务控制块的指针 3.3任务堆栈的栈增长方式:
#define0S—STK—GR0wTH1//0向上,1向下;与 处理器相关
3.4针对不同的处理鼍采用相应的汇编指令从指向任务控 制块的指针中得到任务堆栈的指针,把当前工作堆栈转刭要
切换的任务堆栈上,通过中断返回指令切换刭新的任务. 3.5实例:
(1)80x86中的实现:
80x86工作在实模式下,C和ASM都用大模式编译,应用 程序和数据最大寻址空间为1MB,程序指针为32位即由16位 段地址和16位偏移量组成.
a.与处理器和编译器相关量的定义:
#define0S—STK—GR0WTH1
typedefunsignedint0S—STKl
typedefunsignedintINT16U; b.堆栈初始化;
任何一个新建任务都要做这个初始化他与处理器相关对 于中断返回后正确切换到新任务至关重要.
voidOSTaskStklnit(void(*ask)(voidpd),void*
pdata,voidptos,INT16Uopt) {
0S—STK*stkl
stk=(INT16U*)ptosl
?61?
MicrocomputerApplicationsVo1.22,No.4,2006技术交流截型电脑应用2006年第22
卷第4期
*stk一(INT16U)FP—SEG(pdata);//获得任务
的附加数据区指针
*stk一一(INT16U)FP—OFF(pdata); *stk一一(INT16U)FP—SEG(task);//本任务的人 口地址(段值:偏移值)
*stk一一=(INT16U)FP—OFF(task); *stk一(INT16U)0x0202;//标志寄存器设为使
中断允许
*stk一一=(INT16U)FP—SEG(task);//本任务的人 口地址(段值:偏移值)
*stk一一(INT16U)FP—OFF(task); stk一一(INT16U)0xAAAA;//AX,CX,DX,BX,
SP,BP,SIDI,ES
*stk一一(INT16U)OxCCCC; *stk一一=(INT16U)0xDDDDl *stk一一=(INT16U)0xBBBBl *stk一一=(INT16U)0x0000; *stk一一=(INT16U)0xllllI *stk一一=(INT16U)0x2222l *stk一一=(INT16U)0x3333; *stk一一=(INT16U)0x4444; *stk=一DS;//当前数据段
return((void*)stk); )
C.获得任务堆栈指针进行切换
EXTRN一0STCBCur:DW0RD;外部C程序中定义的 指向TCB的指针
………………
?
M0VAX,SEG—0STCBCur;得到0STCBCur变量的 段值
M0VDS.AX
LESBX,Dw0RDPTRDS:一0STCBCur;把要切换任 务的TCB的段值传送到ES,
;偏移值传送到BX
MOVSs,ES:[BX+2];把要切称任务的任务堆栈的段
值传送到SS
MOVSP,ES:[BX-];偏移值传送到SP,从而实现了从当 前工作栈
;切换到要切换任务和任务堆栈上
POPDS;按任务堆栈初始化顺序倒过来出栈 P0PES
P0PA
IRET
(2)8051中的实现:
C和ASM都用大模式编译;8051中一般指针为三字节 a.与处理器和编译器相关量的定义:
#defineOS—STK—GR0WTH0
typedefunsignedchar0S—STKl
typedefunsignedintINT1fU; b.堆栈初始化
void*0STaskStkInit(void(*task)(voidpd),void
ppdata,voidptos,unsignedintopt)
reentrant
{
0S—STK*stk:
ppdata—ppdata;
opt—opt;//opt没被用到,保留此语句防止告警产生 stk一(0S—STK*)ptos;//用户堆栈最低有效地址 *stk++一15;//用户堆栈长度
*stk++一(INT16U)task8L0xFF;//任务地址低8 位
*stk++一(INT16U)task>>8;//任务地址高8位 *stk++一0x00;//PSW
*stk++一0x0AI//ACC
*stk++一0x0B;//B
*stk++一0x00;//DPL
*stk++一0x00;//DPH
*stk++一0x00;//R0
*stk++一0x01;//R1
*stk++一0x02;//R2
*stk++一0x03;//R3
*stk++:0x04;//R4
*stk++一0x05;//R5
*stk++一0x06;//R6
*stk++一0x07;//R7return((void*)ptos);
)
C.获得任务堆栈指针进行切换
EXTRNIDATA(0STCBCur) ?STACKSEGMENTIDATA;定义堆栈段 RSEG?STACK
oSStack:
DS1OH
OSStkStartIDATAOSStack一1OSStkSart中存放SP 的初始起点值
M0VR0,#LOW(0STCBCur);获得OSTCBCur指针 低地址,指针占3字节.+0类型
;+1高8位数据+2低8位数据
INCR0
MOVDPH,@R0;全局变量OSTCBCur在IDATA中, 0STCBCur指向的TCB的
;高8位的地址值放人DPH,低8位的地址值放人DPL中 (下转第64页)
?62?
MicrocomputerApplicationsVo1.22,No.4,2006学习园地微型电脑应用2006年第22
卷第4期
a=20;b一30;c一40
d=sum3(a,b,C);
printf("%d+d+d一d",a,b,C,d);
)
在命令行下,执行:
TCCexal,C..ib/addlib.1ib 运行exa1.exe,可以看到输出结果:2O+3O+40=90 如果要在TC集成环境下使用函数库addlib.1ib时,需要 建立一个工程文件.如建立名为add—exa1.prj文件: add--exaladdlib.1ib
在alt+p功能中选工程文件名为:add--exa1.prj后,即可 用Alt+R运行程序.
4方法改进
用上述方法建立的库函数在DOS下编译和连接比较麻 烦,即使在TC集成环境下使用也要建立工程文件,也比较烦 琐.因此可以考虑将自定义函数的目标模加入到运行时库里 面.运行时库是系统提供的函数库,位于系统的lib子目录下, 无论建立保种程序都要连接这些函数库.并且不同的编译模 式,对应不同的运行时库.编译模式可以在TC集成环境Op— tion—Compiler—Model中设置,在一般情况下用的是小编译 模式,对应的运行时库为CS.1ib.要使上面建立的库函数在TC 集成环境下实现编译和连接,在上面的第?步中,TLIB命令 的搪行改为TLIBCS.1ib+addI.obj,这里是将自定义函数的 目标模块加入到运行时库CS.1ib里面.然后在集成环境下编译 连接exa1.C就可以了.
5小结
TurboC的函数库管理程序TLIB,为我们提供了对库函
数的维护手段,我们还可以把自己经常使用的程序模块添加 到函数库中,或是建立自己的函数库,为开发自己的程序服 务.
参考文献:
f-1]谭浩强,张基温,唐永炎.c语言程序设计教程[M].高等 教育出版社,2001
[23邢馥生,刘志远,姜德森.c语言程序设计及应用I-M].高 等教育出版社,2002
(收稿日期:2OO5—2—20)
???????????????????????????????????
?????????????????
(上接第62页)
INCR0
M0VDPL,@R0
INCDPTR;DPTR加1移到任务堆栈的指针高8位地 址上
MOVXA,@DPTR;.0STCBStkPtr是void指针 MOVRO,A;获得任务堆栈指针的高8位地址值放入RO 暂存
INCDPTR
MOVXA,@DPTR;获得任务堆栈指针的低8位地址值 放入R1暂存
M0VR1.A
M0VDPH.R0.
MOVDPL,R1;已得到堆栈的指针放在DPTR中 MOVXA,@DPTR;用户堆栈中是unsignedchar类型数 据;从任务堆栈中取出堆栈
;长度值
MOVR5,A;R5一用户堆栈长度
;恢复现场堆栈内容
M0VR0.#OSStkStart
restore--stack:
INCDPTR
INCR0
M0VXA,@DPTR
M0V@RO,A
DJNZR5,restore--stack ;恢复堆栈指针SP
M0VSP,R0
;RO—R7DPHDPLBAPSw出栈
RETI
由上两例比较可以看到要正确移植,关键在于对工作栈 和中断返回指令的理解,搞清处理器,C编译器和汇编及指针 的内存存放方式将能够对C/0S—l进行很好的移植. 4结束语:
pC/OS--I中通过中断返回实现任务切换是其重要的工 作原理之一,上述原理的分析和实现也同样适合在其它处理 器上的移植.
参考文献:
[1]JEANJ.LABR0ssE着邵贝贝译.pC/OS—l一源码公 开的实时嵌入式探作系统I-M].中国电力出版社2002.6 [2]徐爱钧,彭秀华壕着单片机高级语言C51Windows环境 嫡程与应用[M].电子工业出版社2002.4 [-33朱慧真嫡着.80x86汇嫡语言教程I-M].清华大学出版社 1995.9
[4]杨屹~COS51移植
[Z].巨龙公司系统集成开发部 2002/10/03
(收稿日期:2005—6—27)
?64?