ARM Integrator-CP Bare Bones
Jump to navigation
Jump to search
WAIT! Have you read Getting Started, Beginner Mistakes, and some of the related OS theory? |
Difficulty level |
---|
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