embassy-rs/embassy · error

RTS and CTS pins must be either both set or none set.

Error message

RTS and CTS pins must be either both set or none set.

What it means

UARTE (UART with EasyDMA) construction checks that hardware flow control pins are configured consistently. RTS and CTS are a pair used by the hardware flow-control feature; enabling only one is meaningless at the hardware level, so `new_inner` panics when exactly one of the two pins is `Some`. Both set enables hardware flow control; neither set disables it.

Solutions

  1. Pass both RTS and CTS pins (or neither) so the pair matches.
  2. If the board only routes one flow-control pin, pass None for both and disable hardware flow control in the Config.
  3. Fix the board config/pin mapping so the flow-control pair is complete.

Example fix

// before
let mut uarte = Uarte::new(p.UARTE0, irq, p.P0_06, p.P0_08, p.P0_05, NoPin, config);
// after
let mut uarte = Uarte::new(p.UARTE0, irq, p.P0_06, p.P0_08, p.P0_05, p.P0_07, config); // RTS + CTS both set (or use NoPin for both)
Defensive patterns

Strategy: validation

Validate before calling

fn flow_pins_consistent(rts: Option<AnyPin>, cts: Option<AnyPin>) -> bool {
    rts.is_some() == cts.is_some()
}
assert!(flow_pins_consistent(rts, cts), "RTS/CTS must both be set or both None");

Type guard

fn both_or_none<T>(a: &Option<T>, b: &Option<T>) -> bool { a.is_some() == b.is_some() }

Prevention

When it happens

Trigger: Calling `Uarte::new` / `Uarte::new_with_rtscts` (or the blocking variant) passing `rts: Some(pin)` with `cts: None`, or `rts: None` with `cts: Some(pin)`.

Common situations: Board support configs that define only a CTS pin (or only RTS) in pin mappings; copying an example and deleting one flow-control pin because it is not routed on the board; typos in peripheral config macros.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10). Data as JSON: /api/errors/9faf9526b3ff73c2. Report an issue: GitHub.

Appendix: source

Thrown at embassy-nrf/src/uarte.rs:218

            Some(rts.into()),
            config,
        )
    }

    fn new_inner<T: Instance>(
        _uarte: Peri<'d, T>,
        rxd: Peri<'d, AnyPin>,
        txd: Peri<'d, AnyPin>,
        cts: Option<Peri<'d, AnyPin>>,
        rts: Option<Peri<'d, AnyPin>>,
        config: Config,
    ) -> Self {
        let r = T::regs();

        let hardware_flow_control = match (rts.is_some(), cts.is_some()) {
            (false, false) => false,
            (true, true) => true,
            _ => panic!("RTS and CTS pins must be either both set or none set."),
        };
        configure(r, config, hardware_flow_control);
        configure_rx_pins(r, rxd, rts);
        configure_tx_pins(r, txd, cts);

        T::Interrupt::unpend();
        unsafe { T::Interrupt::enable() };
        r.enable().write(|w| w.set_enable(vals::Enable::Enabled));

        let s = T::state();
        s.tx_rx_refcount.store(2, Ordering::Relaxed);

        Self {
            tx: UarteTx {
                r: T::regs(),
                state: T::state(),
                _p: PhantomData {},
            },

View on GitHub (pinned to 463a07b963)