Change the CROSS variable to point at the location of your cross-compiler. The example assumes a build environment was setup with the [[MokoMakefile]] in <tt>/mnt/oe/openmoko</tt>. We first compile, asssemble and link our code into an ELF binary. It seems like u-boot has some support for using ELF files directly, but we'll instead extract the raw machine code from the ELF using objcopy and load it manually.

+

Change the CROSS variable to point at the location of your cross-compiler. The example assumes a build environment was setup with the [[MokoMakefile]] in <tt>/mnt/oe/openmoko</tt>. We first compile, assemble and link our code into an ELF binary. It seems like u-boot has some support for using ELF files directly, but we'll instead extract the raw machine code from the ELF using objcopy and load it manually.

<pre>

<pre>

Revision as of 09:52, 23 August 2008

Here is an example of how to run your own C code on the bare metal, without any operating system. Since I don't yet have a physical device, this has only been tested using Qemu.

Example program

C code (app.c)

The GPIO Port B data register (GPBDAT) of the S3C2410 is located at physical address 0x56000014. The LCD backlight is controlled by GPB0, so we enter an infinite loop toggling bit 0 of GPBDAT on and off. The for loop is to just sleep for a while so that it flashes on and off slow enough that a human can see it.

Note that without extra work you won't be able to use global variables or string constants. You might be able to fix this by experimenting with U-boot's ELF support and linker scripts. Of course you will also not be able to use any system calls or the C library as you are running without an OS.

Assembler head (app.S)

This is a tiny piece of ARM assembler that will be the first instructions in our program. The bootloader will execute this after loading our program into memory. We simply set the stack pointer register to somewhere in RAM and jump to our C code.

Linker script (app.lds)

You can setup specific instructions for the linker here to tell it how things should be layed out in memory. You might be able to get global variables working by fiddling with this, for example. For now we just say our program will be running at 0x35000000.

SECTIONS
{
. = 0x35000000;
}

Makefile

Change the CROSS variable to point at the location of your cross-compiler. The example assumes a build environment was setup with the MokoMakefile in /mnt/oe/openmoko. We first compile, assemble and link our code into an ELF binary. It seems like u-boot has some support for using ELF files directly, but we'll instead extract the raw machine code from the ELF using objcopy and load it manually.

Kermit script (download.kermit)

We use C-Kermit to download our binary code into the phone's memory. We do this by issuing loadb 0x350000000 to u-boot to tell it to receive a file into address 0x35000000. We then send the file using the kermit protocol. Finally we tell u-boot to jump to address 0x35000000 and start executing our program.

Example program

C code (app.c)

The GPIO Port B data register (GPBDAT) of the S3C2410 is located at physical address 0x56000014. The LCD backlight is controlled by GPB0, so we enter an infinite loop toggling bit 0 of GPBDAT on and off. The for loop is to just sleep for a while so that it flashes on and off slow enough that a human can see it.

Note that without extra work you won't be able to use global variables or string constants. You might be able to fix this by experimenting with U-boot's ELF support and linker scripts. Of course you will also not be able to use any system calls or the C library as you are running without an OS.

Assembler head (app.S)

This is a tiny piece of ARM assembler that will be the first instructions in our program. The bootloader will execute this after loading our program into memory. We simply set the stack pointer register to somewhere in RAM and jump to our C code.

Linker script (app.lds)

You can setup specific instructions for the linker here to tell it how things should be layed out in memory. You might be able to get global variables working by fiddling with this, for example. For now we just say our program will be running at 0x35000000.

SECTIONS
{
. = 0x35000000;
}

Makefile

Change the CROSS variable to point at the location of your cross-compiler. The example assumes a build environment was setup with the MokoMakefile in /mnt/oe/openmoko. We first compile, asssemble and link our code into an ELF binary. It seems like u-boot has some support for using ELF files directly, but we'll instead extract the raw machine code from the ELF using objcopy and load it manually.

Kermit script (download.kermit)

We use C-Kermit to download our binary code into the phone's memory. We do this by issuing loadb 0x350000000 to u-boot to tell it to receive a file into address 0x35000000. We then send the file using the kermit protocol. Finally we tell u-boot to jump to address 0x35000000 and start executing our program.