Skip to content

fix(rp2040): tolerate delayed Windows CDC re-enumeration after UF2 flash #1074

Description

@zackees

Context

Parent: #1040
Related deployment parity work: #1049
Regression surfaced after merged #1073.

A genuine Pico 1 on Windows successfully completed the hard parts of a touchless subsequent deployment through the current editable fbuild main: application CDC reset, verified BOOTSEL discovery, UF2 transfer, ROM-volume disappearance, and application boot. fbuild nevertheless returned failure because its RP2040 runtime-CDC watcher expired before Windows exposed the catalogue-identified port:

Running: ...\.venv\Scripts\fbuild.exe ...\.build\pio\rp2040 deploy -e rp2040 -p COM12

deploy error: deploy failed: RP2040 firmware was transferred, but no catalogue-identified runtime CDC port appeared; verify that the firmware enables USB serial and that FastLED/boards USB data is current

Deploy failed (fbuild) [19.7s]

The next fbuild port scan, run immediately after the failure, showed the expected runtime endpoint:

COM12  2E8A:000A  USB Serial Device (COM12)  ser=5303284720C4641C
       Raspberry Pi Foundation / Raspberry Pi Pico SDK CDC UART (RP2040)

Reproduction command from ~/dev/fastled:

$env:UV_NO_SYNC='1'
bash autoresearch rp2040 --upload-port COM12 --tx-pin 1 --rx-pin 0 --timeout 120 --skip-lint

The editable FastLED environment used fbuild 2.5.2 from ~/dev/fbuild at current main; #1073 was present. The firmware was transferred and booted, so this is not a BOOTSEL-entry, UF2-write, firmware-USB, or USB-profile identity failure. It is a false-negative post-flash recovery timeout.

The RP2040 deployer currently owns an inline post_deploy_timeout = 15s. Separately, BoardFamily::NativeUsbCdcReset1200Bps exposes a HandoffTiming policy, but the deployer does not use it for this complete BOOTSEL-to-application transition. The watcher also returns the timeout error without a final authoritative catalogue scan or diagnostics showing which candidates and timings it observed.

Proposal

Harden RP2040 post-flash CDC recovery without weakening device selection:

  1. Replace the inline RP2040 recovery timeout with an explicit, tested board-family handoff policy suitable for Windows' double enumeration (runtime CDC -> BOOTSEL -> runtime CDC). Keep the wait bounded, but allow normal delayed Windows enumeration.
  2. Perform one final FastLED/boards-backed catalogue scan at the deadline before returning a timeout, so a port arriving on the boundary is accepted.
  3. Continue selecting by the requested USB serial when available and return the actual post-deploy COM name. Do not accept an unrelated or ambiguous serial device.
  4. Include elapsed time, prior port/serial, and catalogue-identified candidates in verbose timeout diagnostics.
  5. Keep production USB identity exclusively sourced from the verified FastLED/boards profile cache. Do not add built-in VID/PID constants or fallback tables.
  6. Validate through the normal fbuild deploy / bash autoresearch path. Do not require a BOOTSEL button press, manual replug, raw uploader, or PlatformIO.

Acceptance criteria

  • A deterministic unit test simulates a matching runtime CDC port appearing after the former 15-second boundary and proves deployment succeeds without real sleeps.
  • A boundary test proves a matching port returned by the final deadline scan is accepted.
  • Timeout coverage still fails when no matching FastLED/boards runtime profile appears.
  • Serial-preserving selection returns a renumbered COM port for the requested Pico and rejects unrelated or ambiguous candidates.
  • Timeout diagnostics report elapsed timing and observed catalogue candidates without embedding production VID/PID data.
  • On the attached genuine Pico 1, the exact reproduction command completes touchlessly and the GPIO phase proceeds on COM12.
  • Hardware evidence records fbuild commit, command, runtime serial, BOOTSEL/UF2 transition, returned COM port, and decisive success output.

Related issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions