Powered by Drupal, an open source content management system

การวิ่ง mini2440 บนเครื่องจำลอง qemu

qemu เป็นโปรแกรมในลักษณะที่เรียกว่า Virtual Mahine คือเป็นเครืองเทียมที่เราสามารถใช้จำลองระบบฮาร์แวร์ เพื่อใช้ในงานพัฒนาโปรแกรมโดยไม่จำเป็นต้องมีฮาร์แวร์จริง  บทความนี้จะแสดงวิธีการจำลองระบบ mini2440 ด้วย qemu

ภาพตัวอย่าง fluidlauncher วิ่งบน qemu + lcd 7 "

ขั้นตอนการติดตั้งจะเป็นดังนี้ครับ

1. เตรียม Host Machine

Host ที่ใช้สาธิตจะวิ่ง OS Ubuntu 9.10 ภายใต้ user ที่มีชื่อว่า mini2440

ให้ติดตั้งโปรแกรมที่จำเป็นต่อการคอมไพล์ดังนี้ 

$ sudo apt-get update
$ sudo apt-get install build-essential
$ sudo apt-get install git-core
$ sudo apt-get install zlib1g-dev
$ sudo apt-get install libsdl-console-dev

 

2. สร้าง qemu-system-arm สำหรับ mini2440

$ mkdir ~/qemu
$ cd ~/qemu
$ git clone git://repo.or.cz/qemu/mini2440.git
$ cd mini2440
$ ./configure --target-list=arm-softmmu
$ make

เราจะได้โปรแกรมที่ใช้ในการรันอยู่ที่ ~/qemu/mini2440/arm-softmmu/qemu-system-arm

และ script สำหรับการรันอยู่ที่ ~/qemu/mini2440/mini2440/mini2440_start.sh

ให้สร้างไฟล์ start.sh ภายใต้ directory ~/qemu/mini2440/mini2440 เป็นดังนี้ (ให้ใช้คำสั่ง chmod 755 mini2440/start.sh เพื่อกำหนดให้ไฟล์สามารถ execute ได้ด้วย)

#!/bin/bash

base=$(dirname $0)

echo Starting in $base

name_nand="$base/mini2440_nand.bin"
name_sd="$base/sd.img"

if [ ! -f "$name_nand" ]; then
 echo $0 : creating NAND empty image : "$name_nand"
 dd if=/dev/zero of="$name_nand" bs=528 count=131072
fi

cmd="$base/../arm-softmmu/qemu-system-arm \
 -M mini2440 $* \
 -serial stdio \
 -mtdblock "$name_nand" \
 -sd $name_sd \
 -show-cursor \
 -usb -usbdevice keyboard -usbdevice mouse \
 -net nic,vlan=0 \
 -net tap,vlan=0,ifname=tap1,script=/etc/qemu-ifup \
 -monitor telnet::5555,server,nowait"

echo $cmd
$cmd

3. เตรียมระบบ network ของ Host เพื่อให้เชื่อมต่อกับ network ภายใน qemu

ติดตั้ง utilities สองตัวดังนี้

$ sudo apt-get install bridge-utils
$ sudo apt-get install uml-utilities

สร้าง script ชื่อ network.sh ภายใต้ direcotry mini2440 เป็นดังนี้ (ให้ใช้คำสั่ง chmod 755 mini2440/network.sh เพื่อกำหนดให้ไฟล์สามารถ execute ได้ด้วย)

#!/bin/sh
sudo chown root.users /dev/net/tun
sudo chmod g+rw /dev/net/tun
sudo brctl addbr br0
sudo ifconfig eth0 0.0.0.0 promisc
sudo brctl addif br0 eth0
sudo dhclient br0
sudo tunctl -t tap1 -u `whoami`

network.sh จะทำการ

  • สร้าง Bridge Device br0
  • ปลด eth0 จากเน็กเวิร์คหลัก
  • เชื่อม eth0 ผ่าน br0
  • ขอ ip address จาก dhcp server ให้กับ br0
  • สร้าง Device tap1

หมายเหตุ โปรดระวังเครื่องหมายหน้าและหลังคำสั่ง whoami

4. สร้างscript ที่ชื่อ /etc/qemu-ifup เพื่อทำการเชื่อมต่อ tap1 เข้ากับ bridge br0 ดังข้อความนี้ 

qemu-ifup จะถูกเรียกใช้เมื่อวิ่ง start.sh

