Current status of qemu-omap3

Jan 5th, 2009 | Posted by yajin | Filed under OMAP, emulation

1. u-boot and linux kernel can boot from mmc image

2. Because twl4030 emulation is not complete, mmc device can not be found in linux kernel.

Next step:

1. twl4030 emulation. Big effort is needed.

2. dss/dma emulation

3. usb

nand flash emulation in qemu-omap3

Dec 24th, 2008 | Posted by yajin | Filed under OMAP, emulation

Qemu currently supports nand flash emulation in hw/nand.c. But it is for spi flash and it's not ready for big page nand flash, 2k page nand flash for example. I add the big page nand flash emulation to it, but it has some bugs. When I boots jffs2 rootfs from qemu-omap, some error messages appear.

<4>mtd->read(0x1f9f4 bytes from 0x2060c) returned ECC error

<4>mtd->read(0x1f9f4 bytes from 0x2060c) returned ECC error

<5>jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00020800: 0xb1e0 instead

jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00020800: 0xb1e0 instead

After hours of debuging, I find that the message is related to bugs of nand flash emulation.But I do not want to change nand.c code too much because I am afraid it will have some sideeffect to other type nand flash emulation. So I decide to wirte a new nand flash emulation for beagle board or other big page nand flash. After that, rootfs can be booted from nand flash.

code reorder of x-loader using arm-none-linux-gnueabi-gcc

Dec 22nd, 2008 | Posted by yajin | Filed under OMAP

I meet a strange problem when doing MMC emulation. The x-loader code is downloaded from http://beagleboard.googlecode.com/files/x-load_beagle_revb.tar.gz.

In function mmc_send_cmd(cpu/omap3/mmc.c)

