Skip to main content

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        while !self.read_flags_errors()?.contains(Flags::RXC) {
111            core::hint::spin_loop();
112        }
113
114        let mut bytes_read = 0;
115
116        while self.read_flags_errors()?.contains(Flags::RXC) {
117            let w = nb::block!(<Self as embedded_hal_nb::serial::Read<u8>>::read(self))?;
118            buf[bytes_read] = w;
119            bytes_read += 1;
120        }
121
122        Ok(bytes_read)
123    }
124
125    #[inline]
126    fn read_exact(
127        &mut self,
128        buf: &mut [u8],
129    ) -> Result<(), embedded_io::ReadExactError<Self::Error>> {
130        if buf.is_empty() {
131            return Ok(());
132        }
133
134        for byte in buf.iter_mut() {
135            let w = nb::block!(<Self as embedded_hal_nb::serial::Read<u8>>::read(self))?;
136            *byte = w;
137        }
138
139        Ok(())
140    }
141}
142
143impl embedded_hal_nb::serial::Error for UartError {
144    #[inline]
145    fn kind(&self) -> embedded_hal_nb::serial::ErrorKind {
146        use embedded_hal_nb::serial::ErrorKind;
147
148        match self {
149            Self::ParityError => ErrorKind::Parity,
150            Self::FrameError => ErrorKind::FrameFormat,
151            Self::Overflow => ErrorKind::Overrun,
152            _ => ErrorKind::Other,
153        }
154    }
155}
156
157impl<C, D, R, T, W> embedded_hal_nb::serial::ErrorType for Uart<C, D, R, T>
158where
159    C: ValidConfig<Word = W>,
160    W: Copy,
161    D: Capability,
162{
163    type Error = UartError;
164}
165
166impl<C, D, R, T> embedded_hal_nb::serial::Read<C::Word> for Uart<C, D, R, T>
167where
168    C: ValidConfig,
169    D: Receive,
170    DataReg: AsPrimitive<C::Word>,
171{
172    #[inline]
173    fn read(&mut self) -> nb::Result<C::Word, Self::Error> {
174        // Wait for an `RXC` flag, then read the word
175        let flags = self.read_flags_errors()?;
176        if flags.contains(Flags::RXC) {
177            unsafe { Ok(self.read_data().as_()) }
178        } else {
179            Err(WouldBlock)
180        }
181    }
182}
183
184impl<C, D, R, T> embedded_hal_nb::serial::Write<C::Word> for Uart<C, D, R, T>
185where
186    C: ValidConfig,
187    D: Transmit,
188{
189    /// Wait for a `DRE` flag, then write a word
190    #[inline]
191    fn write(&mut self, word: C::Word) -> nb::Result<(), Self::Error> {
192        if self.read_flags().contains(Flags::DRE) {
193            unsafe { self.write_data(word.as_()) };
194            Ok(())
195        } else {
196            Err(WouldBlock)
197        }
198    }
199
200    /// Wait for a `TXC` flag
201    #[inline]
202    fn flush(&mut self) -> nb::Result<(), Self::Error> {
203        if self.read_flags().contains(Flags::TXC) {
204            self.clear_flags(Flags::TXC);
205            Ok(())
206        } else {
207            Err(WouldBlock)
208        }
209    }
210}
211
212#[cfg(feature = "dma")]
213mod dma {
214    use super::*;
215    use crate::{
216        dmac::{AnyChannel, Beat, Ready},
217        sercom::{
218            Sercom,
219            dma::{SercomPtr, SharedSliceBuffer, read_dma, write_dma},
220        },
221    };
222
223    impl<C, D, R, T, W> Uart<C, D, R, T>
224    where
225        C: ValidConfig<Word = W>,
226        D: Capability,
227        W: Beat,
228    {
229        pub(in super::super) fn sercom_ptr(&self) -> SercomPtr<W> {
230            SercomPtr(self.data_ptr())
231        }
232    }
233
234    impl<P, D, R, T, S> embedded_io::Write for Uart<Config<P, EightBit>, D, R, T>
235    where
236        P: ValidPads<Sercom = S>,
237        D: Transmit,
238        T: AnyChannel<Status = Ready>,
239        S: Sercom,
240    {
241        #[inline]
242        fn write(&mut self, bytes: &[u8]) -> Result<usize, Self::Error> {
243            let sercom_ptr = self.sercom_ptr();
244            let channel = self.tx_channel.as_mut();
245            let mut buffer = SharedSliceBuffer::from_slice(bytes);
246
247            unsafe {
248                write_dma::<_, _, S>(channel, sercom_ptr, &mut buffer);
249            }
250
251            while !channel.xfer_complete() {
252                core::hint::spin_loop();
253            }
254
255            while !self.read_flags().contains(Flags::TXC) {
256                core::hint::spin_loop();
257            }
258
259            Ok(bytes.len())
260        }
261
262        /// Wait for a `TXC` flag
263        #[inline]
264        fn flush(&mut self) -> Result<(), Self::Error> {
265            nb::block!(<Self as embedded_hal_nb::serial::Write<u8>>::flush(self))?;
266            Ok(())
267        }
268    }
269
270    impl<P, D, R, T, S> embedded_io::Read for Uart<Config<P, EightBit>, D, R, T>
271    where
272        P: ValidPads<Sercom = S>,
273        D: Receive,
274        R: AnyChannel<Status = Ready>,
275        S: Sercom,
276    {
277        #[inline]
278        fn read(&mut self, mut buffer: &mut [u8]) -> Result<usize, Self::Error> {
279            if buffer.is_empty() {
280                return Ok(0);
281            }
282
283            let sercom_ptr = self.sercom_ptr();
284            let channel = self.rx_channel.as_mut();
285
286            unsafe {
287                read_dma::<_, _, S>(channel, sercom_ptr, &mut buffer);
288            }
289
290            while !channel.xfer_complete() {
291                core::hint::spin_loop();
292            }
293
294            while !self.read_flags().contains(Flags::RXC) {
295                core::hint::spin_loop();
296            }
297
298            self.read_flags_errors()?;
299
300            Ok(buffer.len())
301        }
302    }
303}