分类:
2009-09-28 12:08:51
ARM Linux应该归类为一种非抢占式的分时多任务操作系统(相关术语可以Google一下),它不适合用来做伺服控制、图像处理等对系统实时性要求较高的控制。uCOS-II,VxWork可以胜任那样的工作。Linux的优点在于开源(Open Source)、网络支持和跨平台支持。其中我最看重的是跨平台支持。因为我的实验室经常使用DSP、单片机控制机器人,而这些程序不具有平台移植性,所以每届硕士做机器人的控制都是从学习DSP或单片机做起,相当浪费时间。我的工作的目的就是利用ARM、Linux、uCOS-II,设计ARM-DSP双核系统,搭建一个控制平台。
硬件环境就是必须购买一个ARM开发板,推荐买猎人的,这个与三星的SMDK2410这块“大众型”开发板完全兼容。搞嵌入式开发和普通的DSP、单片机开发不同,需要最多的是代码的移植,一个与“大众”系统兼容的开发板,可以节约移植别人编写的针对“大众”系统代码的时间。软件环境指的是需要有一台可以运行Linux的PC,以及PC的软件。这些软件包括gcc编译器、gcc交叉编译器(在PC平台编译非PC平台程序的编译器)、Linux NFS支持(用于网络下载内核到开发板)、Linux SMB支持(Linux访问Windows网络共享)、代码察看软件(例如Source Navigator)、Bootloader和内核源代码。其中前四项在安装Linux时候就必须选定,后几项从网络上获得。推荐在Windows下使用虚拟机建立开发系统,可以带来非常大的方便。具体的软硬件系统建立步骤“HOWTO”请看5月15日我写的文章。Linux内核和相应的编译器的下载地址我后面的文章会写出来。另外,有一定硬件电路开发经验的人会有需不需要仿真器的疑问,答案是:根本不需要也不可能用仿真器来调试,一个烧写电缆足以,除非你搞ARM7TDMI-S这种经过裁剪的ARM CPU的程序。主要的调试信息显示渠道是串口,主要的代码下载渠道是串口或者以太网——这由你的Bootloader决定,一个好的Bootloader可以大大减少内核调试的时间。我调试内核使用的是U-Boot的网络下载功能,800kB的内核只需要5~6秒就可以下载结束,我的开发板原配的VIVI的串口需要3分钟多,效率的差距显而易见,更不用说内核之后动辄几个或者几十个MB的文件系统了。
Bootloader是系统上电以后执行的第一段程序,它主要的功能和作用有:初始化硬件,复制Linux内核和Ramdisk文件(如果使用的话)到内存中,把预先设定的内核参数传递给内核并启动,提供硬件诊断、Flash烧写、网络连接等功能。推荐使用U-Boot,U-Boot的下载地址。U-Boot的“HOWTO”可以看我5月23、30日写的文章。还必须说明的是,通常从开源工程网站下来的都是软件的源码,需要自己进行编译。编译由源码目录下的“Makefile”这个文件决定,其中包含有关于编译的配置和操作类型的信息。一般用于多平台的源码,Makefile中都有CROSS_COMPILE这一项,在编译之前必须将它指定到交叉编译器。对于arm-linux-gcc这个交叉编译器,如果设置了指向arm-linux-gcc的缺省路径,可以填写CROSS_COMPILE=arm-linux-,注意,后面的“-”不可以少。通常由于开源代码的编译器兼容性太差,你需要在你的电脑里安装多个版本的交叉编译器,例如我的U-Boot用2.95.3编译器编译,而Linux内核用的是3.4.1,我设置2.95.3为默认编译器。对于使用非默认路径编译器的代码,可以填写CROSS_COMPILE到绝对路径,例如CROSS_COMPILE=/usr/local/arm/3.4.1/bin/arm-linux-。另外,Linux内核的Makefile还有一个ARCH选项要修改,以后说。 编译开源代码的一般步骤为:清除之前编译结果(clean)、设定编译配置(config)、编译(make) 1.清除之前编译结果一般可以用:# make clean或者# make distclean这2种写法的区别在于,distclean不仅仅清除编译生成的*.o文件,而且还清除已经设定的编译配置。2.设定编译配置主要作用是将繁杂的代码进行组织,屏蔽所需编译目标不需用到的源代码文件,并将这个组织的结果保存下来。设定编译配置命令例如:Linux内核编译的:# make menuconfig# make config# make smdk2410_defconfigU-Boot编译的:# make smdk2410_configmenuconfig是最常用的一种方式,它将调用本机编译器(HOSTCC)产生一个交互的文本菜单式界面,对内核的编译选项、驱动支持、文件系统、调试、外设等进行设置。config是一个提问式的配置方式,很麻烦,不推荐使用。smdk2410_defconfig是针对三星的SMDK2410开发板的基本硬件进行配置,这可以节约一些配置内核的时间。类似这种xxxx_config的配置,体现了购买“大众”型开发板的优势,可以用最短的时间,建立起一套有效的嵌入式系统。3.最后是编译一般可以直接输入make。但是对于Linux2.4内核,之前还必须输入# make dep用以产生源代码之间的关联信息,2.6版本的内核不再需要这个步骤。对于Linux内核,编译可以生成不同格式的映像文件,例如:# make zImage# make uImagezImage是ARM Linux常用的一种压缩映像文件,uImage是U-boot专用的映像文件,它是在zImage之前加上一个长度为0x40的“头”,说明这个映像文件的类型、加载位置、生成时间、大小等信息。换句话说,如果直接从uImage的0x40位置开始执行,zImage和uImage没有任何区别。另外,Linux2.4内核不支持uImage,Linux2.6内核加入了很多对嵌入式系统的支持,但是uImage的生成也需要设置,这个以后我会介绍。另外,我假设内核不采用任何模块。没有编译模块这一步。
内核的移植和调试是整个嵌入式系统开发中最麻烦的一步,建议如果没有良好的硬件和C语言基础,以及健壮的神经和充裕的时间,不要涉足内核的开发,尽可能采用网络上例如我的Blog中提供的现成方法,包括所有细节都要一一仿制,完成内核的移植。其实,这是考验你运气的一个环节,可能有的人一次就移植成功,可能有的人因为一些小小环节的问题,例如编译器版本问题、内核版本问题、代码修改输入错误之类的,遇到一些稀奇古怪的错误,卡住你的工作而无法继续。同时,这对你的耐心和毅力也是一个考验。呵呵,我被考验了一个月,也算是比较倒霉吧。内核修改和编译需要做的工作很多,由于Linux设备的驱动是集成在内核里的(当然还可以作为模块挂载,但是我不讨论模块问题),需要对内核代码进行修改。以后我会专门介绍。内核实现的功能是对硬件资源如内存、串口、液晶控制器的管理,以及对操作系统执行的任务程序的调度。
内核不能包括一个嵌入式系统所需的所有东西,例如程序,资料等,而且如果没有文件系统,对嵌入式系统工作过程产生信息的纪录也会成问题,所以一般的嵌入式Linux系统需要文件系统。当然没有文件系统内核也不是不能工作,这我就不太懂了,毕竟是个高深的问题……以我的跟踪内核运行认识来看,只要把你所需要执行的任务编译进内核,然后对初始化部分进行修改,让其在没有root文件系统的时侯继续下去,对你的任务进行调度也许就可以。嵌入式Linux和PCLinux不同,一般嵌入式系统没有硬盘,所以传统的Linux文件系统如ext2,hpfs之类的不能用在嵌入式Linux上。常见的嵌入式文件系统有:romfs,cramfs,jffs,yaffs等,当然也可以通过Ramdisk使用ext2。这些文件系统的特性可以自己Google一下。我最初接触到文件系统的时候,曾经有个很纯朴的想法,既然电脑硬盘上有文件系统,需要分区后格式化,那么嵌入式系统的Flash是不是也必须进行这样的操作呢,而且,分区表纪录在那里呢?在嵌入式Linux中,对Flash并不需要进行分区,目前我的解决方法是把“分区表”信息写入内核,然后直接在内核中分区表信息对应的Flash区域读写,这在内核中叫做MTD支持(Memomry Techonlogy Device),Flash同样需要擦除后写入相应内容——这可以通过Bootloader来完成,不像PC中用的是安装程序。关于文件系统的建立,我还没有完全研究完,我仅仅是利用了从我的开发板原始文件系统中剥离的一个文件系统,还有很多错误,以后我会补充上文件系统建立的详细文章。