145         OMAP_HSMMC_BLK = BLEN_512BYTESLEN | NBLK_STPCNT;
146         OMAP_HSMMC_STAT = 0xFFFFFFFF;
147         OMAP_HSMMC_ARG = arg;
148         OMAP_HSMMC_CMD = cmd | CMD_TYPE_NORMAL | CICE_NOCHECK |
149             CCCE_NOCHECK | MSBS_SGLEBLK | ACEN_DISABLE | BCE_DISABLE |
150             DE_DISABLE;
That means cpu write to OMAP3 MMC register in the sequence of BLK->STAT->ARG->CMD. But the compiler reorder the register write order.
40201d7c:    e5821108     str    r1, [r2, #264]       <- ARG          40201d80:    e5823104     str    r3, [r2, #260]       <-BLK
40201d84:    e582010c     str    r0, [r2, #268]        <-CMD
40201d88:    e3e03000     mvn    r3, #0    ; 0x0
40201d8c:    e5823130     str    r3, [r2, #304]         <-STAT

The register access order becomes ARG->BLK->CMD->STAT. It will confuse MMC emulation. According to the datasheet of omap3 mmc, write to stat register 0xffffffff will clear the stat register. But x-loader will check the stat register untile it is not 0.

153                 do {
154                         mmc_stat = OMAP_HSMMC_STAT;
155                 } while (mmc_stat == 0);

I post a message on the beagle board group. That's because when the compiler believes that the semantics are the same since the memory operations are being done to different 
locations, it will reorder code for the sake of performance. If you do not want the compiler to do so, tell him using the 'volatile' keyword.

Change the macro from

#define OMAP_HSMMC_STAT            (*(unsigned int *) 0x4809C130)

to

#define OMAP_HSMMC_STAT            (*(volatile unsigned int *) 0x4809C130)

The compiler do not reorder the memory operation order if it is volatile.

Another stupid way to solve the problem is turn off the optimization option. Remove -Os from compiler flag of x-loader.

OPTFLAGS= #-Os #-fomit-frame-pointer

The compiler will generate stupid but right order register operation asm code.

40202b44:    e59f20f4     ldr    r2, [pc, #244]    ; 40202c40 <mmc_send_cmd+0x134>
40202b48:    e3e03000     mvn    r3, #0    ; 0x0
40202b4c:    e5823000     str    r3, [r2]
40202b50:    e59f20ec     ldr    r2, [pc, #236]    ; 40202c44 <mmc_send_cmd+0x138>
40202b54:    e51b300c     ldr    r3, [fp, #-12]
40202b58:    e5823000     str    r3, [r2]
40202b5c:    e59f20e4     ldr    r2, [pc, #228]    ; 40202c48 <mmc_send_cmd+0x13c>
40202b60:    e51b3008     ldr    r3, [fp, #-8]
40202c38:    4809c124     .word    0x4809c124
40202c3c:    4809c104     .word    0x4809c104
40202c40:    4809c130     .word    0x4809c130
40202c44:    4809c108     .word    0x4809c108
40202c48:    4809c10c     .word    0x4809c10c
40202c4c:    4809c110     .word    0x4809c110
40202c50:    4809c114     .word    0x4809c114
40202c54:    4809c118     .word    0x4809c118
40202c58:    4809c11c     .word    0x4809c11c

You can refer the disscussion in beagle board group for more information.

[1]code reorder of x-loader using arm-none-linux-gnueabi-gcc

[2]OMAP3: X-Loader: Make MMC register macros volatile

[3]U-Boot v1: Clean up MMC code

I have issues when using qemu-omap3

Dec 19th, 2008 | Posted by yajin | Filed under emulation

If you have issues when using qemu-omap3, please post it on issues page of qemu-omap3 on googlecode. A google groups of qemu-omap3 is also available. Thanks.

Linux is running on qemu-omap3

Dec 15th, 2008 | Posted by yajin | Filed under OMAP, emulation

Hi everyone, a good news for you. Linux in running successfully on qemu-omap3. Following is the screenshot.

However, MMC/USB/audio/LCD display/keyboard emulation are not ok . I will work on it.

In the following I will give you some informations of how to run qemu-omap3.

1. checkout qemu-omap3 from svn. Tag v0.01 is working.

svn checkout http://qemu-omap3.googlecode.com/svn/tags/v0.01 qemu-omap3

Or you can download it from http://qemu-omap3.googlecode.com/files/qemu-omap3-v0.01.tar.bz2 .

2. make qemu-omap3

cd qemu-omap3
./configure --target-list=arm-softmmu
make

qemu-system-arm will be generated in directory qemu-omap3/arm-softmmu.

3. download the x-loader/u-boot/kernel image.

cd qemu-omap3/arm-softmmu
wget http://qemu-omap3.googlecode.com/files/image-v0.01.tar.bz2
tar jxvf image-v0.01.tar.bz2

4. download the rootfs from beagle board site.

wget http://beagleboard.googlecode.com/files/rd-ext2-8M.bin

5. make nand flash image

cd qemu-omap3/arm-softmmu
cp ../bb_nandflash.sh .
cp ../bb_nandflash_ecc .
./bb_nandflash.sh x-load.bin.ift beagle-nand.bin x-loader
./bb_nandflash.sh u-boot.bin beagle-nand.bin u-boot
./bb_nandflash.sh uImage beagle-nand.bin kernel
./bb_nandflash.sh rd-ext2-8M.bin  beagle-nand.bin  rootfs
./bb_nandflash_ecc beagle-nand.bin 0x0 0xe80000

6. run qemu-omap3

./qemu-system-arm -M beagle -mtdblock beagle-nand.bin

7. During the graphical emulation, you can use the following keys:
Ctrl-Alt-f
Toggle full screen
Ctrl-Alt-n
Switch to virtual console 'n'. Standard console mappings are:
1
Target system display
2
Monitor
3
Serial port
Ctrl-Alt
Toggle mouse and keyboard grab.

Using Ctrl-Alt-3 to switch to beagle board serial port. You can see x-loader and u-boot booting message. When u-boot command line appears, type the following commands.

OMAP3 beagleboard.org # nand read 0x80000000 0x280000 0x400000
NAND read: device 0 offset 0x280000, size 0x400000
4194304 bytes read: OK
OMAP3 beagleboard.org # nand read 0x81600000 0x680000 0x800000
NAND read: device 0 offset 0x680000, size 0x800000
8388608 bytes read: OK
OMAP3 beagleboard.org # setenv bootargs 'console=ttyS2,115200n8 ramdisk_size=8192 root=/dev/ram0 rw rootfstype=ext2 initrd=0x81600000,8M nohz=0ff'
OMAP3 beagleboard.org # bootm 0x80000000

Linux will boot with some debug information of qemu-omap3. Enjoy it.

Update: 2010-02-20

I am too busy to do omap3 emulation these days. The guy at maemo has made great improvement in qemu omap3 emulation. Go to this page for more information. I do not know whether the steps in this artilcle can be used in the new version of qemu-omap3.

a misunderstanding of git-checkout

Dec 12th, 2008 | Posted by yajin | Filed under Git

I work in branch master and there are some changes uncommited. Now I have some ideas and want to try it *without* effecting the branch master. I first create a branch test and then checkout to branch test.

kill-bill:/home/root/sdc/qemu/qemu-omap/svn# git branch test
kill-bill:/home/root/sdc/qemu/qemu-omap/svn# git checkout test
Switched to branch "test"
kill-bill:/home/root/sdc/qemu/qemu-omap/svn# git branch
 master
*test

And then I work in branch test and make some changes to source file a.c b.c and etc. At last, I want to return to branch master and abandon the changes in branch test. But the result is not same as what I thought. The files changed in branch test are also changed in branch master!!

Git-checkout DOES NOT save your context and uncommitted changes to somewhere and restore them when you return. If you want git to do so, please use git-switch-branch instead.

low level debug of linux omap

Dec 12th, 2008 | Posted by yajin | Filed under OMAP, emulation, kernel

Working on qmeu-omap3. A starange problem. If I use the kernel image downloaded from http://beagleboard.googlecode.com/files/uImage_OTG, some kernel boot informations can be displayed in uart3. But when I use the kernel source from linux omap git and build it by myself, there are NO linux kernel boot informations at all.

Linux kernel uses printk to output informations to console and the console struct is initialized in function console_init(). So why the linux can be displayed before function console_init()?

The answer is that there is another way to output informations to console. That is low level debug. It uses printascii to print informations. The following is the code in vprintk.

556 #ifdef  CONFIG_DEBUG_LL
557         printascii(printk_buf);
558 #endif

So if we want to output debug information as early as possible, define CONFIG_DEBUG_LL first.

The default configuration of beagle board in http://www.beagleboard.org/uploads/2.6_kernel_revb-v2.tar.gz defines this macro while the source code from  linux omap git does not define this macro.

Function printascii is defined in include/asm-arm/arch-omap/debug-macro.S.

add ecc value to nand flash image

Dec 6th, 2008 | Posted by yajin | Filed under OMAP, emulation

I use qemu-omap3 to boot linux kernel from nand. The linux image is downloaded from http://beagleboard.googlecode.com/files/uImage_OTG.

OMAP3 beagleboard.org #
OMAP3 beagleboard.org # nand read 0x80000000 0x280000 0x400000
NAND read: device 0 offset 0x280000, size 0x400000
 4194304 bytes read: ERROR
OMAP3 beagleboard.org # bootm 0x80000000
## Booting kernel from Legacy Image at 80000000 ...
   Image Name:   Linux-2.6.22.18-omap3
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    1856616 Bytes =  1.8 MB
   Load Address: 80008000
   Entry Point:  80008000
   Verifying Checksum ... Bad Data CRC
ERROR: can't get kernel image!
OMAP3 beagleboard.org #

It means crc error in linux image. I use qemu console command 'memsave' to dump the data from address 0x80000000 to a file and compare it to uImage_OTG. The result is that linux image in ram(from 0x80000000) is different from uImage_OTG. In every block(256 bytes), there is one bit different from uImage_OTG. The linux image is changed when using 'nand read' command to read it from nand flash image to sram.

What has happened when reading linux image from nand flash image into sram??

After debuging about half a day, I find that the data are changed by the correct_data function. I *DID NOT* save ecc value in nand flash image so u-boot thinks the ecc value in oob is wrong and correct it. Ecc can only correct one bit in an block, that is why a bit has been changed in 256 bytes.

ecc_status = this->correct_data(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]);

I write a file(bb_nandflash_ecc.c) to generate ecc value for nand flash image. Now I can boot linux image using u-boot command.

OMAP3 beagleboard.org # nand read 0x80000000 0x280000 0x400000
NAND read: device 0 offset 0x280000, size 0x400000
 4194304 bytes read: OK
OMAP3 beagleboard.org # bootm 0x80000000
## Booting kernel from Legacy Image at 80000000 ...
   Image Name:   Linux-2.6.22.18-omap3
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    1856616 Bytes =  1.8 MB
   Load Address: 80008000
   Entry Point:  80008000
   Verifying Checksum ... OK
   Loading Kernel Image ... OK
OK
Starting kernel ...
smc 80e80414  insn 1600070
Uncompressing Linux.......................................................................................................................... done, booting the kernel.
<5>Linux version 2.6.22.18-omap3 (root@fedoraserver) (gcc version 4.2.1 (CodeSourcery Sourcery G++ Lite 2007q3-51)) #1 Thu Jul 24 15:29:36 IST 2008
CPU: ARMv7 Processor [411fc082] revision 2 (ARMv7), cr=00003837
Machine: OMAP3 Beagle board
Memory policy: ECC disabled, Data cache writeback
<7>On node 0 totalpages: 32768
<7>  DMA zone: 256 pages used for memmap
<7>  DMA zone: 0 pages reserved
<7>  DMA zone: 32512 pages, LIFO batch:7
<7>  Normal zone: 0 pages used for memmap
Unassigned mem readl 4830a204

Because of omap3 emulation is not complete, linux kernel will stop after linux kernel booting. I will work on it.

LCD is working in qemu-omap3

Dec 4th, 2008 | Posted by yajin | Filed under OMAP, emulation

Good news. LCD is working in qemu-omap3

Beagle board has an DVI transmitter TFP 410 and it outputs ditigal signal to LCD panel which has DVI connector. However, we do not care TFP 410 because it is just a pipe for LCD output data. What we care about is the LCD output data itself.

According to the datasheet of OMAP3530, it has three interfaces for LCD output:Parellel Interface, SDI interface and DSI interface. In the case of parellel interface, it can work in two modes: RFBI mode and RFBI bypass mode.

In RFBI mode, the datapath for LCD output data is display controller and RFBI chip. In RFBI bypass mode, the data is output to LCD panel or other interfaces directly. Beagle board uses TFP 410 to receive 24 bit LCD data and then transmits the data to LCD through DVI interface.

Qemu already has omap dss emulation. But it is not complete and only for RFBI mode(Nokia N800 uses RFBI). I just follow the Blizzard template and write my own omap3_lcd_panel_template. And then add the sdl update function omap3_lcd_panel_update_display to omap_dss.c. Also some other utility functions are needed. It works now, the beagle and penguin are displayed in my LCD panel. The following is the screenshot.

I have tested the LCD emulation speed and the result is not bad. It can reach about 20-30 frames per second. I think it is good enough for an emulator.

The next steps for qemu-omaps are: running linux kernel and distribution(Ångström for example). However the most exciting part is the 3D virtualization for OMAP3. That is you can run 3D application in qemu by using the host 3D accelerator hardware.

Please be patient. I am working on it.

Qemu omap gp-timer bug

Nov 28th, 2008 | Posted by yajin | Filed under OMAP, emulation

在u-boot中,采用函数udelay来进行延时。这是一个单纯等待的算法。在beagle board的u-boot中,udelay会不断去读OMAP general purpose timer的count值,然后根据general purpose timer的输入时钟来得到已经经过的时间。

在u-boot中,gp timer2的输入时钟为系统时钟,beagle board中为13MHZ。并且时钟经过了256分频。因此,每一秒钟的时间,gp timer2的count的值会增加1*(13MHZ/256)。

对于qemu来说,必须要保证当u-boot去读gptimer寄存器值的时候,返回的count值是正确的。也就是说,必须是实际经过的时间*13MHZ/256。
在qemu中,ticks_per_sec的值为1000000000。函数qemu_get_clock可以得到当前时间的ticks。因此,当u-boot来读gptimer寄存器值的时候,返回的count值应该为:

(qemu_get_clock/ticks_per_sec)*(13MHZ/256)

也就是

(qemu_get_clock*13MHZ)/(ticks_per_sec*256)

见函数omap_gp_timer_read

distance = muldiv64(distance, timer->rate, timer->ticks_per_sec);

这里,timer->ticks_per_sec= ticks_per_sec*256。

可是问题的关键在于,函数muldiv64的原型为

/* compute with 96 bit intermediate result: (a*b)/c */
uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)

也就是说,参数b和c都是32bit的。而timer->ticks_per_sec已经超过了32bit。导致distance的计算出错,后果是u-boot中的延时函数是不准的。

解决方法:

首先判断一下ticks_per_secis有没有超过32bit,然后根据情况分别计算。

/*if ticks_per_secis bigger than 32bit, we can not use muldiv64 anymore!*/
if (timer->ticks_per_sec>0xffffffff){
  distance = distance/(ticks_per_sec/1000);  /*distance ms*/
  rate = timer->rate >> (timer->pre ? timer->ptv + 1 : 0);
  distance = muldiv64(distance, rate, 1000);
 }
else
  distance = muldiv64(distance, timer->rate, timer->ticks_per_sec);

现在U-boot中的时间是准确的了。

Tags: