diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 04e01b242..e88e45d25 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added +- uart: Added `with_cts`/`with_rts`s methods to configure CTS, and RTS pins (#1592) +- uart: Constructors now require TX and RX pins (#1592) +- uart: Added `Uart::new_with_default_pins` constructor (#1592) +- uart: Added `UartTx` and `UartRx` constructors (#1592) - Add Flex / AnyFlex GPIO pin driver (#1659) @@ -18,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Refactor `Dac1`/`Dac2` drivers into a single `Dac` driver (#1661) ### Removed +- uart: Removed `configure_pins` methods (#1592) ## [0.18.0] - 2024-06-04 diff --git a/esp-hal/src/prelude.rs b/esp-hal/src/prelude.rs index 2abcb5a29..216eb3d19 100644 --- a/esp-hal/src/prelude.rs +++ b/esp-hal/src/prelude.rs @@ -41,5 +41,5 @@ pub use crate::timer::timg::{ #[cfg(any(systimer, timg0, timg1))] pub use crate::timer::Timer as _esp_hal_timer_Timer; #[cfg(any(uart0, uart1, uart2))] -pub use crate::uart::{Instance as _esp_hal_uart_Instance, UartPins as _esp_hal_uart_UartPins}; +pub use crate::uart::Instance as _esp_hal_uart_Instance; pub use crate::{entry, macros::*}; diff --git a/esp-hal/src/rom/md5.rs b/esp-hal/src/rom/md5.rs index 73412e0f8..b55f1d244 100644 --- a/esp-hal/src/rom/md5.rs +++ b/esp-hal/src/rom/md5.rs @@ -32,9 +32,11 @@ #![doc = crate::before_snippet!()] //! # use esp_hal::rom::md5; //! # use esp_hal::uart::Uart; +//! # use esp_hal::gpio::Io; //! # use core::writeln; //! # use core::fmt::Write; -//! # let mut uart0 = Uart::new(peripherals.UART0, &clocks); +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! # let mut uart0 = Uart::new(peripherals.UART0, &clocks, io.pins.gpio1, io.pins.gpio2).unwrap(); //! # let data = "Dummy"; //! let d: md5::Digest = md5::compute(&data); //! writeln!(uart0, "{}", d); @@ -46,9 +48,11 @@ #![doc = crate::before_snippet!()] //! # use esp_hal::rom::md5; //! # use esp_hal::uart::Uart; +//! # use esp_hal::gpio::Io; //! # use core::writeln; //! # use core::fmt::Write; -//! # let mut uart0 = Uart::new(peripherals.UART0, &clocks); +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! # let mut uart0 = Uart::new(peripherals.UART0, &clocks, io.pins.gpio1, io.pins.gpio2).unwrap(); //! # let data0 = "Dummy"; //! # let data1 = "Dummy"; //! let mut ctx = md5::Context::new(); diff --git a/esp-hal/src/soc/esp32/efuse/mod.rs b/esp-hal/src/soc/esp32/efuse/mod.rs index 4bae02441..d452b0d8b 100644 --- a/esp-hal/src/soc/esp32/efuse/mod.rs +++ b/esp-hal/src/soc/esp32/efuse/mod.rs @@ -22,10 +22,12 @@ //! ```rust, no_run #![doc = crate::before_snippet!()] //! # use esp_hal::efuse::Efuse; +//! # use esp_hal::gpio::Io; //! # use esp_hal::uart::Uart; //! # use core::writeln; //! # use core::fmt::Write; -//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks); +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks, io.pins.gpio4, io.pins.gpio5).unwrap(); //! let mac_address = Efuse::read_base_mac_address(); //! writeln!( //! serial_tx, diff --git a/esp-hal/src/soc/esp32c2/efuse/mod.rs b/esp-hal/src/soc/esp32c2/efuse/mod.rs index ecc687210..569fc8bbb 100644 --- a/esp-hal/src/soc/esp32c2/efuse/mod.rs +++ b/esp-hal/src/soc/esp32c2/efuse/mod.rs @@ -22,10 +22,12 @@ //! ```rust, no_run #![doc = crate::before_snippet!()] //! # use esp_hal::efuse::Efuse; +//! # use esp_hal::gpio::Io; //! # use esp_hal::uart::Uart; //! # use core::writeln; //! # use core::fmt::Write; -//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks); +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks, io.pins.gpio4, io.pins.gpio5).unwrap(); //! let mac_address = Efuse::read_base_mac_address(); //! writeln!( //! serial_tx, diff --git a/esp-hal/src/soc/esp32c3/efuse/mod.rs b/esp-hal/src/soc/esp32c3/efuse/mod.rs index 7ed70bea1..4f5af98b0 100644 --- a/esp-hal/src/soc/esp32c3/efuse/mod.rs +++ b/esp-hal/src/soc/esp32c3/efuse/mod.rs @@ -22,10 +22,12 @@ //! ```rust, no_run #![doc = crate::before_snippet!()] //! # use esp_hal::efuse::Efuse; +//! # use esp_hal::gpio::Io; //! # use esp_hal::uart::Uart; //! # use core::writeln; //! # use core::fmt::Write; -//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks); +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks, io.pins.gpio4, io.pins.gpio5).unwrap(); //! let mac_address = Efuse::read_base_mac_address(); //! writeln!( //! serial_tx, diff --git a/esp-hal/src/soc/esp32c6/efuse/mod.rs b/esp-hal/src/soc/esp32c6/efuse/mod.rs index a16a854ba..3c33b89bb 100644 --- a/esp-hal/src/soc/esp32c6/efuse/mod.rs +++ b/esp-hal/src/soc/esp32c6/efuse/mod.rs @@ -22,10 +22,12 @@ //! ```rust, no_run #![doc = crate::before_snippet!()] //! # use esp_hal::efuse::Efuse; +//! # use esp_hal::gpio::Io; //! # use esp_hal::uart::Uart; //! # use core::writeln; //! # use core::fmt::Write; -//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks); +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks, io.pins.gpio4, io.pins.gpio5).unwrap(); //! let mac_address = Efuse::read_base_mac_address(); //! writeln!( //! serial_tx, diff --git a/esp-hal/src/soc/esp32h2/efuse/mod.rs b/esp-hal/src/soc/esp32h2/efuse/mod.rs index f5c628f0a..8f4c90f8a 100644 --- a/esp-hal/src/soc/esp32h2/efuse/mod.rs +++ b/esp-hal/src/soc/esp32h2/efuse/mod.rs @@ -22,10 +22,12 @@ //! ```rust, no_run #![doc = crate::before_snippet!()] //! # use esp_hal::efuse::Efuse; +//! # use esp_hal::gpio::Io; //! # use esp_hal::uart::Uart; //! # use core::writeln; //! # use core::fmt::Write; -//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks); +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks, io.pins.gpio4, io.pins.gpio5).unwrap(); //! let mac_address = Efuse::read_base_mac_address(); //! writeln!( //! serial_tx, diff --git a/esp-hal/src/soc/esp32s2/efuse/mod.rs b/esp-hal/src/soc/esp32s2/efuse/mod.rs index 786d3d480..1fa74165f 100644 --- a/esp-hal/src/soc/esp32s2/efuse/mod.rs +++ b/esp-hal/src/soc/esp32s2/efuse/mod.rs @@ -22,10 +22,12 @@ //! ```rust, no_run #![doc = crate::before_snippet!()] //! # use esp_hal::efuse::Efuse; +//! # use esp_hal::gpio::Io; //! # use esp_hal::uart::Uart; //! # use core::writeln; //! # use core::fmt::Write; -//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks); +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks, io.pins.gpio4, io.pins.gpio5).unwrap(); //! let mac_address = Efuse::read_base_mac_address(); //! writeln!( //! serial_tx, diff --git a/esp-hal/src/soc/esp32s3/efuse/mod.rs b/esp-hal/src/soc/esp32s3/efuse/mod.rs index da84efce3..70a0535ff 100644 --- a/esp-hal/src/soc/esp32s3/efuse/mod.rs +++ b/esp-hal/src/soc/esp32s3/efuse/mod.rs @@ -22,10 +22,12 @@ //! ```rust, no_run #![doc = crate::before_snippet!()] //! # use esp_hal::efuse::Efuse; +//! # use esp_hal::gpio::Io; //! # use esp_hal::uart::Uart; //! # use core::writeln; //! # use core::fmt::Write; -//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks); +//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); +//! # let mut serial_tx = Uart::new(peripherals.UART0, &clocks, io.pins.gpio4, io.pins.gpio5).unwrap(); //! let mac_address = Efuse::read_base_mac_address(); //! writeln!( //! serial_tx, diff --git a/esp-hal/src/uart.rs b/esp-hal/src/uart.rs index e2a1eb848..1f1cb7983 100644 --- a/esp-hal/src/uart.rs +++ b/esp-hal/src/uart.rs @@ -21,14 +21,12 @@ //! ```rust, no_run #![doc = crate::before_snippet!()] //! # use core::option::Option::Some; -//! # use esp_hal::uart::{config::Config, TxRxPins, Uart}; +//! # use esp_hal::uart::{config::Config, Uart}; //! use esp_hal::gpio::Io; //! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); -//! let pins = TxRxPins::new_tx_rx(io.pins.gpio1, io.pins.gpio2); //! -//! let mut uart1 = -//! Uart::new_with_config(peripherals.UART1, Config::default(), Some(pins), -//! &clocks, None); +//! let mut uart1 = Uart::new(peripherals.UART1, &clocks, io.pins.gpio1, +//! io.pins.gpio2).unwrap(); //! # } //! ``` //! @@ -49,17 +47,17 @@ //! #### Sending and Receiving Data //! ```rust, no_run #![doc = crate::before_snippet!()] -//! # use esp_hal::uart::{config::Config, TxRxPins, Uart}; +//! # use esp_hal::uart::{config::Config, Uart}; //! use esp_hal::gpio::Io; //! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); -//! # let pins = TxRxPins::new_tx_rx(io.pins.gpio1, io.pins.gpio2); //! # let mut uart1 = Uart::new_with_config( //! # peripherals.UART1, //! # Config::default(), -//! # Some(pins), //! # &clocks, //! # None, -//! # ); +//! # io.pins.gpio1, +//! # io.pins.gpio2, +//! # ).unwrap(); //! // Write bytes out over the UART: //! uart1.write_bytes("Hello, world!".as_bytes()).expect("write error!"); //! # } @@ -68,17 +66,17 @@ //! #### Splitting the UART into TX and RX Components //! ```rust, no_run #![doc = crate::before_snippet!()] -//! # use esp_hal::uart::{config::Config, TxRxPins, Uart}; +//! # use esp_hal::uart::{config::Config, Uart}; //! use esp_hal::gpio::Io; //! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); -//! # let pins = TxRxPins::new_tx_rx(io.pins.gpio1, io.pins.gpio2); //! # let mut uart1 = Uart::new_with_config( //! # peripherals.UART1, //! # Config::default(), -//! # Some(pins), //! # &clocks, //! # None, -//! # ); +//! # io.pins.gpio1, +//! # io.pins.gpio2, +//! # ).unwrap(); //! // The UART can be split into separate Transmit and Receive components: //! let (mut tx, mut rx) = uart1.split(); //! @@ -98,13 +96,14 @@ use core::marker::PhantomData; use self::config::Config; use crate::{ clock::Clocks, - gpio::{InputPin, InputSignal, NoPinType, OutputPin, OutputSignal}, + gpio::{InputPin, InputSignal, OutputPin, OutputSignal}, interrupt::InterruptHandler, - peripheral::{Peripheral, PeripheralRef}, + peripheral::Peripheral, peripherals::{ uart0::{fifo::FIFO_SPEC, RegisterBlock}, Interrupt, }, + private::Internal, system::PeripheralClockControl, Blocking, Mode, @@ -118,6 +117,68 @@ use crate::soc::constants::RC_FAST_CLK; #[cfg(any(esp32, esp32s2))] use crate::soc::constants::REF_TICK; +// Default TX and RX pins for Uart/Serial communication (UART0) +cfg_if::cfg_if! { + if #[cfg(esp32)] { + pub type DefaultTxPin = crate::gpio::Gpio1; + pub type DefaultRxPin = crate::gpio::Gpio3; + } else if #[cfg(esp32c2)] { + pub type DefaultTxPin = crate::gpio::Gpio20; + pub type DefaultRxPin = crate::gpio::Gpio19; + } else if #[cfg(esp32c3)] { + pub type DefaultTxPin = crate::gpio::Gpio21; + pub type DefaultRxPin = crate::gpio::Gpio20; + }else if #[cfg(esp32c6)] { + pub type DefaultTxPin = crate::gpio::Gpio16; + pub type DefaultRxPin = crate::gpio::Gpio17; + }else if #[cfg(esp32h2)] { + pub type DefaultTxPin = crate::gpio::Gpio24; + pub type DefaultRxPin = crate::gpio::Gpio23; + } else if #[cfg(esp32s2)] { + pub type DefaultTxPin = crate::gpio::Gpio43; + pub type DefaultRxPin = crate::gpio::Gpio44; + } else if #[cfg(esp32s3)] { + pub type DefaultTxPin = crate::gpio::Gpio43; + pub type DefaultRxPin = crate::gpio::Gpio44; + } +} + +/// Returns the default TX and RX pins for Uart/Serial communication (UART0) +#[macro_export] +macro_rules! default_uart0_pins { + ($io:expr) => {{ + let io = $io; + #[cfg(feature = "esp32")] + { + (io.pins.gpio1, io.pins.gpio3) + } + #[cfg(feature = "esp32c2")] + { + (io.pins.gpio20, io.pins.gpio19) + } + #[cfg(feature = "esp32c3")] + { + (io.pins.gpio21, io.pins.gpio20) + } + #[cfg(feature = "esp32c6")] + { + (io.pins.gpio16, io.pins.gpio17) + } + #[cfg(feature = "esp32h2")] + { + (io.pins.gpio24, io.pins.gpio23) + } + #[cfg(feature = "esp32s2")] + { + (io.pins.gpio43, io.pins.gpio44) + } + #[cfg(feature = "esp32s3")] + { + (io.pins.gpio43, io.pins.gpio44) + } + }}; +} + /// UART Error #[derive(Debug, Clone, Copy, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -171,6 +232,12 @@ pub enum ClockSource { /// UART Configuration pub mod config { + + // see + const UART_FULL_THRESH_DEFAULT: u16 = 120; + // see + const UART_TOUT_THRESH_DEFAULT: u8 = 10; + /// Number of data bits #[derive(PartialEq, Eq, Copy, Clone, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -211,6 +278,8 @@ pub mod config { pub parity: Parity, pub stop_bits: StopBits, pub clock_source: super::ClockSource, + pub rx_fifo_full_threshold: u16, + pub rx_timeout: u8, } impl Config { @@ -267,6 +336,16 @@ pub mod config { }; length } + + pub fn rx_fifo_full_threshold(mut self, threshold: u16) -> Self { + self.rx_fifo_full_threshold = threshold; + self + } + + pub fn rx_timeout(mut self, timeout: u8) -> Self { + self.rx_timeout = timeout; + self + } } impl Default for Config { @@ -280,6 +359,8 @@ pub mod config { clock_source: super::ClockSource::Xtal, #[cfg(not(any(esp32c6, esp32h2, lp_uart)))] clock_source: super::ClockSource::Apb, + rx_fifo_full_threshold: UART_FULL_THRESH_DEFAULT, + rx_timeout: UART_TOUT_THRESH_DEFAULT, } } } @@ -312,118 +393,8 @@ pub mod config { } } -/// Pins used by the UART interface -pub trait UartPins { - fn configure_pins( - &mut self, - tx_signal: OutputSignal, - rx_signal: InputSignal, - cts_signal: InputSignal, - rts_signal: OutputSignal, - ); -} - -/// All UART pins (TX, RX, CTS, RTS) -pub struct AllPins<'d, TX: OutputPin, RX: InputPin, CTS: InputPin, RTS: OutputPin> { - pub(crate) tx: Option>, - pub(crate) rx: Option>, - pub(crate) cts: Option>, - pub(crate) rts: Option>, -} - -impl<'d, TX: OutputPin, RX: InputPin, CTS: InputPin, RTS: OutputPin> AllPins<'d, TX, RX, CTS, RTS> { - pub fn new( - tx: impl Peripheral

+ 'd, - rx: impl Peripheral

+ 'd, - cts: impl Peripheral

+ 'd, - rts: impl Peripheral

+ 'd, - ) -> AllPins<'d, TX, RX, CTS, RTS> { - crate::into_ref!(tx, rx, cts, rts); - AllPins { - tx: Some(tx), - rx: Some(rx), - cts: Some(cts), - rts: Some(rts), - } - } -} - -impl UartPins - for AllPins<'_, TX, RX, CTS, RTS> -{ - fn configure_pins( - &mut self, - tx_signal: OutputSignal, - rx_signal: InputSignal, - cts_signal: InputSignal, - rts_signal: OutputSignal, - ) { - if let Some(ref mut tx) = self.tx { - tx.set_to_push_pull_output(crate::private::Internal); - tx.connect_peripheral_to_output(tx_signal, crate::private::Internal); - } - - if let Some(ref mut rx) = self.rx { - rx.set_to_input(crate::private::Internal); - rx.connect_input_to_peripheral(rx_signal, crate::private::Internal); - } - - if let Some(ref mut cts) = self.cts { - cts.set_to_input(crate::private::Internal); - cts.connect_input_to_peripheral(cts_signal, crate::private::Internal); - } - - if let Some(ref mut rts) = self.rts { - rts.set_to_push_pull_output(crate::private::Internal); - rts.connect_peripheral_to_output(rts_signal, crate::private::Internal); - } - } -} - -/// TX and RX pins -pub struct TxRxPins<'d, TX: OutputPin, RX: InputPin> { - pub tx: Option>, - pub rx: Option>, -} - -impl<'d, TX: OutputPin, RX: InputPin> TxRxPins<'d, TX, RX> { - pub fn new_tx_rx( - tx: impl Peripheral

+ 'd, - rx: impl Peripheral

+ 'd, - ) -> TxRxPins<'d, TX, RX> { - crate::into_ref!(tx, rx); - TxRxPins { - tx: Some(tx), - rx: Some(rx), - } - } -} - -impl UartPins for TxRxPins<'_, TX, RX> { - fn configure_pins( - &mut self, - tx_signal: OutputSignal, - rx_signal: InputSignal, - _cts_signal: InputSignal, - _rts_signal: OutputSignal, - ) { - if let Some(ref mut tx) = self.tx { - tx.set_to_push_pull_output(crate::private::Internal); - tx.set_output_high(true, crate::private::Internal); - tx.connect_peripheral_to_output(tx_signal, crate::private::Internal); - } - - if let Some(ref mut rx) = self.rx { - rx.set_to_input(crate::private::Internal); - rx.connect_input_to_peripheral(rx_signal, crate::private::Internal); - } - } -} - /// UART (Full-duplex) pub struct Uart<'d, T, M> { - #[cfg(not(esp32))] - symbol_len: u8, tx: UartTx<'d, T, M>, rx: UartRx<'d, T, M>, } @@ -438,6 +409,8 @@ pub struct UartRx<'d, T, M> { phantom: PhantomData<(&'d mut T, M)>, at_cmd_config: Option, rx_timeout_config: Option, + #[cfg(not(esp32))] + symbol_len: u8, } impl<'d, T, M> UartTx<'d, T, M> @@ -451,6 +424,15 @@ where } } + /// Configure RTS pin + pub fn with_rts(self, rts: impl Peripheral

+ 'd) -> Self { + crate::into_ref!(rts); + rts.set_to_push_pull_output(Internal); + rts.connect_peripheral_to_output(T::rts_signal(), Internal); + + self + } + /// Writes bytes pub fn write_bytes(&mut self, data: &[u8]) -> Result { let count = data.len(); @@ -473,7 +455,8 @@ where } } - fn flush_tx(&self) -> nb::Result<(), Error> { + /// Flush the transmit buffer of the UART + pub fn flush_tx(&mut self) -> nb::Result<(), Error> { if T::is_tx_idle() { Ok(()) } else { @@ -482,19 +465,65 @@ where } } +impl<'d, T> UartTx<'d, T, Blocking> +where + T: Instance + 'd, +{ + /// Create a new UART TX instance in [`Blocking`] mode. + pub fn new( + uart: impl Peripheral

+ 'd, + clocks: &Clocks, + interrupt: Option, + tx: impl Peripheral

+ 'd, + ) -> Result { + Self::new_with_config(uart, Default::default(), clocks, interrupt, tx) + } + + /// Create a new UART TX instance with configuration options in + /// [`Blocking`] mode. + pub fn new_with_config( + uart: impl Peripheral

+ 'd, + config: Config, + clocks: &Clocks, + interrupt: Option, + tx: impl Peripheral

+ 'd, + ) -> Result { + crate::into_ref!(tx); + tx.set_to_push_pull_output(Internal); + tx.connect_peripheral_to_output(T::tx_signal(), Internal); + + let (uart_tx, _) = + Uart::<'d, T, Blocking>::new_with_config_inner(uart, config, clocks, interrupt)? + .split(); + + Ok(uart_tx) + } +} + impl<'d, T, M> UartRx<'d, T, M> where T: Instance, M: Mode, { - fn new_inner() -> Self { + fn new_inner(#[cfg(not(esp32))] symbol_len: u8) -> Self { Self { phantom: PhantomData, at_cmd_config: None, rx_timeout_config: None, + #[cfg(not(esp32))] + symbol_len, } } + /// Configure CTS pin + pub fn with_cts(self, cts: impl Peripheral

+ 'd) -> Self { + crate::into_ref!(cts); + cts.set_to_input(Internal); + cts.connect_input_to_peripheral(T::cts_signal(), Internal); + + self + } + /// Read a byte from the UART pub fn read_byte(&mut self) -> nb::Result { // On the ESP32-S2 we need to use PeriBus2 to read the FIFO: @@ -531,6 +560,131 @@ where } count } + + /// Configures the RX-FIFO threshold + /// + /// # Errors + /// `Err(Error::InvalidArgument)` if provided value exceeds maximum value + /// for SOC : + /// - `esp32` **0x7F** + /// - `esp32c6`, `esp32h2` **0xFF** + /// - `esp32c3`, `esp32c2`, `esp32s2` **0x1FF** + /// - `esp32s3` **0x3FF** + fn set_rx_fifo_full_threshold(&mut self, threshold: u16) -> Result<(), Error> { + #[cfg(esp32)] + const MAX_THRHD: u16 = 0x7F; + #[cfg(any(esp32c6, esp32h2))] + const MAX_THRHD: u16 = 0xFF; + #[cfg(any(esp32c3, esp32c2, esp32s2))] + const MAX_THRHD: u16 = 0x1FF; + #[cfg(esp32s3)] + const MAX_THRHD: u16 = 0x3FF; + + if threshold > MAX_THRHD { + return Err(Error::InvalidArgument); + } + + #[cfg(any(esp32, esp32c6, esp32h2))] + let threshold: u8 = threshold as u8; + + T::register_block() + .conf1() + .modify(|_, w| unsafe { w.rxfifo_full_thrhd().bits(threshold) }); + + Ok(()) + } + + /// Configures the Receive Timeout detection setting + /// + /// # Arguments + /// `timeout` - the number of symbols ("bytes") to wait for before + /// triggering a timeout. Pass None to disable the timeout. + /// + /// # Errors + /// `Err(Error::InvalidArgument)` if the provided value exceeds the maximum + /// value for SOC : + /// - `esp32`: Symbol size is fixed to 8, do not pass a value > **0x7F**. + /// - `esp32c2`, `esp32c3`, `esp32c6`, `esp32h2`, esp32s2`, esp32s3`: The + /// value you pass times the symbol size must be <= **0x3FF** + fn set_rx_timeout(&mut self, timeout: Option) -> Result<(), Error> { + #[cfg(esp32)] + const MAX_THRHD: u8 = 0x7F; // 7 bits + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s2, esp32s3))] + const MAX_THRHD: u16 = 0x3FF; // 10 bits + + #[cfg(esp32)] + let reg_thrhd = &T::register_block().conf1(); + #[cfg(any(esp32c6, esp32h2))] + let reg_thrhd = &T::register_block().tout_conf(); + #[cfg(any(esp32c2, esp32c3, esp32s2, esp32s3))] + let reg_thrhd = &T::register_block().mem_conf(); + + #[cfg(any(esp32c6, esp32h2))] + let reg_en = &T::register_block().tout_conf(); + #[cfg(any(esp32, esp32c2, esp32c3, esp32s2, esp32s3))] + let reg_en = &T::register_block().conf1(); + + match timeout { + None => { + reg_en.modify(|_, w| w.rx_tout_en().clear_bit()); + } + Some(timeout) => { + // the esp32 counts directly in number of symbols (symbol len fixed to 8) + #[cfg(esp32)] + let timeout_reg = timeout; + // all other count in bits, so we need to multiply by the symbol len. + #[cfg(not(esp32))] + let timeout_reg = timeout as u16 * self.symbol_len as u16; + + if timeout_reg > MAX_THRHD { + return Err(Error::InvalidArgument); + } + + reg_thrhd.modify(|_, w| unsafe { w.rx_tout_thrhd().bits(timeout_reg) }); + reg_en.modify(|_, w| w.rx_tout_en().set_bit()); + } + } + + self.rx_timeout_config = timeout; + + Uart::<'d, T, M>::sync_regs(); + Ok(()) + } +} + +impl<'d, T> UartRx<'d, T, Blocking> +where + T: Instance + 'd, +{ + /// Create a new UART RX instance in [`Blocking`] mode. + pub fn new( + uart: impl Peripheral

+ 'd, + clocks: &Clocks, + interrupt: Option, + rx: impl Peripheral

+ 'd, + ) -> Result { + Self::new_with_config(uart, Default::default(), clocks, interrupt, rx) + } + + /// Create a new UART RX instance with configuration options in + /// [`Blocking`] mode. + pub fn new_with_config( + uart: impl Peripheral

+ 'd, + config: Config, + clocks: &Clocks, + interrupt: Option, + rx: impl Peripheral

+ 'd, + ) -> Result { + crate::into_ref!(rx); + rx.set_to_input(Internal); + rx.connect_input_to_peripheral(T::rx_signal(), Internal); + + let (_, uart_rx) = + Uart::<'d, T, Blocking>::new_with_config_inner(uart, config, clocks, interrupt)? + .split(); + + Ok(uart_rx) + } } impl<'d, T> Uart<'d, T, Blocking> @@ -539,21 +693,54 @@ where { /// Create a new UART instance with configuration options in [`Blocking`] /// mode. - pub fn new_with_config

( + pub fn new_with_config( uart: impl Peripheral

+ 'd, config: Config, - pins: Option

, clocks: &Clocks, interrupt: Option, - ) -> Self - where - P: UartPins, - { - Self::new_with_config_inner(uart, config, pins, clocks, interrupt) + tx: impl Peripheral

+ 'd, + rx: impl Peripheral

+ 'd, + ) -> Result { + crate::into_ref!(tx); + crate::into_ref!(rx); + tx.set_to_push_pull_output(Internal); + tx.connect_peripheral_to_output(T::tx_signal(), Internal); + + rx.set_to_input(Internal); + rx.connect_input_to_peripheral(T::rx_signal(), Internal); + Self::new_with_config_inner(uart, config, clocks, interrupt) } /// Create a new UART instance with defaults in [`Blocking`] mode. - pub fn new(uart: impl Peripheral

+ 'd, clocks: &Clocks) -> Self { + pub fn new( + uart: impl Peripheral

+ 'd, + clocks: &Clocks, + tx: impl Peripheral

+ 'd, + rx: impl Peripheral

+ 'd, + ) -> Result { + crate::into_ref!(tx); + crate::into_ref!(rx); + tx.set_to_push_pull_output(Internal); + tx.connect_peripheral_to_output(T::tx_signal(), Internal); + + rx.set_to_input(Internal); + rx.connect_input_to_peripheral(T::rx_signal(), Internal); + Self::new_inner(uart, clocks) + } + + /// Create a new UART instance with defaults in [`Blocking`] mode. + /// Verify that the default pins (DefaultTxPin and DefaultRxPin) are used. + pub fn new_with_default_pins( + uart: impl Peripheral

+ 'd, + clocks: &Clocks, + tx: &mut DefaultTxPin, + rx: &mut DefaultRxPin, + ) -> Result { + tx.set_to_push_pull_output(Internal); + tx.connect_peripheral_to_output(T::tx_signal(), Internal); + + rx.set_to_input(Internal); + rx.connect_input_to_peripheral(T::rx_signal(), Internal); Self::new_inner(uart, clocks) } } @@ -563,34 +750,26 @@ where T: Instance + 'd, M: Mode, { - fn new_with_config_inner

( + pub(crate) fn new_with_config_inner( _uart: impl Peripheral

+ 'd, config: Config, - mut pins: Option

, clocks: &Clocks, interrupt: Option, - ) -> Self - where - P: UartPins, - { + ) -> Result { Self::init(); - if let Some(ref mut pins) = pins { - pins.configure_pins( - T::tx_signal(), - T::rx_signal(), - T::cts_signal(), - T::rts_signal(), - ); - } - let mut serial = Uart { tx: UartTx::new_inner(), - rx: UartRx::new_inner(), - #[cfg(not(esp32))] - symbol_len: config.symbol_length(), + rx: UartRx::new_inner( + #[cfg(not(esp32))] + config.symbol_length(), + ), }; + serial + .rx + .set_rx_fifo_full_threshold(config.rx_fifo_full_threshold)?; + serial.rx.set_rx_timeout(Some(config.rx_timeout))?; serial.change_baud_internal(config.baudrate, config.clock_source, clocks); serial.change_data_bits(config.data_bits); serial.change_parity(config.parity); @@ -620,17 +799,29 @@ where .int_clr() .write(|w| unsafe { w.bits(u32::MAX) }); - serial + Ok(serial) } - fn new_inner(uart: impl Peripheral

+ 'd, clocks: &Clocks) -> Self { - Self::new_with_config_inner( - uart, - Default::default(), - None::>, - clocks, - None, - ) + fn new_inner(uart: impl Peripheral

+ 'd, clocks: &Clocks) -> Result { + Self::new_with_config_inner(uart, Default::default(), clocks, None) + } + + /// Configure CTS pin + pub fn with_cts(self, cts: impl Peripheral

+ 'd) -> Self { + crate::into_ref!(cts); + cts.set_to_input(Internal); + cts.connect_input_to_peripheral(T::cts_signal(), Internal); + + self + } + + /// Configure RTS pin + pub fn with_rts(self, rts: impl Peripheral

+ 'd) -> Self { + crate::into_ref!(rts); + rts.set_to_push_pull_output(Internal); + rts.connect_peripheral_to_output(T::rts_signal(), Internal); + + self } /// Split the UART into a transmitter and receiver @@ -684,100 +875,10 @@ where .clk_conf() .modify(|_, w| w.sclk_en().set_bit()); - self.sync_regs(); + Self::sync_regs(); self.rx.at_cmd_config = Some(config); } - /// Configures the Receive Timeout detection setting - /// - /// # Arguments - /// `timeout` - the number of symbols ("bytes") to wait for before - /// triggering a timeout. Pass None to disable the timeout. - /// - /// # Errors - /// `Err(Error::InvalidArgument)` if the provided value exceeds the maximum - /// value for SOC : - /// - `esp32`: Symbol size is fixed to 8, do not pass a value > **0x7F**. - /// - `esp32c2`, `esp32c3`, `esp32c6`, `esp32h2`, esp32s2`, esp32s3`: The - /// value you pass times the symbol size must be <= **0x3FF** - pub fn set_rx_timeout(&mut self, timeout: Option) -> Result<(), Error> { - #[cfg(esp32)] - const MAX_THRHD: u8 = 0x7F; // 7 bits - #[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s2, esp32s3))] - const MAX_THRHD: u16 = 0x3FF; // 10 bits - - #[cfg(esp32)] - let reg_thrhd = &T::register_block().conf1(); - #[cfg(any(esp32c6, esp32h2))] - let reg_thrhd = &T::register_block().tout_conf(); - #[cfg(any(esp32c2, esp32c3, esp32s2, esp32s3))] - let reg_thrhd = &T::register_block().mem_conf(); - - #[cfg(any(esp32c6, esp32h2))] - let reg_en = &T::register_block().tout_conf(); - #[cfg(any(esp32, esp32c2, esp32c3, esp32s2, esp32s3))] - let reg_en = &T::register_block().conf1(); - - match timeout { - None => { - reg_en.modify(|_, w| w.rx_tout_en().clear_bit()); - } - Some(timeout) => { - // the esp32 counts directly in number of symbols (symbol len fixed to 8) - #[cfg(esp32)] - let timeout_reg = timeout; - // all other count in bits, so we need to multiply by the symbol len. - #[cfg(not(esp32))] - let timeout_reg = timeout as u16 * self.symbol_len as u16; - - if timeout_reg > MAX_THRHD { - return Err(Error::InvalidArgument); - } - - reg_thrhd.modify(|_, w| unsafe { w.rx_tout_thrhd().bits(timeout_reg) }); - reg_en.modify(|_, w| w.rx_tout_en().set_bit()); - } - } - - self.rx.rx_timeout_config = timeout; - - self.sync_regs(); - Ok(()) - } - - /// Configures the RX-FIFO threshold - /// - /// # Errors - /// `Err(Error::InvalidArgument)` if provided value exceeds maximum value - /// for SOC : - /// - `esp32` **0x7F** - /// - `esp32c6`, `esp32h2` **0xFF** - /// - `esp32c3`, `esp32c2`, `esp32s2` **0x1FF** - /// - `esp32s3` **0x3FF** - pub fn set_rx_fifo_full_threshold(&mut self, threshold: u16) -> Result<(), Error> { - #[cfg(esp32)] - const MAX_THRHD: u16 = 0x7F; - #[cfg(any(esp32c6, esp32h2))] - const MAX_THRHD: u16 = 0xFF; - #[cfg(any(esp32c3, esp32c2, esp32s2))] - const MAX_THRHD: u16 = 0x1FF; - #[cfg(esp32s3)] - const MAX_THRHD: u16 = 0x3FF; - - if threshold > MAX_THRHD { - return Err(Error::InvalidArgument); - } - - #[cfg(any(esp32, esp32c6, esp32h2))] - let threshold: u8 = threshold as u8; - - T::register_block() - .conf1() - .modify(|_, w| unsafe { w.rxfifo_full_thrhd().bits(threshold) }); - - Ok(()) - } - /// Listen for AT-CMD interrupts pub fn listen_at_cmd(&mut self) { T::register_block() @@ -870,7 +971,7 @@ where } /// Flush the transmit buffer of the UART - pub fn flush_tx(&self) -> nb::Result<(), Error> { + pub fn flush_tx(&mut self) -> nb::Result<(), Error> { self.tx.flush_tx() } @@ -1032,7 +1133,7 @@ where .clkdiv() .write(|w| unsafe { w.clkdiv().bits(divider).frag().bits(0) }); - self.sync_regs(); + Self::sync_regs(); } #[cfg(any(esp32, esp32s2))] @@ -1134,7 +1235,7 @@ where #[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))] // TODO introduce a cfg symbol for this #[inline(always)] - fn sync_regs(&self) { + fn sync_regs() { #[cfg(any(esp32c6, esp32h2))] let update_reg = T::register_block().reg_update(); @@ -1150,30 +1251,30 @@ where #[cfg(not(any(esp32c3, esp32c6, esp32h2, esp32s3)))] #[inline(always)] - fn sync_regs(&mut self) {} + fn sync_regs() {} fn rxfifo_reset(&mut self) { T::register_block() .conf0() .modify(|_, w| w.rxfifo_rst().set_bit()); - self.sync_regs(); + Self::sync_regs(); T::register_block() .conf0() .modify(|_, w| w.rxfifo_rst().clear_bit()); - self.sync_regs(); + Self::sync_regs(); } fn txfifo_reset(&mut self) { T::register_block() .conf0() .modify(|_, w| w.txfifo_rst().set_bit()); - self.sync_regs(); + Self::sync_regs(); T::register_block() .conf0() .modify(|_, w| w.txfifo_rst().clear_bit()); - self.sync_regs(); + Self::sync_regs(); } } @@ -1854,19 +1955,23 @@ mod asynch { { /// Create a new UART instance with configuration options in [`Async`] /// mode. - pub fn new_async_with_config

( + pub fn new_async_with_config( uart: impl Peripheral

+ 'd, config: Config, - pins: Option

, clocks: &Clocks, - ) -> Self - where - P: UartPins, - { + tx: impl Peripheral

+ 'd, + rx: impl Peripheral

+ 'd, + ) -> Result { + crate::into_ref!(tx); + crate::into_ref!(rx); + tx.set_to_push_pull_output(Internal); + tx.connect_peripheral_to_output(T::tx_signal(), Internal); + + rx.set_to_input(Internal); + rx.connect_input_to_peripheral(T::rx_signal(), Internal); Self::new_with_config_inner( uart, config, - pins, clocks, Some(match T::uart_number() { #[cfg(uart0)] @@ -1881,13 +1986,23 @@ mod asynch { } /// Create a new UART instance with defaults in [`Async`] mode. - pub fn new_async(uart: impl Peripheral

+ 'd, clocks: &Clocks) -> Self { - Self::new_async_with_config( - uart, - Default::default(), - None::>, - clocks, - ) + pub fn new_async( + uart: impl Peripheral

+ 'd, + clocks: &Clocks, + tx: impl Peripheral

+ 'd, + rx: impl Peripheral

+ 'd, + ) -> Result { + Self::new_async_with_config(uart, Default::default(), clocks, tx, rx) + } + + /// Create a new UART instance with defaults in [`Async`] mode. + pub fn new_async_with_default_pins( + uart: impl Peripheral

+ 'd, + clocks: &Clocks, + tx: DefaultTxPin, + rx: DefaultRxPin, + ) -> Result { + Self::new_async_with_config(uart, Default::default(), clocks, tx, rx) } } @@ -1909,10 +2024,50 @@ mod asynch { } } - impl UartTx<'_, T, Async> + impl<'d, T> UartTx<'d, T, Async> where - T: Instance, + T: Instance + 'd, { + /// Create a new UART TX instance in [`Async`] mode. + pub fn new_async( + uart: impl Peripheral

+ 'd, + clocks: &Clocks, + tx: impl Peripheral

+ 'd, + ) -> Result { + Self::new_async_with_config(uart, Default::default(), clocks, tx) + } + + /// Create a new UART TX instance with configuration options in + /// [`Async`] mode. + pub fn new_async_with_config( + uart: impl Peripheral

+ 'd, + config: Config, + clocks: &Clocks, + tx: impl Peripheral

+ 'd, + ) -> Result { + crate::into_ref!(tx); + tx.set_to_push_pull_output(Internal); + tx.connect_peripheral_to_output(T::tx_signal(), Internal); + + let (uart_tx, _) = Uart::<'d, T, Async>::new_with_config_inner( + uart, + config, + clocks, + Some(match T::uart_number() { + #[cfg(uart0)] + 0 => uart0, + #[cfg(uart1)] + 1 => uart1, + #[cfg(uart2)] + 2 => uart2, + _ => unreachable!(), + }), + )? + .split(); + + Ok(uart_tx) + } + pub async fn write_async(&mut self, words: &[u8]) -> Result { let mut count = 0; let mut offset: usize = 0; @@ -1948,10 +2103,50 @@ mod asynch { } } - impl UartRx<'_, T, Async> + impl<'d, T> UartRx<'d, T, Async> where - T: Instance, + T: Instance + 'd, { + /// Create a new UART RX instance in [`Async`] mode. + pub fn new_async( + uart: impl Peripheral

+ 'd, + clocks: &Clocks, + rx: impl Peripheral

+ 'd, + ) -> Result { + Self::new_async_with_config(uart, Default::default(), clocks, rx) + } + + /// Create a new UART RX instance with configuration options in + /// [`Async`] mode. + pub fn new_async_with_config( + uart: impl Peripheral

+ 'd, + config: Config, + clocks: &Clocks, + rx: impl Peripheral

+ 'd, + ) -> Result { + crate::into_ref!(rx); + rx.set_to_input(Internal); + rx.connect_input_to_peripheral(T::rx_signal(), Internal); + + let (_, uart_rx) = Uart::<'d, T, Async>::new_with_config_inner( + uart, + config, + clocks, + Some(match T::uart_number() { + #[cfg(uart0)] + 0 => uart0, + #[cfg(uart1)] + 1 => uart1, + #[cfg(uart2)] + 2 => uart2, + _ => unreachable!(), + }), + )? + .split(); + + Ok(uart_rx) + } + /// Read async to buffer slice `buf`. /// Waits until at least one byte is in the Rx FiFo /// and one of the following interrupts occurs: diff --git a/examples/src/bin/advanced_serial.rs b/examples/src/bin/advanced_serial.rs index 98afe1197..12b4d4551 100644 --- a/examples/src/bin/advanced_serial.rs +++ b/examples/src/bin/advanced_serial.rs @@ -20,7 +20,7 @@ use esp_hal::{ peripherals::Peripherals, prelude::*, system::SystemControl, - uart::{config::Config, TxRxPins, Uart}, + uart::Uart, }; use esp_println::println; use nb::block; @@ -32,15 +32,8 @@ fn main() -> ! { let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let pins = TxRxPins::new_tx_rx(io.pins.gpio4, io.pins.gpio5); - let mut serial1 = Uart::new_with_config( - peripherals.UART1, - Config::default(), - Some(pins), - &clocks, - None, - ); + let mut serial1 = Uart::new(peripherals.UART1, &clocks, io.pins.gpio4, io.pins.gpio5).unwrap(); let delay = Delay::new(&clocks); diff --git a/examples/src/bin/embassy_serial.rs b/examples/src/bin/embassy_serial.rs index 7ce64ac11..9aa7b1c1e 100644 --- a/examples/src/bin/embassy_serial.rs +++ b/examples/src/bin/embassy_serial.rs @@ -14,11 +14,18 @@ use embassy_sync::{blocking_mutex::raw::NoopRawMutex, signal::Signal}; use esp_backtrace as _; use esp_hal::{ clock::ClockControl, + default_uart0_pins, + gpio::Io, peripherals::{Peripherals, UART0}, prelude::*, system::SystemControl, timer::timg::TimerGroup, - uart::{config::AtCmdConfig, Uart, UartRx, UartTx}, + uart::{ + config::{AtCmdConfig, Config}, + Uart, + UartRx, + UartTx, + }, Async, }; use static_cell::StaticCell; @@ -82,11 +89,18 @@ async fn main(spawner: Spawner) { let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); esp_hal_embassy::init(&clocks, timg0); - let mut uart0 = Uart::new_async(peripherals.UART0, &clocks); + let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); + + // Default pins for Uart/Serial communication + let (tx_pin, rx_pin) = default_uart0_pins!(io); + + let config = Config::default(); + config.rx_fifo_full_threshold(READ_BUF_SIZE as u16); + + let mut uart0 = + Uart::new_async_with_config(peripherals.UART0, config, &clocks, tx_pin, rx_pin).unwrap(); uart0.set_at_cmd(AtCmdConfig::new(None, None, None, AT_CMD, None)); - uart0 - .set_rx_fifo_full_threshold(READ_BUF_SIZE as u16) - .unwrap(); + let (tx, rx) = uart0.split(); static SIGNAL: StaticCell> = StaticCell::new(); diff --git a/examples/src/bin/hello_world.rs b/examples/src/bin/hello_world.rs index a7e5653de..d61338998 100644 --- a/examples/src/bin/hello_world.rs +++ b/examples/src/bin/hello_world.rs @@ -17,7 +17,9 @@ use core::fmt::Write; use esp_backtrace as _; use esp_hal::{ clock::ClockControl, + default_uart0_pins, delay::Delay, + gpio::Io, peripherals::Peripherals, prelude::*, system::SystemControl, @@ -32,7 +34,13 @@ fn main() -> ! { let delay = Delay::new(&clocks); - let mut uart0 = Uart::new(peripherals.UART0, &clocks); + let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); + + // Default pins for Uart/Serial communication + let (mut tx_pin, mut rx_pin) = default_uart0_pins!(io); + + let mut uart0 = + Uart::new_with_default_pins(peripherals.UART0, &clocks, &mut tx_pin, &mut rx_pin).unwrap(); loop { writeln!(uart0, "Hello world!").unwrap(); diff --git a/examples/src/bin/ieee802154_sniffer.rs b/examples/src/bin/ieee802154_sniffer.rs index d23174111..8f8179b59 100644 --- a/examples/src/bin/ieee802154_sniffer.rs +++ b/examples/src/bin/ieee802154_sniffer.rs @@ -10,6 +10,8 @@ use esp_backtrace as _; use esp_hal::{ clock::ClockControl, + default_uart0_pins, + gpio::Io, peripherals::Peripherals, prelude::*, reset::software_reset, @@ -25,7 +27,13 @@ fn main() -> ! { let system = SystemControl::new(peripherals.SYSTEM); let clocks = ClockControl::max(system.clock_control).freeze(); - let mut uart0 = Uart::new(peripherals.UART0, &clocks); + let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); + + // Default pins for Uart/Serial communication + let (mut tx_pin, mut rx_pin) = default_uart0_pins!(io); + + let mut uart0 = + Uart::new_with_default_pins(peripherals.UART0, &clocks, &mut tx_pin, &mut rx_pin).unwrap(); // read two characters which get parsed as the channel let mut cnt = 0; diff --git a/examples/src/bin/lp_core_uart.rs b/examples/src/bin/lp_core_uart.rs index b9d0823f3..bdd1df4f1 100644 --- a/examples/src/bin/lp_core_uart.rs +++ b/examples/src/bin/lp_core_uart.rs @@ -21,7 +21,7 @@ use esp_hal::{ peripherals::Peripherals, prelude::*, system::SystemControl, - uart::{config::Config, lp_uart::LpUart, TxRxPins, Uart}, + uart::{config::Config, lp_uart::LpUart, Uart}, }; use esp_println::println; @@ -35,15 +35,15 @@ fn main() -> ! { // Set up (HP) UART1: - let pins = TxRxPins::new_tx_rx(io.pins.gpio6, io.pins.gpio7); - let mut uart1 = Uart::new_with_config( peripherals.UART1, Config::default(), - Some(pins), &clocks, None, - ); + io.pins.gpio6, + io.pins.gpio7, + ) + .unwrap(); // Set up (LP) UART: let lp_tx = LowPowerOutput::new(io.pins.gpio5); diff --git a/examples/src/bin/serial_interrupts.rs b/examples/src/bin/serial_interrupts.rs index 2a6cce02a..70a947cf2 100644 --- a/examples/src/bin/serial_interrupts.rs +++ b/examples/src/bin/serial_interrupts.rs @@ -13,14 +13,14 @@ use critical_section::Mutex; use esp_backtrace as _; use esp_hal::{ clock::ClockControl, + default_uart0_pins, delay::Delay, - gpio, + gpio::Io, peripherals::{Peripherals, UART0}, prelude::*, system::SystemControl, uart::{ config::{AtCmdConfig, Config}, - TxRxPins, Uart, }, Blocking, @@ -36,17 +36,26 @@ fn main() -> ! { let delay = Delay::new(&clocks); + let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); + + // Default pins for Uart/Serial communication + let (tx_pin, rx_pin) = default_uart0_pins!(io); + + let config = Config::default(); + config.rx_fifo_full_threshold(30); + let mut uart0 = Uart::new_with_config( peripherals.UART0, - Config::default(), - None::>, + config, &clocks, Some(interrupt_handler), - ); + tx_pin, + rx_pin, + ) + .unwrap(); critical_section::with(|cs| { uart0.set_at_cmd(AtCmdConfig::new(None, None, None, b'#', None)); - uart0.set_rx_fifo_full_threshold(30).unwrap(); uart0.listen_at_cmd(); uart0.listen_rx_fifo_full(); diff --git a/hil-test/Cargo.toml b/hil-test/Cargo.toml index ad5379b47..1080d8efe 100644 --- a/hil-test/Cargo.toml +++ b/hil-test/Cargo.toml @@ -73,6 +73,16 @@ name = "uart_async" harness = false required-features = ["async", "embassy"] +[[test]] +name = "uart_tx_rx" +harness = false + + +[[test]] +name = "uart_tx_rx_async" +harness = false + + [dependencies] cfg-if = "1.0.0" critical-section = "1.1.2" diff --git a/hil-test/tests/uart.rs b/hil-test/tests/uart.rs index c5c0fdbcd..a6a56880e 100644 --- a/hil-test/tests/uart.rs +++ b/hil-test/tests/uart.rs @@ -17,17 +17,17 @@ use esp_backtrace as _; use esp_hal::{ clock::{ClockControl, Clocks}, gpio::Io, - peripherals::{Peripherals, UART0}, + peripherals::{Peripherals, UART1}, prelude::*, system::SystemControl, - uart::{config::Config, ClockSource, TxRxPins, Uart}, + uart::{ClockSource, Uart}, Blocking, }; use nb::block; struct Context { clocks: Clocks<'static>, - uart: Uart<'static, UART0, Blocking>, + uart: Uart<'static, UART1, Blocking>, } impl Context { @@ -37,15 +37,8 @@ impl Context { let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let pins = TxRxPins::new_tx_rx(io.pins.gpio2, io.pins.gpio4); - let uart = Uart::new_with_config( - peripherals.UART0, - Config::default(), - Some(pins), - &clocks, - None, - ); + let uart = Uart::new(peripherals.UART1, &clocks, io.pins.gpio2, io.pins.gpio4).unwrap(); Context { clocks, uart } } diff --git a/hil-test/tests/uart_async.rs b/hil-test/tests/uart_async.rs index 86efeda7d..5f4ea4632 100644 --- a/hil-test/tests/uart_async.rs +++ b/hil-test/tests/uart_async.rs @@ -18,13 +18,12 @@ use esp_hal::{ gpio::Io, peripherals::{Peripherals, UART0}, system::SystemControl, - uart::{config::Config, TxRxPins, Uart, UartRx, UartTx}, + uart::Uart, Async, }; struct Context { - tx: UartTx<'static, UART0, Async>, - rx: UartRx<'static, UART0, Async>, + uart: Uart<'static, UART0, Async>, } impl Context { @@ -33,13 +32,11 @@ impl Context { let system = SystemControl::new(peripherals.SYSTEM); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let pins = TxRxPins::new_tx_rx(io.pins.gpio2, io.pins.gpio4); let uart = - Uart::new_async_with_config(peripherals.UART0, Config::default(), Some(pins), &clocks); - let (tx, rx) = uart.split(); + Uart::new_async(peripherals.UART0, &clocks, io.pins.gpio2, io.pins.gpio4).unwrap(); - Context { rx, tx } + Context { uart } } } @@ -61,14 +58,11 @@ mod tests { const SEND: &[u8] = &*b"Hello ESP32"; let mut buf = [0u8; SEND.len()]; - // Drain the FIFO to clear previous message: - ctx.tx.flush_async().await.unwrap(); - while ctx.rx.drain_fifo(&mut buf[..]) > 0 {} + ctx.uart.flush_async().await.unwrap(); + ctx.uart.write_async(&SEND).await.unwrap(); + ctx.uart.flush_async().await.unwrap(); - ctx.tx.write_async(&SEND).await.unwrap(); - ctx.tx.flush_async().await.unwrap(); - - ctx.rx.read_async(&mut buf[..]).await.unwrap(); + ctx.uart.read_async(&mut buf[..]).await.unwrap(); assert_eq!(&buf[..], SEND); } } diff --git a/hil-test/tests/uart_tx_rx.rs b/hil-test/tests/uart_tx_rx.rs new file mode 100644 index 000000000..96c987e2a --- /dev/null +++ b/hil-test/tests/uart_tx_rx.rs @@ -0,0 +1,70 @@ +//! UART TX/RX Test +//! +//! Folowing pins are used: +//! TX GPIP2 +//! RX GPIO4 +//! +//! Connect TX (GPIO2) and RX (GPIO4) pins. + +//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 + +#![no_std] +#![no_main] + +use defmt_rtt as _; +use esp_backtrace as _; +use esp_hal::{ + clock::ClockControl, + gpio::Io, + peripherals::{Peripherals, UART0, UART1}, + prelude::*, + system::SystemControl, + uart::{UartRx, UartTx}, + Blocking, +}; +use nb::block; + +struct Context { + tx: UartTx<'static, UART0, Blocking>, + rx: UartRx<'static, UART1, Blocking>, +} + +impl Context { + pub fn init() -> Self { + let peripherals = Peripherals::take(); + let system = SystemControl::new(peripherals.SYSTEM); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); + + let tx = UartTx::new(peripherals.UART0, &clocks, None, io.pins.gpio2).unwrap(); + let rx = UartRx::new(peripherals.UART1, &clocks, None, io.pins.gpio4).unwrap(); + + Context { tx, rx } + } +} + +#[cfg(test)] +#[embedded_test::tests] +mod tests { + use defmt::assert_eq; + + use super::*; + + #[init] + fn init() -> Context { + Context::init() + } + + #[test] + #[timeout(3)] + fn test_send_receive(mut ctx: Context) { + let byte = [0x42]; + + ctx.tx.flush_tx().unwrap(); + ctx.tx.write_bytes(&byte).unwrap(); + let read = block!(ctx.rx.read_byte()); + + assert_eq!(read, Ok(0x42)); + } +} diff --git a/hil-test/tests/uart_tx_rx_async.rs b/hil-test/tests/uart_tx_rx_async.rs new file mode 100644 index 000000000..ec391ded4 --- /dev/null +++ b/hil-test/tests/uart_tx_rx_async.rs @@ -0,0 +1,69 @@ +//! UART TX/RX Async Test +//! +//! Folowing pins are used: +//! TX GPIP2 +//! RX GPIO4 +//! +//! Connect TX (GPIO2) and RX (GPIO4) pins. + +//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 + +#![no_std] +#![no_main] + +use defmt_rtt as _; +use esp_backtrace as _; +use esp_hal::{ + clock::ClockControl, + gpio::Io, + peripherals::{Peripherals, UART0, UART1}, + system::SystemControl, + uart::{UartRx, UartTx}, + Async, +}; + +struct Context { + tx: UartTx<'static, UART0, Async>, + rx: UartRx<'static, UART1, Async>, +} + +impl Context { + pub fn init() -> Self { + let peripherals = Peripherals::take(); + let system = SystemControl::new(peripherals.SYSTEM); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); + + let tx = UartTx::new_async(peripherals.UART0, &clocks, io.pins.gpio2).unwrap(); + let rx = UartRx::new_async(peripherals.UART1, &clocks, io.pins.gpio4).unwrap(); + + Context { tx, rx } + } +} + +#[cfg(test)] +#[embedded_test::tests(executor = esp_hal_embassy::Executor::new())] +mod tests { + use defmt::assert_eq; + + use super::*; + + #[init] + async fn init() -> Context { + Context::init() + } + + #[test] + #[timeout(3)] + async fn test_send_receive(mut ctx: Context) { + let byte = [0x42]; + let mut read = [0u8; 1]; + + ctx.tx.flush_async().await.unwrap(); + ctx.tx.write_async(&byte).await.unwrap(); + let _ = ctx.rx.read_async(&mut read).await; + + assert_eq!(read, byte); + } +}