QEMU 仿真嵌入式开发


Did you know that elinux.org has Mailing Lists? Please feel free to register today to discuss the wiki in general, request features, etc. etc.. Thanks!--Wmat (talk)

Virtual Development Board

If you want to have an Embedded Linux Development Board, and you don't want to pay for it, then you can DIY a Virtual Development Board.

The Virtual Development Board is an emulation board which made from QEMU, actually it's a Virtual Machine.

Debug Mode

QEMU

Download QEMU

There are two ways in which you will usually obtain the source code:

   $ tar zxvf qemu-0.14.0.tar.gz
  • Using the git tool to track the source code.
   $ git clone git://git.qemu.org/qemu.git
Install QEMU

According to the Filesystem Hierarchy Standard, the directory '/opt' is reserved for the installation of add-on application software packages.

   $ sudo chmod 777 /opt

Install QEMU to '/opt/qemu', now we can go into the source code directory of QEMU

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

Linux determines the executable search path with the $PATH environment variable. The place to add a directory to the $PATH of all users except user root, add the line "PATH=/opt/qemu/bin:$PATH" to the file '/etc/profile' in root authority, and then use the "dot" command let the shell program executed in the current shell:

   $ . /etc/profile

Make sure there is a space between the dot (.) and the script name.

Then you can download arm-test-0.2.tar.gz from the QEMU Download Page, that's the ARM Linux 2.6 test kernel and initrd disk image (thanx to Paul Brook).

   $ tar zxvf arm-test-0.2.tar.gz
   $ cd arm-test
   $ qemu-system-arm -kernel zImage.integrator -initrd arm_root.img

It will startup a virtual ARM machine, if your mouse is grabbed by it, press "Ctrl-Alt" to exit. That's good, installation is done.

Bootloader

Prepare Cross Toolchain

Open Sourcery G++ Lite Edition for ARM, select GNU/Linux > Packages > Recommended Packages > IA32 GNU/Linux Installer, download the file arm-2010.09-50-arm-none-linux-gnueabi.bin, install it:

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

The default installation path is at your home, you can also modify it to be '/opt/CodeSourcery/Sourcery_G++_Lite' in the installation process, in default, it will automatically modify $PATH in the file '.bash_profile' at your home, thus add product to the $PATH for you only.

After the installation is done, you can find the sysroot directories provided with Sourcery G++ in the '/opt/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/libc'. Now you can also write a "hello world" program to test it:

   $ arm-none-linux-gnueabi-gcc -o hello hello.c
   $ qemu-arm -L ~/CodeSourcery/Sourcery_G++_Lite/arm-none-linux-gnueabi/libc hello

If you can see "hello world" or something others you let it print on the screen, the cross toolchain is prepared.

Download U-Boot
   $ tar jxvf u-boot-2010.09.tar.bz2
  • current source code:
   $ git clone git://git.denx.de/u-boot.git
Cross compile U-Boot

Go into the U-Boot root directory, then do

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

It will generate 'u-boot' and 'u-boot.bin' in the directory.

And we will get the tool "mkimage" under the directory "tools", we will use it to make Linux Kernel uImage, so

   $ sudo ln -sf $PWD/tools/mkimage /usr/local/bin/mkimage

You can start the u-boot in qemu now:

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

It will start u-boot in your console, now you can type u-boot command, like "printenv", after the "VersatilePB # " prompt. type "CTRL-a x" to quit.

Debug U-Boot

Add -s and -S options while involking QEMU

  • -s shorthand for -gdb tcp::1234
  • -S freeze CPU at startup (use 'c' to start execution)
   $ qemu-system-arm -M versatilepb -nographic -kernel u-boot -s -S

To debug u-boot, load the file "u-boot" into gdb (not "u-boot.bin") that is produced by "make" when building u-boot, This file is in ELF format and contain all the symbol information and are not stripped of debugging data until you run "strip" on them, unlike "u-boot.bin". Start ARM gdb in another console window and load "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.

in the QEMU console window, it will show something like this:

   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 #

type u-boot command "printenv" in the QEMU console window, it will be broken by the ARM gdb:

   VersatilePB # printenv

in the ARM gdb console window, it will show:

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

from here we should be able to use all the usual GDB commands, that's good!

Linux Kernel

Download Linux Kernel
   $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Cross Compile Linux Kernel
   $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- versatile_defconfig -s
   $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- uImage -s

Then we will get the file "uImage" at the location "arch/arm/boot/".

Link the uImage file to your tftpserver home path, for example '/opt/versatilepb/kernel', like this:

   $ mkdir -p /opt/versatilepb/kernel
   $ ln -sf $PWD/arch/arm/boot/uImage /opt/versatilepb/kernel/
Load Linux Kernel
Download and Install Open TFTP Server

Download the tftp server opentftpmtV1.63.tar.gz from Open TFTP Server Main Page, and install it

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

Modify the file "opentftpd.ini" to specify one directory as home directory, from where files will be served or deposited, for example, we add '/opt/versatilepb/kernel' line under the [HOME] entry in the file. To start tftpserver like this:

   $ sudo rc.opentftp start
   $ sudo rc.opentftp status

