Skip to content

fbuild: standardize flash→monitor handoff timing as per-family HandoffTiming on BoardFamily #691

Description

@zackees

TL;DR

Deployer::post_deploy_recovery() (the hook landed via #605) lets each deploy backend define how to bring the device back into a monitorable state. But the timing — how long to sleep after reset before opening monitor, how long the boot-banner drain should be, how many re-enumeration retries — is currently hardcoded per-deployer and varies wildly between known-good configurations. As fbuild grows board coverage this drift becomes a real bug source.

The FastLED #3339 LPC bring-up confirmed:

  • LPC845-BRK: ~0.5 s settle after pyocd reset, then drain residual bytes for ~2 s.
  • ESP32 native USB CDC: ~0.2 s settle, no drain.
  • Estimated for RP2040 BOOTSEL → app re-enumerate: 1-2 s VCOM disappear, ~3 s reattach.

No single place captures the table. This issue requests one.

Proposed shape

Add per-family settings on BoardFamily (proposed in #687):

pub struct HandoffTiming {
    /// Sleep after reset before first byte is expected.
    pub post_reset_settle_ms: u32,
    /// How long to drain boot-banner / boot-up junk before bring-up RPC.
    pub boot_drain_ms: u32,
    /// How long to wait for the port to reappear after USB drop (CDC re-enum,
    /// 1200-bps-touch bootloader, BOOTSEL).
    pub port_reappear_timeout_ms: u32,
    /// Max retries on transient open failures during the reappear window.
    pub open_retry_count: u8,
}

impl BoardFamily {
    pub fn handoff_timing(&self) -> HandoffTiming {
        use BoardFamily::*;
        match self {
            Esp32NativeUsbCdc | Esp32ExternalUart => HandoffTiming {
                post_reset_settle_ms: 200, boot_drain_ms: 0,
                port_reappear_timeout_ms: 3000, open_retry_count: 5,
            },
            CdcAcmBridge { .. } => HandoffTiming {
                post_reset_settle_ms: 500, boot_drain_ms: 2000,
                port_reappear_timeout_ms: 3000, open_retry_count: 3,
            },
            Teensy | NativeUsbCdcReset1200Bps => HandoffTiming {
                post_reset_settle_ms: 100, boot_drain_ms: 500,
                port_reappear_timeout_ms: 5000, open_retry_count: 10,
            },
            ArduinoAutoReset => HandoffTiming {
                post_reset_settle_ms: 1500, boot_drain_ms: 0,
                port_reappear_timeout_ms: 0, open_retry_count: 1,
            },
        }
    }
}

Then post_deploy_recovery() consumes the settings instead of hardcoding numbers.

Acceptance criteria

  • HandoffTiming struct on BoardFamily (depends on #687 landing).
  • Each deployer (esp32_native, future LpcDeployer, etc.) reads the settings instead of inline magic numbers.
  • FastLED-side autoresearch's _run_bring_up_tests can adopt the same settings via an exported helper (avoids drift between fbuild and FastLED's Python sleep numbers).
  • Per-family table documented in the usb-cdc-control-line-matrix.md doc proposed in #689.

Refs

Filed from the audit fan-out on FastLED/FastLED#3339.

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