>
首页 » 技术文章 » μC/OS2Ⅱ在军用FM80386EX处理器上的移植应用

μC/OS2Ⅱ在军用FM80386EX处理器上的移植应用

作者:武海巍 惠凯 刘亚侠 于平  时间:2006-11-24 15:42  来源:电子设计信息网-www.edires.net
摘要:嵌入式实时操作系统μC/OS-Ⅱ公开所有的源代码,90%的代码使用标准的ANSIC语言书写,它体积小、执行速度快,具有良好的可裁减性和可移植性.作为一种多任务实时操作系统,μC/OS-Ⅱ具有较高的可靠性和实时性,能满足对实时性和可靠性要求较高的嵌入式系统.通过详细研究μC/OS-Ⅱ的特点和内核结构,完成了μC/OS-Ⅱ在军用FM80386EX上的移植并给出了相关代码,同时对内核进行测试、数据分析,对内存管理、代码临界区、信号量机制提出了改进方法.移植成功后,μC/OS-Ⅱ可实时完成各个任务的调度,通过嵌入式操作系统μC/OS-Ⅱ在各个任务间实现通信,用户可以根据需要完成自己的多任务操作.

关键词:μC/OS-Ⅱ;FM80386EX;移植;实时操作系统

μC/OS-Ⅱ是实时操作系统(RTOS),已经通过了非常严格的测试,得到了美国航空管理局(FederalAviationAdministration)的认证.μC/OS-Ⅱ功能强大,支持56个用户任务,其内核为占先式,支持信号量、邮箱、消息队列等多种常用的进程通信机制,现已成功应用到众多商业嵌入式系统中,是1种成熟稳定的实时内核.与大多商用RTOS不同的是,μC/OS-Ⅱ公开所有的源代码,90%的代码使用标准的ANSIC语言书写,程序可读性强,移植性好.同时,它可以免费获得,即使商业应用也只收取少量的许可费用.因此,对μC/OS-Ⅱ实时操作系统的学习研究、开发、应用具有重要的意义.

军用FM80386EX嵌入式处理器是1种高度集成,32位总线结构,专为恶劣环境下的嵌入式控制应用优化设计的全静态CPU.它采用16位外部数据总线,26位地址总线及Intel系统管理模式(SMM),能在廉价的16位硬件系统中运行32位程序,可将基于Intel386架构的大量软件应用于嵌入式系统.为了有效地管理多任务,以及满足系统的实时性要求,常常需要使用实时嵌入式操作系统.

要移植μC/OS-Ⅱ,处理器必须满足以下要求:处理器的C编译器能产生可重入代码;用C语言可以打开和关闭中断;处理器支持中断,并且能产生定时中断;处理器能容纳一定数量的硬件堆栈;处理器有将堆栈指针和其他CPU寄存器读出、存储到堆栈或内存中的指令.FM80386EX满足以上条件,可以进行μC/OS-Ⅱ的移植.

μC/OS-Ⅱ实时操作系统结构

应用程序处于整个系统的顶层,每个任务都可以认为自己独占了CPU,因此任务被设计成了1个无限循环.而μC/OS-Ⅱ与处理器无关的代码提供了该实时系统的系统服务,应用程序利用这些API函数进行内存管理,任务间的通信以及创建、删除任务等.μC/OS-Ⅱ的代码大部分是使用ANSIC书写,与微处理器硬件相关的部分使用汇编语言编写,并且汇编语言编写的部分已经压倒最低限度,因此μC/OS-Ⅱ的可移植性好.而处理器80386具有堆栈指针、CPU内部寄存器入栈、出栈指令.所使用的C编译器BorlandC3.1支持内嵌汇编,使得关中断和开中断能在C语言程序中实现.

实时内核μC/OS-Ⅱ在FM80386EX上的移植

我们使用BorlandC3.1编译器移植μC/OS-Ⅱ主要包括以下几个步骤:

编写OS-CPU.A.ASM

这里要实现4个汇编函数改写:多任务启动函数中调用OSOSTartHighRdy(),任务切换函数OSCtxSw(),中断任务切换函数OSIntCtrSw(),时钟节拍服务函数OSTickISR().

1) OSStartHighRdy()函数.该函数被OSStart()函数调用,功能是运行优先级最高的就绪任务,其主要代码如下:
CALL FAR PTR-OSTaskSwHook ;恢复最高优先级任务的浮点寄;存器内容
LES BX, DWORD PTR DS:-OSTCBHighRdy ;从任务控制快OS-TCB
;中获得并恢复堆栈指针
MOVSS,ES:[BX+2]
MOVSP,ES:[BX+0]

