jh71xx_hal/
uart.rs

1//! UART peripheral access
2
3use core::marker::PhantomData;
4
5mod config;
6mod error;
7mod serial;
8
9pub use config::*;
10pub use error::*;
11pub use serial::*;
12
13/// Clock used by Dw_apb_uart: 50 MHz
14pub const APB0: usize = 50_000_000;
15/// Core clock oscillator: 24 MHz
16pub const CLK_OSC: usize = 24_000_000;
17
18/// Transaction timeout in microseconds.
19pub const TIMEOUT_US: u64 = 1_000_000;
20
21/// Represents UART TX functionality.
22///
23/// Inspired by `esp-hal` implementation: <https://github.com/esp-rs/esp-hal>
24pub struct UartTx<T: Serial> {
25    _serial: PhantomData<T>,
26}
27
28impl<T: Serial> UartTx<T> {
29    fn new_inner() -> Self {
30        Self {
31            _serial: PhantomData,
32        }
33    }
34
35    /// Writes bytes over serial.
36    ///
37    /// Blocking function.
38    ///
39    /// Returns:
40    ///
41    /// - `Ok(written: usize)` on success, `written` bytes written to peripheral
42    /// - `Err(Error)` on failure
43    pub fn write_bytes(&mut self, data: &[u8]) -> Result<usize> {
44        let count = data.len();
45
46        data.iter()
47            .try_for_each(|&c| nb::block!(self.write_byte(c)))?;
48
49        Ok(count)
50    }
51
52    fn write_byte(&mut self, byte: u8) -> nb::Result<(), Error> {
53        T::write_byte(byte)
54    }
55
56    fn flush(&mut self) -> nb::Result<(), Error> {
57        T::flush()
58    }
59}
60
61/// Represents UART RX functionality.
62///
63/// Based on the implementation in `esp-hal`: <https://github.com/esp-rs/esp-hal>
64pub struct UartRx<T: Serial> {
65    _serial: PhantomData<T>,
66}
67
68impl<T: Serial> UartRx<T> {
69    fn new_inner() -> Self {
70        Self {
71            _serial: PhantomData,
72        }
73    }
74
75    /// Reads bytes from the peripheral.
76    ///
77    /// Continues to read bytes while receive FIFO is full, or at least one byte is read.
78    pub fn read_bytes(&mut self, buf: &mut [u8]) -> Result<usize> {
79        let mut count = 0usize;
80
81        for byte in buf.iter_mut() {
82            match self.read_byte() {
83                Ok(b) => {
84                    *byte = b;
85                    count = count.saturating_add(1);
86                }
87                Err(nb::Error::WouldBlock) => {
88                    // Block until we have at least one byte
89                    if count > 0 {
90                        break;
91                    }
92                }
93                Err(nb::Error::Other(e)) => return Err(e),
94            }
95        }
96
97        Ok(count)
98    }
99
100    fn read_byte(&mut self) -> nb::Result<u8, Error> {
101        T::read_byte()
102    }
103}
104
105/// Represents a UART peripheral.
106///
107/// Based on the implementation in [`esp-hal`](https://github.com/esp-rs/esp-hal).
108#[repr(C)]
109pub struct Uart<UART: Serial> {
110    tx: UartTx<UART>,
111    rx: UartRx<UART>,
112    timeout: u64,
113    config: Config,
114}
115
116impl<UART: Serial> Uart<UART> {
117    /// Creates a new [Uart].
118    ///
119    /// Parameters:
120    ///
121    /// - `uart`: UART peripheral that implements the [Serial] trait.
122    ///
123    /// Example:
124    ///
125    /// ```no_run
126    /// # use jh71xx_hal::{pac, uart};
127    /// let dp = pac::Peripherals::take().unwrap();
128    /// let _uart = uart::Uart::new(dp.uart0);
129    /// ```
130    pub fn new(uart: UART) -> Self {
131        Self::new_with_config(uart, TIMEOUT_US, Config::new())
132    }
133
134    /// Creates a new [Uart] from a custom configuration.
135    ///
136    /// Parameters:
137    ///
138    /// - `uart`: UART peripheral that implements the [Serial] trait.
139    /// - `timeout`: time in microseconds before aborting transaction.
140    /// - `config`: UART configuration parameters.
141    ///
142    /// Example:
143    ///
144    /// ```no_run
145    /// # use jh71xx_hal::{pac, uart};
146    /// let dp = pac::Peripherals::take().unwrap();
147    /// let _uart = uart::Uart::new_with_config(
148    ///     dp.uart0,
149    ///     // timeout in microseconds
150    ///     1_000_000,
151    ///     uart::Config {
152    ///         data_len: uart::DataLength::Eight,
153    ///         stop: uart::Stop::One,
154    ///         parity: uart::Parity::None,
155    ///         baud_rate: uart::BaudRate::B115200,
156    ///         // default APB0 clock frequency
157    ///         clk_hz: 50_000_000,
158    ///     },
159    /// );
160    /// ```
161    pub fn new_with_config(mut uart: UART, timeout: u64, config: Config) -> Self {
162        uart.setup(config).ok();
163
164        Self {
165            tx: UartTx::new_inner(),
166            rx: UartRx::new_inner(),
167            timeout,
168            config,
169        }
170    }
171
172    /// Splits the [Uart] into a transmitter and receiver
173    pub fn split(self) -> (UartTx<UART>, UartRx<UART>) {
174        (self.tx, self.rx)
175    }
176
177    /// Read a byte from the UART FIFO.
178    pub fn read_byte(&mut self) -> Result<u8> {
179        Ok(self.rx.read_byte()?)
180    }
181
182    /// Write a byte to the UART FIFO.
183    pub fn write_byte(&mut self, byte: u8) -> Result<()> {
184        Ok(self.tx.write_byte(byte)?)
185    }
186
187    /// Gets the timeout (in microseconds).
188    pub const fn timeout(&self) -> u64 {
189        self.timeout
190    }
191
192    /// Sets the timeout (in microseconds).
193    ///
194    /// **NOTE**: `timeout` must be greater than zero, no-op otherwise.
195    pub fn set_timeout(&mut self, timeout: u64) {
196        if timeout > 0 {
197            self.timeout = timeout;
198        }
199    }
200
201    /// Builder function that sets the timeout (in microseconds).
202    ///
203    /// **NOTE**: `timeout` must be greater than zero, no-op otherwise.
204    pub fn with_timeout(mut self, timeout: u64) -> Self {
205        self.set_timeout(timeout);
206        self
207    }
208
209    /// Gets the [Config].
210    pub const fn config(&self) -> Config {
211        self.config
212    }
213
214    /// Sets the [Config].
215    pub fn set_config(&mut self, config: Config) {
216        self.config = config;
217    }
218
219    /// Builder function that sets the [Config].
220    pub fn with_config(mut self, config: Config) -> Self {
221        self.set_config(config);
222        self
223    }
224}
225
226impl<UART: Serial> io::ErrorType for Uart<UART> {
227    type Error = Error;
228}
229
230impl<UART: Serial> io::ErrorType for UartRx<UART> {
231    type Error = Error;
232}
233
234impl<UART: Serial> io::ErrorType for UartTx<UART> {
235    type Error = Error;
236}
237
238impl<UART: Serial> embedded_hal_nb::serial::ErrorType for Uart<UART> {
239    type Error = Error;
240}
241
242impl<UART: Serial> embedded_hal_nb::serial::ErrorType for UartRx<UART> {
243    type Error = Error;
244}
245
246impl<UART: Serial> embedded_hal_nb::serial::ErrorType for UartTx<UART> {
247    type Error = Error;
248}
249
250impl<UART: Serial> io::Read for Uart<UART> {
251    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
252        self.rx.read_bytes(buf)
253    }
254}
255
256impl<UART: Serial> io::Read for UartRx<UART> {
257    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
258        self.read_bytes(buf)
259    }
260}
261
262impl<UART: Serial> io::Write for Uart<UART> {
263    fn write(&mut self, buf: &[u8]) -> Result<usize> {
264        self.tx.write_bytes(buf)
265    }
266
267    fn flush(&mut self) -> Result<()> {
268        self.tx.flush()?;
269        Ok(())
270    }
271}
272
273impl<UART: Serial> io::Write for UartTx<UART> {
274    fn write(&mut self, buf: &[u8]) -> Result<usize> {
275        self.write_bytes(buf)
276    }
277
278    fn flush(&mut self) -> Result<()> {
279        self.flush()?;
280        Ok(())
281    }
282}
283
284impl<UART: Serial> embedded_hal_nb::serial::Read for Uart<UART> {
285    fn read(&mut self) -> nb::Result<u8, Self::Error> {
286        self.rx.read_byte()
287    }
288}
289
290impl<UART: Serial> embedded_hal_nb::serial::Read for UartRx<UART> {
291    fn read(&mut self) -> nb::Result<u8, Self::Error> {
292        self.read_byte()
293    }
294}
295
296impl<UART: Serial> embedded_hal_nb::serial::Write for Uart<UART> {
297    fn write(&mut self, val: u8) -> nb::Result<(), Self::Error> {
298        self.tx.write_byte(val)
299    }
300
301    fn flush(&mut self) -> nb::Result<(), Self::Error> {
302        self.tx.flush()
303    }
304}
305
306impl<UART: Serial> embedded_hal_nb::serial::Write for UartTx<UART> {
307    fn write(&mut self, val: u8) -> nb::Result<(), Self::Error> {
308        self.write_byte(val)
309    }
310
311    fn flush(&mut self) -> nb::Result<(), Self::Error> {
312        self.flush()
313    }
314}