构建嵌入式Linux系统
1.取本实验相关的软件包
到ftp下载以下软件包:
文件名 |
备注 |
binutils-2.16.1.tar.bz2gcc-4.0.2.tar.bz2 glibc-2.3.6.tar.bz2glibc-linuxthreads-2.3.6.tar.bz2 linux-2.6.15.4.tar.bz2linux-libc-headers-2.6.12.0.tar.bz2 |
制作交叉编译工具链所需的源码包 |
crosstool-0.43.tar.gz |
制作交叉编译工具链的脚本和补丁 |
crosstool.tar.bz2 |
已制作好的交叉编译工具链,需要解包到/opt目录使用 |
linux-2.6.27.tar.bz2 |
内核2.6.27 |
patch-2.6.27-aka |
针对2440开发板制作的内核patch |
zImage |
已编译好的内核,可直接下载到开发板 |
rootfs-basic.tar |
基本根文件系统打包,由于有设备文件,所以解包需要root权限 |
rootfs-basic.cramfs |
采用cramfs文件系统格式的基本根文件系统映像,可直接下载到开发板 |
busybox-1.9.1.tar.bz2 |
busybox源码包,嵌入式根文件系统基本命令集 |
sqlite-3.4.0.tar.gz |
sqlite源码包,嵌入式数据库 |
libcgi-1.0.tar.gz |
libcgi源码包,用于编写CGI程序的C函数库 |
qtopia-core-opensource-src-4.2.2.tar.gz |
QtopiaCore源码包,Qt的嵌入式版本 |
2.交叉编译工具链
要做嵌入式Linux开发,首先需要有交叉编译工具链(crosscompiling toolchain),也就是在主机(x86PC)上可编译生成目标板可执行文件(ARM指令)的编译工具。和普通的编译工具链一样,交叉编译工具链也包括编译、链接、修改目标文件的各种程序,如gcc、glibc、ld、gas、objdump、readelf等等。交叉编译工具链本身也是需要编译生成的,要得到一套完整的交叉编译工具链需要编译以下源码包:
binutils
gcc
glibc
linux(内核)
linux-libc-headers
glibc-linuxthreads
这些源码包具有非常强的版本依赖关系,如果源码包的版本不匹配,在编译过程中会出现各种各样的问题,有些问题需要对源码做些修改或者打补丁,有些问题则是没有解决办法的,只能更换匹配较好的版本。编译的步骤也是比较复杂的,主要有以下几步:
根据目标平台配置内核源代码,生成内核头文件
编译binutils
编译器的自举(bootstrap),也就是先编译出gcc的部分功能(没有glibc支持,只有C编译器没有C++编译器)
编译glibc
编译完整的gcc
幸运的是,已经有人写出了制作交叉编译器的脚本(http://www.kegel.com/crosstool),该脚本中提供了一系列源码包版本的匹配方案,使用者需要选择目标平台和源码包的版本匹配方案,执行该脚本会自动从官方网站(http://www.gnu.org/和http://www.kernel.org/)下载源代码,自动打补丁,然后自动完成所有的编译步骤。
首先从http://www.kegel.com/crosstool下载crosstool-0.43.tar.gz,在主目录下解包
~$tar xf crosstool-0.43.tar.gz; cd crosstool-0.43
现在选择一种源码包的版本组合,各种版本组合的兼容性可以参考http://www.kegel.com/crosstool/crosstool-0.43/buildlogs/,在此我们选择在arm平台上glibc版本较高,兼容性较好的一个组合:
gcc-4.0.2
cgcc-4.0.2
glibc-2.3.6
binutils-2.16.1
linux-2.6.15.4
hdrs-2.6.12.0
修改crosstool-0.43目录下的脚本demo-arm.sh,取消这一行开头的#号注释符:
#eval`cat arm.dat gcc-4.0.2-glibc-2.3.6.dat` sh all.sh --notest
同时将原本没有注释的这一行注释掉(前面加#号):
eval`cat arm.dat gcc-4.1.0-glibc-2.3.2-tls.dat` sh all.sh --notest
注意该脚本开头有
TARBALLS_DIR=$HOME/downloads
RESULT_TOP=/opt/crosstool
这说明,该脚本运行时,自动从http://www.gnu.org/和http://www.kernel.org/下载相关的源码包到主目录的downloads目录下,如果你已经下载过这些源码包,将它们拷到downloads目录下就可以不必再次下载了。对应于我们选择的版本组合,downloads目录下的源码包有:
binutils-2.16.1.tar.bz2
gcc-4.0.2.tar.bz2
glibc-2.3.6.tar.bz2
glibc-linuxthreads-2.3.6.tar.bz2
linux-2.6.15.4.tar.bz2
linux-libc-headers-2.6.12.0.tar.bz2
整个编译结束后,交叉编译工具链将放在/opt/crosstool目录下,因此脚本需要在/opt下建子目录,如果不希望使用root权限运行该脚本,则需要事先给/opt目录设置写权限:
~$sudo chmod a+w /opt
然后修改arm.dat,其中有
TARGET=arm-unknown-linux-gnu
这是按标准的命名规则为工具链命名的,但是通常我们都采用更简单的命名,很多软件的Makefile中交叉编译器默认也都采用简单的命名,为此我们把它改为TARGET=arm-linux。
由于编译过程需要用到patch、bison、flex,确认你的系统中安装了这些软件包。
在编译过程中可能还会遇到脚本的兼容性问题,如果你的Linux发行版将sh指向dash(例如Ubuntu),应将其改指向bash:
$cd /bin
$sudo ln -sf bash sh
虽然用dash执行脚本时非常高效并且其实现完全遵守POSIX标准,然而现存的很多脚本(比如glibc中的脚本)有不符合POSIX标准的用法,所以仍需改用bash执行。
准备就绪后,在crosstool-0.43目录下运行demo-arm.sh脚本开始编译。编译完成后,交叉编译工具链的可执行文件位于/opt/crosstool/gcc-4.0.2-glibc-2.3.6/arm-linux/bin目录,我们可以把这个路径添加到PATH环境变量中,例如将以下命令添加到~/.bashrc启动脚本:
exportPATH=$PATH:/opt/crosstool/gcc-4.0.2-glibc-2.3.6/arm-linux/bin
此外,网上也可下载到已编译好的交叉编译工具链,比如http://www.snapgear.org/snapgear/downloads.html,但是使用别人编译好的交叉编译工具链有很多限制,不能按自己的特殊需要对其定制,比如有些项目需要特定版本的gcc和glibc,再比如需要soft-float的编译器(生成指令模拟浮点数运算)。
以上编译步骤需要很长时间,也可以直接从ftp下载已制作好的交叉编译工具链安装到主机:
~$sudo chmod a+w /opt
~$tar xf crosstool.tar.bz2 -C /opt
然后在~/.bashrc启动脚本中修改PATH环境变量。
3.熟悉开发环境
3.1U-boot的基本使用方法
连接好开发板的网线和串口线,启动minicom(配置成1152008N1,无FlowControl)。按下开发板电源,立刻按除回车以外的任意键,进入bootloader提示符AKAE2440#。如果没来及按键就已经启动了内核,可以按开发板上的RESET键重来。
注意:u-boot的终端不能处理控制字符,不要用移动光标键或翻页键等,退格键可以用。按了产生控制字符的键再输入命令就会产生错乱,这时可以按下回车输入当前这条已经错乱的命令,然后在新的提示符下重新键入命令。
输入printenv命令显示bootloader的参数。
更改参数使用命令set或者setenv,如下图所示:
上图中,
setenv ipaddr 192.168.1.22表示设置开发板的IP地址为192.168.1.22。
setenv netmask 255.255.255.0表示设置子网掩码为255.255.255.0。
setenv serverip 192.168.1.21表示设置与开发板相连的PC机IP是192.168.1.21。
可以根据你的情况重新设置。为了统一起见,在后面的实验中,我们统一设置为:
AKAE2440#set ipaddr 192.168.2.100
AKAE2440# setserverip 192.168.2.21 (这一项应该和你的主机IP一致)
AKAE2440#set netmask 255.255.255.0
AKAE2440# set gateway 192.168.2.21 (网关ip设置成什么无所谓,一般都设为主机ip)
AKAE2440#save
save将这些设定写入flash中,下次开发板上电时仍然有效。如果不save则仅改变内存中的参数值,reset后会恢复flash中原来的参数值。