经历近2周的时间,查阅大量的参考资料和贴子,终于成功将linux2.6.22移植到ARM2410上。中间走了不少弯路,不过走弯路也是一种收获,因为可以碰到和解决许多问题,增长知识。因为linux版本问题以及开发平台的不同,网上的很多文章并不完全适合自己的板子,需要自己摸索和修改。写这点东西算是对前一阶段工作的总结,以免将来忘记。
移植大体的步骤主要有:
(1) 交叉编译环境的建立(我的主机系统是ubuntu7.04);
(2) 开发板(我用的是博创的2410)NAND flash 分区管理;
(3) LCD、网卡驱动的移植;
(4) linux内核配置和编译;
(5) rootfs的制作;
(6) 完成linux的启动和文件系统的挂载。
下面我会按照步骤逐一介绍。
一、 交叉编译环境的建立
建立交叉编译环境就是在宿主机(也就是pc机)的系统上建立一个模拟ARM的工作环境,使得在这个环境下编译产生的程序能够顺利的在ARM上的系统内运行。主要工作包括binutils、gcc以及glibc的编译生成,还有一些环境变量的设置。
(1) 准备工作:
下载源代码包: binutils-2.18.tar.bz2,gcc-4.2.1.tar.bz2,glibc-2.6.1.tar.bz2,glibc-ports-2.6.1.tar.gz,linux-2.6.22.tar.bz2
补丁包: binutils-2.18-genscripts_multilib-1.patch
binutils-2.18-posix-1.patch
gcc-4.2.1-cross_search_paths-1.patch
gcc-4.2.1-posix-1.patch
gcc-4.2.1-specs-1.patch
glibc-2.6.1-cross_hacks-1.patch
glibc-2.6.1-hppa_nptl-1.patch
glibc-2.6.1-libgcc_eh-1.patch
glibc-2.6.1-RTLD_SINGLE_THREAD_P-1.patch
glibc-2.6.1-sysdep_cancel-1.patch
glibc-csu.patch
注:Binutils 是一组开发工具,包括连接器,汇编器和其他用于目标文件和档案的工具;
GCC是C编译器,用来将C代码编译成汇编代码;
Glibc就是gcc编译时需要的库了,glibc-ports是提供glibc对ARM的支持;
Linux-2.6.22.tar.bz2是内核源代码包。
需要注意的是gcc和glibc以及linux内核版本需要保持对应。如果用比较老的编译器去编译新的内核,或者用新的编译器编译老版本的内核,会出现一些莫名其妙的错误。另外补丁包也是必备的,否则编译过程中也会出错。刚开始我就深受其害。
(2) 工作目录的建立:
目录的结构可以参考《Building.Embedded.Linux.Systems》。推荐整个目录放到/usr/local下,这样所有的用户都有访问权限。我当初没经验,直接放到home下了,后来会有些用户权限的小麻烦。这里给出我的目录结构:
$root@host:/home# ls
arm host
其中host是我的普通登陆用户帐号目录,arm就是工作目录了。为了方便,我平时用root登陆。
$root@host:/home# cd arm
$root@host:/home/arm# mkdir build-tools kernel rootfs tmp tools
其中编译交叉工具时的主要工作都在build-tools目录下完成,kernel目录用来存放内核源代码,rootfs目录是用来建立启动根文件系统的(后面会详细介绍),tmp是临时文件存放目录,tools目录就是最终生成的编译器gcc和glibc存放的地方。
(3) 设置环境变量:
$root@host:/home/arm# export PRJROOT=/home/arm
$root@host:/home/arm# TARGET=arm-linux
$root@host:/home/arm# PREFIX=${PRJROOT}/tools
$root@host:/home/arm# TARGET_PREFIX=${PREFIX}/${TARGET}
$root@host:/home/arm# PATH=${PREFIX}/bin:${PATH}
其中TARGET定义了交叉工具的工作平台类型,PREFIX指定交叉工具的最终安装目录,PATH指定系统寻找交叉工具可执行文件所在的路径。
(4) 编译前的准备:
$root@host:/home/arm# cd ${PRJROOT}/build-tools
$root@host:/home/arm/build-tools# mkdir build-binutils build-boot-gcc build-glibc build-gcc build-glibc-headers patch
将源码包放到这个目录下
$root@host:/home/arm/build-tools# ls
build-boot-gcc build-glibc build-binutils build-gcc build-glibc-headers patch
binutils-2.18.tar.bz2 gcc-4.2.1.tar.bz2 glibc-2.6.1.tar.bz2 glibc-ports-2.6.1.tar.gz
将补丁放到patch目录下:
$root@host:/home/arm/build-tools# cd patch
$root@host:/home/arm/build-tools/patch# ls
binutils-2.18-genscripts_multilib-1.patch binutils-2.18-posix-1.patch
gcc-4.2.1-cross_search_paths-1.patch gcc-4.2.1-posix-1.patch
glibc-2.6.1-cross_hacks-1.patch
glibc-2.6.1-hppa_nptl-1.patch glibc-2.6.1-libgcc_eh-1.patch
glibc-2.6.1-RTLD_SINGLE_THREAD_P-1.patch
glibc-2.6.1-sysdep_cancel-1.patch glibc-csu.patch
将内核源码包放到${PRJROOT}/kernel目录下
$root@host:/home/arm# cd kernel
$root@host:/home/arm/kernel# ls
linux-2.6.22.tar.bz2
(5) 开始编译
编译的过程主要有6个步骤;
a. 内核头文件的生成
b. Binary utilties的生成
c. Glibc头文件的生成
d. 第一阶段gcc的生成
e. glibc库文件的生成
f. 完整编译工具的生成
注:生成第一阶段gcc主要是用来生成glibc库文件。
1、 生成内核头文件
$root@host:/home/arm/kernel# tar xvjf linux-2.6.22.tar.bz2
$root@host:/home/arm/kernel# cd linux-2.6.22
$root@host:/home/arm/kernel/linux-2.6.22#
make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig
其中menuconfig指定了配置界面,可用的还有config(全字符界面) xconfig(xwindow下的图形界面)。Ubuntu需要安装tk8.4以支持xconfig。另外需要将mawk卸载,安装gawk。(mawk有bug)
linux2.6的内核提供了对s3c2410的支持。在system中选上s3c2410系列就可以了。配置完毕退出保存。
$root@host:/home/arm/kernel/linux-2.6.22# cd include
$root@host:/home/arm/kernel/linux-2.6.22/include# cd linux
$root@host:/home/arm/kernel/linux-2.6.22/include/linux# ls version.h autoconf.h
version.h autoconf.h
这2个文件在后面的编译中会用到。如果没有,退到内目录下make version.h就可以了。
下面建立链接:
$root@host:/home/arm/kernel/linux-2.6.22/include# ln –s asm-arm asm
$root@host:/home/arm/kernel/linux-2.6.22/include# ln -s asm/arch-s3c2410 asm/arch
将内核头文件拷贝到最终安装目录下:
$root@host:/home/arm/kernel/linux-2.6.22/include# mkdir –p ${TARGET_PREFIX}/include
$root@host:/home/arm/kernel/linux-2.6.22/include#
cp –r asm- ${TARGET_PREFIX}/include
$root@host:/home/arm/kernel/linux-2.6.22/include# cp –r linux ${TARGET_PREFIX}/include
$root@host:/home/arm/kernel/linux-2.6.22/include# cp –d asm ${TARGET_PREFIX}/include
至此内核头文件建立完毕。
2、 建立Binary utilities:
binutils是一些二进制工具的集合,其中常用的是as ,ar和ld。
$root@host:/home/arm/kernel/include# cd ${PRJROOT}/build-tools
$root@host:/home/arm/build-tools# tar xvjf binutils-2.18.tar.bz2
$root@host:/home/arm/build-tools# cd build-binutils
$root@host:/home/arm/build-tools/build-binutils#
patch –Np1 –i /home/arm/build-tools/patch/binutils-2.18*
$root@host:/home/arm/build-tools/build-binutils#
../binutils-2.18/configure --target=${TARGET} –prefix=${PREFIX}
$root@host:/home/arm/build-tools/build-binutils# make
$root@host:/home/arm/build-tools/build-binutils# make install
${PREFIX}/bin下应该生成一些以arm-linux开头的文件
$root@host:/home/arm/build-tools/build-binutils# ls ${PREFIX}/bin
3、 生成glibc头文件:
$root@host:/home/arm/build-tools/build-binutils# cd ..
$root@host:/home/arm/build-tools/# tar xvjf glibc-2.6.1.tar.bz2
$root@host:/home/arm/build-tools/#
tar xvzf glibc-ports-2.6.1.tar.gz --directory ./glibc-2.6.1/
$root@host:/home/arm/build-tools/# cd glibc-2.6.1
$root@host:/home/arm/build-tools/glibc-2.6.1# mv glibc-ports-2.6.1 ports –v
打上补丁:
$root@host:/home/arm/build-tools/glibc-2.6.1#
patch –Np1 –i /home/arm/build-tools/patch/glibc-2.6.1-*patch
$root@host:/home/arm/build-tools/glibc-2.6.1# cd ..
$root@host:/home/arm/build-tools/# cd build-glibc-headers
这里需要添加对NPTL线程库的支持:
$root@host:/home/arm/build-tools/build-glibc-headers#
echo “libc_cv_forced_unwind=yes”>>config.cache
echo “libc_cv_c_cleanup=yes”>>config.cache
echo “libc_cv_arm_tls=yes”>>config.cache
注:如果编译中出现”cannot compute long double size”,添加:
echo “ac_cv_sizeof_long_double=12”>>config.cache
$root@host:/home/arm/build-tools/build-glibc-headers#
../glibc-2.6.1/configure --host=${TARGET} --prefix=”/usr” --enable-add-ons
--with-headers=${TARGET_PREFIX}/include --cache-file=config.cache
$root@host:/home/arm/build-tools/build-glibc-headers#
make cross-compiling=yes install_root=${TARGET_PREFIX} prefix=””
install-headers
$root@host:/home/arm/build-tools/build-glibc-headers#
mkdir –p ${TARGET_PREFIX}/include/gnu
$root@host:/home/arm/build-tools/build-glibc-headers#
touch ${TARGET_PREFIX}/include/gnu/stubs.h
注:如果编译过程中出现找不到头文件的错误,可以根据错误提示的文件名用touch命令在相应目录下建立一个空文件,一般就可以编译通过了。
4、 生成第一阶段gcc:
$root@host:/home/arm/build-tools/# tar xvjf gcc-4.2.1.tar.bz2
打补丁:
$root@host:/home/arm/build-tools/# cd gcc-4.2.1
$root@host:/home/arm/build-tools/gcc-4.2.1#
patch –Np1 –i /home/arm/build-tools/patch/gcc-4.2.1-*
$root@host:/home/arm/build-tools/ gcc-4.2.1# cd ..
$root@host:/home/arm/build-tools/# cd build-boot-gcc
$root@host:/home/arm/build-tools/build-boot-gcc#
../gcc-4.2.1/configure --target=${TARGET} --prefix=${PREFIX} --with-headers=${TARGET_PREFIX}/include
--with-newlib --enable-languages=c --disable-threads --disable-shared
$root@host:/home/arm/build-tools/build-boot-gcc # make all-gcc
$root@host:/home/arm/build-tools/build-boot-gcc # make install-gcc
在${PREFIX}/bin下会生成 arm-linux-开头的文件:
$root@host:/home/arm/build-tools/build-boot-gcc # ls ${PREFIX}/bin
5、 生成glibc库文件:
$root@host:/home/arm/build-tools/build-boot-gcc # cd ..
$root@host:/home/arm/build-tools# cd build-glibc
$root@host:/home/arm/build-tools/build-glibc# CC=arm-linux-gcc ../glibc-2.6.1/configure --host=$TARGET --prefix=”/usr”
--enable-add-ons --with-headers=${TARGET_PREFIX}/include
--cache-file=config.cache
这里的config.cache与前面编译glibc头文件时的config.cache完全相同。
$root@host:/home/arm/build-tools/build-glibc# make
$root@host:/home/arm/build-tools/build-glibc#
make install_root=${TARGET_PREFIX} prefix=”” install
对libc.so作出修改:
$root@host:/home/arm/build-tools/build-glibc# cd ${TARGET_PREFIX}/lib
$root@host:/home/arm/tools/arm-linux/lib# cat libc.so
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf32-littlearm)
GROUP ( /lib/libc.so.6 /lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux.so.2 ) )
将GROUP这一行的内容改为:
GROUP ( libc.so.6 libc_nonshared.a AS_NEEDED ( ld-linux.so.2 ) )
$root@host:/home/arm/tools/arm-linux/lib# cat libpthread.so
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf32-littlearm)
GROUP ( /lib/libpthread.so.0 /lib/libpthread_nonshared.a )
将GROUP这一行的内容改为:
GROUP (libpthread.so.0 libpthread_nonshared.a )
6、 生成完整的编译工具:
$root@host:/home/arm/tools/arm-linux/lib# cd ${PRJROOT}/build-tools/build-gcc
$root@host:/home/arm/build-tools/build-gcc#
../gcc-4.2.1/configure --target=$TARGET --prefix=${PREFIX} --enable-shared
--enable-languages=c,c++ --with-threads=posix
$root@host:/home/arm/build-tools/build-glibc# make all
$root@host:/home/arm/build-tools/build-glibc# make install
(待续....)