This is my attempt to do baremetal programming on cortex-a9 using qemu and vexpress-a9 board.
- Keyboard using ARM (PL050)
- Display using ARM (PL111)
- Timer usin ARM (SP804)
- UART using ARM (PL011)
- SD card using ARM (PL181)
- Real Time Clock (RTC) using ARM (PL031)
- Interrrupts using ARM (GIC) and IRQ code stub
- µGUI - free and open source graphic library for embedded systems Port
- FatFs - Generic FAT Filesystem Module Port
- uClibc - C library for developing embedded Linux systems syscall Port
- Code Cleanup & Refactoring
- Better Build Script and IDE Support (Debugging, Building, and Running)
- Audio Support using ARM Advance Audio Codec Interface (PL041)
- Network Support using LAN9118 ethernet
- Porting Network Stack using lwIP
- MultiCore Support
- Better Driver Support and Imporovements
- Code Documentation and overall Walkthrough
- Detailed Walkthrough of My BareMetal Adventure
- arm-none-eabi
- qemu-system-arm
- gdb-multiarch (only if you need to debug)
I've tested this on Linux platform only, the Makefile
is hopefully easy to read, you can change flags there
make
will build the projectmake qemu
will run elf kernel in qemumake dqemu
will instruct qemu to pause execution and listen for gdb remote connection on port1234
make gdb
will run the gdb-multiarch [do this in seperate terminal and after runninmake dqemu
]- note you need to execute
target remote :1234
to connect to qemu debug port
- note you need to execute
In this section I'll briefly highlight main point of important file. This will help explain the big picture. Hopefully, I'll write detailed guide in future.
Linker Script linker.ld
:
- ensures Interrupt vector is at the start of the kernel binary
- contains necessary symbols for stack, heap, ulibc, ...etc to work (refrenced by
startup.S
) and_sbrk()
formalloc()
- describe how the final layout of the binary
Code entry point is the statup.S
which will do the following:
- Initialize the interrupt vectors
- Initialize the stack and ARM code
- jump to C code
ulibC and syscall.c
:
- contains implemenation of needed stubs for standard C library to work properly
_write
has been implemented to print to uart. This will allow printf to work_sbrk
has been implemented utilizing symbols inlinker.ld
. This will allowmalloc
to work- before jumping to main standard C will initialize the
.bss
section to zero (C runtime)
interrupt.c
and gic.c
:
- here we Initialize the ARM
GIC
(Generic Interrupt Controller) c_irq
is the function that will handle irq. The function works by getting the IRQ# (who triggered the interrupt) and then use this number to check in a function pointer array (is there a handler for this irq?). if yes then call that handler, else print no handler foundinstall_isr
function will allow device driver code to hook intterupt handler for specific IRQ# [c_irq
will call this hook]enable_irq
will enable specified IRQ# inGIC
[[To be Continued..]]