导读:μC/OS-II是专门为嵌入式系统应用而设计的嵌入式实时操作系统,人们在学习μC/OS-II时,一开始往往在基于PC机的DOS或 Windows环境下进行分析与研究。在这种环境中,带有μC/OS-II内核的应用系统的运行,让人觉得它好像是一个 DOS程序,人们无法真实地领略实时操作系统的面貌。
1 引言
μC/OS-II是专门为嵌入式系统应用而设计的嵌入式实时操作系统,人们在学习μC/OS-II时,一开始往往在基于PC机的DOS或 Windows环境下进行分析与研究。在这种环境中,带有μC/OS-II内核的应用系统(简称μC/OS-II应用系统)的运行,让人觉得它好像是一个 DOS程序,人们无法真实地领略实时操作系统的面貌。实际上,在PC机的DOS或Windows环境中,μC/OS-II应用系统确实是一个DOS可执行程序,它的运行离不开DOS或Windows环境。为了让更多的人掌握和理解μC/OS-II实时操作系统,笔者对μC/OS-II进行移植,使其完全脱离DOS或Windows环境而运行。首先设计Bootloader引导程序,由它来装入μC/OS-II应用系统;其次修改BORLAND C++编译器中的EXE启动代码,剥去与DOS相关的代码;最后修改μC/OS-II内核代码中与硬件平台相关部分的代码,使其能正常运行和正常退出。
2 bootloader的设计
Bootloader引导程序的设计是嵌入式系统软件开发的一个重要环节,它把操作系统和硬件平台衔接在一起,通过初始化硬件设备、建立内存空间映射,为最终加载操作系统内核建立正确的环境。由于Bootloader的实现依赖于CPU的体系结构,因此大多数初始化引导程序分为两部分,第一部分主要包含依赖于CPU体系结构的硬件初始化代码,第二部分实现的功能比第一部分更多更复杂,它为内核程序准备运行的环境,将内核装入到指定位置,并转到内核处运行。本文设计的Bootloader也是由两部分构成,一部分称作BOOT的引导记录,另一部分是LOADER装入程序。BOOT的大小固定为512个字节,作为引导记录存放在软盘的0面0磁道1扇区,它所实现的功能是在软盘的目录区中寻找LOADER文件,并将LOADER装入到内存中,然后由 LOADER负责初始化工作环境并引导内核的运行。
软盘采用FAT文件系统,并对它进行格式化,使用工具将BOOT写到0面0磁道1扇区中,将LOADER和μC/OS-II应用系统程序复制到软盘中,然后用软盘启动系统,就能观察到μC/OS-II实时操作系统的运行情况,它完全脱离了DOS运行环境。同样,也可以通过Bochs、QEMU或 VMware等虚拟机做一个磁盘映像文件,用BOOT替换该映像文件的前512个字节,将LOADER和μC/OS-II应用系统复制到该映像文件中,然后就可以在虚拟机中完成系统的启动。这样,在每次修改程序后,不需要重新启动机器来验证系统的正确性,而只需要调整映像文件,在虚拟机中重启系统即可,使用虚拟机使内核的修改和调试变得十分容易。
2.1 BOOT的设计
当PC机加电后,首先进行自检,然后寻找启动盘,如果从软盘启动,计算机读取软盘的0面0磁道1扇区的内容,若该扇区最后两个字节是0x55、 0xaa,则其为引导扇区,计算机将其内容装入到内存地址0x7c00开始处,并转到该处运行。因BOOT只能占用一个扇区,其大小固定为512个字节,其实现的功能受到限制,所以BOOT的主要功能是在磁盘的目录区中寻找LOADER程序,并将其装入到内存中,最后将CPU的控制权交给LOADER,其后的任务就由LOADER完成。BOOT程序的算法描述如下:
(1) 在显示屏上显示“Booting...”提示信息,同时使软驱复位;
(2) 在磁盘的目录区中寻找LOADER文件;
(3) 若LOADER文件存在,则转(5);
(4) LOADER文件不存在,显示提示信息“Boot fail!”,关闭软驱马达,程序进入死循环;
(5) 将LOADER读到内存0x90000处;
(6) CPU转到0x90000处运行,即将CPU的控制权交给LOADER。
这段程序用汇编语言编写,它经过汇编连接后,使用工具软件,比如debug将其写到软盘的0面0道1扇区。
2.2 LOADER的设计
2.2.1 EXE文件格式
在DOS或Windows环境中,μC/OS-II使用BORLAND C++开发工具,因此,μC/OS-II应用系统的文件采用DOS的EXE格式,在装入μC/OS-II应用系统时,引导程序将按EXE文件格式的要求将内核加载到内存中。EXE文件由两部分组成:文件首部和程序主体。文件首部包含重定位信息和控制信息,它由编译器和连接程序自动生成;程序主体包含代码段、栈段、数据段等,它由EXE启动代码和程序员编的程序构成,它是程序实际运行部分。EXE文件首部内容如表1所示。
表1 EXE文件首部
偏 移说 明
00-01EXE型程序标志“MZ”
02-03文件长度除以512的余数
04-05文件长度除512的商
06-07重定位项数
08-09文件首部长度(单位为节,每16字节为一节)
0A-0B程序装入后要求高地址内存的最小节数
0C-0D程序装入后要求高地址内存的最大节数
0E-0F堆栈段SS的值
10-11SP的初值
12-13文件校验和
14-15IP的初值
16-17代码段CS的值
18-19第一个重定位项的位置
1A-1B覆盖号
1C 保留
[18-19]重定位表
2.2.2 LOADER程序的设计
LOADER程序实现的主要功能是负责将内核装入到内存指定位置。假定TEST.EXE为带μC/OS-II内核的应用程序的文件名,LOADER 装入程序将首先在磁盘中查找TEST.EXE文件,若找到,将其读入内存地址0x10000开始的空间中。LOADER根据EXE文件首部的重定位表对加载到内存中的程序进行地址重定位后,初始化运行环境,然后转到程序主体的入口处运行。LOADER程序算法描述如下:
(1) 软驱复位,然后在软盘目录表中查找文件TEST.EXE,若找到转(3);
(2) 在软盘中没有找到TEST.EXE文件,显示信息“Kernel file do not exist!”,关闭软驱马达,程序进入死循环;
(3) 将TEST.EXE程序读到内存0x10000h处;
(4) 根据重定位表对装入内存中的TEST.EXE相关内容进行调整;
(5) 初始化TEST.EXE的运行环境;
(6) 转TEST.EXE入口处,开始运行TEST.EXE;
(7) 结束。
3 移植μC/OS-II
3.1 EXE启动代码的设计
BORLAND C++是μC/OS-II在DOS或Windows环境中的开发工具,在BORLAND c++环境下编译的μC/OS-II应用系统是直接以DOS的EXE文件来执行。EXE文件的程序主体由EXE启动代码和程序员编的程序构成。EXE启动代码的功能是为用户的程序设置初始运行环境。而EXE程序在执行时,依赖于DOS环境,主要原因是EXE启动代码需要调用DOS系统功能请求。若能对 EXE启动代码进行修改,使其脱离DOS运行环境,那么μC/OS-II应用系统就可离开DOS环境。BORLAND c++编译器的EXE启动代码在\BORLANDC\LIB\STARTUP\C0.ASM文件中,对C0.ASM进行修改,使启动代码仅仅为main函数设置好参数后,就调用C程序的main()函数转至μC/OS-II内核处开始引导,这时就完成了EXE启动代码脱离DOS的运行环境。由于μC /OS-II使用大模式进行编译,所以将C0.ASM汇编后的C0L.OBJ复制到\BORLANDC\LIB目录下,即可使编译的μC/OS-II应用系统脱离DOS独立运行。
EXE启动代码默认的栈大小为128字节,若μC/OS-II应用系统在主程序中大量使用栈空间,致使栈溢出,将会发生异常情况。从安全的角度出发,可修改C0.ASM汇编源程序中默认的栈大小,使其足够大,以确保系统的正常运行。
3.2 键盘接收程序的移植
通过上面的步骤,编译出的μC/OS-II应用系统已可以脱离DOS运行,但无法通过键盘实现对程序的控制。经过分析,问题出在μC/OS-II应用系统无法接收键盘输入。经过分析与硬件相关的程序PC.C的源代码,发现键盘输入函数PC_GetKey()是通过 kbhit()和getch()两个C库函数来实现,而这两个函数使用了DOS系统功能请求,为此对函数PC_GetKey进行改造,使其不依赖DOS系统功能请求,而采用BIOS提供的子程序实现。改造后的源程序代码如下:
BOOLEAN PC_GetKey (INT16S *c)
{ if (bioskey(1)!=0) {
*c=bioskey(0);
if (*c&0xff) *c=*c&0x00FF;
return(TRUE);
} else {*c=0x00; return(FALSE); }
}
3.3 退出系统的设计
虽然μC/OS-II应用系统可以接收键盘字符了,但仍然无法正常退出系统,主要原因是μC/OS-II应用系统在退出系统时,执行的主要工作是回到DOS环境,但现在它已脱离DOS环境,致使无法正常退出,而系统中的任务都处于活动中,所以从表面上看,μC/OS-II应用系统中的任务仍然处于活动中,为此对PC_DOSSaveReturn()函数进行改进,当用户要求结束运行时,程序控制返回到setjmp(PC_JumpBuf)的下一条语句执行时,完成以下操作步骤:(1) 给调度器上锁,禁止调度器进行调度;(2) 删除空闲任务之外的所有任务;(3) 清屏;(4)显示提示符“μC/OS-II End!”,然后等待用户关机。
4 结束语
本文创新点:在PC机上μC/OS-II应用系统脱离DOS或Windows运行环境的束缚,真正让软件开发人员掌握和理解μC/OS-II实时操作系统的真实情况,虽然笔者是以软盘来实现的,但在实际应用中可以使用磁盘映像文件应用在虚拟机环境中。当然这个移植还不太完善,因为μC/OS-II工作在80X86CPU实模下,其文件大小受到限制,本文将μC/OS-II应用系统装到内存的0x10000至0x90000空间中,要求μC/OS- II应用系统文件的长度不能大于512KB。本文所介绍的方法同样适用于采用80x86CPU的实时控制系统。