echoplayer: implement boot from debugger

rockbox-gerrit-noreply--- via rockbox-cvs <[email protected]>
Newsgroups gmane.comp.systems.archos.rockbox.cvs
Message-ID <[email protected]>
commit d5506dfa2258c644a0863a14c8fd51165ffa7f54
Author: Aidan MacDonald <[email protected]>
Date:   Thu Jan 22 15:06:38 2026 +0000

    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

diff --git a/bootloader/echoplayer.c b/bootloader/echoplayer.c
index 15e4d743b4..113c457f5f 100644
--- a/bootloader/echoplayer.c
+++ b/bootloader/echoplayer.c
@@ -41,6 +41,20 @@
 #define LOAD_SIZE           (2 * 1024 * 1024)
 #define LOAD_BUFFER_ADDR    (STM32_SDRAM1_BASE + SDRAM_SIZE - LOAD_SIZE)
 
+/* Values at GDB_MAGICx */
+#define GDB_MAGICVAL1   0x726f636b
+#define GDB_MAGICVAL2   0x424f4f54
+#define GDB_MAGICVAL3   0x6764626c
+#define GDB_MAGICVAL4   0x6f616455
+
+/* Addresses used by GDB boot protocol */
+#define GDB_MAGIC1      (*(volatile uint32_t*)(STM32_SRAM4_BASE + 0x00))
+#define GDB_MAGIC2      (*(volatile uint32_t*)(STM32_SRAM4_BASE + 0x04))
+#define GDB_MAGIC3      (*(volatile uint32_t*)(STM32_SRAM4_BASE + 0x08))
+#define GDB_MAGIC4      (*(volatile uint32_t*)(STM32_SRAM4_BASE + 0x0c))
+#define GDB_ELFADDR     (*(volatile uint32_t*)(STM32_SRAM4_BASE + 0x10))
+#define GDB_ELFSIZE     (*(volatile uint32_t*)(STM32_SRAM4_BASE + 0x14))
+
 /* Events for the monitor callback to signal the main thread */
 #define EV_POWER_PRESSED    MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 0)
 #define EV_POWER_RELEASED   MAKE_SYS_EVENT(SYS_EVENT_CLS_PRIVATE, 1)
@@ -320,6 +334,35 @@ static void launch(void)
     launch_elf();
 }
 
+static bool handle_gdb_boot(void)
+{
+    /* Look for magic values that signal the GDB boot protocol */
+    bool gdb_boot = (GDB_MAGIC1 == GDB_MAGICVAL1 &&
+                     GDB_MAGIC2 == GDB_MAGICVAL2 &&
+                     GDB_MAGIC3 == GDB_MAGICVAL3 &&
+                     GDB_MAGIC4 == GDB_MAGICVAL4);
+
+    /* Clear them so they won't hang around on a system reset */
+    GDB_MAGIC1 = 0;
+    GDB_MAGIC2 = 0;
+    GDB_MAGIC3 = 0;
+    GDB_MAGIC4 = 0;
+
+    if (!gdb_boot)
+        return false;
+
+    /* "Call" GDB by entering breakpoint */
+    GDB_ELFADDR = 0;
+    GDB_ELFSIZE = 0;
+    asm volatile("bkpt");
+
+    /* Read location of the loaded binary */
+    elf_load_addr = (void *)GDB_ELFADDR;
+    elf_load_size = (size_t)GDB_ELFSIZE;
+
+    return true;
+}
+
 void main(void)
 {
     system_init();
@@ -349,6 +392,10 @@ void main(void)
     filesystem_init();
     disk_mount_all();
 
+    /* GDB assisted boot takes precedence */
+    if (handle_gdb_boot())
+        launch_elf();
+
     if (echoplayer_boot_reason == ECHOPLAYER_BOOT_REASON_SW_REBOOT ||
         usb_detect() == USB_INSERTED)
     {
diff --git a/tools/echoplayer/openocd.make b/tools/echoplayer/openocd.make
index f7664d128e..de9d557314 100644
--- a/tools/echoplayer/openocd.make
+++ b/tools/echoplayer/openocd.make
@@ -2,16 +2,56 @@ GDB         := gdb
 OPENOCD     := openocd
 OPENOCD_CFG := $(ROOTDIR)/tools/echoplayer/openocd.cfg
 
+# GDB boot protocol 'registers' used for communicating with the bootloader
+GDBBOOT_REG_BASE    := 0x38000000
+GDBBOOT_REG_MAGIC1  := ($(GDBBOOT_REG_BASE) + 0x00)
+GDBBOOT_REG_MAGIC2  := ($(GDBBOOT_REG_BASE) + 0x04)
+GDBBOOT_REG_MAGIC3  := ($(GDBBOOT_REG_BASE) + 0x08)
+GDBBOOT_REG_MAGIC4  := ($(GDBBOOT_REG_BASE) + 0x0c)
+GDBBOOT_REG_ELFADDR := ($(GDBBOOT_REG_BASE) + 0x10)
+GDBBOOT_REG_ELFSIZE := ($(GDBBOOT_REG_BASE) + 0x14)
+
+# Address where the RB binary will be loaded
+GDBBOOT_LOAD_ADDR := 0x71e00000
+GDBBOOT_LOAD_SIZE := 0x200000
+
 ifneq (,$(findstring bootloader,$(APPSDIR)))
   TARGET_ELF := $(BUILDDIR)/bootloader.elf
 else
   TARGET_ELF := $(BUILDDIR)/rockbox.elf
+  TARGET_BIN := $(BUILDDIR)/rockbox.echo
 endif
 
+# Attach to running process
 debug:
-	$(GDB) $(TARGET_ELF) -ex "target extended-remote | openocd -c \"gdb_port pipe\" -f $(OPENOCD_CFG)"
+	$(GDB) $(TARGET_ELF) \
+		-ex "target extended-remote | openocd -c \"gdb_port pipe\" -f $(OPENOCD_CFG)"
+.PHONY: debug
 
+ifneq (,$(findstring bootloader,$(APPSDIR)))
+
+# Flash bootloader
 flash: $(TARGET_ELF)
-	$(OPENOCD) -f $(OPENOCD_CFG) -c "program $(TARGET_ELF) verify reset exit"
+	$(OPENOCD) -f $(OPENOCD_CFG) -c "program $< verify reset exit"
+.PHONY: flash
+
+else
+
+# Start Rockbox via debugger
+start: $(TARGET_BIN)
+	$(GDB) $(TARGET_ELF) \
+		-ex "target extended-remote | openocd -c \"gdb_port pipe\" -f $(OPENOCD_CFG)" \
+		-ex "monitor reset halt" \
+		-ex "set *$(GDBBOOT_REG_MAGIC1) = 0x726f636b" \
+		-ex "set *$(GDBBOOT_REG_MAGIC2) = 0x424f4f54" \
+		-ex "set *$(GDBBOOT_REG_MAGIC3) = 0x6764626c" \
+		-ex "set *$(GDBBOOT_REG_MAGIC4) = 0x6f616455" \
+		-ex "continue" \
+		-ex "restore $(TARGET_BIN) binary $(GDBBOOT_LOAD_ADDR)" \
+		-ex "set *$(GDBBOOT_REG_ELFADDR) = $(GDBBOOT_LOAD_ADDR)" \
+		-ex "set *$(GDBBOOT_REG_ELFSIZE) = $(GDBBOOT_LOAD_SIZE)" \
+		-ex "continue"
+.PHONY: start
+
+endif
 
-.PHONY: debug flash
-- 
rockbox-cvs mailing list
[email protected]
https://lists.haxx.se/mailman/listinfo/rockbox-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.