1use core::fmt;
2use core::ops::Deref;
3use core::marker::PhantomData;
4
5use crate::{
6 typestates::{
7 pin::{
8 flexcomm::{
9 Usart,
11 UsartPins,
12 },
13 PinId,
14 },
15 },
16 traits::wg::serial,
17 time::Hertz,
18};
19
20pub mod config;
21
22#[derive(Debug)]
24pub enum Error {
25 Framing,
27 Noise,
29 Overrun,
31 Parity,
33 #[doc(hidden)]
34 _Extensible,
35}
36
37pub struct Serial<TX, RX, USART, PINS>
49where
50 TX: PinId,
51 RX: PinId,
52 USART: Usart,
53 PINS: UsartPins<TX, RX, USART>,
54{
55 usart: USART,
56 pins: PINS,
57 _tx: PhantomData<TX>,
58 _rx: PhantomData<RX>,
59}
60
61pub struct Tx<USART: Usart> {
68 addr: usize,
69 _usart: PhantomData<USART>,
70}
71
72pub struct Rx<USART: Usart> {
74 addr: usize,
75 _usart: PhantomData<USART>,
76}
77
78impl<USART: Usart> Deref for Tx<USART> {
79 type Target = raw::usart0::RegisterBlock;
80 fn deref(&self) -> &Self::Target {
81 let ptr = self.addr as *const _;
82 unsafe { &*ptr }
83 }
84}
85
86impl<USART: Usart> Deref for Rx<USART> {
87 type Target = raw::usart0::RegisterBlock;
88 fn deref(&self) -> &Self::Target {
89 let ptr = self.addr as *const _;
90 unsafe { &*ptr }
91 }
92}
93
94impl<TX, RX, USART, PINS> Serial<TX, RX, USART, PINS>
95where
96 TX: PinId,
97 RX: PinId,
98 USART: Usart,
99 PINS: UsartPins<TX, RX, USART>,
100{
101 const CLOCK_SPEED: u32 = 12_000_000;
102
103 pub fn new(usart: USART, pins: PINS, config: config::Config) -> Self {
104 use self::config::*;
105
106 let speed: Hertz = config.speed.into();
107 let speed: u32 = speed.0;
108
109 usart.fifocfg.modify(|_, w| w
110 .enabletx().enabled()
111 .enablerx().enabled()
112 );
113
114 usart.fifotrig.modify(|_, w| unsafe { w
115 .txlvl().bits(0)
116 .txlvlena().enabled()
117 .rxlvl().bits(1)
118 .rxlvlena().enabled()
119 });
120
121 usart.cfg.write(|w| unsafe { w
122 .paritysel().bits(match config.parity {
123 Parity::ParityNone => 0,
124 Parity::ParityEven => 2,
125 Parity::ParityOdd => 3,
126 })
127 .stoplen().bit(match config.stopbits {
128 StopBits::STOP1 => false,
129 StopBits::STOP2 => true,
130 })
131 .datalen().bits(match config.wordlength {
132 WordLength::DataBits7 => 0,
133 WordLength::DataBits8 => 1,
134 WordLength::DataBits9 => 2,
135 })
136
137 .loop_().normal()
141 .syncen().asynchronous_mode()
143 .clkpol().falling_edge()
145
146 .enable().enabled()
148 });
149
150 let mut best_diff = !0;
152 let mut best_osr = 15;
153 let mut best_brg = !0;
154
155 for osr in (9..=16).rev() {
158 let brg = Self::CLOCK_SPEED / (osr * speed);
159 if brg >= 0xffff {
160 continue;
161 }
162 let realized_speed = Self::CLOCK_SPEED / (osr * brg);
163 let diff = if speed > realized_speed { speed - realized_speed} else { realized_speed - speed };
164 if diff < best_diff {
165 best_diff = diff;
166 best_osr = osr;
167 best_brg = brg;
168 }
169 }
170
171 if best_brg >= 0xffff {
173 panic!("baudrate not supported");
174 }
175
176 usart.brg.write(|w| unsafe { w.brgval().bits(best_brg as u16 - 1) });
177 usart.osr.write(|w| unsafe { w.osrval().bits(best_osr as u8 - 1) });
178
179 Self {
180 usart,
181 pins,
182 _tx: PhantomData,
183 _rx: PhantomData,
184 }
185 }
186
187 fn addr(&self) -> usize {
188 &(*self.usart) as *const _ as usize
189 }
190
191 pub fn split(self) -> (Tx<USART>, Rx<USART>) {
192 (
203 Tx {
204 addr: self.addr(),
205 _usart: PhantomData,
206 },
207 Rx {
208 addr: self.addr(),
209 _usart: PhantomData,
210 },
211 )
212 }
213
214 pub fn release(self) -> (USART, PINS) {
215 (self.usart, self.pins)
216 }
217}
218
219impl<TX, RX, USART, PINS> serial::Read<u8> for Serial<TX, RX, USART, PINS>
220where
221 TX: PinId,
222 RX: PinId,
223 USART: Usart,
224 PINS: UsartPins<TX, RX, USART>,
225{
226 type Error = Error;
227
228 fn read(&mut self) -> nb::Result<u8, Error> {
229 let mut rx: Rx<USART> = Rx {
230 addr: self.addr(),
231 _usart: PhantomData,
232 };
233 rx.read()
234 }
235}
236
237impl<USART: Usart> serial::Read<u8> for Rx<USART> {
238 type Error = Error;
239
240 fn read(&mut self) -> nb::Result<u8, Error> {
241 let fifostat = self.fifostat.read();
242
243 if fifostat.rxnotempty().bit() {
244
245 let fiford = self.fiford.read();
248
249 if fiford.framerr().bit_is_set() {
250 return Err(nb::Error::Other(Error::Framing));
251 }
252
253 if fiford.parityerr().bit_is_set() {
254 return Err(nb::Error::Other(Error::Parity));
255 }
256
257 if fiford.rxnoise().bit_is_set() {
258 return Err(nb::Error::Other(Error::Noise));
259 }
260
261 if fifostat.rxerr().bit_is_set() {
262 self.fifocfg.modify(|_, w| w.emptyrx().set_bit());
264 self.fifostat.modify(|_, w| w.rxerr().set_bit());
265 return Err(nb::Error::Other(Error::Overrun));
266 }
267
268 Ok(fiford.rxdata().bits() as u8)
269
270 } else {
271 Err(nb::Error::WouldBlock)
273 }
274 }
275}
276
277
278impl<TX, RX, USART, PINS> serial::Write<u8> for Serial<TX, RX, USART, PINS>
279where
280 TX: PinId,
281 RX: PinId,
282 USART: Usart,
283 PINS: UsartPins<TX, RX, USART>,
284{
285 type Error = Error;
286
287 fn flush(&mut self) -> nb::Result<(), Self::Error> {
288 let mut tx: Tx<USART> = Tx {
289 addr: self.addr(),
290 _usart: PhantomData,
291 };
292 tx.flush()
293 }
294
295 fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
296 let mut tx: Tx<USART> = Tx {
297 addr: self.addr(),
298 _usart: PhantomData,
299 };
300 tx.write(byte)
301 }
302}
303
304impl<USART: Usart> serial::Write<u8> for Tx<USART> {
305 type Error = Error;
306
307 fn flush(&mut self) -> nb::Result<(), Self::Error> {
308 if self.stat.read().txidle().bit() {
309 Ok(())
310 } else {
311 Err(nb::Error::WouldBlock)
312 }
313 }
314
315 fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
316 if self.fifostat.read().txnotfull().bit() {
317 self.fifowr.write(|w| unsafe { w.bits(byte as u32) } );
320
321 Ok(())
322 } else {
323 Err(nb::Error::WouldBlock)
324 }
325 }
326}
327
328impl<USART: Usart> fmt::Write for Tx<USART>
329where
330 Tx<USART>: serial::Write<u8>,
331{
332 fn write_str(&mut self, s: &str) -> fmt::Result {
333 use crate::traits::wg::serial::Write;
334 let _ = s
335 .as_bytes()
336 .iter()
337 .map(|c| nb::block!(self.write(*c)))
338 .last();
339 Ok(())
340 }
341}