Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 7503

General • Custom Bootloader Jump to Application Issues on RP2040 and RP2350

$
0
0
Hello everyone,

I'm currently developing a custom bootloader for the Raspberry Pi Pico (RP2040 and RP2350) and I'm encountering issues when jumping from the bootloader to the application. The intended flow is:

Pico Boot → Custom Bootloader → Application

Problem Description
The jump from the bootloader to the application does not work as expected. I have tried two different approaches:

Approach 1: Manual Jump Using Assembly
bootloader.cpp

Code:

int main(void){    stdio_init_all();    sleep_ms(100);    printf("Bootloader\\r\\n");    uint32_t APP_OFFSET = 0x20000;    save_and_disable_interrupts();    asm volatile (        "mov r0, %[start]\\n"        "ldr r1, =%[vtable]\\n"        "str r0, [r1]\\n"        "ldmia r0, {r0, r1}\\n"        "msr msp, r0\\n"        "bx r1\\n"        :        : [start] "r" (XIP_BASE + APP_OFFSET), [vtable] "X" (PPB_BASE + M33_VTOR_OFFSET)        :    );    while(1);}
application.cpp (linked at 0x20000)

Code:

int main(void){    gpio_init(34);    gpio_set_dir(34, true);    gpio_put(34, true);    sleep_ms(2000);    gpio_put(34, false);    sleep_ms(2000);    gpio_put(34, true);    sleep_ms(2000);    gpio_put(34, false);    stdio_init_all();    sleep_ms(100);    printf("Application");    ...}
Observations:

GPIO toggling works.
USB stdio does not work.
PIO works.
UART0 (which uses interrupts) does not work.
On the RP2040, this approach works if I use:

Code:

[start] "r" (APP_START + 0x100), [vtable] "X" (PPB_BASE + M0PLUS_VTOR_OFFSET)
In that case, USB stdio and UART0 (with interrupts) work fine in both bootloader and application.

Approach 2: Using watchdog_reboot
bootloader.cpp

Code:

int main(void){    stdio_init_all();    sleep_ms(100);    printf("Bootloader\\r\\n");    uint32_t APP_OFFSET = 0x20000;    uint32_t sp = *(uint32_t*) (XIP_BASE + APP_OFFSET);    uint32_t pc = *(uint32_t*) (XIP_BASE + APP_OFFSET + 4);    printf("rebooting %08x/%08x in 100ms...\\r\\n", pc, sp);    watchdog_enable(1000, 1);    watchdog_reboot(pc, sp, 1);    while(1);}
Output:
rebooting 1002015d/20082000 in 100ms...
The disassembly confirms that the addresses match the _reset_handler:
10020000 <__VECTOR_TABLE>:
10020000: 20082000
...
1002010c: 1002011d
...
1002015c <_reset_handler>:
1002015c: f04f 4050 mov.w r0, #0xd0000000
...
Result: This approach does not work at all.

Additional Observation
If I start the bootloader from itself (i.e., APP_OFFSET = 0), the USB output only works the first time. On subsequent runs, USB output fails, but GPIO toggling still works. The second approach still fails.

Question
What am I doing wrong?
Why does USB stdio and UART0 (with interrupts) fail in the application when started via the bootloader?
Is there a better or more reliable way to jump from a custom bootloader to an application on the RP2040/RP2350?

Any help or insights would be greatly appreciated!

Statistics: Posted by derGerd — Fri Jul 25, 2025 8:58 am — Replies 0 — Views 29



Viewing all articles
Browse latest Browse all 7503

Trending Articles