摘要: 结合开发基于Motorola M68VZ328 微处理器的嵌入式系统的实际经验,较为详细地探讨了uCLinux 的特点及通过一个实例来介绍如何利用现有的Linux 开放资源开发新的嵌入式操作系统。 uClinux 是Linux2.0 版本的一个分支,它被设计用来应用微控制领域。众所周知,Linux 是一种很受欢迎的操作系统。它与Unix 系统兼容,开放源代码。它原本被设计为桌面系统,现广泛应用于服务器领域。而更大的影响在于它正逐渐地应用于嵌入式设备。uClinux 正是在这种氛围下产生的。在uClinux这个英文单词中u 表示Micro ,小的意思,C 表示Control ,控制的意思,所以uClinux 就是Micro-Control-Linux ,字面上的理解就是“针对微控制领域而设计的Linux 系统”。 1 uClinux 系统分析 uClinux 最大的特征就是没有MMU (内存管理单元模块) 。 标准Linux 是针对有内存管理单元的处理器设计的,它采用了虚拟存储器技术。这种技术用于提供比计算机系统中实际使用的物理内存大得多的内存空间。使用者将感觉到好像程序可以使用非常大的内存空间,从而使得编程人员在写程序时不用考虑计算机中的物理内存的实际容量。而对于uClinux 来说,其设计针对没有MMU 的处理器,即uClinux 不能使用处理器的虚拟内存管理技术(应该说这种不带有MMU 的处理器在嵌入式设备中相当普遍) 。uClinux仍然采用存储器的分页管理,系统在启动时把实际存储器进行分页。在加载应用程序时程序分页加载。但是由于没有MMU 管理,所以实际上uClinux 采用实存储器管理策略(real memory management) 。这一点影响了系统工作的很多方面。uClinux 系统对于内存的访问是直接的, (它对地址的访问不需要经过MMU ,而是直接送到地址线上输出) ,所有程序中访问的地址都是实际的物理地址。操作系统对内存空间没有保护(这实际上是很多嵌入式系统的特点) ,各个进程实际上共享一个运行空间(没有独立的地址转换表) 。一个进程在执行前,系统必须为进程分配足够的连续地址空间,然后全部载入主存储器的连续空间中。与之相对应的是标准Linux 系统在分配内存时没有必要保证实际物理存储空间是连续的,而只要保证虚存地址空间连续就可以了。另外一个方面程序加载地址与预期(ld 文件中指出的) 通常都不相同,这样relocation 过程就是必须的。此外磁盘交换空间也是无法使用的,系统执行时如果缺少内存将无法通过磁盘交换来得到改善。 uClinux 对内存的管理减少同时就给开发人员提出了更高的要求。如果从易用性这一点来说,uClinux的内存管理是一种倒退,退回到了Unix 早期或是DOS 系统时代。开发人员不得不参与系统的内存管理。从编译内核开始,开发人员必须告诉系统这块开发板到底拥有多少内存(假如你欺骗了系统,那将在后面运行程序时受到惩罚) ,从而系统将在启动的初始化阶段对内存进行分页,并且标记已使用的和未使用的内存。系统将在运行应用时使用这些分页内存。由于应用程序加载时必须分配连续的地址空间,而针对不同硬件平台的可一次成块(连续地址) 分配内存大小限制是不同的(目前针对ez328 处理器的uClinux是128kB ,而针对coldfire 处理器的系统内存则无此限制) ,所以开发人员在开发应用程序时必须考虑内存的分配情况并关注应用程序需要运行空间的大小。 另外由于采用实存储器管理策略,用户程序同内核以及其它用户程序在一个地址空间,程序开发时要保证不侵犯其它程序的地址空间,以使得程序不至于破坏系统的正常工作,或导致其它程序的运行异常。从内存的访问角度来看,开发人员的权利增大了(开发人员在编程时可以访问任意的地址空间) ,但与此同时系统的安全性也大为下降。 虽然uClinux 的内存管理与标准Linux 系统相比功能相差很多,但应该说这是嵌入式设备的选择。在嵌入式设备中,由于成本等敏感因素的影响,普遍地采用不带有MMU 的处理器,这决定了系统没有足够的硬件支持实现虚拟存储管理技术。从嵌入式设备实现的功能来看,嵌入式设备通常在某一特定的环境下运行,只要实现特定的功能,其功能相对简单,内存管理的要求完全可以由开发人员考虑。 2 开发实例—基于Motorola M68VZ328 微处理器的嵌入式OS 的开发 2.1 项目介绍 M68VZ328 微处理器是Motorola 龙珠系列的第三代产品,其主要特点是: 省时、节能、低开销。它有2MB 的Flash、1MB ROM,主要用于中低端产品。与Motorola 龙珠系列的其它产品有一定的差别。根据Motorola 公司的官方技术手册(MC68EZ328 用户手册、MC68VZ328 用户手册、MC68EZ328 和MC68VZ328 区别技术手册) 68VZ328 较68EZ328 增加了一些外设及增强了外设功能,提高了处理速度,但在处理器内核及指令集方面完全相同(以程序员观点来说) 。目前,还没有哪个嵌入操作系统支持这一代产品,鉴于此,我们立项开发支持M68VZ328 微处理器的OS。
2.2 开发思路 目前,市面上虽然还没有支持M68VZ328 微处理器的嵌入式操作系统内核,但已有支持M68EZ328 微处理器的嵌入式操作系统内核uClinux 2.0.38 ,即在Linux 2.0.38 的基础上打补丁uClinux22.0.38.1 pre7。分析M68VZ328 微处理器的技术文档,可知它没有内存管理单元且它与M68EZ328 微处理器有很多的相同之处。鉴于此,我们用uClinux2.0.38 作为我们的原型,利用它的可配置性,增加我们为驱动M68VZ328微处理器而编写的模块。从而确定开发思路如下: (1) 让内核在芯片上跑起来。 - 选择Linux 的版本;
- 配置环境的建立;
- 修改Linux 的代码;
- 编写所增加的模块。
(2) 利用修改的内核,配置uClinux 的开发环境。若要挂GUI ,可接着做下一步。 (3) 在内核的基础上挂上GUI。 - 分析开发板的配置,选取合适的Linux GUI ;
- 修改与微处理器有关的代码;
- 增加设备驱动程序;
- GUI 与内核的整合。
2.3 内核的开发 2.3.1 配置环境的建立 uClinux 目录结构的编排非常有规律。linux/arch/m68knommu/platform下面是各种硬件体系结构平台, 如68EZ328、68328 等等。进入68EZ328 目录后,下面又有一些目录,这些目录里分别存放了各种采用了68EZ328 的板子,如ucsimm、palm 等等。这些板子具有相同的68EZ328 硬件体系结构,因此都放在68EZ328 目录下。而这些板子之间又有区别,如内存配置、外设配置的不同,所以又以子目录的形式分开存放。我们现在的开发板采用的是68VZ328 ,根据Motorola 公司的官方技术手册(MC68EZ328 用户手册、MC68VZ328 用户手册、MC68EZ328 和MC68VZ328 区别技术手册) ,68VZ328 较68EZ328 增加了一些外设及增强了外设功能,提高了处理速度,但在处理器内核及指令集方面完全相同(以程序员观点来说) 。因此,让uClinux 在68VZ328 的硬件体系结构上运行是完全可行的。 首先要让uClinux 可以配置我们的开发板,开发板名称暂时命名为vz328。这就需要修改如下几个文件: /opt/uClinux/linux/arch/m68knommu/config.in /opt/uClinux/linux/arch/m68knommu/Boards.mk (config.in 是“make config”或“make menuconfig”的输入文件,用于控制配置菜单的显示及从属关系,以及编译内核时要用到的宏。Boards.mk 是用于定义开发板的目录名。) 修改完毕后,便可对自己的开发板进行配置了。即在/opt/uClinux/linux 目录下运行“make menuconfig”,选择“Platform dependant setup”(硬件体系结构平台开发设置) 就会出现CPU 类型“68EZ/VZ328”,选择了“68EZ/VZ328”后,增加的开发板选项“sunshine2sunny support (VZ) ”就会出现。选择VZ328 ,并对其它选项做出选择,保存退出即可。
2.3.2 修改uClinux 的源代码 查找/opt/uClinux/linux 目录下的所有包含CONFIG_PILOT 这个导航宏的文件,.c 、.h、.s 文件中有CONFIG_PILOT这个宏出现的地方一般就是需要根据实际情况修改的部分。经过查找和选择(例如其它处理器目录下的文件就肯定不用修改) 有如下文件需要修改: /opt/uClinux/linux/include/asm2m68knommu/page.h - 页偏移值; /opt/uClinux/linux/drivers/block/blkmem.c - 详细说明romdisk 的开始位置; /opt/uClinux/linux/drivers/char/68328serial.c - 设置默认的串口配置; /opt/uClinux/linux/arch/m68knommu/kernel/setup.c - 修改启动标语和版权申明; /opt/uClinux/linux/arch/m68knommu/mm/memory.c - 根据开发板的内存映射修改is_in_rom() ,使其返回正确结果。
2.3.3 自举代码 在/opt/uClinux/linux/arch/m68knommu/platform/68EZ328 目录下,针对每一种采用MC68EZ328 的开发板都建立了一个目录,目录下有如下几个文件: bootlogo.h 开机后在LCD 上显示的画面; bootstd.h 自举加载器系统调用接口; crt0_rom.s ROM版本的内核自举代码; crt0_ram.s RAM版本的内核自举代码; rom.ld ROM版本的内核内存定位文件; ram.ld RAM版本的内核内存定位文件; 其中crt0_ram.s 和ram.ld 是针对RAM版本的内核,现在是针对ROM版本的内核,因此先不做这两个文件。bootstd.h 可以照搬ucsimm 目录下的。crt0_rom.s 需要参考ucsimm 目录下的crt0_rom.s 进行重新编写。程序的流程如下: - 硬件初始化;
- 初始化栈和状态寄存器;
- 打印“ /r/nA”;
- 打印“B”- PLL 稳定;
- 打印“C”- 将ROM中的变量初值(也就是数据段、linux.data) 拷贝到RAM的数据段中,赋初值;
- 打印“D”- bss 段清零;
- 打印“E”- 栈调整;
- 打印“F”- 跳转到start kernel 执行(位于init/main.c) 中;
- 这里是串口打印子过程。
完成以上所有的工作后,把内核烧录到开发板上,便可看到我们为之设计的开机画面。(其烧录工具由Motorola 公司提供)
2.3.4 uClinux 开发环境的配置 建立uClinux 开发环境需要下载如下文件: (1) linux-2.0.38.tar.gz (2) uClinux-2.0.38.1pre7.diff .gz (3) binutils-22.9.1.tar.gz (4) gcc-2.7.2.3.tar.gz (5) uClinuxgcc-kit-160899.tar.gz (6) coff2flt-0.5.tar.gz (7) uC2libc-310899.tar.gz (8) uC2libm-0.9.1.tar.gz (9) genromfs-0.3.tar.gz (10) genromfs-0.3.diff .gz (11) romdisk-0.9.1.tar.gx 在linux-2.0.38 上打补丁uClinux-2.0.38.1pre7.diff 后可配置支持M68EZ328。在此基础上,参照内核的开发过程,便可让它支持M68VZ328。(3) ~ (5) 这三个文件是建立uClinux 的交叉编译环境用的。第(6) 个文件是一处格式转换文件。uClinux 系统使用flat 可执行文件格式,gcc 的编译器不能直接形成这种文件格式,但是可以形成coff 或elf 格式的可执行文件,这两种文件需要coff2flt 或elf2flt 工具进行格式转换,形成flat 文件。(7) ~ (8) 是两个标准的库文件。Genromfs 是用来生成ROM 文件系统的,而romdisk 压缩包包含了许多设备结点。 用上述文件建立uClinux 开发环境后,把应用程序和内核一起烧录到开发板上,应用程序可在开发板上运行。 3 结束语 当前,以信息家电为中心的嵌入式系统正得到蓬勃的发展。并且现在出现的市场只是冰山一角。我们相信,随着嵌入式系统和网络技术的发展,整个世界将更加网络化、计算化。世界是丰富多彩的,因而无处不在的嵌入式系统也要适应这个千变万化的世界。嵌入式系统也是千变万化的! 嵌入式系统的这种特点注定了其市场的碎片化。任何公司都没有足够的能量统一市场。这带来新的游戏规则,给新生的公司以机会。开放源码软件的特点注定了它非常适合嵌入式系统。开放源码导致定制的方便,我们完全可以从多个软件中提取需要的精华,应用到自己的应用上去,大大节省了开发成本。我们认为以服务为主导,以开放源码软件为支柱的公司将是嵌入式系统市场上的重要角色。
|