|
40 | 40 | use core::marker::PhantomData;
|
41 | 41 | use core::ptr;
|
42 | 42 | use core::sync::atomic::{self, Ordering};
|
| 43 | +use core::ops::Deref; |
43 | 44 |
|
44 | 45 | use nb;
|
45 | 46 | use crate::pac::{USART1, USART2, USART3};
|
@@ -118,11 +119,73 @@ impl Pins<USART3> for (PD8<Alternate<PushPull>>, PD9<Input<Floating>>) {
|
118 | 119 | ///
|
119 | 120 | /// Note that reading / writing is done on the USART peripheral, not on the
|
120 | 121 | /// rx / tx pins!
|
121 |
| -trait UsartReadWrite { |
122 |
| - fn read() -> nb::Result<u8, Error>; |
123 |
| - fn write(byte: u8) -> nb::Result<(), Infallible>; |
124 |
| - fn flush() -> nb::Result<(), Infallible>; |
| 122 | +trait UsartReadWrite: Deref<Target=crate::stm32::usart1::RegisterBlock> { |
| 123 | + fn read(&self) -> nb::Result<u8, Error> { |
| 124 | + let sr = self.sr.read(); |
| 125 | + |
| 126 | + // Check for any errors |
| 127 | + let err = if sr.pe().bit_is_set() { |
| 128 | + Some(Error::Parity) |
| 129 | + } else if sr.fe().bit_is_set() { |
| 130 | + Some(Error::Framing) |
| 131 | + } else if sr.ne().bit_is_set() { |
| 132 | + Some(Error::Noise) |
| 133 | + } else if sr.ore().bit_is_set() { |
| 134 | + Some(Error::Overrun) |
| 135 | + } else { |
| 136 | + None |
| 137 | + }; |
| 138 | + |
| 139 | + if let Some(err) = err { |
| 140 | + // Some error occured. In order to clear that error flag, you have to |
| 141 | + // do a read from the sr register followed by a read from the dr |
| 142 | + // register |
| 143 | + // NOTE(read_volatile) see `write_volatile` below |
| 144 | + unsafe { |
| 145 | + ptr::read_volatile(&self.sr as *const _ as *const _); |
| 146 | + ptr::read_volatile(&self.dr as *const _ as *const _); |
| 147 | + } |
| 148 | + Err(nb::Error::Other(err)) |
| 149 | + } else { |
| 150 | + // Check if a byte is available |
| 151 | + if sr.rxne().bit_is_set() { |
| 152 | + // Read the received byte |
| 153 | + // NOTE(read_volatile) see `write_volatile` below |
| 154 | + Ok(unsafe { |
| 155 | + ptr::read_volatile(&self.dr as *const _ as *const _) |
| 156 | + }) |
| 157 | + } else { |
| 158 | + Err(nb::Error::WouldBlock) |
| 159 | + } |
| 160 | + } |
| 161 | + } |
| 162 | + |
| 163 | + fn write(&self, byte: u8) -> nb::Result<(), Infallible> { |
| 164 | + let sr = self.sr.read(); |
| 165 | + |
| 166 | + if sr.txe().bit_is_set() { |
| 167 | + // NOTE(unsafe) atomic write to stateless register |
| 168 | + // NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API |
| 169 | + unsafe { |
| 170 | + ptr::write_volatile(&self.dr as *const _ as *mut _, byte) |
| 171 | + } |
| 172 | + Ok(()) |
| 173 | + } else { |
| 174 | + Err(nb::Error::WouldBlock) |
| 175 | + } |
| 176 | + } |
| 177 | + |
| 178 | + fn flush(&self) -> nb::Result<(), Infallible> { |
| 179 | + let sr = self.sr.read(); |
| 180 | + |
| 181 | + if sr.tc().bit_is_set() { |
| 182 | + Ok(()) |
| 183 | + } else { |
| 184 | + Err(nb::Error::WouldBlock) |
| 185 | + } |
| 186 | + } |
125 | 187 | }
|
| 188 | +impl UsartReadWrite for &crate::stm32::usart1::RegisterBlock {} |
126 | 189 |
|
127 | 190 | pub enum Parity {
|
128 | 191 | ParityNone,
|
@@ -357,112 +420,42 @@ macro_rules! hal {
|
357 | 420 | }
|
358 | 421 | }
|
359 | 422 |
|
360 |
| - impl UsartReadWrite for $USARTX { |
361 |
| - fn read() -> nb::Result<u8, Error> { |
362 |
| - // NOTE(unsafe) atomic read with no side effects |
363 |
| - let sr = unsafe { (*$USARTX::ptr()).sr.read() }; |
364 |
| - |
365 |
| - // Check for any errors |
366 |
| - let err = if sr.pe().bit_is_set() { |
367 |
| - Some(Error::Parity) |
368 |
| - } else if sr.fe().bit_is_set() { |
369 |
| - Some(Error::Framing) |
370 |
| - } else if sr.ne().bit_is_set() { |
371 |
| - Some(Error::Noise) |
372 |
| - } else if sr.ore().bit_is_set() { |
373 |
| - Some(Error::Overrun) |
374 |
| - } else { |
375 |
| - None |
376 |
| - }; |
377 |
| - |
378 |
| - if let Some(err) = err { |
379 |
| - // Some error occured. In order to clear that error flag, you have to |
380 |
| - // do a read from the sr register followed by a read from the dr |
381 |
| - // register |
382 |
| - // NOTE(read_volatile) see `write_volatile` below |
383 |
| - unsafe { |
384 |
| - ptr::read_volatile(&(*$USARTX::ptr()).sr as *const _ as *const _); |
385 |
| - ptr::read_volatile(&(*$USARTX::ptr()).dr as *const _ as *const _); |
386 |
| - } |
387 |
| - Err(nb::Error::Other(err)) |
388 |
| - } else { |
389 |
| - // Check if a byte is available |
390 |
| - if sr.rxne().bit_is_set() { |
391 |
| - // Read the received byte |
392 |
| - // NOTE(read_volatile) see `write_volatile` below |
393 |
| - Ok(unsafe { |
394 |
| - ptr::read_volatile(&(*$USARTX::ptr()).dr as *const _ as *const _) |
395 |
| - }) |
396 |
| - } else { |
397 |
| - Err(nb::Error::WouldBlock) |
398 |
| - } |
399 |
| - } |
400 |
| - } |
401 |
| - |
402 |
| - fn write(byte: u8) -> nb::Result<(), Infallible> { |
403 |
| - // NOTE(unsafe) atomic read with no side effects |
404 |
| - let sr = unsafe { (*$USARTX::ptr()).sr.read() }; |
405 |
| - |
406 |
| - if sr.txe().bit_is_set() { |
407 |
| - // NOTE(unsafe) atomic write to stateless register |
408 |
| - // NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API |
409 |
| - unsafe { |
410 |
| - ptr::write_volatile(&(*$USARTX::ptr()).dr as *const _ as *mut _, byte) |
411 |
| - } |
412 |
| - Ok(()) |
413 |
| - } else { |
414 |
| - Err(nb::Error::WouldBlock) |
415 |
| - } |
416 |
| - } |
417 |
| - |
418 |
| - fn flush() -> nb::Result<(), Infallible> { |
419 |
| - // NOTE(unsafe) atomic read with no side effects |
420 |
| - let sr = unsafe { (*$USARTX::ptr()).sr.read() }; |
421 |
| - |
422 |
| - if sr.tc().bit_is_set() { |
423 |
| - Ok(()) |
424 |
| - } else { |
425 |
| - Err(nb::Error::WouldBlock) |
426 |
| - } |
427 |
| - } |
428 |
| - } |
429 |
| - |
430 | 423 | impl crate::hal::serial::Read<u8> for Rx<$USARTX> {
|
431 | 424 | type Error = Error;
|
432 | 425 |
|
433 | 426 | fn read(&mut self) -> nb::Result<u8, Error> {
|
434 |
| - $USARTX::read() |
| 427 | + unsafe { &*$USARTX::ptr() }.read() |
435 | 428 | }
|
436 | 429 | }
|
437 | 430 |
|
438 | 431 | impl crate::hal::serial::Write<u8> for Tx<$USARTX> {
|
439 | 432 | type Error = Infallible;
|
440 | 433 |
|
441 | 434 | fn flush(&mut self) -> nb::Result<(), Self::Error> {
|
442 |
| - $USARTX::flush() |
| 435 | + unsafe { &*$USARTX::ptr() }.flush() |
443 | 436 | }
|
444 | 437 | fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
|
445 |
| - $USARTX::write(byte) |
| 438 | + unsafe { &*$USARTX::ptr() }.write(byte) |
446 | 439 | }
|
447 | 440 | }
|
448 | 441 |
|
449 | 442 | impl<PINS> crate::hal::serial::Read<u8> for Serial<$USARTX, PINS> {
|
450 | 443 | type Error = Error;
|
451 | 444 |
|
452 | 445 | fn read(&mut self) -> nb::Result<u8, Error> {
|
453 |
| - $USARTX::read() |
| 446 | + self.usart.deref().read() |
454 | 447 | }
|
455 | 448 | }
|
456 | 449 |
|
457 | 450 | impl<PINS> crate::hal::serial::Write<u8> for Serial<$USARTX, PINS> {
|
458 | 451 | type Error = Infallible;
|
459 | 452 |
|
460 | 453 | fn flush(&mut self) -> nb::Result<(), Self::Error> {
|
461 |
| - $USARTX::flush() |
| 454 | + self.usart.deref().flush() |
462 | 455 | }
|
463 | 456 |
|
464 | 457 | fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
|
465 |
| - $USARTX::write(byte) |
| 458 | + self.usart.deref().write(byte) |
466 | 459 | }
|
467 | 460 | }
|
468 | 461 |
|
|
0 commit comments