From fadac1567aed13591a7ccf463b5887b083d2299f Mon Sep 17 00:00:00 2001 From: Arturs Artamonovs Date: Thu, 19 Jun 2025 22:14:16 +0100 Subject: pre published notes on raspi5 baremetal debuging --- md/writeup/raspberry5_baremetal_helloworld.md | 229 ++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 md/writeup/raspberry5_baremetal_helloworld.md diff --git a/md/writeup/raspberry5_baremetal_helloworld.md b/md/writeup/raspberry5_baremetal_helloworld.md new file mode 100644 index 0000000..ba5a575 --- /dev/null +++ b/md/writeup/raspberry5_baremetal_helloworld.md @@ -0,0 +1,229 @@ +title: Raspberry 5 baremetal Hello World example +keywords:raspi5,asm,c,kernel,arm64 + +# Raspberry 5 baremetal Hello World example + +## Intro + +Here is base example that will allow to print out message to serial console, +and debug application. This example is picked up from variouse resources to +make easy start into baremetal programming for raspi5, similar route is for +all other models. All commands are tested from raspi4, adjust sources +for your system. + +## Source code + + +### boot.S + +``` +.section ".text.boot" + +.global _start + +_start: + // read cpu id, stop slave cores + mrs x1, mpidr_el1 + and x1, x1, #3 + cbz x1, 2f + // cpu id > 0, stop +1: wfe + b 1b +2: // cpu id == 0 + + // set top of stack just before our code (stack grows to a lower address per AAPCS64) + ldr x1, =_start + mov sp, x1 + + // clear bss + ldr x1, =__bss_start + ldr w2, =__bss_size +3: cbz w2, 4f + str xzr, [x1], #8 + sub w2, w2, #1 + cbnz w2, 3b + + // jump to C code, should not return +4: bl main + // for failsafe, halt this core too + b 1b + +``` + +### kernel.c + +```c +void main() +{ + while (1) { + + } +} +``` + +### Makefile +```Makefile +TOOLCHAIN=aarch64-linux-gnu- +AS = ${TOOLCHAIN}as +LD = ${TOOLCHAIN}ld +SRCS = $(wildcard *.c) +OBJS = $(SRCS:.c=.o) +CFLAGS = -Wall -O2 -ffreestanding +CC=$(TOOLCHAIN)gcc + +all: clean kernel8.img + +boot.o: boot.S + ${CC} ${CFLAGS} -c boot.S -o boot.o + +%.o: %.c + ${CC} ${CFLAGS} -c $< -o $@ + +kernel8.img: boot.o ${OBJS} + ${LD} boot.o ${OBJS} -T linker.ld -o kernel8.elf + ${TOOLCHAIN}objcopy -O binary kernel8.elf kernel8.img + +clean: + rm -rf *.o *.img *.elf +``` + +### config.txt +``` +enable_jtag_gpio=1 +``` + +### Compile source code +```sh +make +``` + +### Prepare for a boot + + + +```sh +cp +``` + + + +## Debugging with OpenOCD+GDB + +The default openocd doesn't configration for raspi5. + +### OpenOCD config for bcm2712.cfg + +If OpenOCD doesn't have the raspi5 config by default here is one +that suppose to work. Copy it for example in default openocd script location in: + +``` +/usr/share/openocd/scripts/target/ +``` + + +```tcl +# bcm2712.cfg +# SPDX-License-Identifier: GPL-2.0-or-later +# OpenOCD target config file +# This file is based on target/bcm2711.cfg +# I have checked that it works with Open On-Chip Debugger 0.12.0 +# using the Raspberry Pi Debug-Probe interface + +transport select swd +adapter speed 1000 + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME bcm2712 +} + +if { [info exists CHIPCORES] } { + set _cores $CHIPCORES +} else { + set _cores 4 +} + +if { [info exists USE_SMP] } { + set _USE_SMP $USE_SMP +} else { + set _USE_SMP 0 +} + +if { [info exists DAP_TAPID] } { + set _DAP_TAPID $DAP_TAPID +} else { + set _DAP_TAPID 0x2ba00477 +} + +# swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID +swd newdap $_CHIPNAME cpu -expected-id $_DAP_TAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +# MEM-AP for direct access +target create $_CHIPNAME.ap mem_ap -dap $_CHIPNAME.dap -ap-num 0 + +# these addresses are obtained from the ROM table via 'dap info 0' command +set _DBGBASE {0x80010000 0x80110000 0x80210000 0x80310000} +set _CTIBASE {0x80020000 0x80120000 0x80220000 0x80320000} + +set _smp_command "target smp" + +for { set _core 0 } { $_core < $_cores } { incr _core } { + set _CTINAME $_CHIPNAME.cti$_core + set _TARGETNAME $_CHIPNAME.cpu$_core + + cti create $_CTINAME -dap $_CHIPNAME.dap -ap-num 0 -baseaddr [lindex $_CTIBASE $_core] + target create $_TARGETNAME aarch64 -dap $_CHIPNAME.dap -ap-num 0 -dbgbase [lindex $_DBGBASE $_core] -cti $_CTINAME + + set _smp_command "$_smp_command $_TARGETNAME" +} + +if {$_USE_SMP} { + eval $_smp_command +} + +# default target is cpu0 +targets $_CHIPNAME.cpu0 +``` + +Connecting pico probe and doint step by step analysis of basic loop + +### Running OpenOCD + +Start openocd server + +``` +openocd -f interface/cmsis-dap.cfg -f target/bcm2712.cfg +``` + +Connect with gdb + +``` +gdb +``` + +and run inside gdb shell + +``` +tar ext :3333 +``` + + +## Links + + +https://www.raspberrypi.com/documentation/computers/config_txt.html +https://wiki.osdev.org/Raspberry_Pi_Bare_Bones + +https://www.rpi4os.com/part1-bootstrapping/ + +https://www.valvers.com/open-software/raspberry-pi/bare-metal-programming-in-c-part-1/ + +https://www.raspberrypi.com/documentation/microcontrollers/debug-probe.html + +https://macoy.me/blog/programming/RaspberryPi5Debugging +https://gist.github.com/tnishinaga/219122a5f1e3973668ee78c0fb1c7bf9 +https://forums.raspberrypi.com/viewtopic.php?p=2172522#p2172522 + +https://github.com/DSERIOUSGUY/HobOS -- cgit v1.2.3