{"record":{"id":"9faf9526b3ff73c2","repo":"embassy-rs/embassy","slug":"rts-and-cts-pins-must-be-either-both-set-or-none-s","errorCode":null,"errorMessage":"RTS and CTS pins must be either both set or none set.","messagePattern":"RTS and CTS pins must be either both set or none set\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-nrf/src/uarte.rs","lineNumber":218,"sourceCode":"            Some(rts.into()),\n            config,\n        )\n    }\n\n    fn new_inner<T: Instance>(\n        _uarte: Peri<'d, T>,\n        rxd: Peri<'d, AnyPin>,\n        txd: Peri<'d, AnyPin>,\n        cts: Option<Peri<'d, AnyPin>>,\n        rts: Option<Peri<'d, AnyPin>>,\n        config: Config,\n    ) -> Self {\n        let r = T::regs();\n\n        let hardware_flow_control = match (rts.is_some(), cts.is_some()) {\n            (false, false) => false,\n            (true, true) => true,\n            _ => panic!(\"RTS and CTS pins must be either both set or none set.\"),\n        };\n        configure(r, config, hardware_flow_control);\n        configure_rx_pins(r, rxd, rts);\n        configure_tx_pins(r, txd, cts);\n\n        T::Interrupt::unpend();\n        unsafe { T::Interrupt::enable() };\n        r.enable().write(|w| w.set_enable(vals::Enable::Enabled));\n\n        let s = T::state();\n        s.tx_rx_refcount.store(2, Ordering::Relaxed);\n\n        Self {\n            tx: UarteTx {\n                r: T::regs(),\n                state: T::state(),\n                _p: PhantomData {},\n            },","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-nrf/src/uarte.rs#L200-L236","documentation":"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.","triggerScenarios":"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)`.","commonSituations":"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.","solutions":["Pass both RTS and CTS pins (or neither) so the pair matches.","If the board only routes one flow-control pin, pass None for both and disable hardware flow control in the Config.","Fix the board config/pin mapping so the flow-control pair is complete."],"exampleFix":"// before\nlet mut uarte = Uarte::new(p.UARTE0, irq, p.P0_06, p.P0_08, p.P0_05, NoPin, config);\n// after\nlet 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)","handlingStrategy":"validation","validationCode":"fn flow_pins_consistent(rts: Option<AnyPin>, cts: Option<AnyPin>) -> bool {\n    rts.is_some() == cts.is_some()\n}\nassert!(flow_pins_consistent(rts, cts), \"RTS/CTS must both be set or both None\");","typeGuard":"fn both_or_none<T>(a: &Option<T>, b: &Option<T>) -> bool { a.is_some() == b.is_some() }","tryCatchPattern":null,"preventionTips":["Define a single board-config struct whose constructor takes flow-control pins as a pair (enum FlowControl { None, Pins { rts, cts } }).","Copy pin assignments verbatim from the board support crate instead of hand-picking pins.","Check the board schematic for RTS/CTS routing before configuring hardware flow control."],"tags":["embedded","uart","nrf","pin-config","panic"],"backgroundTag":"invalid-config-value","analyzedSha":"463a07b963419a1bfe61d5d597c44acb810afb8b","analyzedAt":"2026-09-10T13:38:26.660Z","contentChangedAt":"2026-09-10T13:38:26.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}