Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

echoplayer: implement boot from debugger

Add a 'make start' target which starts Rockbox using a
debugger. This only works to load the main binary, but
makes it much faster to test changes that don't affect
plugins/codecs.

Because SDRAM isn't accessible at reset and the main
binary is usually too big to fit in SRAM, the bootloader
must be flashed first before Rockbox can be loaded in
this way.

The boot protocol involves GDB writing a check pattern
to SRAM while the CPU is held in reset. The bootloader
detects the pattern and takes a breakpoint, by which
time SDRAM is accessible; GDB can then upload a binary
ELF image (copied as a raw file, since the ELF will be
loaded using RB's ELF loader) and leave the breakpoint
to continue booting.

From there the bootloader can load the ELF binary from
memory, exactly like a normal SD card boot.

Change-Id: I4eb971b4162ea422e38660455cfa0958cefaa18d

+90 -3
+47
bootloader/echoplayer.c
··· 41 41 #define LOAD_SIZE (2 * 1024 * 1024) 42 42 #define LOAD_BUFFER_ADDR (STM32_SDRAM1_BASE + SDRAM_SIZE - LOAD_SIZE) 43 43 44 + /* Values at GDB_MAGICx */ 45 + #define GDB_MAGICVAL1 0x726f636b 46 + #define GDB_MAGICVAL2 0x424f4f54 47 + #define GDB_MAGICVAL3 0x6764626c 48 + #define GDB_MAGICVAL4 0x6f616455 49 + 50 + /* Addresses used by GDB boot protocol */ 51 + #define GDB_MAGIC1 (*(volatile uint32_t*)(STM32_SRAM4_BASE + 0x00)) 52 + #define GDB_MAGIC2 (*(volatile uint32_t*)(STM32_SRAM4_BASE + 0x04)) 53 + #define GDB_MAGIC3 (*(volatile uint32_t*)(STM32_SRAM4_BASE + 0x08)) 54 + #define GDB_MAGIC4 (*(volatile uint32_t*)(STM32_SRAM4_BASE + 0x0c)) 55 + #define GDB_ELFADDR (*(volatile uint32_t*)(STM32_SRAM4_BASE + 0x10)) 56 + #define GDB_ELFSIZE (*(volatile uint32_t*)(STM32_SRAM4_BASE + 0x14)) 57 + 44 58 /* Events for the monitor callback to signal the main thread */ 45 59 #define EV_POWER_PRESSED MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0) 46 60 #define EV_POWER_RELEASED MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 1) ··· 320 334 launch_elf(); 321 335 } 322 336 337 + static bool handle_gdb_boot(void) 338 + { 339 + /* Look for magic values that signal the GDB boot protocol */ 340 + bool gdb_boot = (GDB_MAGIC1 == GDB_MAGICVAL1 && 341 + GDB_MAGIC2 == GDB_MAGICVAL2 && 342 + GDB_MAGIC3 == GDB_MAGICVAL3 && 343 + GDB_MAGIC4 == GDB_MAGICVAL4); 344 + 345 + /* Clear them so they won't hang around on a system reset */ 346 + GDB_MAGIC1 = 0; 347 + GDB_MAGIC2 = 0; 348 + GDB_MAGIC3 = 0; 349 + GDB_MAGIC4 = 0; 350 + 351 + if (!gdb_boot) 352 + return false; 353 + 354 + /* "Call" GDB by entering breakpoint */ 355 + GDB_ELFADDR = 0; 356 + GDB_ELFSIZE = 0; 357 + asm volatile("bkpt"); 358 + 359 + /* Read location of the loaded binary */ 360 + elf_load_addr = (void *)GDB_ELFADDR; 361 + elf_load_size = (size_t)GDB_ELFSIZE; 362 + 363 + return true; 364 + } 365 + 323 366 void main(void) 324 367 { 325 368 system_init(); ··· 348 391 */ 349 392 filesystem_init(); 350 393 disk_mount_all(); 394 + 395 + /* GDB assisted boot takes precedence */ 396 + if (handle_gdb_boot()) 397 + launch_elf(); 351 398 352 399 if (echoplayer_boot_reason == ECHOPLAYER_BOOT_REASON_SW_REBOOT || 353 400 usb_detect() == USB_INSERTED)
+43 -3
tools/echoplayer/openocd.make
··· 2 2 OPENOCD := openocd 3 3 OPENOCD_CFG := $(ROOTDIR)/tools/echoplayer/openocd.cfg 4 4 5 + # GDB boot protocol 'registers' used for communicating with the bootloader 6 + GDBBOOT_REG_BASE := 0x38000000 7 + GDBBOOT_REG_MAGIC1 := ($(GDBBOOT_REG_BASE) + 0x00) 8 + GDBBOOT_REG_MAGIC2 := ($(GDBBOOT_REG_BASE) + 0x04) 9 + GDBBOOT_REG_MAGIC3 := ($(GDBBOOT_REG_BASE) + 0x08) 10 + GDBBOOT_REG_MAGIC4 := ($(GDBBOOT_REG_BASE) + 0x0c) 11 + GDBBOOT_REG_ELFADDR := ($(GDBBOOT_REG_BASE) + 0x10) 12 + GDBBOOT_REG_ELFSIZE := ($(GDBBOOT_REG_BASE) + 0x14) 13 + 14 + # Address where the RB binary will be loaded 15 + GDBBOOT_LOAD_ADDR := 0x71e00000 16 + GDBBOOT_LOAD_SIZE := 0x200000 17 + 5 18 ifneq (,$(findstring bootloader,$(APPSDIR))) 6 19 TARGET_ELF := $(BUILDDIR)/bootloader.elf 7 20 else 8 21 TARGET_ELF := $(BUILDDIR)/rockbox.elf 22 + TARGET_BIN := $(BUILDDIR)/rockbox.echo 9 23 endif 10 24 25 + # Attach to running process 11 26 debug: 12 - $(GDB) $(TARGET_ELF) -ex "target extended-remote | openocd -c \"gdb_port pipe\" -f $(OPENOCD_CFG)" 27 + $(GDB) $(TARGET_ELF) \ 28 + -ex "target extended-remote | openocd -c \"gdb_port pipe\" -f $(OPENOCD_CFG)" 29 + .PHONY: debug 30 + 31 + ifneq (,$(findstring bootloader,$(APPSDIR))) 13 32 33 + # Flash bootloader 14 34 flash: $(TARGET_ELF) 15 - $(OPENOCD) -f $(OPENOCD_CFG) -c "program $(TARGET_ELF) verify reset exit" 35 + $(OPENOCD) -f $(OPENOCD_CFG) -c "program $< verify reset exit" 36 + .PHONY: flash 16 37 17 - .PHONY: debug flash 38 + else 39 + 40 + # Start Rockbox via debugger 41 + start: $(TARGET_BIN) 42 + $(GDB) $(TARGET_ELF) \ 43 + -ex "target extended-remote | openocd -c \"gdb_port pipe\" -f $(OPENOCD_CFG)" \ 44 + -ex "monitor reset halt" \ 45 + -ex "set *$(GDBBOOT_REG_MAGIC1) = 0x726f636b" \ 46 + -ex "set *$(GDBBOOT_REG_MAGIC2) = 0x424f4f54" \ 47 + -ex "set *$(GDBBOOT_REG_MAGIC3) = 0x6764626c" \ 48 + -ex "set *$(GDBBOOT_REG_MAGIC4) = 0x6f616455" \ 49 + -ex "continue" \ 50 + -ex "restore $(TARGET_BIN) binary $(GDBBOOT_LOAD_ADDR)" \ 51 + -ex "set *$(GDBBOOT_REG_ELFADDR) = $(GDBBOOT_LOAD_ADDR)" \ 52 + -ex "set *$(GDBBOOT_REG_ELFSIZE) = $(GDBBOOT_LOAD_SIZE)" \ 53 + -ex "continue" 54 + .PHONY: start 55 + 56 + endif 57 +