atsamd_hal/sercom/uart/
impl_ehal.rs

1//! `embedded-hal` trait implementations for [`Uart`]s
2
3use super::{
4    Capability, Config, DataReg, EightBit, Error, Error as UartError, Flags, Receive, Transmit,
5    Uart, ValidConfig, ValidPads,
6};
7use crate::{
8    ehal_02::{
9        blocking,
10        serial::{Read, Write},
11    },
12    typelevel::NoneT,
13};
14use nb::Error::WouldBlock;
15use num_traits::AsPrimitive;
16
17impl<C, D> Read<C::Word> for Uart<C, D>
18where
19    C: ValidConfig,
20    D: Receive,
21    DataReg: AsPrimitive<C::Word>,
22{
23    type Error = Error;
24
25    /// Wait for an `RXC` flag, then read the word
26    #[inline]
27    fn read(&mut self) -> nb::Result<C::Word, Error> {
28        <Self as embedded_hal_nb::serial::Read<C::Word>>::read(self)
29    }
30}
31
32impl<C, D> Write<C::Word> for Uart<C, D>
33where
34    C: ValidConfig,
35    D: Transmit,
36{
37    type Error = UartError;
38
39    /// Wait for a `DRE` flag, then write a word
40    #[inline]
41    fn write(&mut self, word: C::Word) -> nb::Result<(), Self::Error> {
42        <Self as embedded_hal_nb::serial::Write<C::Word>>::write(self, word)
43    }
44
45    /// Wait for a `TXC` flag
46    #[inline]
47    fn flush(&mut self) -> nb::Result<(), Self::Error> {
48        <Self as embedded_hal_nb::serial::Write<C::Word>>::flush(self)
49    }
50}
51
52impl<C, D> blocking::serial::write::Default<C::Word> for Uart<C, D>
53where
54    C: ValidConfig,
55    D: Transmit,
56    Uart<C, D>: Write<C::Word>,
57{
58}
59
60impl embedded_io::Error for UartError {
61    #[inline]
62    fn kind(&self) -> embedded_io::ErrorKind {
63        embedded_io::ErrorKind::Other
64    }
65}
66
67impl<C, D, R, T> embedded_io::ErrorType for Uart<C, D, R, T>
68where
69    C: ValidConfig,
70    D: Capability,
71{
72    type Error = UartError;
73}
74
75impl<P, D, R> embedded_io::Write for Uart<Config<P, EightBit>, D, R, NoneT>
76where
77    P: ValidPads,
78    D: Transmit,
79{
80    #[inline]
81    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
82        for word in buf {
83            nb::block!(<Self as embedded_hal_nb::serial::Write<u8>>::write(
84                self, *word
85            ))?;
86        }
87
88        Ok(buf.len())
89    }
90
91    /// Wait for a `TXC` flag
92    #[inline]
93    fn flush(&mut self) -> Result<(), Self::Error> {
94        nb::block!(<Self as embedded_hal_nb::serial::Write<u8>>::flush(self))?;
95        Ok(())
96    }
97}
98
99impl<P, D, T> embedded_io::Read for Uart<Config<P, EightBit>, D, NoneT, T>
100where
101    P: ValidPads,
102    D: Receive,
103{
104    #[inline]
105    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
106        if buf.is_empty() {
107            return Ok(0);
108        }
109
110        for byte in buf.iter_mut() {
111            let w = nb::block!(<Self as embedded_hal_nb::serial::Read<u8>>::read(self))?;
112            *byte = w;
113        }
114
115        Ok(buf.len())
116    }
117}
118
119impl embedded_hal_nb::serial::Error for UartError {
120    #[inline]
121    fn kind(&self) -> embedded_hal_nb::serial::ErrorKind {
122        use embedded_hal_nb::serial::ErrorKind;
123
124        match self {
125            Self::ParityError => ErrorKind::Parity,
126            Self::FrameError => ErrorKind::FrameFormat,
127            Self::Overflow => ErrorKind::Overrun,
128            _ => ErrorKind::Other,
129        }
130    }
131}
132
133impl<C, D, R, T, W> embedded_hal_nb::serial::ErrorType for Uart<C, D, R, T>
134where
135    C: ValidConfig<Word = W>,
136    W: Copy,
137    D: Capability,
138{
139    type Error = UartError;
140}
141
142impl<C, D, R, T> embedded_hal_nb::serial::Read<C::Word> for Uart<C, D, R, T>
143where
144    C: ValidConfig,
145    D: Receive,
146    DataReg: AsPrimitive<C::Word>,
147{
148    #[inline]
149    fn read(&mut self) -> nb::Result<C::Word, Self::Error> {
150        // Wait for an `RXC` flag, then read the word
151        let flags = self.read_flags_errors()?;
152        if flags.contains(Flags::RXC) {
153            unsafe { Ok(self.read_data().as_()) }
154        } else {
155            Err(WouldBlock)
156        }
157    }
158}
159
160impl<C, D, R, T> embedded_hal_nb::serial::Write<C::Word> for Uart<C, D, R, T>
161where
162    C: ValidConfig,
163    D: Transmit,
164{
165    /// Wait for a `DRE` flag, then write a word
166    #[inline]
167    fn write(&mut self, word: C::Word) -> nb::Result<(), Self::Error> {
168        if self.read_flags().contains(Flags::DRE) {
169            unsafe { self.write_data(word.as_()) };
170            Ok(())
171        } else {
172            Err(WouldBlock)
173        }
174    }
175
176    /// Wait for a `TXC` flag
177    #[inline]
178    fn flush(&mut self) -> nb::Result<(), Self::Error> {
179        if self.read_flags().contains(Flags::TXC) {
180            self.clear_flags(Flags::TXC);
181            Ok(())
182        } else {
183            Err(WouldBlock)
184        }
185    }
186}
187
188#[cfg(feature = "dma")]
189mod dma {
190    use super::*;
191    use crate::{
192        dmac::{AnyChannel, Beat, Ready},
193        sercom::{
194            dma::{read_dma, write_dma, SercomPtr, SharedSliceBuffer},
195            Sercom,
196        },
197    };
198
199    impl<C, D, R, T, W> Uart<C, D, R, T>
200    where
201        C: ValidConfig<Word = W>,
202        D: Capability,
203        W: Beat,
204    {
205        pub(in super::super) fn sercom_ptr(&self) -> SercomPtr<W> {
206            SercomPtr(self.data_ptr())
207        }
208    }
209
210    impl<P, D, R, T, S> embedded_io::Write for Uart<Config<P, EightBit>, D, R, T>
211    where
212        P: ValidPads<Sercom = S>,
213        D: Transmit,
214        T: AnyChannel<Status = Ready>,
215        S: Sercom,
216    {
217        #[inline]
218        fn write(&mut self, bytes: &[u8]) -> Result<usize, Self::Error> {
219            let sercom_ptr = self.sercom_ptr();
220            let channel = self.tx_channel.as_mut();
221            let mut buffer = SharedSliceBuffer::from_slice(bytes);
222
223            unsafe {
224                write_dma::<_, _, S>(channel, sercom_ptr, &mut buffer);
225            }
226
227            while !channel.xfer_complete() {
228                core::hint::spin_loop();
229            }
230
231            while !self.read_flags().contains(Flags::TXC) {
232                core::hint::spin_loop();
233            }
234
235            Ok(bytes.len())
236        }
237
238        /// Wait for a `TXC` flag
239        #[inline]
240        fn flush(&mut self) -> Result<(), Self::Error> {
241            nb::block!(<Self as embedded_hal_nb::serial::Write<u8>>::flush(self))?;
242            Ok(())
243        }
244    }
245
246    impl<P, D, R, T, S> embedded_io::Read for Uart<Config<P, EightBit>, D, R, T>
247    where
248        P: ValidPads<Sercom = S>,
249        D: Receive,
250        R: AnyChannel<Status = Ready>,
251        S: Sercom,
252    {
253        #[inline]
254        fn read(&mut self, mut buffer: &mut [u8]) -> Result<usize, Self::Error> {
255            if buffer.is_empty() {
256                return Ok(0);
257            }
258
259            let sercom_ptr = self.sercom_ptr();
260            let channel = self.rx_channel.as_mut();
261
262            unsafe {
263                read_dma::<_, _, S>(channel, sercom_ptr, &mut buffer);
264            }
265
266            while !channel.xfer_complete() {
267                core::hint::spin_loop();
268            }
269
270            while !self.read_flags().contains(Flags::RXC) {
271                core::hint::spin_loop();
272            }
273
274            self.read_flags_errors()?;
275
276            Ok(buffer.len())
277        }
278    }
279}