#!/bin/sh
echo "Executing /etc/qemu-ifup"
echo "Bringing up $1 for bridged mode..."
sudo /sbin/ifconfig $1 0.0.0.0 promisc up
echo "Adding $1 to br0..."
sudo /usr/sbin/brctl addif br0 $1
sleep 2

 กำหนดให้สามารถ execute ได้ดังนี้

$ sudo chmod 755 /etc/qemu-ifup

5. กำหนดให้ user mini2440 สามารถวิ่งบางคำสั่งที่ต้องการ root acess โดย แก้ไขไฟล์ /etc/sudoers ด้วยคำสั่ง

$ sudo visudo

 เพิ่มบรรทัดที่แสดงด้วยสีดังนี้

# /etc/sudoers
#
# This file MUST be edited with the 'visudo' command as root.
#
# See the man page for details on how to write a sudoers file.
#

Defaults env_reset

# Host alias specification

# User alias specification

# Cmnd alias specification
Cmnd_Alias QEMU=/sbin/ifconfig, /sbin/modprobe, /usr/sbin/brctl

# User privilege specification
root ALL=(ALL) ALL
mini2440 ALL=(ALL) ALL
mini2440 ALL=NOPASSWD: QEMU

# Uncomment to allow members of group sudo to not need a password
# (Note that later entries override this, so you might need to move
# it further down)
# %sudo ALL=NOPASSWD: ALL

# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL

6. ในกรณีที่ไม่มี device tun ให้สร้างดังนี้

$ sudo mknod /dev/net/tun c 10 200

มาถึงจุดนี้ระบบเราพร้อมที่จะใช้งานแล้วครับ

7. รู้จักระบบ qemu-system-arm

จากระบบตัวอย่างของเราไฟล์ต่างๆจะเป็นดังนี้

  • directory ที่เราจะรันอยู่ที่ ~/qemu/mini2440
  • โปรแกรม qemu-system-arm อยู่ที่ ~/qemu/mini2440/arm-softmmu
  • script ที่ใช้เรียกโปรแกรมอยู่ที่ ~/qemu/mini2440/mini2440/start.sh
  • script ที่ใช้เซ็ท network อยู่ที่ ~/qemu/mini2440/mini2440/network.sh
  • script ที่ใช้เซ็ท network อีกตัวที่จะเรียกโดย start.sh อยู่ที่ /etc/qemu-ifup

