esp_lp_hal/
uart.rs

1//! # Universal Asynchronous Receiver/Transmitter (UART)
2//!
3//! ## Overview
4//!
5//! The UART is a hardware peripheral which handles communication using serial
6//! interfaces. This peripheral provides a cheap and ubiquitous method for full-
7//! and half-duplex communication between devices.
8//!
9//! ## Configuration
10//!
11//! The usual setting such as baud rate, data bits, parity, and stop bits can
12//! easily be configured. See the [config] module documentation for more
13//! information.
14//!
15//! ## Usage
16//!
17//! The UART driver implements a number of third-party traits, with the
18//! intention of making the HAL inter-compatible with various device drivers
19//! from the community. This includes the [embedded-hal], [embedded-hal-nb], and
20//! [embedded-io] traits.
21//!
22//! ## Examples
23//!
24//! ```rust
25//! fn main(mut uart: LpUart) -> ! {
26//!     loop {
27//!         writeln!(uart, "Hello, world!").ok();
28//!         esp_lp_hal::delay::Delay.delay_ms(1000);
29//!     }
30//! }
31//! ```
32//!
33//! [embedded-hal]: https://docs.rs/embedded-hal/latest/embedded_hal/
34//! [embedded-hal-nb]: https://docs.rs/embedded-hal-nb/latest/embedded_hal_nb/
35//! [embedded-io]: https://docs.rs/embedded-io/latest/embedded_io/
36
37use crate::pac::LP_UART;
38
39const UART_FIFO_SIZE: u16 = 128;
40
41#[doc(hidden)]
42pub unsafe fn conjure() -> LpUart {
43    LpUart {
44        uart: LP_UART::steal(),
45    }
46}
47
48/// UART Error
49#[derive(Debug)]
50pub enum Error {}
51
52#[cfg(feature = "embedded-hal")]
53impl embedded_hal_nb::serial::Error for Error {
54    fn kind(&self) -> embedded_hal_nb::serial::ErrorKind {
55        embedded_hal_nb::serial::ErrorKind::Other
56    }
57}
58
59#[cfg(feature = "embedded-io")]
60impl embedded_io::Error for Error {
61    fn kind(&self) -> embedded_io::ErrorKind {
62        embedded_io::ErrorKind::Other
63    }
64}
65
66/// UART configuration
67pub mod config {
68    /// Number of data bits
69    #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
70    pub enum DataBits {
71        /// 5 data bits
72        DataBits5 = 0,
73        /// 6 data bits
74        DataBits6 = 1,
75        /// 7 data bits
76        DataBits7 = 2,
77        /// 8 data bits
78        #[default]
79        DataBits8 = 3,
80    }
81
82    /// Parity check
83    #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
84    pub enum Parity {
85        /// No parity
86        #[default]
87        ParityNone = 0,
88        /// Even parity
89        ParityEven = 1,
90        /// Odd parity
91        ParityOdd  = 2,
92    }
93
94    /// Number of stop bits
95    #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
96    pub enum StopBits {
97        /// 1 stop bit
98        #[default]
99        Stop1   = 1,
100        /// 1.5 stop bits
101        Stop1p5 = 2,
102        /// 2 stop bits
103        Stop2   = 3,
104    }
105
106    /// UART configuration
107    #[derive(Debug, Clone, Copy)]
108    pub struct Config {
109        baudrate: u32,
110        data_bits: DataBits,
111        parity: Parity,
112        stop_bits: StopBits,
113    }
114
115    impl Config {
116        /// Configure the UART's baud rate
117        pub fn baudrate(mut self, baudrate: u32) -> Self {
118            self.baudrate = baudrate;
119            self
120        }
121
122        /// Configure the UART to use no parity
123        pub fn parity_none(mut self) -> Self {
124            self.parity = Parity::ParityNone;
125            self
126        }
127
128        /// Configure the UART to use even parity
129        pub fn parity_even(mut self) -> Self {
130            self.parity = Parity::ParityEven;
131            self
132        }
133
134        /// Configure the UART to use odd parity
135        pub fn parity_odd(mut self) -> Self {
136            self.parity = Parity::ParityOdd;
137            self
138        }
139
140        /// Configure the UART's data bits
141        pub fn data_bits(mut self, data_bits: DataBits) -> Self {
142            self.data_bits = data_bits;
143            self
144        }
145
146        /// Configure the UART's stop bits
147        pub fn stop_bits(mut self, stop_bits: StopBits) -> Self {
148            self.stop_bits = stop_bits;
149            self
150        }
151    }
152
153    impl Default for Config {
154        fn default() -> Config {
155            Config {
156                baudrate: 115_200,
157                data_bits: Default::default(),
158                parity: Default::default(),
159                stop_bits: Default::default(),
160            }
161        }
162    }
163}
164
165/// LP-UART driver
166pub struct LpUart {
167    uart: LP_UART,
168}
169
170impl LpUart {
171    /// Read a single byte from the UART in a non-blocking manner.
172    pub fn read_byte(&mut self) -> nb::Result<u8, Error> {
173        if self.rx_fifo_count() > 0 {
174            let byte = self.uart.fifo().read().rxfifo_rd_byte().bits();
175            Ok(byte)
176        } else {
177            Err(nb::Error::WouldBlock)
178        }
179    }
180
181    /// Write a single byte to the UART in a non-blocking manner.
182    pub fn write_byte(&mut self, byte: u8) -> nb::Result<(), Error> {
183        if self.tx_fifo_count() < UART_FIFO_SIZE {
184            self.uart
185                .fifo()
186                .write(|w| unsafe { w.rxfifo_rd_byte().bits(byte) });
187            Ok(())
188        } else {
189            Err(nb::Error::WouldBlock)
190        }
191    }
192
193    /// Write one or more byte to the UART, blocking until the write has
194    /// completed.
195    pub fn write_bytes(&mut self, data: &[u8]) -> Result<usize, Error> {
196        let count = data.len();
197
198        data.iter()
199            .try_for_each(|c| nb::block!(self.write_byte(*c)))?;
200
201        Ok(count)
202    }
203
204    /// Flush the UART's transmit buffer in a non-blocking manner.
205    pub fn flush_tx(&mut self) -> nb::Result<(), Error> {
206        if self.is_tx_idle() {
207            Ok(())
208        } else {
209            Err(nb::Error::WouldBlock)
210        }
211    }
212
213    fn rx_fifo_count(&mut self) -> u16 {
214        self.uart.status().read().rxfifo_cnt().bits().into()
215    }
216
217    fn tx_fifo_count(&mut self) -> u16 {
218        self.uart.status().read().txfifo_cnt().bits().into()
219    }
220
221    fn is_tx_idle(&self) -> bool {
222        self.uart.fsm_status().read().st_utx_out().bits() == 0
223    }
224}
225
226impl core::fmt::Write for LpUart {
227    fn write_str(&mut self, s: &str) -> core::fmt::Result {
228        self.write_bytes(s.as_bytes())
229            .map_err(|_| core::fmt::Error)?;
230        Ok(())
231    }
232}
233
234#[cfg(feature = "embedded-hal")]
235impl embedded_hal_nb::serial::ErrorType for LpUart {
236    type Error = Error;
237}
238
239#[cfg(feature = "embedded-hal")]
240impl embedded_hal_nb::serial::Read for LpUart {
241    fn read(&mut self) -> nb::Result<u8, Self::Error> {
242        self.read_byte()
243    }
244}
245
246#[cfg(feature = "embedded-hal")]
247impl embedded_hal_nb::serial::Write for LpUart {
248    fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
249        self.write_byte(word)
250    }
251
252    fn flush(&mut self) -> nb::Result<(), Self::Error> {
253        self.flush_tx()
254    }
255}
256
257#[cfg(feature = "embedded-io")]
258impl embedded_io::ErrorType for LpUart {
259    type Error = Error;
260}
261
262#[cfg(feature = "embedded-io")]
263impl embedded_io::Read for LpUart {
264    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
265        if buf.is_empty() {
266            return Ok(0);
267        }
268
269        while self.rx_fifo_count() == 0 {
270            // Block until we have received at least one byte
271        }
272
273        let mut count = 0;
274        while self.rx_fifo_count() > 0 && count < buf.len() {
275            buf[count] = self.uart.fifo().read().rxfifo_rd_byte().bits();
276            count += 1;
277        }
278
279        Ok(count)
280    }
281}
282
283#[cfg(feature = "embedded-io")]
284impl embedded_io::ReadReady for LpUart {
285    fn read_ready(&mut self) -> Result<bool, Self::Error> {
286        Ok(self.rx_fifo_count() > 0)
287    }
288}
289
290#[cfg(feature = "embedded-io")]
291impl embedded_io::Write for LpUart {
292    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
293        self.write_bytes(buf)
294    }
295
296    fn flush(&mut self) -> Result<(), Self::Error> {
297        loop {
298            match self.flush_tx() {
299                Ok(_) => break,
300                Err(nb::Error::WouldBlock) => { /* Wait */ }
301                #[allow(unreachable_patterns)]
302                Err(nb::Error::Other(e)) => return Err(e),
303            }
304        }
305
306        Ok(())
307    }
308}