corstone300_hal/
serial.rs

1// Copyright 2022 Arm Limited and/or its affiliates <open-source-office@arm.com>
2//
3// SPDX-License-Identifier: MIT
4
5//! Only one instance per UART may be created (either secure or non secure).
6
7use core::marker::PhantomData;
8use core::{fmt, ops::Deref};
9
10use nb::block;
11
12use crate::pac::{
13    uart0::RegisterBlock, UART0, UART0_SECURE, UART1, UART1_SECURE, UART2, UART2_SECURE, UART3,
14    UART3_SECURE, UART4, UART4_SECURE, UART5, UART5_SECURE,
15};
16
17pub trait ValidUart: Deref<Target = RegisterBlock> {
18    const PTR: *const RegisterBlock;
19}
20pub trait Pins<UART> {}
21pub trait PinTx<UART> {}
22pub trait PinRx<UART> {}
23
24macro_rules! impl_valid_uart {
25    ($($name: ty),+) => {
26        $(
27            impl ValidUart for $name {
28                const PTR: *const RegisterBlock = <$name>::PTR;
29            }
30         )+
31    }
32}
33
34impl_valid_uart!(UART0, UART1, UART2, UART3, UART4, UART5);
35
36impl<UART, TX, RX> Pins<UART> for (RX, TX)
37where
38    TX: PinTx<UART>,
39    RX: PinRx<UART>,
40{
41}
42
43/// Filler type for when the pins are preconfigured in hardware
44pub struct AutoTx;
45/// Filler type for when the pins are preconfigured in hardware
46pub struct AutoRx;
47
48impl PinRx<UART0> for AutoRx {}
49impl PinTx<UART0> for AutoTx {}
50impl PinRx<UART1> for AutoRx {}
51impl PinTx<UART1> for AutoTx {}
52impl PinRx<UART2> for AutoRx {}
53impl PinTx<UART2> for AutoTx {}
54impl PinRx<UART3> for crate::shield::Pin<0, 0, crate::shield::Uart> {}
55impl PinTx<UART3> for crate::shield::Pin<0, 1, crate::shield::Uart> {}
56impl PinRx<UART4> for crate::shield::Pin<1, 0, crate::shield::Uart> {}
57impl PinTx<UART4> for crate::shield::Pin<1, 1, crate::shield::Uart> {}
58impl PinRx<UART5> for AutoRx {}
59impl PinTx<UART5> for AutoTx {}
60impl PinRx<UART0_SECURE> for AutoRx {}
61impl PinTx<UART0_SECURE> for AutoTx {}
62impl PinRx<UART1_SECURE> for AutoRx {}
63impl PinTx<UART1_SECURE> for AutoTx {}
64impl PinRx<UART2_SECURE> for AutoRx {}
65impl PinTx<UART2_SECURE> for AutoTx {}
66impl PinRx<UART3_SECURE> for crate::shield::Pin<0, 0, crate::shield::Uart> {}
67impl PinTx<UART3_SECURE> for crate::shield::Pin<0, 1, crate::shield::Uart> {}
68impl PinRx<UART4_SECURE> for crate::shield::Pin<1, 0, crate::shield::Uart> {}
69impl PinTx<UART4_SECURE> for crate::shield::Pin<1, 1, crate::shield::Uart> {}
70impl PinRx<UART5_SECURE> for AutoRx {}
71impl PinTx<UART5_SECURE> for AutoTx {}
72
73pub struct Serial<UART, RxPin, TxPin> {
74    rx: Rx<UART, RxPin>,
75    tx: Tx<UART, TxPin>,
76}
77
78pub struct Rx<UART, RxPin> {
79    _serial: PhantomData<UART>,
80    _pin: RxPin,
81}
82
83pub struct Tx<UART, TxPin> {
84    _serial: PhantomData<UART>,
85    _pin: TxPin,
86}
87
88#[derive(Debug, Clone, Copy)]
89pub enum Error {
90    /// Rx dada overrun
91    Overrun,
92}
93
94pub mod config {
95    #[derive(Debug, Clone, Copy)]
96    pub enum Error {
97        /// Invalid baudrate
98        UnreachableBaudrate,
99    }
100}
101impl<U: ValidUart, RxPin, TxPin> Serial<U, RxPin, TxPin>
102where
103    (RxPin, TxPin): Pins<U>,
104{
105    /// Initializes the peripheral
106    pub fn new(
107        uart: U,
108        (rx, tx): (RxPin, TxPin),
109        baudrate: fugit::HertzU32,
110    ) -> Result<Self, (U, (RxPin, TxPin), config::Error)> {
111        // configure baudrate
112        if let Some(bauddiv) = (baudrate.to_Hz() != 0)
113            .then(|| crate::PERIPHERAL_CLOCK.to_Hz() / baudrate.to_Hz())
114            .filter(|&bauddiv| bauddiv >= 16)
115        {
116            uart.bauddiv.write(|w| unsafe { w.bits(bauddiv) });
117        } else {
118            return Err((uart, (rx, tx), config::Error::UnreachableBaudrate));
119        }
120
121        // enable receiver/transitter
122        uart.ctrl.modify(|_, w| w.rxen().set_bit().txen().set_bit());
123
124        Ok(Serial {
125            rx: Rx {
126                _serial: PhantomData,
127                _pin: rx,
128            },
129
130            tx: Tx {
131                _serial: PhantomData,
132                _pin: tx,
133            },
134        })
135    }
136
137    /// Splits RX & TX channel to allow independent operations.
138    pub fn split(self) -> (Rx<U, RxPin>, Tx<U, TxPin>) {
139        let Self { rx, tx } = self;
140        (rx, tx)
141    }
142    // TODO: this needs to reset the peripheral
143    // also, Tx<_> and Rx<_> may need to carry their respective pin so that a splited
144    // serial can be reconstituted
145    /*pub fn release(self) -> ($name, PINS) {
146        (self.serial, self.pins)
147    }*/
148}
149
150impl<U: ValidUart, P: PinRx<U>> embedded_hal::serial::Read<u8> for Rx<U, P> {
151    type Error = Error;
152
153    fn read(&mut self) -> nb::Result<u8, Self::Error> {
154        let serial = unsafe { &*U::PTR };
155
156        // TODO: check RX overrun
157
158        if serial.state.read().rxbf().bit_is_clear() {
159            Err(nb::Error::WouldBlock)
160        } else {
161            Ok(serial.data.read().bits())
162        }
163    }
164}
165impl<U: ValidUart, P: PinTx<U>> embedded_hal::serial::Write<u8> for Tx<U, P> {
166    type Error = Error;
167
168    fn flush(&mut self) -> nb::Result<(), Self::Error> {
169        let serial = unsafe { &*U::PTR };
170
171        if serial.state.read().txbf().bit_is_set() {
172            Err(nb::Error::WouldBlock)
173        } else {
174            Ok(())
175        }
176    }
177
178    fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
179        let serial = unsafe { &*U::PTR };
180
181        if serial.state.read().txbf().bit_is_set() {
182            Err(nb::Error::WouldBlock)
183        } else {
184            unsafe {
185                serial.data.write_with_zero(|w| w.bits(byte));
186            }
187            Ok(())
188        }
189    }
190}
191
192// delegate embedded-hal's implementation to inner RX<U> and TX<U>
193impl<U: ValidUart, RxPin, TxPin> embedded_hal::serial::Read<u8> for Serial<U, RxPin, TxPin>
194where
195    (RxPin, TxPin): Pins<U>,
196    RxPin: PinRx<U>,
197{
198    type Error = Error;
199
200    fn read(&mut self) -> nb::Result<u8, Self::Error> {
201        self.rx.read()
202    }
203}
204impl<U: ValidUart, RxPin, TxPin> embedded_hal::serial::Write<u8> for Serial<U, RxPin, TxPin>
205where
206    (RxPin, TxPin): Pins<U>,
207    TxPin: PinTx<U>,
208{
209    type Error = Error;
210
211    fn flush(&mut self) -> nb::Result<(), Self::Error> {
212        self.tx.flush()
213    }
214
215    fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
216        self.tx.write(byte)
217    }
218}
219
220impl<U, RxPin, TxPin> fmt::Write for Serial<U, RxPin, TxPin>
221where
222    U: ValidUart,
223    (RxPin, TxPin): Pins<U>,
224    TxPin: PinTx<U>,
225{
226    fn write_str(&mut self, s: &str) -> fmt::Result {
227        use embedded_hal::serial::Write;
228        for &b in s.as_bytes() {
229            block!(self.write(b)).map_err(|_| core::fmt::Error)?;
230        }
231        Ok(())
232    }
233}
234impl<UART, P> fmt::Write for Tx<UART, P>
235where
236    Tx<UART, P>: embedded_hal::serial::Write<u8>,
237    P: PinTx<UART>,
238{
239    fn write_str(&mut self, s: &str) -> fmt::Result {
240        use embedded_hal::serial::Write;
241        for &b in s.as_bytes() {
242            block!(self.write(b)).map_err(|_| core::fmt::Error)?;
243        }
244        Ok(())
245    }
246}
247
248#[cfg(feature = "eh1-0-alpha")]
249mod eh1 {
250    use eh1_0_alpha::serial::ErrorKind;
251
252    use super::{Error, Rx, Serial, Tx};
253
254    impl eh1_0_alpha::serial::Error for Error {
255        fn kind(&self) -> ErrorKind {
256            match self {
257                Error::Overrun => ErrorKind::Overrun,
258            }
259        }
260    }
261
262    impl<UART, RxPin, TxPin> eh1_0_alpha::serial::ErrorType for Serial<UART, RxPin, TxPin> {
263        type Error = Error;
264    }
265    // redirect eh1_0_alpha API to embedded_hal's implementation
266    impl<UART, RxPin, TxPin> eh1_0_alpha::serial::nb::Read for Serial<UART, RxPin, TxPin>
267    where
268        Self: embedded_hal::serial::Read<u8, Error = Error>,
269    {
270        fn read(&mut self) -> nb::Result<u8, Self::Error> {
271            <Self as embedded_hal::serial::Read<_>>::read(self)
272        }
273    }
274    impl<UART, RxPin, TxPin> eh1_0_alpha::serial::nb::Write for Serial<UART, RxPin, TxPin>
275    where
276        Self: embedded_hal::serial::Write<u8, Error = Error>,
277    {
278        fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
279            <Self as embedded_hal::serial::Write<u8>>::write(self, word)
280        }
281
282        fn flush(&mut self) -> nb::Result<(), Self::Error> {
283            <Self as embedded_hal::serial::Write<u8>>::flush(self)
284        }
285    }
286
287    // redirect blocking API to nb
288    impl<UART, RxPin, TxPin> eh1_0_alpha::serial::blocking::Write for Serial<UART, RxPin, TxPin>
289    where
290        Self: embedded_hal::serial::Write<u8, Error = Error>,
291    {
292        fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
293            for &b in buffer {
294                nb::block!(<Self as eh1_0_alpha::serial::nb::Write>::write(self, b))?
295            }
296            Ok(())
297        }
298
299        fn flush(&mut self) -> Result<(), Self::Error> {
300            nb::block!(<Self as eh1_0_alpha::serial::nb::Write>::flush(self))
301        }
302    }
303
304    // Similarly done for Tx and Rx
305    impl<UART, RxPin> eh1_0_alpha::serial::ErrorType for Rx<UART, RxPin> {
306        type Error = Error;
307    }
308    impl<UART, RxPin> eh1_0_alpha::serial::nb::Read for Rx<UART, RxPin>
309    where
310        Self: embedded_hal::serial::Read<u8, Error = Error>,
311    {
312        fn read(&mut self) -> nb::Result<u8, Self::Error> {
313            <Self as embedded_hal::serial::Read<_>>::read(self)
314        }
315    }
316    impl<UART, TxPin> eh1_0_alpha::serial::ErrorType for Tx<UART, TxPin> {
317        type Error = Error;
318    }
319    impl<UART, TxPin> eh1_0_alpha::serial::nb::Write for Tx<UART, TxPin>
320    where
321        Self: embedded_hal::serial::Write<u8, Error = Error>,
322    {
323        fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
324            <Self as embedded_hal::serial::Write<u8>>::write(self, word)
325        }
326
327        fn flush(&mut self) -> nb::Result<(), Self::Error> {
328            <Self as embedded_hal::serial::Write<u8>>::flush(self)
329        }
330    }
331    impl<UART, TxPin> eh1_0_alpha::serial::blocking::Write for Tx<UART, TxPin>
332    where
333        Self: embedded_hal::serial::Write<u8, Error = Error>,
334    {
335        fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
336            for &b in buffer {
337                nb::block!(<Self as eh1_0_alpha::serial::nb::Write>::write(self, b))?
338            }
339            Ok(())
340        }
341
342        fn flush(&mut self) -> Result<(), Self::Error> {
343            nb::block!(<Self as eh1_0_alpha::serial::nb::Write>::flush(self))
344        }
345    }
346}