embedded_hal_nb/
serial.rs

1//! Serial interface.
2
3/// Serial error.
4pub trait Error: core::fmt::Debug {
5    /// Convert error to a generic serial error kind
6    ///
7    /// By using this method, serial errors freely defined by HAL implementations
8    /// can be converted to a set of generic serial errors upon which generic
9    /// code can act.
10    fn kind(&self) -> ErrorKind;
11}
12
13impl Error for core::convert::Infallible {
14    #[inline]
15    fn kind(&self) -> ErrorKind {
16        match *self {}
17    }
18}
19
20/// Serial error kind.
21///
22/// This represents a common set of serial operation errors. HAL implementations are
23/// free to define more specific or additional error types. However, by providing
24/// a mapping to these common serial errors, generic code can still react to them.
25#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
26#[non_exhaustive]
27pub enum ErrorKind {
28    /// The peripheral receive buffer was overrun.
29    Overrun,
30    /// Received data does not conform to the peripheral configuration.
31    /// Can be caused by a misconfigured device on either end of the serial line.
32    FrameFormat,
33    /// Parity check failed.
34    Parity,
35    /// Serial line is too noisy to read valid data.
36    Noise,
37    /// A different error occurred. The original error may contain more information.
38    Other,
39}
40
41impl Error for ErrorKind {
42    #[inline]
43    fn kind(&self) -> ErrorKind {
44        *self
45    }
46}
47
48impl core::fmt::Display for ErrorKind {
49    #[inline]
50    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
51        match self {
52            Self::Overrun => write!(f, "The peripheral receive buffer was overrun"),
53            Self::Parity => write!(f, "Parity check failed"),
54            Self::Noise => write!(f, "Serial line is too noisy to read valid data"),
55            Self::FrameFormat => write!(
56                f,
57                "Received data does not conform to the peripheral configuration"
58            ),
59            Self::Other => write!(
60                f,
61                "A different error occurred. The original error may contain more information"
62            ),
63        }
64    }
65}
66
67/// Serial error type trait.
68///
69/// This just defines the error type, to be used by the other traits.
70pub trait ErrorType {
71    /// Error type
72    type Error: Error;
73}
74
75impl<T: ErrorType + ?Sized> ErrorType for &mut T {
76    type Error = T::Error;
77}
78
79/// Read half of a serial interface.
80///
81/// Some serial interfaces support different data sizes (8 bits, 9 bits, etc.);
82/// This can be encoded in this trait via the `Word` type parameter.
83pub trait Read<Word: Copy = u8>: ErrorType {
84    /// Reads a single word from the serial interface
85    fn read(&mut self) -> nb::Result<Word, Self::Error>;
86}
87
88impl<T: Read<Word> + ?Sized, Word: Copy> Read<Word> for &mut T {
89    #[inline]
90    fn read(&mut self) -> nb::Result<Word, Self::Error> {
91        T::read(self)
92    }
93}
94
95/// Write half of a serial interface.
96pub trait Write<Word: Copy = u8>: ErrorType {
97    /// Writes a single word to the serial interface.
98    fn write(&mut self, word: Word) -> nb::Result<(), Self::Error>;
99
100    /// Ensures that none of the previously written words are still buffered.
101    fn flush(&mut self) -> nb::Result<(), Self::Error>;
102}
103
104impl<T: Write<Word> + ?Sized, Word: Copy> Write<Word> for &mut T {
105    #[inline]
106    fn write(&mut self, word: Word) -> nb::Result<(), Self::Error> {
107        T::write(self, word)
108    }
109
110    #[inline]
111    fn flush(&mut self) -> nb::Result<(), Self::Error> {
112        T::flush(self)
113    }
114}
115
116/// Implementation of `core::fmt::Write` for the HAL's `serial::Write`.
117///
118/// TODO write example of usage
119
120impl<Word, Error: self::Error> core::fmt::Write for dyn Write<Word, Error = Error> + '_
121where
122    Word: Copy + From<u8>,
123{
124    #[inline]
125    fn write_str(&mut self, s: &str) -> core::fmt::Result {
126        let _ = s
127            .bytes()
128            .map(|c| nb::block!(self.write(Word::from(c))))
129            .last();
130        Ok(())
131    }
132}