參考:
http://blog.csdn.net/linyt/article/details/42504975
環境介紹:
Win7 64 + Vmware 11 + ubuntu14.04 32
u-boot 版本:u-boot-2015-04
Linux kernel版本:linux-3.16.y
busybox版本:1_24_stable
交叉編譯工具鏈:arm-linux-gnueabi-
qemu版本:stable-2.4
下載Linux內核
下載內核有兩種方法,一種是用git直接下載內核代碼樹,方便后面的內核開發。另一種是直接到內核社區下載對應版本的源碼包。我采用第一種方法,但后面發現 主線上3.18版本和后面版本的代碼,使用這種搭建方法運行不起來。目前未查明問題的根因。如果讀者想快速搭建成功,建議選用3.16版本的內核進行搭建。(這個剛開始我用的是linux-4.4版本的內核,用qemu-system-arm無法運行,然后我就改用linux-3.16的內核了)
方法一:使用git
git clonegit://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
方法二:直接下載3.16源代碼包
wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.16.tar.xz
安裝arm的交叉編譯工具鏈
想必做嵌入式開發的朋友,對交叉編譯工具鏈不陌生。如果你訂制一個交叉編譯工具鏈,建議你使用crosstool-ng開源軟件來構建。但在這里建議直接安裝arm的交叉編譯工具鏈:
sudo apt-get install gcc-arm-linux-gnueabi
編譯Linux內核
生成vexpress開發板子的config文件:
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm O=./out_vexpress_3_16 vexpress_defconfig
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm O=./out_vexpress_3_16 menuconfig
將:
System Type --->
[ ] Enable the L2x0 outer cache controller
即, 把 Enable the L2x0 outer cache controller 取消, 否則Qemu會起不來, 暫時還不知道為什么。
編譯:
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm O=./out_vexpress_3_16 zImage -j2
生成的內核鐿像位於./out_vexpress_3_16/arch/arm/boot/zImage, 后續qemu啟動時需要使用該鏡像。
下載和安裝qemu模擬器
下載qemu,我用的版本是2.4版本,可以用如下方式下載,然后checkout到2.4分支上即可
git clone git://git.qemu-project.org/qemu.git
cd qemu git checkout remotes/origin/stable-2.4 -b stable-2.4
配置qemu前,需要安裝幾個軟件包:
sudo apt-get install zlib1g-dev sudo apt-get install libglib2.0-0
sudo apt-get install libglib2.0-dev sudo apt-get install libtool sudo apt-get install libsdl1.2-dev
sudo apt-get install autoconf
配置qemu,支持模擬arm架構下的所有單板,我為了使qemu的代碼干凈一些,采用如下方式編譯,最后生成的中間文件都在build下
mkdir build cd build ../qemu/configure --target-list=arm-softmmu --audio-drv-list=
編譯和安裝:
make
make install
查看qemu支持哪些板子
qemu-system-arm -M help
測試qemu和內核能否運行成功
qemu已經安裝好了,內核也編譯成功了,到這里最好是測試一下,編譯出來的內核是否OK,或者qemu對vexpress單板支持是否夠友好。
運行命令很簡單:
qemu-system-arm \ -M vexpress-a9 \ -m 512M \ -kernel /root/tq2440_work/kernel/linux-stable/out_vexpress_3_16/arch/arm/boot/zImage \ -nographic \ -append "console=ttyAMA0"
可以把上面的命令放到一個腳本中執行。
如果看到內核啟動過程中的打印,說明前的搭建是成功的。
Booting Linux on physical CPU 0x0 Initializing cgroup subsys cpuset Linux version 3.16.7 (root@ubuntu) (gcc version 4.7.3 (Ubuntu/Linaro 4.7.3-12ubuntu1) ) #5 SMP Sat Dec 5 21:17:17 PST 2015 CPU: ARMv7 Processor [410fc090] revision 0 (ARMv7), cr=10c53c7d CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache Machine: ARM-Versatile Express Memory policy: Data cache writeback CPU: All CPU(s) started in SVC mode. sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every 178956969942ns PERCPU: Embedded 7 pages/cpu @9fbed000 s7552 r8192 d12928 u32768 Built 1 zonelists in Zone order, mobility grouping on. Total pages: 130048 Kernel command line: console=ttyAMA0 PID hash table entries: 2048 (order: 1, 8192 bytes) Dentry cache hash table entries: 65536 (order: 6, 262144 bytes) Inode-cache hash table entries: 32768 (order: 5, 131072 bytes) Memory: 513272K/524288K available (4563K kernel code, 190K rwdata, 1292K rodata, 239K init, 149K bss, 11016K reserved) Virtual kernel memory layout: ...... VFS: Cannot open root device "(null)" or unknown-block(0,0): error -6 Please append a correct "root=" boot option; here are the available partitions: 1f00 131072 mtdblock0 (driver?) Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.16.7 #5 [<8001507c>] (unwind_backtrace) from [<800115d4>] (show_stack+0x10/0x14) [<800115d4>] (show_stack) from [<8044f9c8>] (dump_stack+0x74/0x90) [<8044f9c8>] (dump_stack) from [<8044ce08>] (panic+0x90/0x1fc) [<8044ce08>] (panic) from [<805c210c>] (mount_block_root+0x1a0/0x254) [<805c210c>] (mount_block_root) from [<805c22b4>] (mount_root+0xf4/0x114) [<805c22b4>] (mount_root) from [<805c2400>] (prepare_namespace+0x12c/0x190) [<805c2400>] (prepare_namespace) from [<805c1d8c>] (kernel_init_freeable+0x1f4/0x240) [<805c1d8c>] (kernel_init_freeable) from [<8044adb8>] (kernel_init+0x8/0xec) [<8044adb8>] (kernel_init) from [<8000e4b8>] (ret_from_fork+0x14/0x3c) ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
這里簡單介紹下qemu命令的參數:
-M vexpress-a9 模擬vexpress-a9單板,你可以使用-M ?參數來獲取該qemu版本支持的所有單板
-m 512M 單板運行物理內存512M
-kernel /root/tq2440_work/kernel/linux-stable/out_vexpress_3_16/arch/arm/boot/zImage 告訴qemu單板運行內核鏡像路徑
-nographic 不使用圖形化界面,只使用串口
-append "console=ttyAMA0" 內核啟動參數,這里告訴內核vexpress單板運行,串口設備是哪個tty。
注意:
我每次搭建,都忘了內核啟動參數中的console=參數應該填上哪個tty,因為不同單板串口驅動類型不盡相同,創建的tty設備名當然也是不相同的。那 vexpress單板的tty設備名是哪個呢? 其實這個值可以從生成的.config文件CONFIG_CONSOLE宏找到。
如果搭建其它單板,需要注意內核啟動參數的console=參數值,同樣地,可從生成的.config文件中找到。
此時只能通過殺死qemu-system-arm這個進程來退出,我簡單寫了一個腳本來完成這個任務 kill_qemu.sh
#!/bin/bash ps -A | grep qemu-system-arm | awk '{print $1}' | xargs sudo kill -9
制作根文件系統
到這里是否大功告成了呢? 其實在上面的測試中,你會發現內核報panic,因為內核找不到根文件系統,無法啟init進程。
根文件系統要考慮兩個方面:
1. 根文件系統的內容
如果你看過《Linux From Scratch》,相信你會對這一步產生恐懼感,但如果一直從事嵌入式開發,就可以放下心來。根文件系統就是簡單得不能再簡單的幾個命令集和態動態而已。為什么Linux From Scratch會有那么復雜,是因為它要制作出一個Linux發生版。但在嵌入式領域,幾乎所有的東西,都是mini版本,根文件系統也不例外。
本文制本的根文件系統 = busybox(包含基礎的Linux命令) + 運行庫 + 幾個字符設備
2. 根文件系統放在哪里
其實依賴於每個開發板支持的存儲設備,可以放到Nor Flash上,也可以放到SD卡,甚至外部磁盤上。最關鍵的一點是你要清楚知道開發板有什么存儲設備。
本文直接使用SD卡做為存儲空間,文件格式為ext3格式
下載、編譯和安裝busybox
我用的busybox版本是1_24,下載地址:https://busybox.net/downloads/
配置:
在busybox下執行 make menuconfig
做如下配置:
Busybox Settings --->
Build Options --->
[*] Build BusyBox as a static binary (no shared libs)
(arm-linux-gnueabi-) Cross Compiler prefix
然后執行
make
make install
安裝完成后,會在busybox目錄下生成_install目錄,該目錄下的程序就是單板運行所需要的命令。
形成根目錄結構
#!/bin/bash sudo rm -rf rootfs sudo rm -rf tmpfs sudo rm -f a9rootfs.ext3 sudo mkdir rootfs sudo cp busybox/_install/* rootfs/ -raf sudo mkdir -p rootfs/proc/ sudo mkdir -p rootfs/sys/ sudo mkdir -p rootfs/tmp/ sudo mkdir -p rootfs/root/ sudo mkdir -p rootfs/var/ sudo mkdir -p rootfs/mnt/ sudo cp etc rootfs/ -arf sudo cp -arf /usr/arm-linux-gnueabi/lib rootfs/ sudo rm rootfs/lib/*.a sudo arm-linux-gnueabi-strip rootfs/lib/* sudo mkdir -p rootfs/dev/ sudo mknod rootfs/dev/tty1 c 4 1 sudo mknod rootfs/dev/tty2 c 4 2 sudo mknod rootfs/dev/tty3 c 4 3 sudo mknod rootfs/dev/tty4 c 4 4 sudo mknod rootfs/dev/console c 5 1 sudo mknod rootfs/dev/null c 1 3 sudo dd if=/dev/zero of=a9rootfs.ext3 bs=1M count=32 sudo mkfs.ext3 a9rootfs.ext3 sudo mkdir -p tmpfs sudo mount -t ext3 a9rootfs.ext3 tmpfs/ -o loop sudo cp -r rootfs/* tmpfs/ sudo umount tmpfs
其中,etc下是啟動配置文件,可以的到這里下載:
系統啟動運行
qemu-system-arm \ -M vexpress-a9 \ -m 512M \ -kernel /root/tq2440_work/kernel/linux-stable/out_vexpress_3_16/arch/arm/boot/zImage \ -nographic \ -append "root=/dev/mmcblk0 console=ttyAMA0" \ -sd /root/tq2440_work/busybox_study/a9rootfs.ext3
上面是不太圖形界面的,下面的命令可以產生一個圖形界面:
qemu-system-arm \ -M vexpress-a9 \ -serial stdio \ -m 512M \ -kernel /root/tq2440_work/kernel/linux-stable/out_vexpress_3_16/arch/arm/boot/zImage \ -append "root=/dev/mmcblk0 console=ttyAMA0 console=tty0" \ -sd /root/tq2440_work/busybox_study/a9rootfs.ext3
下一節,用Qemu模擬運行vexpress的u-boot。