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    unsafe {
44        LpUart {
45            uart: LP_UART::steal(),
46        }
47    }
48}
49
50/// UART Error
51#[derive(Debug)]
52pub enum Error {}
53
54#[cfg(feature = "embedded-hal")]
55impl embedded_hal_nb::serial::Error for Error {
56    fn kind(&self) -> embedded_hal_nb::serial::ErrorKind {
57        embedded_hal_nb::serial::ErrorKind::Other
58    }
59}
60
61#[cfg(feature = "embedded-io")]
62impl embedded_io::Error for Error {
63    fn kind(&self) -> embedded_io::ErrorKind {
64        embedded_io::ErrorKind::Other
65    }
66}
67
68/// UART configuration
69pub mod config {
70    /// Number of data bits
71    #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
72    pub enum DataBits {
73        /// 5 data bits
74        DataBits5 = 0,
75        /// 6 data bits
76        DataBits6 = 1,
77        /// 7 data bits
78        DataBits7 = 2,
79        /// 8 data bits
80        #[default]
81        DataBits8 = 3,
82    }
83
84    /// Parity check
85    #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
86    pub enum Parity {
87        /// No parity
88        #[default]
89        ParityNone = 0,
90        /// Even parity
91        ParityEven = 1,
92        /// Odd parity
93        ParityOdd  = 2,
94    }
95
96    /// Number of stop bits
97    #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
98    pub enum StopBits {
99        /// 1 stop bit
100        #[default]
101        Stop1   = 1,
102        /// 1.5 stop bits
103        Stop1p5 = 2,
104        /// 2 stop bits
105        Stop2   = 3,
106    }
107
108    /// UART configuration
109    #[derive(Debug, Clone, Copy)]
110    pub struct Config {
111        baudrate: u32,
112        data_bits: DataBits,
113        parity: Parity,
114        stop_bits: StopBits,
115    }
116
117    impl Config {
118        /// Configure the UART's baud rate
119        pub fn baudrate(mut self, baudrate: u32) -> Self {
120            self.baudrate = baudrate;
121            self
122        }
123
124        /// Configure the UART to use no parity
125        pub fn parity_none(mut self) -> Self {
126            self.parity = Parity::ParityNone;
127            self
128        }
129
130        /// Configure the UART to use even parity
131        pub fn parity_even(mut self) -> Self {
132            self.parity = Parity::ParityEven;
133            self
134        }
135
136        /// Configure the UART to use odd parity
137        pub fn parity_odd(mut self) -> Self {
138            self.parity = Parity::ParityOdd;
139            self
140        }
141
142        /// Configure the UART's data bits
143        pub fn data_bits(mut self, data_bits: DataBits) -> Self {
144            self.data_bits = data_bits;
145            self
146        }
147
148        /// Configure the UART's stop bits
149        pub fn stop_bits(mut self, stop_bits: StopBits) -> Self {
150            self.stop_bits = stop_bits;
151            self
152        }
153    }
154
155    impl Default for Config {
156        fn default() -> Config {
157            Config {
158                baudrate: 115_200,
159                data_bits: Default::default(),
160                parity: Default::default(),
161                stop_bits: Default::default(),
162            }
163        }
164    }
165}
166
167/// LP-UART driver
168pub struct LpUart {
169    uart: LP_UART,
170}
171
172impl LpUart {
173    /// Read a single byte from the UART in a non-blocking manner.
174    pub fn read_byte(&mut self) -> nb::Result<u8, Error> {
175        if self.rx_fifo_count() > 0 {
176            let byte = self.uart.fifo().read().rxfifo_rd_byte().bits();
177            Ok(byte)
178        } else {
179            Err(nb::Error::WouldBlock)
180        }
181    }
182
183    /// Write a single byte to the UART in a non-blocking manner.
184    pub fn write_byte(&mut self, byte: u8) -> nb::Result<(), Error> {
185        if self.tx_fifo_count() < UART_FIFO_SIZE {
186            self.uart
187                .fifo()
188                .write(|w| unsafe { w.rxfifo_rd_byte().bits(byte) });
189            Ok(())
190        } else {
191            Err(nb::Error::WouldBlock)
192        }
193    }
194
195    /// Write one or more byte to the UART, blocking until the write has
196    /// completed.
197    pub fn write_bytes(&mut self, data: &[u8]) -> Result<usize, Error> {
198        let count = data.len();
199
200        data.iter()
201            .try_for_each(|c| nb::block!(self.write_byte(*c)))?;
202
203        Ok(count)
204    }
205
206    /// Flush the UART's transmit buffer in a non-blocking manner.
207    pub fn flush_tx(&mut self) -> nb::Result<(), Error> {
208        if self.is_tx_idle() {
209            Ok(())
210        } else {
211            Err(nb::Error::WouldBlock)
212        }
213    }
214
215    fn rx_fifo_count(&mut self) -> u16 {
216        self.uart.status().read().rxfifo_cnt().bits().into()
217    }
218
219    fn tx_fifo_count(&mut self) -> u16 {
220        self.uart.status().read().txfifo_cnt().bits().into()
221    }
222
223    fn is_tx_idle(&self) -> bool {
224        self.uart.fsm_status().read().st_utx_out().bits() == 0
225    }
226}
227
228impl core::fmt::Write for LpUart {
229    fn write_str(&mut self, s: &str) -> core::fmt::Result {
230        self.write_bytes(s.as_bytes())
231            .map_err(|_| core::fmt::Error)?;
232        Ok(())
233    }
234}
235
236#[cfg(feature = "embedded-hal")]
237impl embedded_hal_nb::serial::ErrorType for LpUart {
238    type Error = Error;
239}
240
241#[cfg(feature = "embedded-hal")]
242impl embedded_hal_nb::serial::Read for LpUart {
243    fn read(&mut self) -> nb::Result<u8, Self::Error> {
244        self.read_byte()
245    }
246}
247
248#[cfg(feature = "embedded-hal")]
249impl embedded_hal_nb::serial::Write for LpUart {
250    fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
251        self.write_byte(word)
252    }
253
254    fn flush(&mut self) -> nb::Result<(), Self::Error> {
255        self.flush_tx()
256    }
257}
258
259#[cfg(feature = "embedded-io")]
260impl embedded_io::ErrorType for LpUart {
261    type Error = Error;
262}
263
264#[cfg(feature = "embedded-io")]
265impl embedded_io::Read for LpUart {
266    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
267        if buf.is_empty() {
268            return Ok(0);
269        }
270
271        while self.rx_fifo_count() == 0 {
272            // Block until we have received at least one byte
273        }
274
275        let mut count = 0;
276        while self.rx_fifo_count() > 0 && count < buf.len() {
277            buf[count] = self.uart.fifo().read().rxfifo_rd_byte().bits();
278            count += 1;
279        }
280
281        Ok(count)
282    }
283}
284
285#[cfg(feature = "embedded-io")]
286impl embedded_io::ReadReady for LpUart {
287    fn read_ready(&mut self) -> Result<bool, Self::Error> {
288        Ok(self.rx_fifo_count() > 0)
289    }
290}
291
292#[cfg(feature = "embedded-io")]
293impl embedded_io::Write for LpUart {
294    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
295        self.write_bytes(buf)
296    }
297
298    fn flush(&mut self) -> Result<(), Self::Error> {
299        loop {
300            match self.flush_tx() {
301                Ok(_) => break,
302                Err(nb::Error::WouldBlock) => { /* Wait */ }
303                #[allow(unreachable_patterns)]
304                Err(nb::Error::Other(e)) => return Err(e),
305            }
306        }
307
308        Ok(())
309    }
310}