Repository navigation
Description
Context
Follow-up to #430 / #431 which wired the Teensy dispatch arm so `fbuild deploy -e teensyXX` runs the implemented `TeensyDeployer`. End-to-end testing on a Teensy 4.0 attached at COM22 surfaced a second gap that blocks unattended deploy: the bundled `teensy_loader_cli.exe` (PlatformIO tool-teensy v2.2, the same one fbuild discovers under `~/.platformio/packages/tool-teensy/`) explicitly prints "Soft reboot is not implemented for Win32" when invoked with `-s`, then falls through to waiting for the user to press the button.
Repro:
```
$ teensy_loader_cli --mcu=TEENSY40 -w -s -v firmware.hex
Teensy Loader, Command Line, Version 2.2
Read "firmware.hex": 340992 bytes, 16.8% usage
Soft reboot is not implemented for Win32
Waiting for Teensy device...
(hint: press the reset button)
```
The default `TeensyLoaderParams` uses `-w` plus `-v`; `-s` isn't passed today and even if it were, Windows users get the message above. Net effect: `bash autoresearch teensyXX` succeeds on the first flash (Teensy is already in HalfKay bootloader from the prior flash button press), then times out at 60 s on every subsequent run because the freshly-flashed user firmware never re-enters bootloader without a button press.
This breaks unattended CI / iteration — the exact use case driving FastLED/FastLED#2628 hardware bring-up.
Proposed fix
The Teensyduino USB stack treats opening the CDC ACM port at 134 baud as a signal to re-enter HalfKay (this is the trick `platformio run -t upload` uses on the same Windows toolchain). Implementing this in `crates/fbuild-deploy/src/teensy.rs` before invoking `teensy_loader_cli` closes the gap end-to-end without needing a newer loader binary.
Concrete steps:
- Detect "already-running firmware" state. If a port was passed in (`port: Some(&str)`) AND a serial port is enumerable at that address, the device is running user firmware, not HalfKay — soft-reboot trigger is the right thing to do.
- Send magic-baud trigger. Open the CDC ACM port at 134 baud (Windows: `SetCommState` with `BaudRate = 134`; cross-platform: `serialport-rs` does this for us), wait ~250 ms for the firmware to reset, then close. The Teensy will re-enumerate as HalfKay HID.
- Then invoke `teensy_loader_cli` without `-s` (since we already triggered the reboot) — just `-w -v`. The loader sees the HalfKay device immediately and programs without manual intervention.
Reference implementation (for inspiration):
- PlatformIO's teensy upload script does exactly this: `platformio/builder/tools/piouploader.py` / `teensyduino/cores/teensy4/usb_*.c` baud-134 detection.
- Teensyduino's CLI `teensy_post_compile` uses the same trick when programming via the upload daemon.
Acceptance criteria
- `bash autoresearch teensy40 --simd` (or `teensy41`) succeeds on a Teensy with running user firmware — no button press required.
- First-flash behaviour preserved: when no CDC ACM port is present (device already in HalfKay), the deployer skips the baud trigger and just runs `teensy_loader_cli -w`.
- Cross-platform: works on Windows AND Linux/macOS (where `-s` does work, but doing the baud trick ourselves is equally fine and removes the loader-version dependency).
- Timeout (default 60 s in `TeensyLoaderParams`) is rarely hit because the baud trigger collapses the wait to ~1 s.
- Hard-reboot fallback: if the magic-baud trigger doesn't take (device unresponsive), surface a clear "press the reset button on the Teensy" message AND let `teensy_loader_cli -w` continue waiting up to the configured timeout.
Additional gaps surfaced during the verification (lower priority, separate issues OK)
These came up while reaching the timeout above; filing here for visibility, file separately if scope expands:
- Stale firmware.hex confusion. `teensy_loader_cli` programmed an old Blink hex (`72704 bytes, 3.6% usage`) when `AutoResearch` was the intended example, because the deploy step took whatever was at `.build/pio/teensyXX/.fbuild/build/teensyXX/release/firmware.hex` instead of the most-recent-build for the explicitly-requested example. A `--examples` flag or build-then-deploy chaining in `fbuild deploy` would prevent this.
- HalfKay stuck-state recovery on Windows. Repeated "Programming.error writing to Teensy" on a fresh boot until the device was re-flashed clean. teensy_loader_cli doesn't retry; a single failed program leaves no diagnostic about whether it's a USB issue, a hex-format issue, or actual flash damage. A short retry loop with a clear error tail would help unattended CI.
- TeensyLoaderParams default timeout (60 s) too tight for first-flash button-press waits. Could default to 120 s, or accept an env var override.
References
- feat(deploy): wire Teensy dispatch arm so 'fbuild deploy -e teensyXX' actually runs the implemented TeensyDeployer #430 (closed) — original dispatch wire-up
- feat(deploy): wire Teensy dispatch arm so 'fbuild deploy -e teensyXX' actually runs (#430) #431 (merged) — implementation
- feat(simd): add Cortex-M DSP-extension SIMD backend for Teensy 3.x / 4.x (close the SIMD-dispatch gap) FastLED#2628 — the SIMD work that needs unattended Teensy deploy to validate on hardware
- Teensy USB stack: `teensy4/usb_serial.c` baud-134 detection (cores in the PIO tool-teensy package)
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsTriage
Activity
Feat/433 comprehensive teensy deployer (#449)
refactor(paths) + fix(symbols): BuildLayout single-source + PT_LOAD b…
chore: bump version to 2.2.19
fix(ci): match collapsed `<env>` build path in firmware verify steps