Two regressions on UART boards (heltec_v3_uart, etc.):
1. RADIO_THROTTLED was never cleared on UART. The throttle gate at
src/radio.rs:2017 (added in 276f941, "chart-first restructure ...
soak hardening") silently drops async RX while the flag is true.
USB host_task clears it on first successful write_packet
(src/host/usb.rs:354/373), but the UART path was never updated --
every RX event was dropped from boot. The OLED bar lit up
regardless because record_packet announces PacketRx before the
gate. Mirror the USB pattern: clear on successful tx.write_all,
re-arm on failure.
2. Once RX flowed, sustained bidirectional spam tripped the §3.4
inactivity watchdog spuriously. The select3-based loop serialised
read and write; tx.write_all (~25 ms per max frame at 115_200
baud) blocked the read poll long enough for last_frame_at to age
past 1000 ms under a saturated outbound queue. The Reset cascaded
to radio (Unconfigured) and display (splash), leaving subsequent
host TX commands timing out waiting for TX_DONE. Restructure
host_task into two sub-loops joined in the same task: read_loop
owns rx + watchdog, write_loop owns tx + throttle. The read future
re-polls on every executor wake regardless of write progress.
Same executor, disjoint borrows on the split rx/tx halves, no
Mutex needed.
Also reset the FrameDecoder when the watchdog fires so a host that
resumes mid-frame resyncs cleanly on the next 0x00 sentinel (USB
gets this for free via DTR-drop reset; UART has no DTR).
Build: bump esp-hal/esp-rtos/esp-backtrace/esp-println version
requirements (1.0->1.1, 0.2->0.3, 0.18->0.19, 0.16->0.17) to match
what the upstream esp-rs/esp-hal main branch now publishes. cargo
update had invalidated the [patch.crates-io] entries since the
patched versions were no longer semver-compatible with the old
top-level requirements, which silently dropped the patches and fell
back to crates.io releases that pin embassy-executor 0.9 (mismatched
with our 0.10).
DongLoRa Firmware
Embedded Rust firmware for DongLoRa boards. Exposes the LoRa radio over USB CDC-ACM using a COBS-framed binary protocol.
Building
just setup # one-time toolchain install
just build heltec_v4 # build for a specific board
just flash heltec_v4 # build + flash
just check-all # compile-check all boards
just clippy heltec_v4 # lint
just test # host-side protocol unit tests
All commands are run from the firmware/ directory.
Supported Boards
| Board | Feature | MCU | Radio | USB | Target |
|---|---|---|---|---|---|
| Heltec V3 | heltec_v3 |
ESP32-S3 | SX1262 | Native CDC-ACM | xtensa-esp32s3-none-elf |
| Heltec V3 (UART) | heltec_v3_uart |
ESP32-S3 | SX1262 | CP2102 bridge | xtensa-esp32s3-none-elf |
| Heltec V4 | heltec_v4 |
ESP32-S3 | SX1262 | Native CDC-ACM | xtensa-esp32s3-none-elf |
| ELECROW ThinkNode-M2 | elecrow_thinknode_m2 |
ESP32-S3 | SX1262 | CP2102 bridge | xtensa-esp32s3-none-elf |
| LilyGo T-Beam | lilygo_tbeam |
ESP32 | SX1276 | CP2102 bridge | xtensa-esp32-none-elf |
| LilyGo T-Beam S3 Supreme | lilygo_tbeam_supreme |
ESP32-S3 | SX1262 | Native CDC-ACM | xtensa-esp32s3-none-elf |
| RAK WisBlock 4631 | rak_wisblock_4631 |
nRF52840 | SX1262 | Native CDC-ACM | thumbv7em-none-eabihf |
| Waveshare RP2040-LoRa | waveshare_rp2040_lora |
RP2040 | SX1262 | Native CDC-ACM | thumbv6m-none-eabi |
| Wio Tracker L1 | wio_tracker_l1 |
nRF52840 | SX1262 | Native CDC-ACM | thumbv7em-none-eabihf |
Heltec V3 USB Note
The default heltec_v3 build uses native USB CDC-ACM, which requires a
hardware modification to your board. Stock Heltec V3 boards route USB through a
CP2102 bridge chip to UART — the ESP32-S3's native USB pins (GPIO19/GPIO20) are
routed to header pins but not connected to the USB connector.
To enable native USB on a Heltec V3:
- Solder 0-ohm (or 22-ohm) resistors at pads R29 (D+) and R3 (D-)
- Disconnect the CP2102 from the USB connector's D+/D- lines (cut traces or remove the CP2102 bridge resistors)
After this mod, the board appears as /dev/ttyACM0 with the DongLoRa VID:PID
(1209:5741), just like the V4 and nRF boards.
If you have a stock (unmodified) V3, use heltec_v3_uart instead:
just build heltec_v3_uart
just flash heltec_v3_uart
This builds firmware that communicates via the CP2102 bridge (appears as
/dev/ttyUSB0).
Adding a Board
See src/board/PORTING.md.
Protocol
See PROTOCOL.md for the complete wire format specification.