2011-9-13
目标:熟练u-boot、linux系统、文件系统的优化裁剪;精通系统移植;精通linux系统、文件系统、uboot原理等。
2011-9-13
第一天,尝试在AT91SAM9260 上进行linux系统移植,以前移植系统总希望所有的东西都是自己打造的,所以,移植时总时从0开始进行定制。由于自身知识、经验的不足,导致在mini2440上的移植直到现在都没有成功。严重影响了学习的积极性以及进度,所以,从今天起要改变学习的方法,从简入手,先从最简单的开始。
今天,利用系统自带的u-boot、linux内核映像,自己定制jffs2文件系统,学习文件系统的定制方法。
按照厂家提供的方法,如下():
1、建立交叉编译环境
SecureCRT ssh 到 ubuntu
<1> 进入工作目录,复制光盘资料newmsg/tools/下的 arm-2007-01-21.iso
cd /home/works
cp newmsg/tools/arm-2007-01-21.iso ./
mkdir tmp
chmod 777 tmp
<2>安装交叉编译工具
cd tmp
./install –d ../eldk41gcc40
<3>设置交叉编译工具路径,如下:
vi ~/.bashrc
最后一行添加以下路径,
export PATH=$PATH:/home/newmsg/works/tools/eldk41gcc40/usr/bin
<4>测试安装
重新登录,使环境变量生效
exit
sudo su
查看交叉编译工具版本,测试路径是否正确,如下:
arm-linux-gcc –v
1、制作根文件系统
本篇根文件系统使用 busybox 制作,busybox 以小巧著称,适合于嵌入式设备的linux 文件系统,下面是详细的制作过程:
SecureCRT ssh 到 ubuntu,切换到 root
1. busybox 编译
1>准备源码
cd /home/newmsg/works
tar –xzvf busybox-1.15.3.tar.gz
cd busybox-1.15.3
make clean distclean
make menuconfig 对busybox进行配置,去掉不需要的项目,最后生成.config文件。
2>交叉编译
make ARCH=arm CROSS_COMPILE=arm-linux- install
编译成功后,会在busybox-1.15.3/_install/文件夹下生成如下文件:
2.制作根文件系统
1>创建根文件系统基本架构
cd /home/newmsg/works/nfsroot
mkdir root usr mnt proc tmp var opt etc dev lib sys
cp -a ../busybox-1.15.3/_install/* ./
2>添加必要的库文件
将arm-linux-gcc的库文件全部拷贝到lib目录里,例如我的arm-linux-gcc的安装路径为:/opt/arm_linux_gcc/usr/bin/arm-linux-gcc
则执行如下命令:
cp -a /opt/arm_linux_gcc/arm/lib/* ./lib/
3>添加必要设备文件
mknod ./dev/console c 5 1
mknod ./dev/null c 1 3
mknod ./dev/zero c 1 5
说明:如果在配置了busybox中的mdev选项,这些节点系统会自动生成,但是如果文件系统创建前如果不显式的创建这些节点,系统启动时会报如下警告:
Warning: unable to open an initial console.
原因:mdev 是通过 init 进程来启动的,在使用 mdev 构造 /dev 目录之前,init 至少要用到设备文件/dev/console、 /dev/null ,所以需要事先建立这两个设备文件:
lingd@ubuntu:~/arm2410s/rootfs$ cd dev
lingd@ubuntu:~/arm2410s/rootfs/dev$ sudo mknod -m 660 console c 204 64
[sudo] password for lingd:
lingd@ubuntu:~/arm2410s/rootfs/dev$ sudo mknod -m 660 null c 1 3
lingd@ubuntu:~/arm2410s/rootfs/dev$ ls -l
total 0
crw-rw---- 1 root root 5, 1 2010-04-02 15:49 console
crw-rw---- 1 root root 1, 3 2010-04-02 15:50 null
注意:本来console的主次设备号应为5和1.但是因为init在执行完/etc/init.d/rcS脚本后,就 会在一个控制台上,按照inittab的指示开一个shell(或者是开getty+login,这样用户就会看到提示输入用户名的提示符)。在mdev -s未执行之前,/dev目录下只有我们创建的/dev/null和/dev/console,也就是说,没有控制台可供init用来按照inittab 的指示开一个shell。而在s3c24xx 系列芯片的串口驱动里面用了s3c2410_serial做为设备名(在内核源码的“drivers/serial/s3c2410.c”文件的949 行),因此,启动时可用s3c2410_serial0、s3c2410_serial1或s3c2410_serial2作为init用来按照 inittab的指示开一个shell的控制台,这里我用了串口0,即s3c2410_serial0(主次设备号为204和64)作为控制台。这里直接 将console当s3c2410_serial0,所以console的主次设备号才会为204和64。
4>添加基本配置文件
cd etc
mkdir init.d
touch inittab init.d/rcS profile fstab
vi inittab
添加以下内容(以下内容的原理和详细解释会在威步出品的同系列的手册中找到,查看《手册使用介绍》即可找到相应手册) :
::sysinit:/etc/init.d/rcS
ttyS0::respawn:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/bin/umount -a –r
vi profile
添加以下内容:
PATH=/bin:/sbin
PS1='[\u@\h: \W]\$ '
说明:试验中发现,如果配置busybox时没有配置
Busybox Settings --->
Busybox Library Tuning --->
[*] Username completion
[*] Fancy shell prompts
上面两项,文件系统是不会正确识别PS1这个环境变量的参数的。
vi fstab
添加以下内容:
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
vi init.d/rcS
添加以下内容:
/bin/mount -n -t proc /proc proc
/bin/mount -n -o remount,rw /
/bin/mount -av
/bin/hostname NewMsg
/bin/mount -t tmpfs mdev /dev
mkdir /dev/pts
/bin/mount -t devpts devpts /dev/pts
echo /sbin/mdev>/proc/sys/kernel/hotplug
/sbin/mdev –s
给 rcS 脚本可执行权限:
chmod 777 init.d/rcS
以上几步,基本的根文件系统已经构建完成,接下来就是制作文件系统镜像。
3. 打包成指定格式的根文件镜像
cd /home/newmsg/works
制作成 jffs2 格式镜像:
针对 64M 的 nand flash 用户:
mkfs.jffs2 –r ./nfsroot –o rootfs.jffs2 –e 0x4000 –n –p
针对 128M 的 nand flash 用户:
mkfs.jffs2 –r ./nfsroot –o rootfs.jffs2 –e 0x20000 –n -p
本集中器板子为128M的nand flash 。
4. 烧写映像、文件系统
1>进入uboot,先设置以下参数: ( 直接粘贴即可 ) setenv `bootargs console=ttyS0,57600 root=/dev/nfs nfsroot=192.168.0.154:/home/nfsroot ip=192.168.0.219:192.168.0.154:192.168.0.1:255.255.255.0:::eth0:off setenv ipaddr 192.168.0.219 setenv serverip 192.168.0.* setenv gatewayip 192.168.0.1注:上面的serverip指是服务器的ip,可自己设置, 一般在自己本机上运行tftp32.exe 即可当作一个ftp服务器, 并把内核文件(uImage_v1.*)放在tftp32.exe所在的目录, 并将内核文件的名字都改为uImage.`
2>烧写内核文件 内核文件放在服务器的Kernel目录下,其中有各个版本,详见版本信息 在uboot中执行以下命令,( 直接粘贴即可 )
tftp 0x22000000 uImagenand erase 0xa0000nand write 0x22000000 0xa0000 0x200000
3>烧写文件系统
tftp 0x20000000 rootfs_128.jffs2
nand erase 0x400000
nand write 0x20000000 0x400000 0xxxxxxxxx
编译补充:
——————————————————————-
交叉编译busybox
交叉编译器: 3.3.2
# wget -c http://www.busybox.net/downloads/busybox-1.7.0.tar.bz2
# tar jxvf busybox-1.7.0.tar.bz2
# cd busybox-1.7.0
# vi Makefile +176
ARCH ?= arm
CROSS_COMPILE ?= /usr/local/arm/3.3.2/bin/arm-linux-
# make menuconfig
Busybox Settings --->
Build Options --->
[*] Build BusyBox as a static binary (no shared libs) //(1)
Installation Options --->
[*] Don't use /usr //(2)
Linux System Utilities --->
[*] mdev //(3)
[*] Support /etc/mdev.conf
[*] Support command execution at device addition/removal
Shells --->
Choose your default shell (msh) ---> //(4)
(1) 这个选项是一定要选择的,这样才能把busybox编译成静态链接的可执行文件,运行时才独立于其他函数库.否则必需要其他库文件才能运行,在单一个linux内核不能使他正常工作。
(2) 这个选项也一定要选,否则make install后,busybox将安装在原系统的/usr下,这将覆盖掉系统原有的命令.选择这个选项后,make install后会在busybox目录下生成一个叫_install的目录,里面有busybox和指向他的链接.
(3) 如果没有启动udev,造成/dev下没有设备文件。也就是说所有的设备都没有挂接进来。最新的busybox已经包含了udev的简化版本即mdev,且使用非常简单。 要使用mdev还需要在rootfs中做适当配置。
vi rootfs/etc/init.d/rcS ---------------------------
mount -t tmpfs mdev /dev
mkdir /dev/pts
mount -t devpts devpts /dev/pts
mount -t sysfs sysfs /sys
mount -a
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
mdev需要改写/dev和/sys两个目录。所以必须保证这两个目录是可写的(一般会用到sysfs,tmpfs。所以要重新编译内核)。然后在你的启动脚本文件中加入/sbin/mdev -s
linux-2.6.19 -- make menuconfig
File systems --->
Pseudo filesystems --->
[*] sysfs file system support
[*] Virtual memory file system support (former shm fs)
[*] Tmpfs POSIX Access Control Lists
(4) 由于ash功能不够强大,不能支持tab补齐,历史纪录等等的高级功能,所以使用busybox里面的msh代替ash.
因为busybox主要应用于对空间要求非常严格的嵌入式系统,所以它推荐使用uclibc而不鼓励使用glibc,如果你没有安装uclibc,而且在 build Options也选择了Build BusyBox as a static binary(no shared libs),那肯定无法编译通过的,当然如果你之前build Options选择的是动态编译的话就不会有这样的问题出现了。假设你是第一种情况,我们可以这样解决:把applets/applets.c开头的几行 warning注释掉
# vi applets/applets.c
/*
#if ENABLE_STATIC && defined(__GLIBC__) && !defined(__UCLIBC__)
#warning Static linking against glibc produces buggy executables
#warning (glibc does not cope well with ld --gc-sections).
#warning See sources.redhat.com/bugzilla/show_bug.cgi?id=3400
#warning Note that glibc is unsuitable for static linking anyway.
#warning If you still want to do it, remove -Wl,--gc-sections
#warning from top-level Makefile and remove this warning.
#error Aborting compilation.
#endif
*/
# make
# make install
这时会在你的编译目录下生成一个_install的目录,里面包含了生成的所有文件和目录结构。
如果busybox编译成static linking
Busybox Settings --->
Build Options --->
[*] Build BusyBox as a static binary (no shared libs)
# make
将会遇到下面问题:
applets/applets.c:20:2: error: #warning Static linking against glibc produces buggy executables
applets/applets.c:21:2: error: #warning (glibc does not cope well with ld --gc-sections).
applets/applets.c:22:2: error: #warning See sources.redhat.com/bugzilla/show_bug.cgi?id=3400
applets/applets.c:23:2: error: #warning Note that glibc is unsuitable for static linking anyway.
applets/applets.c:24:2: error: #warning If you still want to do it, remove -Wl,--gc-sections
applets/applets.c:25:2: error: #warning from top-level Makefile and remove this warning.
make[1]: *** [applets/applets.o] Error 1
这个警告的定义在applets/applets.c中。将这段警告注释掉就可以了。这段警告的意思是告诉你最好用uclibc编译,而不是用glibc因为glibc比较大,busybox在寸土寸金的嵌入式系统中运用比较多,所以会有这样的要求。
# vi /busybox-1.7.0/applets/applets.c +20
注释掉20 -- 28行内容即可
miscutils/taskset.c:17: error: parse error before '*' token
最根本的解决办法是换一个libc库,可是现在还不知道哪个库最合适,唯有暂时将有问题的命令关掉
Miscellaneous Utilities --->
[ ] taskset
runit/runsv.c: In function `gettimeofday_ns':
Runit Utilities --->
[ ] runsv
“could not run '/bin/sh': No such file or directory”
解决方法:
要这样配置:
Shells --->
Choose your default shell (ash) --->
如果是这样配置的话,虽然可以生成ash,但不能生成sh,将会在内核启动时出现上面出现的问题:
Shells --->
Choose your default shell (none) --->
[*] ash
烧写完毕重新启动即可。
经过一天的忙碌,终于取得了以上成就,但是,还有很多疑问需要处理:
1> uboot 命令,烧写位置是根据什么确定的?
2> mkfs.jffs2 工具的使用方法
3> busybox各个选项的意义
4> nfs文件系统的搭建,如何通过nfs登陆服务器进行开发,系统烧写
5> yaffs2文件系统的移植,烧写
6> linux系统移植
7> u-boot的修改
8> mdev
9> 嵌入式linux系统 登录密码 账号 管理