qemu虛擬開發板

如果你想擁有一塊開發板,而又不想花錢,那你就可以自己做一個虛擬開發板。

虛擬開發板是用QEMU模擬出來的一塊板子,實際上就是一個虛擬機。

Contents

[hide]

調試模式

QEMU

下載QEMU

通常我們有兩種方式來獲取源代碼:

$ tar zxvf qemu-0.13.0.tar.gz
  • 用git工具來抓取源代碼:
$ git clone git://git.qemu.org/qemu.git

安裝QEMU

現在我們可以進到QEMU的源代碼目錄中,執行以下命令安裝QEMU的ARM仿真部分到本機的'/opt/qemu/'目錄下

$ ./configure --prefix=/opt/qemu --target-list=arm-softmmu,arm-linux-user --enable-debug $ make -s $ make install -s

添加 "PATH=/opt/qemu/bin:$PATH" 到文件 '/etc/profile' 中, 然後執行以下命令,就可以在控制檯直接運行QEMU相關命令了

$ . /etc/profile

我們可以從QEMU下載頁面中下載arm-test-0.2.tar.gz, 這是ARM Linux 2.6的測試內核和initrd磁盤鏡像(感謝Paul Brook)。

$ tar zxvf arm-test-0.2.tar.gz $ cd arm-test $ qemu-system-arm -kernel zImage.integrator -initrd arm_root.img -nographic -append "console=ttyAMA0"

命令將啓動一個帶命令行的ARM虛擬機,鍵入"CTRL-a x"可以退出。好了,安裝完成。

bootloader

準備交叉編譯工具

打開網頁Sourcery G++ Lite Edition for ARM,依次點擊" GNU/Linux > Packages > Recommended Packages > IA32 GNU/Linux Installer"。 下載後,將它安裝到目錄'/opt'中:

$ chmod +x arm-VERSION-arm-none-linux-gnueabi.bin $ ./arm-VERSION-arm-none-linux-gnueabi.bin

安裝完成後,我們可以在目錄'/opt/CodeSourcery/Sourcery_G++_Lite/bin'中找到我們需要的交叉編輯工具。可以寫一個"hello world"測試程序來測試一下它們:

$ sudo mkdir -p /usr/gnemul $ sudo ln -sf /opt/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/libc /usr/gnemul/qemu-arm $ arm-none-linux-gnueabi-gcc -o hello hello.c $ qemu-arm hello

如果我們可以看到有"hello world"或者別的你讓輸出的字符出現在屏幕上了, 交叉編譯工具就準備好了.

下載U-Boot

$ git clone git://git.denx.de/u-boot.git

交叉編譯U-Boot

到U-Boot的根目錄下,然後執行:

$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- versatilepb_config $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- -s

在目錄下將會產生文件'u-boot'和'u-boot.bin'。

同時我們也可以在'tools'目錄中得到工具"mkimage", 在編譯Linux內核uImage時將會用到它,所以

$ sudo ln -sf `pwd`/tools/mkimage /usr/local/bin/mkimage

現在我們可以在控制檯中啓動U-Boot了:

$ qemu-system-arm -M versatilepb -nographic -kernel u-boot

啓動成功後會顯示命令提示符"VersatilePB #",現在就可以輸入像"printenv"等U-Boot命令了。 輸入組合鍵"CTRL-a x"即可以退出。

調試U-Boot

當調用QEMU時添加 -s 和 -S 選項

  • -s -gdb tcp::1234 的所寫
  • -S 在啓動時停止CPU (鍵入'c'纔會開始執行)
$ qemu-system-arm -M versatilepb -nographic -kernel u-boot -s -S

調試U-Boot時,加載文件'u-boot' 到gdb(記住不是'u-boot.bin'),'u-boot'是一個ELF格式的文件,它含有所有調試時會用到的符號信息,不像'u-boot.bin'是在執行"stripe"命令後,剔除了調試信息的文件。 另開一個控制檯窗口執行ARM的交叉調試工具並加載文件'u-boot':

