1 | //! Serial interface. |
2 | |
3 | /// Serial error. |
4 | pub 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 | |
13 | impl 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 ] |
27 | pub 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 | |
41 | impl Error for ErrorKind { |
42 | #[inline ] |
43 | fn kind(&self) -> ErrorKind { |
44 | *self |
45 | } |
46 | } |
47 | |
48 | impl 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. |
70 | pub trait ErrorType { |
71 | /// Error type |
72 | type Error: Error; |
73 | } |
74 | |
75 | impl<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. |
83 | pub 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 | |
88 | impl<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. |
96 | pub 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 | |
104 | impl<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 | |
120 | impl<Word, Error: self::Error> core::fmt::Write for dyn Write<Word, Error = Error> + '_ |
121 | where |
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 | |