Tuesday, February 24, 2009

Beagle board

A week or so ago, I got a Beagle board. So far, I've proved that it is unbrickable (by corrupting the NAND ROM and practically bricking it, then spending a couple of days and using a wide selection of computers and software to nurse it back to health).

Today I just got a self-built linux kernel to boot on it (not doing anything useful yet, though).

Once I'd got a set of working binutils and gcc (built for the arm-elf target), I got a long way, until the kernel was generating the uImage file. There were two problems.

The second, mkimage not found, was simple to fix - it comes with the u-boot code, also available here:

The first was heralded by the following error message:

"arm-elf-ld: ERROR: arch/arm/boot/compressed/misc.o uses VFP instructions, whereas arch/arm/boot/compressed/vmlinux does not"

It turned out the problem wasn't with arch/arm/boot/compressed/vmlinux at all (which is not surprising, since it's actually the output file), but with the head.o and piggy.o in the same directory.

The output of this command:

readelf -a arch/arm/boot/compressed/*.o | grep Flags:

included the lines:
Flags: 0x200, GNU EABI, software FP
Flags: 0x600, GNU EABI, software FP, VFP
Flags: 0x200, GNU EABI, software FP

What was needed was to re-assemble the head.S and piggy.S files with the -mfpu=vfp flag. Now, I doubt I've run any floating point code in the kernel since it's only booted up and hasn't really done anything, so it could be that I've compiled everything else wrong and it shouldn't use VFP, but that can wait for now.

Oh, I also edited drivers/video/omap/Makefile, to add the following line:

objs-y$(CONFIG_ARCH_OMAP3) += dispc.o

(I won't be able to work on anything for the next week and a half, but I'm looking forward to getting ROLF working on my TV, it's already worked with OMAP on the Nokia N800, and the VNC code points to a better solution.)

Friday, February 06, 2009

ARM emulation

Yesterday, I decided to implement my own ARM code emulator.

I think my problems with getting AWRender to work have been to do with self modifying ARM code in the AWRender module. I had a half-hearted go at finding a way to implement OS_SynchroniseCodeAreas with QEMU, then I decided to just implement my own.

The interface is very simple: global storage for the registers, and a routine that returns a pointer to some x86 code that implements whatever ARM code is pointed to by r15 on entry. The x86 code will return when it comes to an instruction it can't deal with by itself, such as a SWI or a floating point operation.

The idea is to keep the emulator as the core of an ARM system, and anything else that needs emulating (like an Operating System, or a co-processor) will be taken care of outside the core. That way, I think, I can create something that can be finished!

I'm moving away from QEMU for a couple of reasons. Firstly, because it does much more than I need and it's heading off in a direction of increased complexity. For example, when I found a bug in the (latest release) version I was using, I discovered that later versions (with that bug long since fixed) don't work the same way as the one I had been working with, and I was told that, surprisingly, I didn't really want to use it that way!

Another reason is that a stripped version of the QEMU library is a little under half a megabyte in size (478568 bytes, to be specific), whereas my replacement is about 8k, at the moment, with maybe half the instruction set dealt with (bearing in mind that floating point is a co-processor feature). Perhaps I could strip QEMU down, but not that far, and not that quickly.

QEMU has given me some good ideas about how to approach the problem, but it's too bloated for my liking, now.

Update: It's going quite well.

It took me a while to work out that the x86 uses the carry flag in the opposite way to the ARM when subtracting, that jb isn't quite the same as BHI, and a day and a half to realise that I'd implemented BIC as AND instead of AND NOT.

Anyway, I'm now at the point where I have to start looking at which SWIs to emulate in order to get AWRender to, well, render something. I've chosen to attempt to get the freely available ArtWorks renderer working as a proof of concept for the compatibility layer (the whole thing isn't free, but apparently very good). Unfortunately, the application doesn't work out of the box, because the BASIC uses inline assembler and Brandy (http://sourceforge.net/projects/brandy) doesn't include that. I'll ask on comp.sys.acorn.programmer if there's an alternative that does.