$ arm-none-linux-gnueabi-gdb u-boot (gdb) target remote :1234 (gdb) b do_printenv Breakpoint 1 at 0x10080f4: file cmd_nvedit.c, line 147. (gdb) c Continuing.

此時在QEMU的控制檯窗口中, 將會有如下顯示:

U-Boot 2010.06 (Aug 31 2010 - 16:23:16) DRAM: 0 Bytes Flash: 64 MiB *** Warning - bad CRC, using default environment In: serial Out: serial Err: serial Net: SMC91111-0 VersatilePB #

在提示符"VersatilePB #"後輸入U-Boot命令"printenv",它的執行將會被gdb中斷:

VersatilePB # printenv

在gdb的控制檯窗口中, 將會顯示:

Breakpoint 1, do_printenv (cmdtp=0x1015520, flag=0, argc=1, argv=0xfddee4) at cmd_nvedit.c:147 147 if (argc == 1) { (gdb)

從這兒開始我們就可以使用普通的gdb調試命令進行調試了, 不錯!

Linux內核

下載Linux內核

$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git

交叉編譯Linux內核

$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- versatile_defconfig -s $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- uImage -s

編譯完成後會在目錄'arch/arm/boot'中生成文件'uImage'。

加載Linux內核

下載並安裝 TFTP Server

Open TFTP Server的主頁上下載opentftpmtV1.63.tar.gz,然後安裝它:

$ tar zxvf opentftpmtV1.63.tar.gz $ mv opentftp/ /opt/ $ cd /opt/opentftp/

修改配置文件'opentftpd.ini'來指定tftpserver的工作目錄, 也就是向外提供tftp服務的目錄, 比如, 我們添加"/opt/versatilepb/firmware"這行字到配置文件'opentftpd.ini'的[HOME]條目下,然後將編譯好的Linux內核uImage鏈接到這個目錄下:

$ ln -sf PATH_TO_LINUX_KERNEL/arch/arm/boot/uImage /opt/versatilepb/firmware/

用如下命令來啓動tftpserver:

$ mkdir -p /opt/versatilepb/firmware $ sudo rc.opentftp start

顯示"Server opentftpd started"說明tftpserver已經啓動.

我們可以將如下兩行文字添加到文件'/etc/rc.d/rc.local'中,使得tftpserver可以在開機時自動啓動:

$ /opt/opentftp/rc.opentftp start $ /opt/opentftp/rc.opentftp status
準備qemu-ifup和qemu-ifdown

用TAP網絡接口是QEMU通往真實網絡的標準方式。

如果不存在設備'/dev/net/tun',用如下命令創建它:

$ sudo mkdir -p /dev/net $ sudo mknod /dev/net/tun c 10 200 $ sudo /sbin/modprobe tun

我們也可以將如上命令添加到文件'/etc/rc.d/rc.local'中, 使得設備在每次開機時就被自動創建。

參考QEMU/Networking, 做出兩個文件: 'qemu-ifup' 和 'qemu-ifdown', 但是不需要其中與open***相關的那一行,註釋掉就可以了:

$ sudo cp qemu-ifup qemu-ifdown /etc/ $ sudo chmod +x qemu-ifup $ sudo chmod +x qemu-ifdown
tftpboot uImage

假設虛擬開發板的IP是:192.168.1.123, PC主機(tftpserver)的IP是:192.168.1.234.

$ sudo qemu-system-arm -M versatilepb -nographic -net nic -net tap,ifname=tap0 -kernel $PATH_TO_YOUR_U-BOOT/u-boot U-Boot 2010.09 (Dec 15 2010 - 18:16:35) DRAM: 0 Bytes ## Unknown FLASH on Bank 1 - Size = 0x00000000 = 0 MB Flash: 0 Bytes *** Warning - bad CRC, using default environment In: serial Out: serial Err: serial Net: SMC91111-0 VersatilePB # sete ipaddr 192.168.1.123 VersatilePB # sete serverip 192.168.1.234 VersatilePB # sete bootfile uImage VersatilePB # tftpboot SMC91111: PHY auto-negotiate timed out SMC91111: MAC 52:54:00:12:34:56 Using SMC91111-0 device TFTP from server 192.168.1.234; our IP address is 192.168.1.123 Filename 'uImage'. Load address: 0x7fc0 Loading: T ###################################T ############################## ########################################## done Bytes transferred = 1556392 (17bfa8 hex) VersatilePB # iminfo ## Checking Image at 00007fc0 ... Legacy image found Image Name: Linux-2.6.36.2 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 1556328 Bytes = 1.5 MiB Load Address: 00008000 Entry Point: 00008000 Verifying Checksum ... OK VersatilePB #

? 如何在普通用戶模式下執行帶tap網絡的qemu-system-arm?

運行Linux內核

準備ROOTFS
準備NFS
運行uImage

設備驅動

添加一個設備到QEMU

設備驅動程序

GUI

Run Mode

QEMU

Support FLASH on QEMU

Now, the emulation of Intel flashes is present in Qemu (in hw/pflash_cfi01.c) and this emulation is already used in some emulated ARM platforms, but not the Versatile PB platform that we use for our object (this platform is nice because it has Ethernet, serial ports, LCD, etc.). So, we must add flash emulation to the Versatile PB platform. Firstly, we should go into the source code directory of QEMU, and modify the file hw/versatilepb.c, assume to support a 64MB flash device, like this:

--- qemu-0.12.5/hw/versatilepb.c	2010-07-22 20:39:04.000000000 +0800 +++ qemu_armux/hw/versatilepb.c	2010-09-01 11:59:33.000000000 +0800 @@ -16,6 +16,11 @@ #include "pci.h" #include "usb-ohci.h" #include "boards.h" +#include "flash.h" + +#define VERSATILE_FLASH_ADDR 0x34000000 +#define VERSATILE_FLASH_SIZE	(64*1024*1024) +#define VERSATILE_FLASH_SECT_SIZE(256*1024)   /* Primary interrupt controller. */   @@ -172,7 +177,9 @@ NICInfo *nd; int n; int done_smc = 0; - + DriveInfo *dinfo; + int hasflash = 0; + if (!cpu_model) cpu_model = "arm926"; env = cpu_init(cpu_model); @@ -280,13 +287,29 @@ /* 0x101f2000 UART1. */ /* 0x101f3000 UART2. */ /* 0x101f4000 SSPI. */ - - versatile_binfo.ram_size = ram_size; - versatile_binfo.kernel_filename = kernel_filename; - versatile_binfo.kernel_cmdline = kernel_cmdline; - versatile_binfo.initrd_filename = initrd_filename; - versatile_binfo.board_id = board_id; - arm_load_kernel(env, &versatile_binfo); +	+ dinfo = drive_get(IF_PFLASH, 0, 0); + if(dinfo) { + if(!pflash_cfi01_register(VERSATILE_FLASH_ADDR, +	 qemu_ram_alloc(VERSATILE_FLASH_SIZE), +	 dinfo->bdrv, +	 VERSATILE_FLASH_SECT_SIZE, +	 VERSATILE_FLASH_SIZE / VERSATILE_FLASH_SECT_SIZE, +	 4, 0, 0, 0, 0)) { +	 fprintf(stderr, "qemu: error registering flash memory./n"); +	 exit(1); +	} +	hasflash =1; + } + if(!hasflash) { + versatile_binfo.ram_size = ram_size; + versatile_binfo.kernel_filename = kernel_filename; + versatile_binfo.kernel_cmdline = kernel_cmdline; + versatile_binfo.initrd_filename = initrd_filename; + versatile_binfo.board_id = board_id; + arm_load_kernel(env, &versatile_binfo); + } else + env->regs[15] = VERSATILE_FLASH_ADDR; }   static void vpb_init(ram_addr_t ram_size,

then save the file.

U-Boot

burn U-Boot into flash

Firstly, we must create a 64MB flash file, then we can burn the 'u-boot.bin' into the flash:

$ dd if=/dev/zero of=flash.img bs=1M count=64 $ dd if=u-boot.bin of=flash.img conv=notrunc $ qemu-system-arm -M versatilepb -nographic -pflash flash.img

References

External links

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章