一. 基礎環境
0. 安裝virtualbox
下載最新virtualbox (4.2),安裝
1. 安裝ubuntu12.04
下載ubuntu-12.04的dvd安裝iso,搜索下載
2. virtualbox安裝ubuntu時候,分配100G,的動態盤
3. 裝好ubuntu后, 安裝virtualbox增強功能,重啟
4. 設置共享文件夾,自動掛載+固定分配,重啟
5. sudo adduser xxx vboxsf,設置了用戶加到vboxsf組,獲取權限,重啟
6. 修改ubuntu源,網易很給力:
deb http://mirrors.163.com/ubuntu/ precise-updates main restricted
deb http://mirrors.163.com/ubuntu/ precise universe
deb http://mirrors.163.com/ubuntu/ precise-updates universe
deb http://mirrors.163.com/ubuntu/ precise multiverse
deb http://mirrors.163.com/ubuntu/ precise-updates multiverse
deb http://mirrors.163.com/ubuntu/ precise-backports main restricted universe multiverse
deb http://mirrors.163.com/ubuntu/ precise-security main restricted
deb http://mirrors.163.com/ubuntu/ precise-security universe
deb http://mirrors.163.com/ubuntu/ precise-security multiverse
二. 安裝交叉工具鏈
- sudo apt-get insatll gcc-arm-linux-gnueabi
- sudo apt-get insatll g++-arm-linux-gnueabi
注意:此處arm-linux-gnueabi-gdb沒有被安裝,可以自己編譯一個:
(2) 安裝
(3) 解壓配置
默認地址 /usr/local
sudo make install
(5) sudo ldconfig系統配置生效
(6) 可以使用了
三. 安裝Qemu
四. 下載u-boot
www.denx.de是uboot的官網,denx軟件和硬件都有,工具鏈eldk也很好用,可以用eldk的工具鏈編譯,ftp下載時候,使用http方式的,不要使用ftp方式,可能看不見東西.
五. 編譯uboot
編譯uboot需要確定板子,板子和cpu、soc等是密切相關的,看uboot源碼根目錄下的boards.cfg,可以知道所有支持的板子名字,對應的架構,cpu,廠商等,
因為我們要使用Qemu來模擬這個板子,所以要找到一個Qemu和uboot同時支持的板子,同時還是cortex-a9架構核心的.
boards.cfg中有一行:
同時,使用qemu-system-arm -M ?命令,能看到支持的板子列表,其中包括:
就是說vexpress 這個板子,在uboot和qemu中,同時支持,且是cortex-a9的.
(1) export ARCH=arm
(2) export CROSS_COMPILE=arm-linux-gnueabi-
(3) make ca9x4_ct_vxp_config
編譯成功后,源碼根目錄下出現 u-boot u-boot.bin等文件.
六. 運行
- qemu-system-arm -M vexpress-a9 -m 256M -nographic -kernel u-boot 此命令沒有圖形只有命令行輸出
- 或者
-
- qemu-system-arm -M vexpress-a9 -m 256M -serial stdio -kernel u-boot 此命令包括圖形和命令行輸出
可以gdb調試:
注意
(1) gdb調試
qemu-system-arm -M vexpress-a9 -m 256M -kernel u-boot -S -s和qemu-system-arm -m 256 -kernel u-boot -gdb tcp::1234 -S同一個意思-s 表示 -gdb tcp::1234
-S 表示停下來,另一個終端可用arm-linux-gnueabi-gdb,啟動后用參數target remote tcp::1234連接
當然,連接之前,需要用file 制定一個有符號的目標,比如u-boot .
同時gdb的 directory命令可以制定源文件的搜索路徑.
(2) kernel 文件類型
支持ld鏈接出來的elf文件,gdb調試端,需要用file加載相應的有調試信息符號的elf文件.
七. 編譯運行linux內核
1. 獲取內核
ftp://ftp.kernel.org/pub/linux/kernel/v3.x/linux-3.8.tar.bz22. 編譯export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-
make clean distclean
make vexpress_defconfig
make -j4
3. 啟動
qemu-system-arm -M vexpress-a9 -m 256M -kernel linux/linux-3.8/arch/arm/boot/zImage -append "console=tty0"
八. 根文件系統
1. busybox編譯
(1) 下載源碼
http://www.busybox.net/downloads/busybox-1.21.0.tar.bz2(2) 編譯
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-
make -j4
make install
(3) _install目錄就是所有的busybox編譯的結果
2. 制作根文件系統目錄
(0) 根目錄
mkdir rootfs
cd rootfs
(1) 目錄結構
mkdir bin etc dev lib proc tmp root home sys usr sbin var mnt
(2) 運行庫-來自工具鏈
cp -a /usr/arm-linux-gnueabi/lib/* lib
(3) 配置文件-來自busybox
cp -a <busybox_dir>/examples/bootfloppy/etc/* etc
(4) busybox工具集
cp -a <busybox_dir>/_install/* .
(5) 設備文件
sudo cp -a /dev/console /dev/loop0 /dev/loop1 /dev/null /dev/ram0 /dev/tty /dev/tty0 /dev/tty1 /dev/zero /dev
(6) 修改mdev配置,mdev負責自動生成設備節點,mdev.conf是配置文件
vi etc/mdev.conf
- controlC[0-9] 0:0 0660 =snd/
- pcm.* 0:0 0660 =snd/
- seq.* 0:0 0660 =snd/
- mix.* 0:0 0660 =snd/
- timer 0:0 0660 =snd/
(7) 修改啟動配置
vi etc/init.d/rcS
增加
mount -n -t proc none /proc
-
mount -n -t sysfs none /sys
-
mdev -s 這句很重要,生成所有的設備節點
如果用nfs的話,有了以上目錄就可以了
3. 根文件系統鏡像
dd if=/dev/zero of=rootfs.img bs=1M count=32 # 32M的鏡像
mkfs.ext3 rootfs.img
mkdir tmpfs
sudo mount -o loop rootfs.img tmpfs
sudo cp -a rootfs/* tmpfs/
sudo umount tmpfs
rootfs.img中就有了文件系統鏡像了,ext3格式.
4. 文件系統鏡像啟動qemu - 此時不需要u-boot了,直接啟動內核指定參數即可
qemu-system-arm -M vexpress-a9 -m 256M -kernel linux/linux-3.8/arch/arm/boot/zImage -append "root=/dev/mmcblk0 console=tty0 init=/linuxrc" -sd rootfs.img九. qemu網絡配置
0. qemu支持tap網絡
1. ubuntu-12.04本身內核支持了tun設備,所以不用再編譯模塊了.
2. 安裝nfs
(1) sudo apt-get install nfs-kernel-server
(2) sudo vi /etc/exports
/home/xxxx/work/rootfs/fs *(rw,sync,no_subtree_check,all_squash,insecure,anonuid=1000,anongid=1000)
(3) service portmap restart(4) service nfs restart
3. 修改qemu網絡啟動腳本
sudo vi /etc/qemu-ifup
#!/bin/sh
/sbin/ifconfig $1 172.20.0.1
意思就是說host機器的ip是172.20.0.14. nfs啟動內核
sudo qemu-system-arm -M vexpress-a9 -m 256M -kernel linux/linux-3.8/arch/arm/boot/zImage -append "root=/dev/nfs nfsroot=172.20.0.1:/home/rda/work/rootfs/fs rw ip=172.20.0.2:172.20.0.1:172.20.0.1:255.255.255.0 init=/linuxrc console=tty0" -net nic -net tapip=本機IP:對方IP:網關IP:掩碼
nfsroot=nfs的地址 對方IP:路徑 - 和/etc/exports中導出的路徑一樣
十. GDB和GDBServer的交叉編譯和使用
1. gdbserver
gdbserver很好用,作為設備端的應用為pc端gdb提供需要的信息,編譯也簡單
(1) 下載源碼
gdb-7.5.tar.bz2
地址: ftp://prep.ai.mit.edu/pub/gnu/(2) 編譯
cd gdb-7.5/gdb/gdbserver
./configure --host=arm-linux-gnueabi --target=arm-linux-gnueabi
make -j4
即生成了gdbserver,file查看文件類型,copy到板子上
(3) 使用
板子上:
./gdbserver localhost:1234 helloworld # helloworld是程序,執行后等待連接
PC上:
arm-linux-gnueabi-gdb helloworld
target remote 172.20.0.2:1234
以上連接上,就可以直接調試了
2. gdb
(1) 源碼 - gdb依賴termcap庫
termcap-1.3.1.tar.gz
地址: ftp://prep.ai.mit.edu/pub/gnu/(2) 交叉編譯termcap
cd termcap-1.3.1
./configure
后,修改Makefile如下
vi Makefile
CC = arm-linux-gnueabi-gcc
AR = arm-linux-gnueabi-ar
RANLIB = arm-linux-gnueabi-ranlib
make
(3) 交叉編譯GDB
把剛編譯出的libtermcap.a復制到gdb-7.5/gdb
cp -a libtermcap.a gdb-7.5/gdb
cd gdb-7.5
修改gdb/configure
case $host_os in
cygwin*)
if test -d $srcdir/libtermcap; then
........
esac
------->
ac_cv_search_rgetent="libtermcap.a"
配置
./configure --target=arm-linux-gnueabi --host=arm-linux-gnueabi
make -j4
(4) 運行GDB
GDB復制到板子上,就和調試PC程序一樣了.
十一. 問題
1. 參考鏈接
2. uboot出現問題
WARNING: Caches not enabled
Flash: ## Unknown flash on Bank 1 - Size = 0x00000000 = 0 MB
## Unknown flash on Bank 2 - Size = 0x00000000 = 0 MB
*** failed ***
### ERROR ### Please RESET the board ###
3. gdb運行出現
"Remote ‘g’ packet reply is too long"
注釋掉:
if (buf_len > 2 * rsa->sizeof_g_packet) error (_(“Remote ‘g’ packet reply is too long: %s”), rs->buf);
並在后面添加:
if (buf_len > 2 * rsa->sizeof_g_packet) { rsa->sizeof_g_packet = buf_len ; for (i = 0; i < gdbarch_num_regs (gdbarch); i++) { if (rsa->regs[i].pnum == -1) continue; if (rsa->regs[i].offset >= rsa->sizeof_g_packet) rsa->regs[i].in_g_packet = 0; else rsa->regs[i].in_g_packet = 1; } }
4. 高版本gdb可能會遇到調試錯誤,段錯誤等,可以換用低版本gdb,如gdb-7.0,gdb-6.8
gdb-7.0a這個版本是好用的.
5. 如果出現編譯錯誤
Werror相關的,那么配置的時候:
./configure --enable-werror=no ......
6. 注意gdbserver和gdb要用同一版本的
7. gdb和gdbserver通信過程中,共享庫符號問題
因為板子上的庫路徑和pc庫路徑不同,所以pc上gdb可能出現加載不了動態庫的問題,方法是:
set solib-absolute-prefix /usr/arm-linux-gnueabi/
set solib-search-path /uar/arm-linux-gnueabi/lib/