2) OSCtxSW()函数.该函数被OS-Sched()函数调用,通常是用汇编语言编写的,因为C编译器不能从C语言中直接处理CPU寄存器.OSCtxSW()的功能是在任务级实现任务切换,任务切换是模拟软中断来实现的,其主要代码如下:
OSTCBCur->OSTCBStkPtr =SP ;见图1(4)
OSTCBCur =OSTCBHighRdy ;见图1(1)
SP =OSTCBHighRdy->OSTCBStkPtr;见图1(2)

图1任务级任务切换时的堆栈结构

3) OSIntCtxSw( )函数.该函数只能在中断子程序里被OSIntExit()函数调用.由于中断的产生可能引起任务切换,在中断服务程序的最后会调用OSIntExit()函数来检查任务就绪状态,如果满足任务切换条件,则OSIntExit()调用此函数实现任务切换,除了不应调用任务切换函数OS-TASK-SW()外,其余代码与-OSCtxSw相同.

4) OSTickISR( )函数.发生中断时,CPU的中断向量会指向该ISR.其主要代码如下:
INC BYTEPTRDS:-OSIntNesting
CMP BUTEPTRDS:-OSIntNesting,1 ;判断中断嵌套层数
JNE SHORT-OSTickISR1
MOV AX,SEG(-OSTCBCur)
MOV DS,AX
LES BX,DWORDPTRDS:-OSTCBCur ;保存堆栈指针到OS-TCB中
MOVES:[BX+2],SS
MOVES:[BX+0],SP
-OSTickISR1
INT 081H;调用DOS时钟节拍处理程序
CALL FARPTR-OSTimeTick;给节拍参数减1
CALL FARPTR-OSIntExit;退出中段
一般情况下,产生调用OSTickISR()函数时,时钟节拍的设备应设置成每隔10~100ms产生1次中断.必须在多任务系统启动以后,也就是在调用OSStart()之后,再开启时钟节拍器.

用C语言编写6个操作系统相关的函数

-(OS-CPU-C.C)
OS-STKOSTaskStkInit(void(*task)(void*pd),void*pdata,OS-STK*ptos,INT16Uopt)
{
INT16U* stk;
opt =opt;
stk=(INT16U)ptos;/*建立并初始化局部指针变量*/
*stk--=(INT16U)FP-SEG(pdata);/*按次序保存参数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;/*初始化寄存器*/
*stk-- =(INT16U)0xCCCC;
*stk-- =(INT16U)0xDDDD;
*stk-- =(INT16U)0xBBBB;
*stk-- =(INT16U)0x0000;
*stk-- =(INT16U)0x1111;
*stk-- =(INT16U)0x2222;
*stk-- =(INT16U)0x3333;
*stk-- =(INT16U)0x4444;
*stk-- =DS;/*把DS寄存器复制到堆栈中*/
return((OS-STK*)stk);/*返回新的堆栈栈顶指针*/
后5个函数是钩子函数,可以不加代码:
void OSTaskCreateHook(OS-TCB*ptcb){ptcb=ptcb;}
void OSTaskDelHook(OS-TCB-*ptcb){ptcb=ptcb;}
void OSTaskSwHook(void){}
void OSTaskStatHook(void){}
void OSTimeTickHook(void){}

设置OS-CPU.H中与处理器和编译器相关的代码

80386处理器的堆栈从内存高地址向低地址递减,所以把OS-STK-GROWTH置1.
#defineOS-STK-GROWTH1
#defineOS-ENTER-CRITICAL() (cpu-sr=OSCPUSaveSR())
#defineOS-EXIT-CRITICAL() (OSCPURestoreSR(cpu-sr))
#defineOS-TASK-SW()asm INT uCOS
完成上述工作后,μC/OS-Ⅱ就可以运行在80386处理器上了.另外根据用户需求按需配置OS-CFG.H,裁减μC/OS-Ⅱ,使之占用尽量少的内存.

测试

为了验证μC/OS-Ⅱ内核运行的正确性,编写了以下测试程序:系统时钟周期设为20ms,设置4个任务,Task1.Task4,任务的优先级分别为4,5,6,7,每个任务都有1个变量TasknData;任务1和任务2延时50个系统周期,任务3和任务4延时100个系统周期,每执行1次任务循环,将该任务的变量加1,如下:
voidTaskn (void)
{ while(1) {
OSTimeDly(time);
TasknData++;
}}
每次运行10s,观察OSTime变量与TasknData的值.其中OSTime记录了系统时钟数.初值均为0,10s后,得到如下的值:
结果分析:10s系统时钟应该是10×50=500≈510;任务1和任务2每个循环延时50个系统周期,也就是1s,所以10s内应该运行10次;任务3与任务4在10s内应该运行5次;上面的结果可以证明内核已经正常运行,并实现基本任务调度;为了便于分析程序运行的先后顺序,在每个任务中加入myprintf语句,把任务4改为打印任务,为最低.在任务1中加入1个发送邮箱,任务2中加入接受邮箱.
VoidTask1(void) voidTask2(void)
{ {charerr,*mail;
char*id1=”Iamthetask1a”; char*id1=”Iamthetask2a”;
chari*d2=”Iamthetask1b”; char*id2=”Iamthetask2b”;
while(1){ while(1){
OSTimeDly(50);
Myprintf(id1); myprintf(id1);
OSMboxPost(TxMbox,(void*)&id); mail=(char*)OSMboxPend(TxMbox,0,&err);
Myprintf(id2); myprintf(id2);
Task1Data++; Task2Data++;
}} }}

运行10s后,PC串口接受到如下数据(省略“Iamthetask”前缀):2a1a2b2a1b31a2b2a1b2b1b31a2b2a1b1a2b1b3.....从该次试验结果分析可看出,内核的通讯功能运行正常.

移植分析

1) 在中断子程序里启动任务的方法.使用μC/OS-Ⅱ嵌入式操作系统后,为了缩短中断处理时间,常常需要将某些比较费时的程序作为任务从中断子程序里独立出来,同时,这个任务又需要由中断来激活.我们可以通过信号量、邮箱、消息队列来实现这个目的.以邮箱为例,在C程序中,需要先创建邮箱MyMbox,在调用OSMboxPend()函数等待消息,在中断子程序里发送就可以了.

