`--ser` with several RP2350s on USB sends PICOBOOT requests to the wrong interface

Chiusa
#370 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub

@will-v-pi ci sta già lavorando.

Dal 22/10/2026.

  • #372 di @will-v-pi — aperta

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
48/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
c
Ambito
embedded-iot

Direzione di ricerca

Start with picoboot_connection/picoboot_connection.c, especially picoboot_open_device() and the later reset and command status calls that use the interface and endpoint globals. Trace how the selected device handle is kept while serial matching opens other devices. Done means requests for each selected device use that device’s own interface and endpoints, including the mixed RP2350 layout described here.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Title

--ser with several RP2350s on USB sends PICOBOOT requests to the wrong interface (global interface/out_ep/in_ep), locking up the target's bootrom

Body

Summary

picoboot_connection.c keeps the PICOBOOT interface number and bulk endpoints in process-wide globals:

// picoboot_connection/picoboot_connection.c (2.3.1, same on master)
unsigned int interface;
unsigned int out_ep;
unsigned int in_ep;

picoboot_open_device() overwrites them for every device it examines:

if (config->bNumInterfaces == 1) {
    interface = 0;
} else {
    interface = 1;
}

With --ser, picotool has to open each RP-series device on the bus to read its serial number. Afterwards, the globals describe the last device opened, not the one that matched. Every later picoboot_reset() / picoboot_cmd_status() (and anything else that uses interface) goes to the selected device with another device's interface number.

That's harmless while all devices share a layout. It goes wrong once one RP2350 has its BOOTSEL mass-storage interface disabled in OTP (BOOT_FLAGS0.DISABLE_BOOTSEL_USB_MSD_IFC = 1), so PICOBOOT is its only interface (0), and another RP2350 next to it is still in BOOTSEL with the default layout (MSD = 0, PICOBOOT = 1).

Environment
  • picotool v2.3.1 (Linux, GNU-16.2.1, Release), libusb 1.0.30, Fedora 44
  • Device A: RP2350, OTP BOOT_FLAGS0 = 0x0A0000 (DISABLE_BOOTSEL_USB_MSD_IFC, DISABLE_BOOTSEL_UART_BOOT), white-label set, flash empty, so it sits in BOOTSEL with a single vendor interface (PICOBOOT, interface 0)
  • Device B: blank RP2350 in BOOTSEL (MSD interface 0, PICOBOOT interface 1)
  • Both on the same host (behind a USB 1.1 hub, though that doesn't seem to matter)
Steps to reproduce
  1. Put A and B in BOOTSEL on the same host.
  2. picotool info --ser <serial of A> (or otp get … --ser <A>, reboot --ser <A>, …)
Expected

picotool talks to A on A's PICOBOOT interface (0).

Actual

ERROR: Communication with RP2350 device failed (exit 247). Every later attempt says No accessible RP2350 devices in BOOTSEL mode were found with serial number … (exit 249). A remains enumerated, but answers nothing until it's reset or power-cycled.

A libusb trace (LD_PRELOAD shim) of picotool info --ser <A>. A is opened first and gets interface 0 claimed, then B gets interface 1, then the requests meant for A carry wIndex = 1:

CLAIM 0 -> 0                                         # A (1 interface)
GET_STRING  -> "M080DEV001"                          # A's serial: the match
CLAIM 1 -> 0                                         # B (2 interfaces) -> globals now say interface 1
GET_STRING  -> "B5E96FC879D69AD4"                    # B's serial
CTRL rt=82 rq=00 idx=0084 -> 2                       # is_halted(in_ep)
CTRL rt=82 rq=00 idx=0003 -> 2                       # is_halted(out_ep)
CTRL rt=41 rq=41 val=0000 idx=0001 len=0  -> -7      # PICOBOOT_IF_RESET to A, interface 1 (!)
CTRL rt=c1 rq=42 val=0000 idx=0001 len=16 -> -7      # PICOBOOT_IF_CMD_STATUS, interface 1
ERROR: Communication with RP2350 device failed

With --bus/--address instead of --ser, only A is opened, IF_RESET goes to idx=0000, and everything works.

Consequence on the device (bootrom side, for context)

On A, that single vendor request for the non-existent interface 1 puts the bootrom into a HardFault lockup. Over SWD: IPSR = 3, PC = 0xEFFFFFFE, HFSR = 0x40000000 (FORCED), CFSR = 0x00000001 (IACCVIOL), SFSR = 0x00000001 (INVEP). The stacked non-secure frame has PC = 0x72726562. I confirmed it's this one request by sending it by hand on a freshly reset bootrom: IF_RESET with wIndex = 1 locks it up, while wIndex = 0 followed by GET_INFO, EXCLUSIVE_ACCESS, EXIT_XIP, READ and GET_INFO(PARTITION_TABLE / UF2_*) all work. Chip: CHIP_ID = 0x30004927, ROM header at 0x10: 4d 75 02 04. That bootrom behaviour probably deserves its own report against the bootrom, but picotool is what sends the request.

In practice this happens on any multi-board system where some RP2350s are already provisioned (MSD disabled) and another one is still blank. It looks like the board was bricked by its own provisioning.

Suggested fix

Keep interface, out_ep and in_ep per connection (next to the libusb_device_handle), or at least recompute them from the selected device after selection instead of keeping whatever the last opened device left behind. Until then, --bus/--address is a workaround.

Lingua principale
C++
Stelle
1k
Fork
195
Merge medio
14g 8h
PR unite (30g)
3

Preparare l'ambiente

  • Nessun Dockerfile né file Docker Compose
  • Ha un modello di pull request
  • Nessuna guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di raspberrypi/picotool

Tutte le issue di raspberrypi/picotool

Issue simili

Altre issue su C++

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.