按照我的开发过程想分以下几部分逐一介绍。
1.开发平台的选择和论证
2.开发环境的建立
3.一般程序的开发
4.Linux程序向ARM+uClinux平台的移植
5.剩下的问题
希望诸位多多补充自己的想法,以利于大家共同提高。
1. 开发平台的选择和论证
一个项目拿到手,如何选择开发平台(主要是指CPU和操作系统以及开发环境和工具)应该说至关重要,有时这不光影响进度,产品质量,可维护性等一般问题,甚至涉及到方案的可实现性。本人结合自己的网络监控系统简单归纳了一些对平台的考虑,还请各位补充。
从系统功能实现考虑:
(1) 是否有片上外设,专用指令或配套的软件模块直接实现系统功能要求。 感 觉这一条对很多人的决策影响很大
(2) 价格
这一点应通过CPU提供的资源综合考虑,它提供了多少有用的资源,多少没用的资源(那可都是银子呀!),还是那三个字,性价比,另一方面,是要抓主要矛盾,是不是有些特性是必须的,什么特性是用户需求里的亮点(就靠这些亮点往上抬价),这时该花的就得花了。
(3) 功耗
本系统对CPU功耗要求不高,但对移动设备,这一点可是致命,而且这一点不是仅针对CPU,所有几乎器件都要勒紧裤腰带运行。
(4) 处理速度
这项不用多说,大家都明白重要性,但具体算起来可是一门学问,一方面是自己需要多快的速度,如果加上非实时操作系统这事就不好控制,余量还是大点稳妥,另 一方面,CPU指令周期多少,有没有流水,有没有并行,什么体系结构,有没有专用指令(看人家DSP多牛,干这事一绝),对外部存储器和外设的存取速度等 等,哪一个慢了都叫瓶颈。
(5) 需要的硬件支持(如外部存储器,双电源等)
这算是杂项,但会增加额外的价格,系统体积等,不容忽视。
从开发者的角度考虑:
(1) 是否有足够的技术支持包括demo版及原理图,demo程序,操作系统和BSP,测试开发工具等。
(2) 自身条件;包括对项目开发周期的要求,开发人员对器件和开发模式的熟悉程度以及掌握的难易程度。
(3) 可用资源是否丰富(书籍,网络等)
以上三点主要考虑迅速开发出稳定的系统。
(4) 系统的可继承性,可移植性和可扩展性。
(5) 是否有现货。
(6) 方案提供商的素质。(包括技术水平和服务意识)。
根据以上考虑选择了s3c4510b(ARM7TDMI)+uClinux开发模式
(1) 以下是该平台对我的系统的满足情况:(和上面几点对应)
本监控系统硬件部分主要要求以下部分:
a.以太网接口 (s3c4510b自带网络控制器)
b.串口 (自带)
c.与数据采集芯片的接口(8位数据线,小于8位地址总线)。(自带)
本系统软件部分主要要求以下部分:
a. 硬件接口驱动程序 (uClinux提供串口和网络控制器驱动)
b. 网络协议栈支持(uClinux提供TCPIP,UDP等的协议栈)
c. 应用层程序(如果算上可以从linux移植的程序来看,那就太多了,我就用到了一个现成的)
(2) 本应用系统不是那种批量的东西,对价格要求不苛刻,而且这款CPU最便宜可以到55左右,可以接受。
(3) 本应用系统有固定电源,功耗要求不高。当然,据说ARM在节省功耗上很有特点。
(4) 本应用系统速度方面要满足两方面:1。串口:115200bps 2。网络速度 能到10Mbps就行,所以对系统速度要求也不高。这款ARM内部可以到50M。
(5) 系统对体积要求也不高,加片flash和RAM还是没问题(到目前为止感觉我的系统真是无欲无求!)
从开发者的角度考虑:
(1) 因为时间很紧(一个半月),所以支持越多越好。目前从开发商那里拿到了开发板,原理图,uClinux,相应驱动,bootloader,拿来就可以用了。软件硬件并行开发。(bootloader和网络控制器驱动没提供原码,比较可惜:-(
(2) 当时我对嵌入式系统的开发模式和ARM都是只有耳闻,linux接触过一个月左右。现在想起来有些后怕。
(3) 网上的资源,非常多。
提供一些我常用的。
::URL::http://www.uClinux.org/ uClinux的大本营。
::URL::http://www.ucdot.org/ 里面有些技术文章非常不错。
::URL::http://www.linuxdevices.com/
::URL::http://www.linuxeden.com/ 这是国产的linux站点。
uClinux-dev@uClinux.org 这是uClinux的邮件列表,回答问题的都是大牛,非常有帮助,记住把你的邮件设置成纯文本格式。 申请是在:
::URL::http://mailman.uClinux.org/mailman/listinfo/uClinux-dev web方式。
(4) 采用以上开发模式,软件的可维护性,可移植性和可扩展性都不错。
(5) 目前该CPU使用还是比较普遍,现货没问题。
(6) 方案提供商的素质吗……..还算可以吧:-)
根据以上考虑和目前的开发情况,这套方案还是比较令人满意。
今天先回家了,下回介绍具体开发步鄹吧。
2.开发环境的建立。
先说两句废话为和我以前一样对操作系统(尤其是嵌入式操作系统)迷惑的弟兄解释些概念。因为总是有人在问是不是一定要用操作系统,我的CPU能不能移植操作系统,可以移植什么操作系统,有了操作系统可不可以运行某些程序。
从我的个人经历来讲,这其实就是许多硬件出身的弟兄对操作系统这个东西有神秘感(和我一年前一样)。说白了,操作系统就是一段设计非常巧妙的程序,和你自 己的程序从本质讲没有区别,于是,以上问题转为,我是不是一定要用这段程序,我的CPU能不能运行这段程序,可以跑什么样的程序。这个程序可以跑,调用这 个程序接口的另一个程序能不能跑!
答案也就变得简单,操作系统对任何一个CPU都不是必须的(对嵌入式系统更是如此),你可以自己编些程序在没有操作系统的PC裸机上跑(BIOS就是这样 的),像玩C51一样,(虽然奢侈的让人有些心痛),或者移植UCOS到上面。另一方面,现代操作系统大多需要一些硬件的支持,(像保护模式的实现),反 过来说,高端CPU中专门有针对支持操作系统的体系结构,这样,许多操作系统的实现是挑剔硬件平台的。其实其它程序也一样,你编的程序使用的片上外设另一 CPU上没有,那这段程序就无法移植了。这就是话粗理不粗。书归正传,还是聊聊ARM+uClinux开发模式下开发环境的建立(其实下面说到的东西不仅 限于这种硬件平台和操作系统)
很久以前就在介绍嵌入式系统开发的书上见过“交叉编译环境”这词,当时觉得很玄,用了以后才知道,其实就是解决在谁的地盘上用谁的工具编谁的代码问题。
编译的最主要的工作就在将你的程序转化成运行该程序的CPU所能识别的机器代码,不同的CPU有相应的编译器,另一方面。编译器本身也是程序,当然也要在 某一个CPU平台上运行。于是交叉编译的交叉点就在那个编译器本身是CPU1上的一个程序,却在为CPU2编译代码(整个一个吃里扒外!)。这么一想,以 前用51和dsp的开发软件(大部分都是IDE-集成开发环境)开发程序时,都算是交叉编译啦。当然,假如在你的ARM系统上,操作系统已经正常运行,并 且你的资源足够多,你可以把PC机上运行的ARM编译工具移植到ARM上,然后所有该系统的应用程序都直接在ARM系统上编译,这就不算交叉编译,但如果 有条件这么作,程序的开发或者移植就方便多了,因为整个开发过程又回到在自己PC机上编应用程序的那种模式了,那就是在自己的地盘上用自己的编译器编自己 的应用程序。
与不使用操作系统的开发模式不同(此处的操作系统尤其指提供了专门的接口函数库的操作系统,目前的UCOS就不算),在目标板(就是实现系统的板子)使用 操作系统的开发模式下,交叉编译环境中还需要该对应该操作系统的库。比如uClinux提供的uClibc。此时,开发用的主机上不光要有目标板CPU所 需的编译工具,还要有对应操作系统的库,又因为一般库文件还要在开发机上拿目标CPU的编译器重新编译一下,所以还要把操作系统的原码也放到开发机上。 (唉,跟目标板没什么关系,却要帮它背这么多东西,真是上辈子欠它的!!)。
虽然操作系统的接口库至关重要,但大家似乎已经淡忘了它的存在。这些多是因为大家已经远离了刀耕火种的年代(需要告诉编译器需要的include路径, lib路径,以及lib的名称),集成的编译环境让我们编译链接的所有繁琐工作化作对BUILD按钮的潇洒一击。而且不论是windows环境,还是 linux环境,都有环境变量去记录这些参数。。但尝试将/usr/lib目录改一个名字,你就会知道你不能无视他们的存在,因为操作系统的功能都是通过 这些库来交给应用层程序使用的。当然如果你的系统不依靠任何操作系统,像最原始的那种完全自己实现所有代码,就只需要一个编译工具,少了这些罗嗦事。
以上的东西一般时候是没有必要仔细研究,但交叉环境下开发或移植比较大的程序时,你可能就需要了解编译器,链接器等开发工具的几乎所有重要参数。
我在开发时,主机完全使用的是linux,如果有条件,建议大家这样作,linux的使用没有想象的复杂(虽然我现在身边还要放一本关于linux使用的 书籍),而且开发程序可以先在主机上调通,然后用交叉编译工具为目标系统重新编译一遍,可以这样做是因为主机是linux,目标系统跑uClinux,两 个操作系统提供的应用程序接口几乎是一样的,所以程序几乎不用修改。
在我的系统上,建立基本的开发环境过程如下。
(1) 安装gnu开发工具链(是GNU开发的针对ARM CPU的一组编译开发程序(是linux程序)。包括arm-elf-gcc,arm-elf-ld等
(2) 将uClinux源代码源代码解压到相应路径下,按照编译内核的步鄹编译一遍(此时使用的编译工具已经是上面提到的ARM编译工具了,因为它要在ARM CPU上运行,另外,和编译linux内核一样,此时可以通过menuconfig来对内核提供的功能进行裁减
(3) 将库(uClibc)解压到相应路径下,用以上工具编译一遍。
这样最基本的环境就算搭建好了。
以上工作对于做过的人来说比较简单,这里介绍一下帮助没有使用或刚开始使用这种开发模式的弟兄们理清一下思路。
3.应用程序的开发
因为目标板上用uClinux,它提供的程序接口和linux下的基本一致,不一致的部分主要在于uClinux不支持MMU(应该说是uClinux是 为不带MMU的cpu定制的),最明显的就是fork函数要用vfork函数替代,这也是编程时,感觉最不爽的一点(没办法,谁让咱们的CPU有生理缺 陷)。另一个不易觉察的差异在于uClinux提供的库uClibc是经过裁减的。更适合于资源紧张的嵌入式系统(上回分解已经说了,应用程序很大一部分 是在和库函数打交道,而且大家最终是链在一起,所以库函数大了,你的程序也小不了)。
于是基于这种开发模式的应用程序开发变成了linux下的程序开发。而且在实际中一般是编好了程序先在主机上拿主机平台上的编译器编译并且调试一下 (linux下的编译器就是gcc了),当然前提是被调试的程序中需要的硬件条件主机具备,例如我的程序中有一段是针对串口的,于是先在主机编一个串口程 序,调通以后拿目标板的编译器重新编译一下(如果看了上一章“交叉编译环境”,这里就不会晕了),下载到目标板上运行,一般来说就可以直接用了。
以上也是为什么我认为开发嵌入式linux 程序主机应该选用 linux环境。对于以前没用过linux的人来说(比如我),开发程序前应该花3,4天时间熟悉linux环境,尤其是它的编辑器,用惯集成编译环境的 人有时连编译器和编辑器的概念都模糊了,所以一般是直接进入集成编译环境,连写带编一气呵成,殊不知有些集成编译器提供的编辑器弱智的一塌胡涂,如果用熟 了linux下的emacs,你就会发现他们之间的差距大概……要像我和盖茨那么大吧。所以编程序时应该选一款优秀的编辑器,linux下,我当然选 emacs,虽然刚看见它的感觉是外表丑陋,使用复杂。但只要多用多练,对提高效率很有帮助。(将你的程序用两个编辑器完成,一半是用emacs的,一半 是不用emacs的,看看效果:-)
对具体的linux编程我就不板门弄斧了,需要提个醒的是咱硬件出身的人作软件应该养成良好的编程习惯,别让作软件的笑话咱。因为作了些网络应用,所以介绍一些网络编程时要用到的网站和书籍;
<>w.Richard.Stevens. 这可是linux网络编程的圣经级的书籍
::URL::http://www.fanqiang.com/a4/b7/ 适合于网络编程的入门。
还有IBM中国上关于linux的教程和文章,都是翻译过来的,有很多写非常不错。
其实类似的资源不计其数,遇到问题时应该先到google上狂搜一圈。
重点想说些关于编译器的东西,不了解它,在交叉编译环境下编译程序就寸步难行了,这无非是因为交叉编译环境下目标板编译器所处的寄人篱下的悲惨环境。想想 在 linux下将myprogram.c编译链接成应用程序myprogram,最简单的一句 gcc –o myprogram myprogram.c 就可以了。(其实在诸如VC下你也可以找到类似的命令,集成开发环境只不过替你来调用它了)。一切看起来天经地义。
但试着把/usr/include路径改一个名字(比如改成stupid_include),再这样编译一下,会发现程序中被< >引用的头文件(比如#include)都找不到了。因为编译器看见这样的头文件会到系统指定的路径下寻找,而这个路径是由环境变量保存的 (linux和windows下都是这样的)。针对以上情况,不将路径名字改回去,但是给编译器加一个参数如下:
gcc –I/usr/stupid_include –o myprogram myprogram.c 会发现错误信息没了,一切又恢复了往日的宁静,顿时明白,不用环境变量,通过参数,同样可以将这些信息告诉编译器。返回来说说你的目标编译器,虽然占用了 人家的地盘,编译器,头文件,库文件,一个都不少,但你要编一个程序编译器照样发晕,因为没有环境变量告诉它自己需要的头文件和库文件在哪里。看来只有两 种办法,一个是抢占了主机的环境变量改成自己的(整个儿一个土匪),或者在编译时加上必要参数(还是这样绅士一些),告诉编译器需要的文件的位置。(除此 之外,还有其他一些参数也是如此)。
从源程序到可执行文件根据情况不同可能分好几步,一般每一步可能都会有一个应用程序实现,像gnu提供的arm开发工具链其实就是这么一组程序。提供从编 译到链接到格式转化的全套服务。你可以用arm-elf-gcc命令一步到底直接产生可执行文件(其实也是在自己的任务完成后调用下一个程序),也可以每 一步加上自己的参数,只作自己的事。
编译器的主要参数的使用下次将程序的移植时再讲。这里想说一下编译器产生应用程序的几个主要步鄹,讲这个问题的原因还是很多人无法区分诸如编译和链接,不 用问,这一切还是IDE集成开发环境惹的祸。有人会说,IDE招你惹你了,你老贬它。其实不然,首先以上说的东西一般在IDE的project菜单下的 option或build option中找到,只是一般不用管罢了。另一个方面,IDE就像是傻瓜照相机,很多工作他都帮你完成了,使用简单。但如果要做摄影师的话,你就少不了要 对每一个细节都了解。其实编译程序也是一样。(你可以对优化,警告级,宏定义等诸多选项进行自己的选择)。以下是几个主要步鄹:(以下有些我也不确认,如 发现问题,请及时纠正。
(1) 预编译。主要工作就是处理所有#开头的,包括头文件。以前搞不清头文件和可执行文件有没有什么联系(因为总看见两个文件名字取一样的),现在知道,他们之 间没有任何联系。在预编译结束后,头文件的使命就结束了。在下一次介绍不同平台程序移植时可以看到,预编译有时非常有用。
(2) 编译。编译应该是最主要的一步,就是将源文件生成CPU能识别的语言,一般是后缀为.o的目标文件,应该说,此时的文件就已经可以执行了。当然这个时候外 部函数等外部符号都没有引入,对于被编译程序来说,这些外部符号还只是留一个倩影,压根儿不知它在不在。你可以在你的程序里调用一个不存在的函数,甚至都 不用声明,在编译阶段,很多编译器只是给个警告。只有在链接时才会报错。(呵呵,够弱智!)
(3) 链接:链接才是清帐的时候,以前在程序里用到的外部符号都要把真正的东西交出来。你可以指定需要连接在一起的目标文件,也可以告诉编译器库文件的名字和路 径(指定方法下次讲)。编译器会去找,需要注意的是,库的指定需要注意顺序。首先,如果不同的库里有同名函数,并且该函数被调用,那么在前面的就被链接进 去了,这一点对于头文件路径的指定也适用,如果你自己的头文件和系统头文件相同,并且你的头文件路径在系统头文件路径前面,你的头文件就会代替头文件。库 文件是由相应的程序(linux下是ar命令)将需要被添加到库里的目标文件(该文件是编译阶段生成的)组织起来生成档案文件,同时可以建立一个检索,检 索内容为所包含的目标文件中定义的符号。也就是说,库文件并不是必须的,但它为经常使用的目标文件中的函数提供了快速的检索机制。
以上就是主要的步鄹,当然除此之外,还有一些用于格式转换的工具等。不一一介绍。知道编译器的细节对于程序的开发和移植都是很有好处的。
程序开发过程中调试也是至关重要,因为可以先在主机上调试,所以可以使用linux下的gdb,(有点像dos 下的debug)。但是只是用到了皮毛,还有一个专用于宿主机模式的调试工具gdbserver,一直没时间研究,希望用过的大侠多发些文章铺路。
另外还会遇到如何作ramdisk,如何让系统启动自己的程序,这些都太linux了,没接触过linux的人会晕,为了大家的健康,就不讲了,遇到问题可以给我email,大家一起讨论。
4.不同平台间程序的移植--简单程序的移植
研究程序移植的那两周是最痛苦的两周,没有太多可以借鉴的东西,只能摸黑向前走,于是更加坚定决心要整理些东西给后来的弟兄。不过话说回来,各位弟兄别被我前面说的吓倒,只要搞清你要作什么,程序移植其实是比较简单的事情。
首先列出一些问题:
(1) X86上运行的程序能不能在51单片机上运行,为什么,有没有可能,如果可以,应该做哪些工作才可以实现。
(2) 相同CPU平台,DOS的程序为什么可以在windows下运行,能不能在linux下运行,为什么,作什么工作可能实现。
为什么可以移植程序,为什么要移植程序?
程序可以移植首先要感谢开发出高级语言的大牛们,记住,无论多么漂亮的代码经过编译以后都要变成CPU可以识别的机器语言,而几乎一千种CPU说着一千种 语言。为保证大家有共同语言,规定一种高级语言――高级语言。每一个CPU派出自己的翻译――编译器。这个翻译精通两国语言,高级语言和自己的语言。(由 此已经可以看出编译工具在程序移植中的重要性)。只要程序没有硬件上的约束,可以说这种沟通是无极限的,甚至于不同操作系统平台。(操作系统也是程序,也 可以移植喽)举例:在x86的windows下用VC(或TC,BC)编一个c程序实现i=i+1,丝毫不改就可以用51的C编译器重新编译并在51单片 机上运行。一次小型的移植就结束了。
可以移植已有的程序还要感谢开放源代码的弟兄,没有这些C文件和H文件让你重新编译一下,怎么在你的CPU上跑?其实不止这些,后面还会看见开源组织的牛人专为程序可移植性所作的专门的工作。
那么为什么要移植程序?
问这问题就像问地上有个钱包为什么要捡一样,答案不言而喻。现成的东西为什么不要。当然,移植程序可没有捡钱包那么简单,尤其是第一次,后面会说一些移植 之前应该考虑的问题。(就像现在地上有个钱包也千万别上去就揣自己兜里,说不定就是套)。另一方面,你给我你写好的程序让我拿去用,我还要考虑一下,或许 里头问题多的还不如自己写一个。我这里所说的可移植的程序应该是维护比较好,比较成熟的源代码(像我后面的所说的UCD-SNMP),目前的开放源代码运 动决不仅仅是把自己的程序公开就行了,而是有了一套成熟完整的版本控制,BUG报告和PATCH提交流程。
这样的代码才有更大的使用价值。
什么时候可以考虑移植程序? 在基于嵌入式操作系统进行开发时,具有一定规模的程序都可以到网上查一查都没有成熟的源代码可用。前面已经说到,程序的移植最终只针对CPU,其实和操作 系统没什么关系,但另一方面,因为代码中可能会使用一些库函数,这些库会包括C语言标准库和操作系统提供的API(应用程序接口)库。假设源代码中只包括 C标准库,那么该程序就可以跨操作系统去移植。例如hello world程序中使用了printf,因为该函数是C标准函数,所以在X86上使用TC(BC或VC)可以直接编译运行,在ARM+uClinux平台下 也一样,但如果程序中调用了vfork函数,那么只有 linux一脉相承的操作系统支持这种特殊服务了,在window或dos操作系统下无法直接编译该程序了。只能找该操作系统支持的类似的功能来实现。再 进一步,硬件上的生理缺陷也会为移植带来麻烦,S3C4510B不支持MMU,在其上运行的uClinux也不提供和MMU有关的服务(其实 uClinux本身可以支持MMU),于是在移植前相关的函数(比如FORK)都要被替代掉(使用VFORK)。好在uClinux和linux提供的应 用接口大部分还是相同的。所以这样的工作还可以承受。
由上可知,如果是在各种嵌入式linux(除了uClinux以外,还有好几种)平台上开发,那么针对该平台以及linux平台上的源代码都可以使用,但 是要牢记他们之间的差异。在我的系统中需要实现网络监控,所以想使用snmp协议,该协议和http,ftp一样属于应用层的成熟协议,专用于网络管理。 目前已经有一些针对该协议成熟的代码,最有名的是ucd- snmp,不光软件本身功能强大,可移植性也比较好,在linux,unix等平台上都可以移植,于是决定将它移植到ARM+uClinux平台上(别看 现在说的这么轻松,当时接这活时都有点哆嗦)。
简单总结一下,移植应用程序的前提是有源代码,移植的关键工具是编译器,源代码中和硬件平台相关的东西越少越好(这里主要指使用了汇编,或做了针对自己平 台的事,比如将指针指向特定地址然后操作),另一方面,如果该程序是基于某个操作系统(利用了操作系统提供的特殊服务,即API),要看自己的操作系统是 否提供了相关服务。
下面简单列出一些我认为移植时需要考虑的问题:
(1) 自己的操作系统的特点以及在当前版本下支持的特性。
例如:uClinux不支持MMU,同样就无法支持相应的特性。
(2) 硬件资源。
因为嵌入式系统资源比较紧张,硬件资源考虑必须要周全:
(1) 软件存储空间的大小
这一般要等用目标编译器重新编译完以后可能才会知道,所以只能大概估算,但千万不要看这个程序在linux下只有几十k,就认为程序很小,这是因为linux下程序多时使用动态库,而在嵌入式系统中,很有可能是把用到的库都链接在一起,所以程序的尺寸会大大增加。
(2) 程序运行空间。.
(3) 硬件以及相应的驱动是否完备
以上工作应该尽量做,但有时事先无法把握,只能听天由命了(有没有搞错!!)
可能有人已经要晕菜了,振奋一下大家,如果找到了好的源代码(可移植性好),那么剩下的如要工作就是玩转你的编译器,只要你能顺利的把源代码用你的编译器重新编译一下。90%的工作就完成了(不是吗)
上回已经介绍了一些编译器方面的东西,下面针对我的ARM编译器的具体参数来讲解一些编译器主要参数的设置。
加入我已经有了hello.c,在x86的linux平台下编译链接一下。
gcc –c hello.c 产生.o
gcc –o hello hello.o 产生可执行文件,上回说过,主机编译器参数都有环境变量保存,所以看起来很简单。这里我故意分两个步鄹。
下面看一下用我的编译器编这个程序(心脏不好的先吃药)。
arm-elf-gcc -Iroot/uClibc/include -msoft-float -mcpu=arm7tdmi -fomit-frame-pointer -fsigned-char -mcpu=arm7tdmi -Os –Wall -DEMBED -D_uClinux_ -c hello.c
这只是编译,将参数逐一讲解。
Arm-elf-gcc 是gnu的arm编译工具
1)Include地址:参数:-I 值:root/uClibc/include(这是在主机上我的uClinux的头文件路径) 用法:-I root/uClibc/include
-I参数保证后面的头文件路径在搜索系统头文件路径前被搜索从而有可能替代系统的头文件,如果有多个这样的参数,则搜索的顺序是从左到右,然后是系统的头文件。
2)-m 是针对CPU的选项。
-mcpu=arm7tdmi 说明CPU类型
-msoft-float 产生包含浮点库的输出
-fsigned-char 让char类型有符号
-fomit-frame-pointer 对所有不需要帧指针的函数都不将其保存在寄存器中。
3) -Os –Wall
-Wall:所有警告都显示
Os:优化尺寸,该选项使能所有所有不增加尺寸的O2优化,并且进一步根据尺寸优化
4) = -DEMBED -D_uClinux_
-D: 将-Dmacro 后的macro定义为字符串1。
以下是链接:
arm-elf-ld -L/root/uClibc/lib -L/usr/local/gnu/arm-elf/lib -L/usr/local/gnu/lib/gcc-lib/arm-elf/3.0.1 -elf2flt –o hello /root/uClibc/lib/crt0.o /usr/local/gnu/lib/gcc-lib/arm-elf/3.0.1/crtbegin.o hello.o
/usr/local/gnu/lib/gcc-lib/arm-elf/3.0.1/crtend.o -lc -lgcc –lc
其中
1) 链接工具: arm-elf-ld
2) -L指明需要链接的库的路径,用法和-I一样,自己的库的路径也可以在这里加入。 -L/root/uClibc/lib -L/usr/local/gnu/arm-elf/lib
-L/usr/local/gnu/lib/gcc-lib/arm-elf/3.0.1
3) –o 后面紧跟生成的最终的文件名
4)/root/uClibc/lib/crt0.o /usr/local/gnu/lib/gcc-lib/arm-elf/3.0.1/crtbegin.o OBJECTS.o
/usr/local/gnu/lib/gcc-lib/arm-elf/3.0.1/crtend.o
这是需要链接在一起的.o文件
5) -lc -lgcc –lc -l 后面紧跟的是需要链接的库的名字,一般库的名字是libxxx.a,使用时为-lxxx即可,不加lib和.a。还要注意位置,自己的库文件应该加在他的库前面。
编译通过后,移植就算完成了,对于比较小的源代码都可以这样,即先分析他的编译选项(用到了那些头文件,库文件等),然后用自己的编译器对照相应参数重新编译一下就行了。
当然这只是简单程序的移植,复杂案例在下一次讲吧。