2) μC/OS-Ⅱ内存管理不够完善.在μC/OS-Ⅱ的应用实例中我们发现,在不知道系统初始化后给用户留下了多少自由内存空间的情况下,很难定义内存分区所使用数组的大小.定义大了,造成内存的浪费;定义小了,系统会崩溃.我们通过把连续的大块内存按分区管理来解决上述问题.

3) 对代码临界区的改进.对于内核程序,在较长的临界段代码中插入可重入点;对于可供用户调用的函数用信号量机制改写1遍,主要是改写有关信号量的函数.

4) 系统时钟中断的改进.μC/OS-Ⅱ中,系统时钟中断的核心函数是OSTimeTick,该函数查找每1个延时的任务是否到期,如果到期则将其放入就绪列表,也就是内核只提供延时OSTimeDly()函数.但在许多情况下需要延时一定时间以触发某1个事件的发生,或者需要1个定时器.这里借鉴了Linux内核原理,引入了32个静态定时器.

运行时需要注意的问题

由于DOS下的C编译器提供的运行库没有考虑多线程应用的问题,运行库中的全局变量和部分函数只适用于单线程.这些函数包括errno,-doserrno,strtok,sterror,tmpnam,tmpfile,asctime,gmtime,ecvt,fcvt等.在μC/OS-Ⅱ中使用这些函数时应注意,要避免2个任务同时调用这些函数,我们可以使用信号量同步对这些函数进行调用.DOS是不能重入的,在调用DOS服务期间,是不能再次调用DOS的,否则会引起系统的崩溃.所以在μC/OS-Ⅱ中,可以调用BIOS或直接操纵硬件,但应尽量减少DOS重入.

结语

μC/OS-Ⅱ和其他一些著名的嵌入式操作系统不同,它的启动过程比较简单.μC/OS-Ⅱ的内核是和应用程序放在一起编译成1个文件,使用者只需要把这个文件转换格式写入ROM中就可以运行了.上电后,它会和普通程序一样运行.通过详细研究μC/OS-Ⅱ的特点和内核结构,完成了μC/OS-Ⅱ在军用FM80386EX上的移植并对相关代码并详尽的对内核进行测试、分析,对内存管理、代码临界区、信号量机制提出改进方法,使之更加有效的在处理器上运行.移植成功后,μC/OS-Ⅱ可实时的完成各个任务的调度,并且通过嵌入式操作系统μC/OS-Ⅱ在各个任务间实现通信.μC/OS-Ⅱ具有良好的实时性和很小的代码量,随着各种智能嵌入式系统的复杂化和系统实时性需求的提高,功能强大的实时操作系统μC/OS-Ⅱ将会有更大的发展空间.


相关推荐

Android平台移植应该做两步工作

Android  移植  Linux驱动  2011-05-23

开发用于深海钻井船的立管管理系统

QNX推出提供产品安全和信息安全认证的实时操作系统

QNX  实时操作系统  2011-05-06

Wind River在MWC上发布最新解决方案

新型无人战机X-47B首航,Wind River提供关键技术

基于RTX51实时操作系统的交通灯控制系统的设计

实时操作系统  RTX51  Keil  2011-01-04
在线研讨会
焦点