目標:熟練u-boot、linux系統、文件系統的優化裁剪;精通系統移植;精通linux系統、文件系統、uboot原理等。
第一天,嘗試在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系統 登錄密碼 賬號 管理