Skip to content

rom_reset_usb_boot_extra appears to pass p0/p1 to rom_reboot in the opposite order from the documented BOOTSEL ABI #2949

Description

@anoshyn

What's wrong

There is a contradiction between (a) the documented REBOOT2_FLAG_REBOOT_TYPE_BOOTSEL parameter ABI and (b) what the SDK's rom_reset_usb_boot_extra() wrapper actually passes to rom_reboot().

Documented ABI

src/common/boot_picoboot_headers/include/boot/picoboot_constants.h:15:

#define REBOOT2_FLAG_REBOOT_TYPE_BOOTSEL      0x2 // param0 = gpio_pin_number, param1 = flags

src/rp2_common/pico_bootrom/include/pico/bootrom.h:469-475:

 * REBOOT2_FLAG_REBOOT_TYPE_BOOTSEL - reboot into BOOTSEL mode.
 *  p0 - the GPIO number to use as an activity indicator (enabled by flag in p1).
 *  p1 - a set of flags:
 *   0x01 : DISABLE_MSD_INTERFACE
 *   0x02 : DISABLE_PICOBOOT_INTERFACE
 *   0x10 : GPIO_PIN_ACTIVE_LOW
 *   0x20 : GPIO_PIN_ENABLED

So per the docs: p0 = GPIO number, p1 = flags.

What the SDK does

src/rp2_common/pico_bootrom/bootrom.c:46 (RP2040 fallback path):

rom_reboot(REBOOT2_FLAG_REBOOT_TYPE_BOOTSEL | REBOOT2_FLAG_NO_RETURN_ON_SUCCESS, 10, flags, usb_activity_gpio_pin_mask);
//                                                                                   ^p0    ^p1

src/rp2_common/pico_bootrom/bootrom.c:66 (newer path, used on RP2350):

rom_reboot(REBOOT2_FLAG_REBOOT_TYPE_BOOTSEL | REBOOT2_FLAG_NO_RETURN_ON_SUCCESS, 10, flags, (uint)usb_activity_gpio_pin);
//                                                                                   ^p0    ^p1

Both pass p0 = flags, p1 = GPIO — the opposite of the documented ABI.

rom_reboot() itself just forwards (flags, delay_ms, p0, p1) to rom_func_lookup_inline(ROM_FUNC_REBOOT), so the wrapper isn't doing any swapping under the hood.

How I noticed

While preparing PR #2947 (fix for the wValue bit-overlap in pico_stdio_usb/reset_interface.c, issue #2713), I tried an end-to-end test on a Pico 2 (RP2350) using the bootsel-reset USB request to specify GPIO 25 as the activity-LED with active_low=true:

wValue = (25 << 10) | 0x200 | 0x100 = 0x6700

The expected observable behaviour during BOOTSEL: with active_low=true the bootrom should hold the activity GPIO HIGH during idle (so the Pico 2's onboard LED on GPIO 25 lights solid). What I actually observed: LED steady off, regardless of active_low value, in both active_low=false and active_low=true runs and with MSD enabled (disable_mask=0) so there was clear MSD enumeration / I/O activity.

The wValue parsing in reset_interface.c is correct (verified by reading the code), so the breakage is downstream of that — at the rom_reset_usb_boot_extrarom_reboot call boundary, exactly where the apparent p0/p1 swap is.

Which side is wrong?

I'm not in a position to say with certainty which of the two is the source of truth (the bootrom's actual behaviour, vs. the SDK doc):

  • If the doc is correct and the bootrom genuinely takes (p0=gpio, p1=flags), then bootrom.c:46 and :66 need to swap the last two args, and the activity-LED feature has been silently broken whenever usb_activity_gpio_pin >= 0 was passed. That matches what I observed.

  • If the SDK code is correct and the bootrom actually takes (p0=flags, p1=gpio), then the doxygen in bootrom.h and the comment in picoboot_constants.h are stale and should be updated. In that case, the activity LED not lighting on my hardware would have a different explanation, which I'd want to understand before closing this.

Picotool's PC_REBOOT2 call (raspberrypi/picotool main.cpp) only passes dParam0=0, dParam1=0, so it doesn't exercise the activity-LED path and can't disambiguate.

Repro / environment

  • SDK: latest develop (origin/develop, includes commit 2492b1c).
  • Board: Pico 2 (RP2350), PID 2e8a:0009 in app mode, 2e8a:000f in BOOTSEL.
  • Firmware: minimal app linking pico_stdlib with pico_enable_stdio_usb(... 1) and PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED=0.
  • Host trigger: libusb control transfer, bmRequestType=0x21, bRequest=0x01 (RESET_REQUEST_BOOTSEL), wValue=0x6700, wIndex=2 (reset interface number from lsusb -v).
  • Observed: device reboots into BOOTSEL (PID 2e8a:000f), MSD enumerates, files browsable; activity-LED on GPIO 25 remains off throughout, including during sustained MSD reads.

Happy to gather any additional traces (e.g. a UART-stdio variant of the same firmware that prints gpio and active_low right before calling rom_reset_usb_boot_extra) if that would help triage.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions