e310x_hal/
serial.rs

1//! Serial interface
2//!
3//! You can use the `Serial` interface with these UART instances
4//!
5//! # UART0
6//! - TX: Pin 17 IOF0
7//! - RX: Pin 16 IOF0
8//! - Interrupt::UART0
9//!
10//! # UART1
11//! *Warning:* UART1 pins are not connected to package in FE310-G000
12//! - TX: Pin 18 IOF0
13//! - RX: Pin 23 IOF0
14//! - Interrupt::UART1
15
16use core::ops::Deref;
17use e310x::{uart0, Uart0, Uart1};
18use embedded_hal_nb::serial;
19
20use crate::{clock::Clocks, time::Bps};
21
22/// TX pin
23pub trait TxPin<UART>: private::Sealed {}
24
25/// RX pin
26pub trait RxPin<UART>: private::Sealed {}
27
28/// UartX trait extends the UART peripheral
29pub trait UartX: Deref<Target = uart0::RegisterBlock> + private::Sealed {
30    /// Steals the UART peripheral
31    ///
32    /// # Safety
33    ///
34    /// Using this function may break the guarantees of the singleton pattern.
35    unsafe fn steal() -> Self;
36}
37
38mod impl_uart {
39    use super::{RxPin, TxPin, Uart0, Uart1, UartX};
40    use crate::gpio::{gpio0, IOF0};
41    // UART0
42    impl UartX for Uart0 {
43        unsafe fn steal() -> Self {
44            Uart0::steal()
45        }
46    }
47    impl<T> TxPin<Uart0> for gpio0::Pin17<IOF0<T>> {}
48    impl<T> RxPin<Uart0> for gpio0::Pin16<IOF0<T>> {}
49
50    // UART1
51    impl UartX for Uart1 {
52        unsafe fn steal() -> Self {
53            Uart1::steal()
54        }
55    }
56    #[cfg(feature = "g002")]
57    impl<T> TxPin<Uart1> for gpio0::Pin18<IOF0<T>> {}
58    #[cfg(feature = "g002")]
59    impl<T> RxPin<Uart1> for gpio0::Pin23<IOF0<T>> {}
60}
61
62/// Serial receiver half
63pub struct Rx<UART, PIN> {
64    uart: UART,
65    pin: PIN,
66}
67
68impl<UART, PIN> Rx<UART, PIN> {
69    /// Releases the UART peripheral and associated pin
70    pub fn free(self) -> (UART, PIN) {
71        (self.uart, self.pin)
72    }
73}
74
75impl<UART: UartX, PIN: RxPin<UART>> serial::ErrorType for Rx<UART, PIN> {
76    type Error = serial::ErrorKind;
77}
78
79impl<UART: UartX, PIN: RxPin<UART>> embedded_io::ErrorType for Rx<UART, PIN> {
80    type Error = embedded_io::ErrorKind;
81}
82
83impl<UART: UartX, PIN: RxPin<UART>> serial::Read for Rx<UART, PIN> {
84    #[inline]
85    fn read(&mut self) -> nb::Result<u8, Self::Error> {
86        let rxdata = self.uart.rxdata().read();
87
88        if rxdata.empty().bit_is_set() {
89            Err(::nb::Error::WouldBlock)
90        } else {
91            Ok(rxdata.data().bits())
92        }
93    }
94}
95
96impl<UART: UartX, PIN: RxPin<UART>> embedded_io::Read for Rx<UART, PIN> {
97    #[inline]
98    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
99        if buf.is_empty() {
100            return Ok(0);
101        }
102        buf[0] = nb::block!(serial::Read::read(self)).unwrap(); // first byte may block
103        let mut count = 1;
104        for byte in buf.iter_mut().skip(1) {
105            match serial::Read::read(self) {
106                Ok(b) => {
107                    *byte = b;
108                    count += 1
109                }
110                Err(nb::Error::WouldBlock) => break,
111                _ => unreachable!(),
112            }
113        }
114        Ok(count)
115    }
116}
117
118/// Serial transmitter half
119pub struct Tx<UART, PIN> {
120    uart: UART,
121    pin: PIN,
122}
123
124impl<UART, PIN> Tx<UART, PIN> {
125    /// Releases the UART peripheral and associated pin
126    pub fn free(self) -> (UART, PIN) {
127        (self.uart, self.pin)
128    }
129}
130
131impl<UART: UartX, PIN: TxPin<UART>> Tx<UART, PIN> {
132    /// Returns true if the transmit buffer is full
133    fn is_buffer_full(&self) -> bool {
134        self.uart.txdata().read().full().bit_is_set()
135    }
136}
137
138impl<UART: UartX, PIN: TxPin<UART>> serial::ErrorType for Tx<UART, PIN> {
139    type Error = serial::ErrorKind;
140}
141
142impl<UART: UartX, PIN: TxPin<UART>> embedded_io::ErrorType for Tx<UART, PIN> {
143    type Error = embedded_io::ErrorKind;
144}
145
146impl<UART: UartX, PIN: TxPin<UART>> serial::Write for Tx<UART, PIN> {
147    #[inline]
148    fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
149        if self.is_buffer_full() {
150            Err(nb::Error::WouldBlock)
151        } else {
152            self.uart.txdata().write(|w| unsafe { w.data().bits(byte) });
153            Ok(())
154        }
155    }
156
157    #[inline]
158    fn flush(&mut self) -> nb::Result<(), Self::Error> {
159        if self.uart.ip().read().txwm().bit_is_set() {
160            // FIFO count is below the receive watermark (1)
161            Ok(())
162        } else {
163            Err(nb::Error::WouldBlock)
164        }
165    }
166}
167
168impl<UART: UartX, PIN: TxPin<UART>> embedded_io::WriteReady for Tx<UART, PIN> {
169    #[inline]
170    fn write_ready(&mut self) -> Result<bool, Self::Error> {
171        Ok(!self.is_buffer_full())
172    }
173}
174
175impl<UART: UartX, PIN: TxPin<UART>> embedded_io::Write for Tx<UART, PIN> {
176    #[inline]
177    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
178        if buf.is_empty() {
179            return Ok(0);
180        }
181        nb::block!(serial::Write::write(self, buf[0])).unwrap(); // first byte may block
182        let mut count = 1;
183        for byte in buf.iter().skip(1) {
184            match serial::Write::write(self, *byte) {
185                Ok(()) => count += 1,
186                Err(nb::Error::WouldBlock) => break,
187                _ => unreachable!(),
188            }
189        }
190        Ok(count)
191    }
192
193    #[inline]
194    fn flush(&mut self) -> Result<(), Self::Error> {
195        nb::block!(serial::Write::flush(self)).unwrap();
196        Ok(())
197    }
198}
199
200/// Serial abstraction
201pub struct Serial<UART, TX, RX> {
202    uart: UART,
203    tx: Tx<UART, TX>,
204    rx: Rx<UART, RX>,
205}
206
207impl<UART: UartX, TX: TxPin<UART>, RX: RxPin<UART>> Serial<UART, TX, RX> {
208    /// Configures a UART peripheral to provide serial communication
209    pub fn new(uart: UART, pins: (TX, RX), baud_rate: Bps, clocks: Clocks) -> Self {
210        let div = clocks.tlclk().0 / baud_rate.0 - 1;
211        unsafe {
212            uart.ie().write(|w| w.txwm().bit(false).rxwm().bit(false));
213            uart.div().write(|w| w.bits(div));
214            uart.txctrl()
215                .write(|w| w.counter().bits(1).enable().bit(true));
216            uart.rxctrl().write(|w| w.enable().bit(true));
217        }
218
219        let tx = Tx {
220            uart: unsafe { UART::steal() },
221            pin: pins.0,
222        };
223        let rx = Rx {
224            uart: unsafe { UART::steal() },
225            pin: pins.1,
226        };
227
228        Serial { uart, tx, rx }
229    }
230
231    /// Starts listening for an interrupt event
232    pub fn listen(self) -> Self {
233        self.uart
234            .ie()
235            .write(|w| w.txwm().bit(false).rxwm().bit(true));
236        self
237    }
238
239    /// Stops listening for an interrupt event
240    pub fn unlisten(self) -> Self {
241        self.uart
242            .ie()
243            .write(|w| w.txwm().bit(false).rxwm().bit(false));
244        self
245    }
246
247    /// Splits the [`Serial`] abstraction into a transmitter and a receiver half
248    pub fn split(self) -> (Tx<UART, TX>, Rx<UART, RX>) {
249        (self.tx, self.rx)
250    }
251
252    /// Releases the UART peripheral and associated pins
253    pub fn free(self) -> (UART, (TX, RX)) {
254        (self.uart, (self.tx.pin, self.rx.pin))
255    }
256}
257
258impl<UART: UartX, TX, RX> serial::ErrorType for Serial<UART, TX, RX> {
259    type Error = serial::ErrorKind;
260}
261
262impl<UART: UartX, TX, RX: RxPin<UART>> serial::Read for Serial<UART, TX, RX> {
263    fn read(&mut self) -> nb::Result<u8, Self::Error> {
264        self.rx.read()
265    }
266}
267
268impl<UART: UartX, TX: TxPin<UART>, RX> serial::Write for Serial<UART, TX, RX> {
269    fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
270        self.tx.write(byte)
271    }
272
273    fn flush(&mut self) -> nb::Result<(), Self::Error> {
274        self.tx.flush()
275    }
276}
277
278impl<UART, TX, RX> embedded_io::ErrorType for Serial<UART, TX, RX> {
279    type Error = embedded_io::ErrorKind;
280}
281
282impl<UART: UartX, TX, RX: RxPin<UART>> embedded_io::Read for Serial<UART, TX, RX> {
283    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
284        self.rx.read(buf)
285    }
286}
287
288impl<UART: UartX, TX: TxPin<UART>, RX> embedded_io::WriteReady for Serial<UART, TX, RX> {
289    fn write_ready(&mut self) -> Result<bool, Self::Error> {
290        self.tx.write_ready()
291    }
292}
293
294impl<UART: UartX, TX: TxPin<UART>, RX> embedded_io::Write for Serial<UART, TX, RX> {
295    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
296        self.tx.write(buf)
297    }
298
299    fn flush(&mut self) -> Result<(), Self::Error> {
300        self.tx.flush()
301    }
302}
303
304// seal the "private" traits
305mod private {
306    use crate::gpio::{gpio0, IOF0};
307    use e310x::{Uart0, Uart1};
308
309    pub trait Sealed {}
310
311    impl Sealed for Uart0 {}
312    impl<T> Sealed for gpio0::Pin17<IOF0<T>> {}
313    impl<T> Sealed for gpio0::Pin16<IOF0<T>> {}
314
315    impl Sealed for Uart1 {}
316    #[cfg(feature = "g002")]
317    impl<T> Sealed for gpio0::Pin18<IOF0<T>> {}
318    #[cfg(feature = "g002")]
319    impl<T> Sealed for gpio0::Pin23<IOF0<T>> {}
320}