Metal ARM x00 - Setup and Hello World (Lab Notes)
The purpose of Project 0 is to get my own, handwritten machine code running on my practically unused EK-TM4C123GXL board.
Goals
- Flash a minimal, handcrafted, working binary to the board
- No HALs or external software will run on the board apart from what I write
- I get to use GDB for debugging
- I get to use external software for flashing and whatever else is needed to get stuff onto the board
- Maximize learning
Work Completed
- Added hx utility for converting
hex text -> binary files, and vice versa
- xxd doesn't support comments, but I wanted to annotate whatever machine code I needed to write and didn't bother looking further
- Created minimal vector table and reset handler
- Initialized stack pointer
- Loop and increment a register forever
- Flashed with openocd and telnet (I think this could have just used openocd)
- Single stepped and verified with gdb
The final program is:
; Vector table should be at 0x0 on reset/power on
; vector table ------------------------------------------
; 0x00 - contains address of initial stack pointer: 0x2000.8000
00 80 00 20
; 0x04 - contains address of reset handler: 0x0000.0008 | 1 (thumb mode set)
09 00 00 00
; -------------------------------------------------------
; Reset handler - Continuously increments R0 ------------------------------------------
; 0x08 - MOV R0 0x01: 0b00100000.00000001 -> 0x2001
01 20
; loop while incrementing R0
; 0x0A - ADD R0 0x01: 0b00110000.00000001 -> 0x3001
01 30
; branch back to the add
; 0x0C - B to 0x0A (-6 offset in bytes, -3 in halfwords): 0b11100111.11111101 -> 0xE7FD
FD E7
; -------------------------------------------------------------------------------------
Commands Used
- Compile hx to binary:
hx program.hxs > program.bin - Start openocd:
openocd -f board/ti_ek-tm4c123gxl.cfg - Flash binary:
> telnet localhost 4444
> flash write_image erase ./program.bin 0x00000000 bin
- Step and inspect with gdb:
> arm-none-eabi-gdb
(gdb) target extended-remote :3333
Remote debugging using :3333
# ...
(gdb) monitor reset halt
[tm4c123gh6pm.cpu] halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x00000008 msp: 0x20008000
(gdb) stepi
halted: PC: 0x0000000a
(gdb) info registers
r0 0x1 1
r1 0x0 0
# ...
pc 0xa 0xa
# ...
(gdb) stepi
halted: PC: 0x0000000c
(gdb) info registers
r0 0x2 2
r1 0x0 0
# ...
pc 0xc 0xc
# ...
- We can see the register increment forever!
Next steps
- Writing raw machine code is a fun exercise once...time for an assembler