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 _ = simpl Iterator>
127 .bytes()
128 .map(|c: u8| nb::block!(self.write(Word::from(c))))
129 .last();
130 Ok(())
131 }
132}
133