先和大家聊一聊我对于系统移植学习的感悟,之前在老师的带领,我们移植系统的时候执行了一条条指令,但是总感觉哪里有一些问题又说不出来,这些指令都解决了很多问题;但是说到底,自己却不明白这些指令到底是怎么去实现的,这样一套学习下来达不到真正学习系统移植的目的,最重要的还是应该培养一种解决问题的思维,老师不可能随时在身边,上班了需要我们亲自去解决系统移植过程中遇到的问题。
以后我们在做每一步的时候,都必须想清楚,我到底在干什么?我要解决什么问题?搞明白这些,以后不管我们在什么开发环境中,拿到什么芯片板子,都会有自己的思路去上手。
好了进入正题,fristly:什么是系统移植?
相信很大部分人曾今都有抱着自己的电脑,去找修电脑的重装系统吧,维修人员拿着大白菜u盘往你电脑一插,一会功夫收费20。其实这也是系统移植,但是我今天要说的不是教大家怎么去赚这20块钱,而是在我们今后的工作中如何给我们拿到手的一个全新开发板移植一个系统。
所以系统移植就是:让系统在一个全新的板子上可以运行起来。
分开来看,
系统:指操作系统
移植:在植物层面上来说就是嫁接,甚至可以把不同植物的枝相互嫁接;在动物层面上来说移植,大家都知道器官移植,必须要求两个人之间相似度极其吻合,不然会出现强烈的排异性导致移植不成功,还必须一直服用避免排异的药物。
那么对于我们全新的开发板来说,系统移植也要衡量新旧板子之间的相似程度。
一般我们这样来认为:CPU一致,RAM最好相似,FLASH最好相同。
所以,我们系统移植的工作量也由这里来决定,越相似,我们移植干的事情越少。
这就是系统移植。
嵌入式的Linux系统移植主要由这四大部分组成:
1.搭建交叉开发环境
2.bootloader的选择和移植
3.kernel的配置,编译和移植
4.根文件系统的制作
一.移植的“手术台”——环境搭建
搭建交叉开发环境,按照开头对于我学习的心得,这里就有两个问题出现了。
1.什么是交叉开发环境?
在嵌入式开发中,交叉开发是很重要的一个概念,开发的第一个环节就是搭建环境,第一步不能完成,后面的步骤从无谈起,这里所说的交叉开发环境主要指的是:在开发主机上(通常是我的pc机)开发出能够在目标机(通常是我们的开发板)上运行的程序。嵌入式比较特殊的是不能在目标机上开发程序(狭义上来说),因为对于一个原始的开发板,在没有任何程序的情况下它根本都跑不起来,为了让它能够跑起来,我们还必须要借助pc机进行烧录程序等相关工作,开发板才能跑起来,这里的pc机就是我们说的开发主机,想想如果没有开发主机,我们的目标机基本上就是无法开发。
2.为什么需要搭建交叉开发环境?
就像我们人做手术移植一样,没有手术室保证手术工具和手术室的消杀灭菌环境是无法顺利完成器官移植的。那么在嵌入式中,也有它自己的原因。
(1)嵌入式系统的硬件资源有很多限制,比如cpu主频相对较低,内存容量较小等,想想让几百MHZ主频的MCU去编译一个Linux kernel会让我们等的不耐烦,相对来说,pc机的速度更快,硬件资源更加丰富,因此利用pc机进行开发会提高开发效率。
(2)嵌入式系统MCU体系结构和指令集不同,因此需要安装交叉编译工具进行编译,这样编译的目标程序才能够在相应的平台上比如:ARM、MIPS、POWEPC上正常运行。
嵌入式linux交叉开发环境硬件基本组成:
1.开发主机Host(pc机)
2.目标机Target(开发板)
3.连接介质(串口线,USB线,网线)
对于串口线:通常我们用串口调试助手,功能很多也都不差,所以不建议各位大佬手写裸机串口驱动了哈。
对于USB线:必须要有USB的驱动才可以,一般对应的芯片公司会提供,对于三星的fs4412,USB下载主要由DNW软件完成
对于网线,则必须要用到网络协议,常用的是tftp和nfs,我最常用的是tftp。
tftp:
主要用于实现文件的下载,比如开发调试的过程中,主要用tftp把要测试的bootloader、kernel和文件系统直接下载到内存中运行,而不需要预先烧录到Flash芯片中,一方面,在测试的过程中,往往需要频繁的下载,如果每次把这些要测试的文件都烧录到Flash中然后再运行也可以,但是缺点是:过程比较麻烦,而且Flash的擦写次数是由限的;另外一方面:测试的目的就是把这些目标文件加载到内存中直接运行就可以了,而tftp就刚好能够实现这样的功能,因此,更没有必要把这些文件都烧录到Flash中去。
nfs:
主要用于实现网络文件的挂载,实际上是实现网络文件的共享,在开发的过程中,通常在系统移植的最后一步会制作文件系统,那么这是可以把制作好的文件系统放置在我们开发主机PC的相应位置,开发板通过nfs服务进行挂载,从而测试我们制作的文件系统是否正确,在整个过程中并不需要把文件系统烧录到Flash中去,而且挂载是自动进行挂载的,bootload启动后,kernel运行起来后会根据我们设置的启动参数进行自动挂载,因此,对于开发测试来讲,这种方式非常的方便,能够提高开发效率。
另外,还有一个名字叫samba的服务也比较重要,主要用于文件的共享,这里说的共享和nfs的文件共享不是同一个概念,nfs的共享是实现网络文件的共享,而samba实现的是开发主机上Windows主机和Linux虚拟机之间的文件共享,是一种跨平台的文件共享,方便的实现文件的传输。
以上这几种开发的工具在嵌入式开发中是必备的工具,对于嵌入式开发的效率提高做出了伟大的贡献,因此,要对这几个工具熟练使用,这样你的开发效率会提高很多。等测试完成以后,就会把相应的目标文件烧录到Flash中去,也就是等发布产品的时候才做的事情,因此对于开发人员来说,所有的工作永远是测试。关于网络连接的选择:
1.选择tftp
使用条件:
(1)需要网络
(2)主机端需要安装tftp服务器软件
(3)目标机需要实现tftp客户端
优点:
(1)传输速度快
(2)可以将编译好的内核下载到目标机,提高开发效率
tftp是用来下载远程文件最简单的网络协议,它基于udp协议而实现,嵌入式linux的tftp开发环境包括两个方面:
(1)Linux开发主机端的tftp-server支持
(2)嵌入式目标系统的tftp-client支持
主机端tftp服务器的配置:
(1)检查是否安装tftp server
#dpkg -s tftpd-hap
(2)如果未安装,则安装tftp-server
#apt-get install tftpd-hpa tftp-hpa
(3)修改文件vim/etc/default/tftpd-hpa
#sudo vi /etc/default/tftpd-hpa
除了路径外配置成这样
(4)创建tftpboot目录,启动tftp-server
#mkdir /tftpboot
#chmod 777 /tftpboot
#service tftp-hpa restart
(5)登录本机测试,命令如下:
#tftp 127.0.0.1
tftp>get
tftp>put
tftp>q
tips,nfs在最后一步根文件系统制作再来说。
交叉编译工具链
这里又有一个问题,不就是一个交叉编译工具吗?为什么又叫交叉工具链呢?原因很简单,程序不能光编译一下就可以运行,还得进行汇编和链接等过程,同时还需要进行调试,对于一个很大工程,还需要进行工程管理等等,所以,这里 说的交叉编译工具是一个由编译器、连接器和解释器组成的综合开发环境,交叉编译工具链主要由binutils(主要包括汇编程序as和链接程序ld)、gcc(为GNU系统提供C编译器)和glibc(一些基本的C函数和其他函数的定义) 3个部分组成。有时为了减小libc库的大小,也可以用别的 c 库来代替 glibc,例如 uClibc、dietlibc 和 newlib。
那么,如何得到一个交叉工具链呢?是从网上下载一个“程序”然后安装就可以使用了吗?回答这个问题之前先思考这样一个问题,我们的交叉工具链顾名思义就是在PC机上编译出能够在我们目标开发平台比如ARM上运行的程序,这里就又有一个问题了,我们的ARM处理器型号非常多,难道有专门针对我们某一款的交叉工具链吗?若果有的话,可以想一想,这么多处理器平台,每个平台专门定制一个交叉工具链放在网络上,然后供大家去下载,想想可能需要找很久才能找到适合你的编译器,显然这种做法不太合理,且浪费资源!因此,要得到一个交叉工具链,就像我们移植一个Linux内核一样,我们只关心我们需要的东西,编译我们需要的东西在我们的平台上运行,不需要的东西我们不选择不编译,所以,交叉工具链的制作方法和系统移植有着很多相似的地方,也就是说,交叉开发工具是一个支持很多平台的工具集的集合(类似于Linux源码),然后我们只需从这些工具集中找出跟我们平台相关的工具就行了,那么如何才能找到跟我们的平台相关的工具,这就是涉及到一个如何制作交叉工具链的问题了。
通常构建交叉工具链有如下三种方法:
方法一 :分步编译和安装交叉编译工具链所需要的库和源代码,最终生成交叉编译工具链。该方法相对比较困难,适合想深入学习构建交叉工具链的读者。如果只是想使用交叉工具链,建议使用下列的方法二构建交叉工具链。
方法二: 通过Crosstool-ng脚本工具来实现一次编译,生成交叉编译工具链,该方法相对于方法一要简单许多,并且出错的机会也非常少,建议大多数情况下使用该方法构建交叉编译工具链。
方法三 :直接通过网上下载已经制作好的交叉编译工具链。该方法的优点不用多说,当然是简单省事,但与此同时该方法有一定的弊端就是局限性太大,因为毕竟是别人构建好的,也就是固定的,没有灵活性,所以构建所用的库以及编译器的版本也许并不适合你要编译的程序,同时也许会在使用时出现许多莫名其妙的错误,建议读者慎用此方法。关于LINUX和ARM的交互编译,我用的是arm-linux-gcc