นอกจาก script ที่กล่าวมาข้างต้นแล้ว ยังมีไฟล์อีกสามตัวที่จำเป็นต่อการใช้งานจำลอง mini2440 นั่นก็คือ

  • ไฟล์ชื่อ u-boot.bin (ต้องเป็นชื่อนี้เท่านั้น) ซึ่งไฟล์นี้จะทำหน้าที่เป็น bootloader และจะถูกเรียกใช้งานทุกครั้งที่เริ่มโปรแกรม โดยจะต้องอยู่ใน directory ~/qemu/mini2440/mini2440 (ดูเรื่องการสร้าง uboot ได้จาก http://project4fun.com/node/12)
  • ไฟล์ชื่อ mini2440_nand.bin ที่จะทำหน้าที่คล้ายๆ nand flash ไฟล์นี้จะถูกสร้างขึ้นอัตโนมัติในกรณีที่ไม่มีมาก่อน
  • ไฟล์ชื่อ sd.img จะทำหน้าที่คล้ายๆ sd card ของระบบ

ไฟล์ sd.img ซึ่งเป็นไฟล์จำลอง sd card สามารถสร้างได้สองวิธีดังนี้

  • สร้างไฟล์ตามนี้ http://code.google.com/p/mini2440/wiki/QEmuSDCardImage
  • สร้างจาก sd card จริง วิธีนี้ค่อนข้างจะมีประโยชน์มากเนื่องจากไฟล์จะมีขนาดเท่ากับ sd card จริงทำให้การ copy ไปมาทำระหว่างไฟล์เทียมกับไฟล์จริงเป็นไปด้วยความง่ายดาย
    • ให้เตรียม sd card ให้พร้อมสำหรับที่จะวิ่งบน mini2440 โดยการแบ่ง partition และ copy file ต่างๆให้เรียบร้อย
    • เสียบ sd card เข้ากับระบบและใช้คำสั่ง sudo fdisk -l เพื่อค้นหาว่าเป็น device อะไร (สมมติว่าเป็น /dev/sdb)
    • ใช้คำสั่ง sudo dd if=/dev/sdb of=sd.img แล้วสามารถที่จะเอาไฟล์ sd.img ไปใช้งานได้ทันที

$ sudo fdisk -l

Disk /dev/sdb: 2013 MB, 2013265920 bytes
16 heads, 15 sectors/track, 16384 cylinders
Units = cylinders of 240 * 512 = 122880 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1         854      102472+   c  W95 FAT32 (LBA)
/dev/sdb2             855       15292     1732560   83  Linux
/dev/sdb3           15293       16384      131040   82  Linux swap / Solaris

$ sudo dd if=/dev/sdb of=sd.img

 

ให้ copy ไฟล์ u-boot.bin และ sd.img(ที่มี linux file system พร้อมสำหรับใช้งานแล้ว)  ไปไว้ที่ ~/qemu/mini2440/mini2440

8. เริ่มการใช้งาน qemu

เบื้องต้นให้ทดสอบดูระบบ network ก่อน จะเห็นว่า eth0 จะเป็นอุปกรณ์หลักของระบบในการต่อเข้ากับ network

mini2440@mini2440-desktop:~$ ifconfig
eth0      Link encap:Ethernet  HWaddr 00:0c:29:63:70:c1 
          inet addr:192.168.1.102  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fe63:70c1/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6 errors:0 dropped:0 overruns:0 frame:0
          TX packets:54 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:934 (934.0 B)  TX bytes:5414 (5.4 KB)
          Interrupt:18 Base address:0x2000

lo        Link encap:Local Loopback 
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:10 errors:0 dropped:0 overruns:0 frame:0
          TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:862 (862.0 B)  TX bytes:862 (862.0 B)

 

สร้าง bridge network ด้วยคำสั่ง ./mini2440/network.sh

mini2440@mini2440-desktop:~$ cd ~/qemu/mini2440
mini2440@mini2440-desktop:~/qemu/mini2440$ ./mini2440/network.sh
[sudo] password for mini2440:
Internet Systems Consortium DHCP Client V3.1.2
Copyright 2004-2008 Internet Systems Consortium.
All rights reserved.
For info, please visit http://www.isc.org/sw/dhcp/

Listening on LPF/br0/00:0c:29:63:70:c1
Sending on   LPF/br0/00:0c:29:63:70:c1
Sending on   Socket/fallback
DHCPREQUEST of 192.168.1.102 on br0 to 255.255.255.255 port 67
DHCPREQUEST of 192.168.1.102 on br0 to 255.255.255.255 port 67
DHCPDISCOVER on br0 to 255.255.255.255 port 67 interval 7
DHCPOFFER of 192.168.1.102 from 192.168.1.1
DHCPREQUEST of 192.168.1.102 on br0 to 255.255.255.255 port 67
DHCPACK of 192.168.1.102 from 192.168.1.1
bound to 192.168.1.102 -- renewal in 39141 seconds.
Set 'tap1' persistent and owned by uid 1000

 

ตรวจสอบอีกครั้งจะเห็นว่าคราวนี้ br0 จะเป็นตัวที่ต่อกับเครือข่ายหลัก โดยมี eth0 เป็นตัวลูก

หมายเหตุ ถ้า br0 ไม่สามารถร้องขอ ip address จาก dhcp ได้ ให้ลองใช้คำสั่ง

$ sudo /etc/init.d/networking restart

แล้วตามด้วย ./mini2440/network.sh อีกครั้งหนึ่ง

mini2440@mini2440-desktop:~/qemu/mini2440$ ifconfig
br0       Link encap:Ethernet  HWaddr 00:0c:29:63:70:c1 
          inet addr:192.168.1.102  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fe63:70c1/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:24 errors:0 dropped:0 overruns:0 frame:0
          TX packets:156 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:5317 (5.3 KB)  TX bytes:31471 (31.4 KB)

eth0      Link encap:Ethernet  HWaddr 00:0c:29:63:70:c1 
          inet6 addr: fe80::20c:29ff:fe63:70c1/64 Scope:Link
          UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1500  Metric:1
          RX packets:209 errors:0 dropped:0 overruns:0 frame:0
          TX packets:208 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:31900 (31.9 KB)  TX bytes:35421 (35.4 KB)
          Interrupt:18 Base address:0x2000

lo        Link encap:Local Loopback 
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:13 errors:0 dropped:0 overruns:0 frame:0
          TX packets:13 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1198 (1.1 KB)  TX bytes:1198 (1.1 KB)

mini2440@mini2440-desktop:~/qemu/mini2440$ brctl show
bridge name bridge id  STP enabled interfaces
br0  8000.000c296370c1 no  eth0

 

ทำการรัน qemu ด้วยคำสั่ง ./mini2440/start.sh ก็จะเห็น window เปิดขึ้นมาอีกอัน ซึ่งอันนั้นเปรียบเสมือนจอ LCD ส่วน window เดิมจะทำหน้าที่แสดงข้อความที่ออกมาจาก serial port ของ qemu (เนื่องจากเรากำหนด option ให้ -serial stdio)

โปรดสังเกตุ *** Warning - bad CRC or NAND, using default environment เนื่องจากตอนนี้ flash file ของเราไม่ได้ถูก format นั่นเอง ลำดับจากนี้ไปก็สามารถทำตามขั้นตอนปกติเหมือนเครื่องจริงได้เลยครับ

U-Boot 1.3.2-mini2440 (Jan 14 2010 - 19:36:26)

I2C:   ready
DRAM:  64 MB
Flash:  2 MB
NAND:  Bad block table not found for chip 0
Bad block table not found for chip 0
64 MiB
*** Warning - bad CRC or NAND, using default environment

USB:   S3C2410 USB Deviced
ERROR: usbd_device_event_irq(), 613: (3401ea64,1) NULL device or device->bus
ERROR: usbd_device_event_irq(), 613: (3401ea64,2) NULL device or device->bus
ERROR: usbd_device_event_irq(), 613: (3401ea64,3) NULL device or device->bus
In:    serial
Out:   serial
Err:   serial
MAC: 08:08:11:18:12:27
Hit any key to stop autoboot:  0
MINI2440 #

 ทำการเคียร์ข้อมูลทุกอย่างบน nand ด้วยคำสั่ง nand scrub

MINI2440 # nand scrub

NAND scrub: device 0 whole chip
Warning: scrub option will erase all factory set bad blocks!
         There is no reliable way to recover them.
         Use this command only for testing purposes if you
         are sure of what you are doing!

Really scrub this NAND flash? <y/N>
Erasing at 0x3ffc000 -- 100% complete.
Bad block table not found for chip 0
Bad block table not found for chip 0
OK
MINI2440 #

สร้าง bad block table ด้วยคำสั่ง nand createbbt

 

MINI2440 # nand createbbt
Create BBT and erase everything ? <y/N>
Skipping bad block at  0x03ff0000                                           
Skipping bad block at  0x03ff4000                                           
Skipping bad block at  0x03ff8000                                           
Skipping bad block at  0x03ffc000                                           

Creating BBT. Please wait ...Bad block table not found for chip 0
Bad block table not found for chip 0
Bad block table written to 0x03ffc000, version 0x01
Bad block table written to 0x03ff8000, version 0x01

MINI2440 #

 

สร้างที่เก็บข้อมูล environment ของ uboot

MINI2440 # dynenv set 40000
device 0 offset 0x40000, size 0x3fc0000
45 4e 56 30 - 00 00 04 00
MINI2440 #

 

 

MINI2440 # saveenv
Saving Environment to NAND...
Erasing Nand...Writing to Nand... done
MINI2440 #

 

จะเห็นว่าเมื่อ reset แล้ว error *** Warning - bad CRC or NAND, using default environment จะหายไป

MINI2440 # reset
S3C: CLK=240 HCLK=240 PCLK=240 UCLK=57
QEMU mini2440_reset: loaded default u-boot from NAND
QEMU mini2440_reset: loaded override u-boot (size 3c000)
S3C: CLK=240 HCLK=240 PCLK=240 UCLK=48
S3C: CLK=304 HCLK=304 PCLK=304 UCLK=48
S3C: CLK=304 HCLK=101 PCLK=50 UCLK=48
S3C: CLK=304 HCLK=76 PCLK=38 UCLK=48
S3C: CLK=304 HCLK=76 PCLK=38 UCLK=48
S3C: CLK=405 HCLK=101 PCLK=50 UCLK=48

U-Boot 1.3.2-moko12 (Jun 26 2009 - 18:16:16)

I2C:   ready
DRAM:  64 MB
Flash:  2 MB
NAND:  64 MiB
Found Environment offset in OOB..
USB:   S3C2410 USB Deviced
In:    serial
Out:   serial
Err:   serial
MAC: 08:08:11:18:12:27
Hit any key to stop autoboot:  0
MINI2440 #

 

มาถึงจุดนี้ระบบเราก็พร้อมที่จะทดสอบแล้วครับ เราจะลองทดสอบการใช้ sd card ซึ่งแบ่งเป็นสาม partion คือ

  • parition 1 type FAT เก็บ uImage
  • parition 2 type ext3 เก็บ linux file system
  • parition 3 type swap

ทำการค้นหาชื่อไฟล์ และกำหนด bootcmd ให้โหลดจาก sd card

MINI2440 # mmcinit
trying to detect SD Card...
Manufacturer:       0xaa, OEM "XY"
Product name:       "QEMU!", revision 0.1
Serial number:      3735928559
Manufacturing date: 2/2006
CRC:                0x0c, b0 = 1
READ_BL_LEN=15, C_SIZE_MULT=3, C_SIZE=3453
size = 4066377728
MINI2440 # fatls mmc 0:1
  2067364   uimage-2.6.32+git-r1-mini2440.bin

1 file(s), 0 dir(s)

MINI2440 # setenv bootcmd 'mmcinit ; fatload mmc 0:1 0x31000000 uimage-2.6.32+git-r1-mini2440.bin ; bootm 0x31000000'
MINI2440 #

กำหนดให้ bootargs เพื่อ Mount file system บน partition 2 ของ sd card หลังจากนั้นบันทึก environment และ ทำการ reset ระบบ

MINI2440 # setenv bootargs 'noinitrd rootdelay=3 root=/dev/mmcblk0p2 console=ttySAC0,115200 rootwait'
MINI2440 # saveenv
Saving Environment to NAND...
Erasing Nand...Writing to Nand... done
MINI2440 #
reset

 

ท่านก็จะได้เห็นภาพคุ้นๆของเพนกวิน และจากตัวอย่างจะเป็น Linux Angstrom

 

 

ข้อควรรู้บางอย่างเมื่อใช้งาน qemu

  • ในการใช้งาน Qt ควรเปลี่ยนจากจอ touch screen เป็น mouse ด้วยคำสั่ง export QWS_MOUSE_PROTO=MouseMan:/dev/psaux ก่อนการรัน application
  • ถ้ากด ctrl-c บน console ที่ใช้ launch qemu จะทำให้ qemu หยุดทำงาน ดังนั้นควรจะเปิดหน้าต่าง console อีกอันแล้วใช้คำสั่ง ssh -l username ipaddress เพื่อ putty เข้าไปใช้งานควบคุมแทนการใช้ copnsole ที่ launch qemu โดยตรง
  • ถ้าผ่าน mini2440-1tb ไปยัง bootargs ดังนี้ setenv bootargs 'noinitrd rootdelay=3 root=/dev/mmcblk0p2 console=ttySAC0,115200 rootwait mini2440=1tb' จะทำให้จอ lcd ของระบบ mini2440 เปลี่ยนไปเป็น 7 นิ้วเหมือนระบบจริง
  • เมื่อคลิ๊กเข้าไปใช้งานบนจอ lcd ของ qemu แล้ว หากจะออกจากระบบ qemu กลับเข้ามายัง console ต้องกดปุ่ม ctrl-alt ก่อนถึงจะสามารถออกจากระบบ qemu ได้
  • ใน script start.sh ที่ใช้วิ่ง qemu หากเปลี่ยน -sd ไปเป็น device จริงเช่นถ้า sd card ต่อกับระบบ linux เป็น /dev/sdb เราสามารถใช้ option -sd /dev/sdb ก็จะสามารถใช้งาน sd card ได้โดยตรง

หวังว่าคงสนุกกับการใช้งาน mini2440 จำลองนะครับ

images ที่ใช้ทดสอบระบบ qemu ในบทความสามารถดาวน์โหลดได้จาก ที่นี่ครับ  

อ้างอิง

http://repo.or.cz/w/qemu/mini2440.git

http://compsoc.dur.ac.uk/~djw/qemu.html

https://help.ubuntu.com/community/WindowsXPUnderQemuHowTo

http://ubuntuforums.org/archive/index.php/t-593577.html

http://www.aurel32.net/info/debian_arm_qemu.php

http://code.google.com/p/mini2440/wiki/QEmuSDCardImage