If displays "Server opentftp is running - Pid : xxxx", that's ok.

We can add the two lines below into the file '/etc/rc.d/rc.local' to start tftpserver at PC startup:

   /opt/opentftp/rc.opentftp start
   /opt/opentftp/rc.opentftp status
prepare qemu-ifup & qemu-ifdown

Using TAP network interfaces is the standard way to connect QEMU to a real network.

if there is not device "/dev/net/tun", we should make it :

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

also we can add them to "/etc/rc.d/rc.local", let it can be made at PC startup.

refer to QEMU/Networking, make two files: qemu-ifup and qemu-ifdown, but do not need openvpn line, then

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

suppose that IP of the target board is 192.168.1.123, IP of the host PC(server) is 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 #

? how to run qemu-system-arm with tap net in user mode?

run linux kernel
prepare the rootfs
prepare the nfs
run linux kernel

driver

add a device to QEMU
write the device driver

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 PBplatform 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.

Fix Compilation Errors
change: qemu_ram_alloc(NULL, "versatile.rom", VERSATILE_FLASH_SIZE) // add 'NULL' and "versatile.rom"
change: 4, 0, 0, 0, 0, 0) // add extra '0'
 
    dinfo = drive_get(IF_PFLASH, 0, 0);
    if(dinfo) {
    	if(!pflash_cfi01_register(VERSATILE_FLASH_ADDR, 
				qemu_ram_alloc(NULL, "versatile.rom", VERSATILE_FLASH_SIZE), 
				dinfo->bdrv, 
				VERSATILE_FLASH_SECT_SIZE, 
				VERSATILE_FLASH_SIZE / VERSATILE_FLASH_SECT_SIZE, 
				4, 0, 0, 0, 0, 0)) {
		fprintf(stderr, "qemu: error registering flash memory.\n");
		exit(1);
	}
	hasflash = 1;
    }
    if(!hasflash) {

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

### QEMU嵌入式开发中的应用指南 QEMU 是一种功能强大的开源模拟器,支持多种架构的虚拟化和模拟。它在嵌入式开发中具有广泛的应用场景,例如硬件仿真、软件调试以及操作系统移植等。以下是 QEMU嵌入式开发中的具体使用指南: #### 1. 支持多架构的硬件仿真 QEMU 提供了对多种架构的支持,包括但不限于 ARM、x86、MIPS 和 RISC-V 等。通过配置不同的目标架构,开发者可以轻松地模拟嵌入式设备的运行环境。例如,为了支持 RISC-V 架构和 ESP32-C3 的模拟,可以通过以下命令完成安装和配置[^1]: ```bash git clone https://github.com/espressif/qemu.git cd qemu && ./configure --target-list=riscv32-softmmu make -j$(nproc) ``` #### 2. 获取 QEMU 源码并进行定制 除了从官方仓库克隆最新版本的 QEMU 源码外,还可以通过下载 tar 包的方式获取特定版本的 QEMU 源码。以命令行下载 2.0 版本的 QEMU 为例[^2]: ```bash wget http://wiki.qemu-project.org/download/qemu-2.0.0.tar.bz2 tar xjvf qemu-2.0.0.tar.bz2 ``` 通过源码编译,开发者可以根据实际需求对 QEMU 进行定制化修改,例如添加新的硬件模型或优化性能。 #### 3. 嵌入式系统的调试与测试 QEMU 可用于嵌入式系统的调试与测试,特别是在没有真实硬件的情况下。开发者可以通过 QEMU 模拟目标设备的运行环境,并结合 GDB 等工具进行程序调试。例如,启动一个 RISC-V 架构的虚拟机并连接 GDB 调试器: ```bash qemu-system-riscv32 -M virt -kernel your_image.elf -s -S gdb your_image.elf target remote :1234 ``` 上述命令将启动一个暂停状态的虚拟机,并允许开发者通过 GDB 连接进行单步调试和断点设置[^1]。 #### 4. 操作系统移植与开发 随着嵌入式硬件能力的提升,越来越多的设备能够运行复杂的操作系统,如 Linux。QEMU 提供了一个理想的平台,用于操作系统的移植与开发。通过模拟目标硬件的运行环境,开发者可以在不依赖真实硬件的情况下完成内核编译、驱动开发和应用程序测试等工作[^4]。 #### 5. 开发资源与学习资料 嵌入式开发需要丰富的学习资源和技术支持。一些优秀的开源项目和资料汇总可以帮助开发者快速上手 QEMU 的使用[^3]。例如,GitHub 上有许多针对不同架构的 QEMU 示例项目,涵盖了从基础入门到高级应用的各个层面。 --- ### 示例代码:启动一个 RISC-V 虚拟机 以下是一个简单的示例,展示如何使用 QEMU 启动一个 RISC-V 架构的虚拟机: ```bash #!/bin/bash # 下载并编译 QEMU(如果尚未完成) git clone https://github.com/espressif/qemu.git cd qemu && ./configure --target-list=riscv32-softmmu make -j$(nproc) # 启动虚拟机 ./qemu-system-riscv32 -M virt -kernel your_kernel_image.elf ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值