ARM Integrator-CP Bare Bones

From OSDev Wiki
Jump to navigation Jump to search

WAIT! Have you read Getting Started, Beginner Mistakes, and some of the related OS theory?

Difficulty level
Difficulty 1.png
Beginner
Kernel Designs
Models
Other Concepts

In this tutorial we are going to compile a simple kernel for the ARM Integrator-CP board and boot it.




Required Tools

For this tutorial you'll need:

  • A cross compiler environment for ARM, minimally arm-elf-as, arm-elf-gcc and arm-elf-ld
  • QEMU - to test the kernel (Unless of course you have a spare Integrator-CP board hanging around)

You should also have read Getting Started and Beginner Mistakes. You should also have a reasonable knowledge of ARM assembly by this point, though in this example there isn't much assembly to understand anyway.

start.s

This is the assembly file, most of it isn't that hard to understand.

interrupt_vector_table:
    b . @ Reset
    b . 
    b . @ SWI instruction
    b . 
    b .
    b .
    b .
    b .

.comm stack, 0x10000 @ Reserve 64k stack in the BSS
_start:
    .globl _start
    ldr sp, =stack+0x10000 @ Set up the stack
    bl main @ Jump to the main function
1: 
    b 1b @ Halt

Assemble with:

 arm-elf-as -o start.o start.s

main.c

Now we get to the interesting part. We're going to display some characters via the serial port, those characters being "hello, world!" of course.

#define SERIAL_BASE 0x16000000
#define SERIAL_FLAG_REGISTER 0x18
#define SERIAL_BUFFER_FULL (1 << 5)

void putc (char c)
{
    /* Wait until the serial buffer is empty */
    while (*(volatile unsigned long*)(SERIAL_BASE + SERIAL_FLAG_REGISTER) 
                                       & (SERIAL_BUFFER_FULL));
    /* Put our character, c, into the serial buffer */
    *(volatile unsigned long*)SERIAL_BASE = c;

    /* Print a carriage return if this is a newline, as the cursor's x position will not reset to 0*/
    if (c == '\n')
    {
        putc('\r');
    }
}

void puts (const char * str)
{
    while (*str) putc (*str++);
}

int main (void)
{
    puts ("hello, world!\n");
    return 0;
}

Compile this with:

arm-elf-gcc -Wall -Wextra -Werror -nostdlib -nostartfiles -ffreestanding -std=gnu99 -c main.c

link.ld

ENTRY (_start)

SECTIONS
{
    . = 0;
    .text : { *(.text*) *(.rodata*) }
    .data : { *(.data*) }
    .bss : { *(.bss*) *(COMMON*) }
}

Now we link everything using:

arm-elf-ld -T link.ld -o kernel start.o main.o

Booting

Boot everything using:

qemu-system-arm -m 128 -kernel kernel -serial stdio

Here is the output: Qemuarmhello.png

Links