做Linux嵌入式系统的对常见的几种嵌入式开发环境一定不会陌生,因为主要接触网路相关产品的一些系统设计,因而,将可能用到的嵌入式开发环境简略总结一下。主要涉及下边的几个东东:
emDebian
emDebian基于将Debian用于嵌入式系统的目的而开发。Debian是一个发展很快的项目,在我第一次用Debian时,就再也不乐意换用其它的发布版了,目前我用的Debian早已安装了有三年的时间了,但如今系统一直是“最新”版本,良好的在线软件升级系统是Debian成功的缘由之一。目前Debian早已支持11个体系的系统,包括X86、PPC、MIPS、ARM、SH等(据近来的一则消息,ARM有可能不再支持),并包含了大量的软件。这种要归功于Debian的开发团队,正由于有许多人使用和支持,因而,不是比较偏门的软件,基本上不须要从源码来安装,这也是我喜欢用Debian的缘由之一。
这样好的一个系统,其实有人乐意将其用到嵌入式系统中去。emDebian基于一个很简易的嵌入式系统开发的看法来构造嵌入式系统,即从一个成熟的系统中清除不须要的部分(如文档和不须要的工具),精简出一个小的系统,这与下边要介绍的几个工具的看法正好相反(下边几个都是基于fromscratch即从无到有,从头建立的方法)。emDebian提供一些工具来协助完成从现有的系统或安装包(deb文件,类似Redhat的rpm)中提取须要的东东,并协助完成完整系统的建立,其实也支持交叉建立了,例如你可以在X86的PC上建立一个基于ARM的嵌入式系统,而整个过程不须要编译任何一行源代码。
顺理成章的,emDebian的重要优势就显露下来了,如今你用的CPU超出11个Debian支持范围了吗?没有,这么你可以简单的通过emDebian建立目标系统;你所须要的主体软件在Debian支持的官方和非官方近2万个软件以外吗?没有,这么恭喜你,今天就可以给老总交工了。其实,对于特定的软件,可能还是须要从源码来建立,不过同样的linux嵌入式开发环境,我们可以将其生成Deb包,之后将配置加到emDebian工具集中linux标准教程,同其它所有软件一样的选定和配置。
buildroot
emDebian实际上并不一定适宜于资源十分短缺的超大型系统,例如只有2MFlash的大型控制系统。另外发行版的软件一般会以通用代码来编译,比如,为了尽可能在各类X86平台上都还能安装,大多数发行版一般会以i686甚至i386代码集来编译软件,可以使文件的通用性很强,但CPU的性能却不能发恢到最好(这就是为何有时会见到一些厂商或爱好者发布PIII、PIV、athlon等优化系统的诱因),这对于嵌入式系统来说也不会是一件好事情。另外,没有源码的控制权,一些须要订制的东西也会显得无法实现,因而,从源码开始建立一直有必要。
嵌入式Linux开发中使用的CPU速率常常向对不会太高,因而,尽可能提升代码的性能就十分必要。一般开发人员应当对该CPU的具体机型有一定的了解,便于启用编译器中对该机型的优化,以ARM为例,我们可以通过-march=armv5te和-mtune=arm9tdmi来对代码在ARM9上的运行进行优化。有时这种优化彰显下来的性能改善是比较大的,我曾对比过一些复杂算法的代码优化前后的性能(执行速率),都有一定的提高。另外在PIV上测试过以i686和pentium4对一个语音编码算法进行优化,运算速率竟然提升了几倍。
这些幅度的提高可能只是一个特例,这个算法有大量的复杂浮点运算,使用i386或i686指令集和使用更先进的PIV指令集编译下来的机器代码对于同一个运算的解释可能采用完全不同的指令来完成,因而性能提高较大就不足为奇了。同样这些代码,在ARM上通过ARM4和ARM5来优化后在ARM9上运行,却没有这么大的提高。看来对CPU的一定了解也应当是嵌入式系统软件设计者应当具备的能力。
这么又怎样控制可执行文件的大小呢?
不仅却除软件中不须要的部分外,我们还应当考虑软件所引用的库文件。GNU的Glibc是一个十分宠大而完整的库,起码对于嵌入式系统来说,其容积变得过分大了一些。uClibc的提出较好的解决了这样一个问题。uClibc尽可能的兼容Glibc,大多数应用程序可以在很小或完全不更改的情况下就可能使用uClibc取代glibc。通过uClibc来取代Glibc,可以在不改变应用程序功能的前提下,大大减低发布文件的大小,无论应用程序以静态链接来编译,还是以动态链接方式编译。
不过使用uClibc取代并不是简单的设置一两个参数就行了,一般须要使用一个不同的工具集(gcc/binutils等)来编译代源码。手工的构造这样一个环境,对于大多数普通程序员来说,不一定是一件很简单的事情,因而,uClibc的开发者创造出一个称作buildroot的工具集。buildroot将手动构造编译基于uClibc代码的工具集和uClibc库,并提供一个可配置的框架和一些建立一个基本系统的配置文件。用户只须要通过配置菜单选择了相应的目标软件,buildroot就可以从建立基本工具集开始,仍然到最后建立出目标系统所须要的东西,如嵌入式系统常用的基于ext2的initrd,jffs根文件系统,压缩的根目录树等,这种代码都是基于uClibc而不是系统的Glibc的。Buildroot对主机系统的要求较小,一般只须要主机系统提供足以建立工具链(toolchain)的工具,如gcc/binutils等,当工具链编译完成后,对目标系统须要的源码的编译过程与主机系统的开发工具集基本上就没有哪些关系了。为此,不同的主机假如才能通过第一步,编译完成工具链,这么编译下来的目标系统的执行代码就可以几乎不存在因为系统造成的差别。这样,开发人员就可能在各自喜欢的Linux发行版上进行开发,而毋须害怕出现哪些兼容性问题。
ucLinux
uClinux与emDebian起码有两个重要的区别,第一是重构方法,上面早已提及过了,uClinux属于fromscratch一类的。另一个不同的地方,uClinux是支持不在emDebian支持的11种CPU的,其实,这个说法不是很恰当,正确的说法是uClinux支持这些不具备MMU单元的CPU体系。uClinux的第一个目的是支持MC68328芯片,如今早已能构支持更多的CPU,如Inteli960,ARM等。不过,uClinux的主体开发团队目前早已不再支持ARM了,还好Samsung的HyokS.Choi接过了接励棒,Linux2.6版本的补丁可以在uClinux/ARM2.6找到。
uClinux之前仅是核心的一些补丁,后来发展成为一个包括核心、库、应用程序、工具和编译相关的配置文件的一个集成开发环境。与buildroot不同的是,uClinux不编译目标系统的工具集,也就是说,相应的编译工具应当提早安装好。如,对于arm来说,须要先安装ARM交叉编译器。uClinux的编译器也须要一些补丁,其中比较重要的两个方面主要包括:
用于生成FLT文件的补丁:因为MMU的关系,uClinux不支持ELF可执行文件,这个补丁主要包括bin2flt工具包和一个ld的wrapper脚本等,用于(透明于用户)生成FLT文件;
用于支持XIP(ExecuteInPlace)的补丁:这个补丁须要对gcc进行一些小的更改;支持XIP主要是为了解决小显存环境中运行的问题。
XIP不一定适用于每种应用环境,对于内在要求非常严格的系统来说(空间第一位,如手机要求使用片内RAM),可以通过将核心和应用程序编译为XIP支持,之后直接在Flash上运行,显存仅用于运行时数据;而对于性能要求为主的系统(如高速网路处理器),则不能由于节约一点空间而使用XIP将程序直接在Flash上运行,这样可能会增加指令的读取速率而影响系统性能(但依然可以使用XIP,使程序的多个实例在显存中共享代码空间,之后详尽说);+FLT可执行文件支持动态链接库(目前仅m68k支持,参见uCdot:SharedlibrariesunderuClinuxmini-HOWTO)的补丁。
uClinux的编译过程大致是,首先,通过可视配置界面(menuconfig/xconfig)选定Vendor和board(实际上是选择了一些配置文件和产品相关的文件),之后按照选择构造一个适用于target的开发环境,如生成头文件和须要的库文件(uClibc、glibc或uC-libc以及其它一些库),之后编译核心、库、应用程序,最后将所有的输出安装到romfs目录中,按照须要生成目标平台须要的映像文件(如:romfs.img、linux.bin、rootfs.gz等)。
因为一些过程细节被隐藏上去,uClinux现今的编译过程便捷到只须要配置一下(makemenuconfig),之后make就可以直接获得最终输出。不过这显然成为一些初学者学习的一个麻烦,本文完成后,按照对本文的反馈,将进一步对uClinux进行详尽介绍。
总的来说,目前的uClinux是一套主要用于无MMU核(但不限于此)的嵌入式Linux集成环境,也是一个十分好的Linuxfromscratch的示例。摒弃其MMU相关的补丁,uClinux也可以作为一套用于包含MMU系统的集成开发环境,Snapgear就是一个挺好的反例。实际上,我们可以从官方的uClinux源码就可以直接编译一个支运行于X86的uClinux。
Scratchbox
Scratchbox的故事要从buildroot讲起(这不一定是scratchbox开发者的故事,只是根据我个人的认识)。buildroot可以从头开始,先构造编译器和基本开发环境,之后按照用户配配置构造一个适用于目标平台的根文件系统。这个文件系统可以有许多用法,比如,做为initrd或通过NFS输出给目标系统使用。为了减轻交叉编译软件带来的麻烦,可以配置buidroot创建一套目标系统的编译环境(Gcc、binutils、lib等),这样用户可以通过这个基本文系统在目标系统上直接本地编译软件。假如目标系统性能足够的话linux培训机构,buildroot的任务到此就基本结束了。对于嵌入式系统的开发者来说,在目标系统上直接编译代码却不一定都才能实现,由于多数情况下,我们的目标平台处理器性能并不会这么高,这样,我们就不得不面对一个两难的选择:
继续通过buildroot编译其它的软件,性能会高许多,但每位软件都须要进行交叉编译相关的改建;
在目标平台上编译软件,对于只有几十或几千兆的低性能核来说,编译一个核心可能会让你等上半天的时间;
有没有好的办法解决性能和交叉编译的问题呢?先剖析一下通过buildroot交叉编译不能解决的问题。Buildroot只在一定程度上对目标平台进行了模拟,但仍有一些是难以实现的,比如,当目标平台不同于主机平台时,不能生成并运行目标平台的中间代码。这样,许多通过autotools(autoconf/automake)配置的软件就可能会出现问题。诸如,configure脚本有时会生成一些中间代码,并企图运行以确认开发环境中是否存在某个库文件或头文件,对于在X86上编译基于uClibcX86目标平台代码可能不会出现问题,但假如目标平台是X86以外的平台,编译就可能会中断;又如,configure脚本确认编译器是否工作,会企图编译一个包含空的主程序的代码并运行,实际一个可运行于目标平台的a.out确实生成了,也可以正常运行于目标平台,并且这个测试会由于a.out被运行在主机系统上而错误的中断。这种问题一些被buildroot通过补丁或复杂的configure参数解决了,个别中间执行文件,则通过HOSTCC(主机上的CC)来世成并运行以生成最终文件。目前buildroot包含的软件或多或少就会有一些这样的补丁,并且开发者一旦深入到对软件的订制,才会不停的被这种问题所困扰。
Scratchbox相比于buildroot有几方面的改进:
运行于chroot的环境,完全独立于主机,编译过程将基本与主机系统无关(但是scratchbox更改了一些库,致使普通用户可以chroot到编译环境中,但是多个用户可以同时使用一套Scratchbox开发套件和完全独立的用户资源);
透过qemu模拟运行或sbrsh解决中间执行文件或类似configure测试文件运行的问题;
对(chroot后)的系统进行修定,达到足以误导大多数软件的疗效,这并不是指的让软件可以不进行整修就可以交叉编译,而是使软件误觉得这就是在目标平台上编译;
不过Scratchbox目前还只能编译ARM和x86的代码,不能支持buildroot所支持的ppc、mips等。
结语
本文不深究每一种环境,因而各个软件都只是点到为止(尽管可以讲得更详尽一些,但这种内容还是独立下来比较好一些),不过这儿还是引入一个很简单的示例,按照scratchbox网站上的文档,安装完成后,进行简单配置就可以使用了(Debian用户的安装可以更简单,由于该站提供Deb包,直接apt-get就行了)。通过/scratchbox/login登陆开发环境,通过sb-menu配置一个基于ARM的环境(其中SelectCPU-transparencymethod选qemu不要先sbrsh),之后写一个helloword.clinux嵌入式开发环境,编译并运行之。通过ldd可以看见,在没有任可改动的情况下,顺利的生成了ARMELF,但在scratchbox里却可以在X86的主机上正常的运行!
假如说化学学是电子设计的基础科学,这么传感就是当下智能设计和工业设计的基础元件,一个小小的传感选用很可能决定你的设计是乏味还是精典。
这么,当下传感领域到底有什么最新动向?传感的发展又在面临着如何的窘境和机遇?你又是否听过智能传感呢?就此,《电子产品世界》特别奉上专题——论传感器技术的发展、困境与突破。为你剖析这个小世界的大乾坤。