Skip to main content

m5stack_core/io/
serial_cmd.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2//! HIL serial-cmd transport — exposes a `Read` endpoint for the
3//! `alternator-regulator::serial_cmd` parser.
4//!
5//! - fire27 (ESP32): UART0 RX (GPIO3), already routed through the on-board
6//!   USB-serial bridge used by `espflash`. TX side is left to `esp-println`.
7//! - cores3 (ESP32-S3): native USB-Serial-JTAG CDC. Independent USB
8//!   endpoint from probe-rs JTAG/RTT.
9
10#[cfg(feature = "fire27")]
11mod imp {
12    use esp_hal::{
13        Blocking,
14        gpio::AnyPin,
15        peripherals::UART0,
16        uart::{Config, UartRx},
17    };
18
19    pub struct SerialCmdResources<'d> {
20        pub uart: UART0<'d>,
21        pub rx_pin: AnyPin<'d>,
22    }
23
24    /// Blocking UartRx — caller drives reads via polling + Timer.
25    ///
26    /// `into_async()` is *not* called here. Two reasons:
27    /// 1. The blocking variant works fine with the polled `run_polled` loop
28    ///    and avoids registering a UART interrupt handler entirely.
29    /// 2. **Init ordering matters:** `UartRx::new(...)` (even without
30    ///    `into_async`) must run *after* the BLE radio has finished initializing
31    ///    on ESP32 — calling it earlier hangs BLE setup silently (LCD goes
32    ///    white, no `Device Address` log). The caller is responsible for
33    ///    deferring `take_rx` until radio is up.
34    pub type SerialRx<'d> = UartRx<'d, Blocking>;
35
36    pub fn take_rx(r: SerialCmdResources<'static>) -> SerialRx<'static> {
37        UartRx::new(r.uart, Config::default())
38            .expect("UART0 RX init")
39            .with_rx(r.rx_pin)
40    }
41}
42
43#[cfg(feature = "cores3")]
44mod imp {
45    use esp_hal::{
46        Async,
47        peripherals::USB_DEVICE,
48        usb_serial_jtag::UsbSerialJtag,
49    };
50
51    pub struct SerialCmdResources<'d> {
52        pub usb: USB_DEVICE<'d>,
53    }
54
55    pub type SerialRx<'d> = UsbSerialJtag<'d, Async>;
56
57    pub fn take_rx(r: SerialCmdResources<'static>) -> SerialRx<'static> {
58        UsbSerialJtag::new(r.usb).into_async()
59    }
60}
61
62pub use imp::{SerialRx, SerialCmdResources, take_rx};