|
@@ -40,6 +40,7 @@
|
|
use core::marker::PhantomData;
|
|
use core::marker::PhantomData;
|
|
use core::ptr;
|
|
use core::ptr;
|
|
use core::sync::atomic::{self, Ordering};
|
|
use core::sync::atomic::{self, Ordering};
|
|
|
|
+use core::ops::Deref;
|
|
|
|
|
|
use nb;
|
|
use nb;
|
|
use crate::pac::{USART1, USART2, USART3};
|
|
use crate::pac::{USART1, USART2, USART3};
|
|
@@ -115,14 +116,73 @@ impl Pins<USART3> for (PD8<Alternate<PushPull>>, PD9<Input<Floating>>) {
|
|
}
|
|
}
|
|
|
|
|
|
/// Internal trait for the serial read / write logic.
|
|
/// Internal trait for the serial read / write logic.
|
|
-///
|
|
|
|
-/// Note that reading / writing is done on the USART peripheral, not on the
|
|
|
|
-/// rx / tx pins!
|
|
|
|
-trait UsartReadWrite {
|
|
|
|
- fn read() -> nb::Result<u8, Error>;
|
|
|
|
- fn write(byte: u8) -> nb::Result<(), Infallible>;
|
|
|
|
- fn flush() -> nb::Result<(), Infallible>;
|
|
|
|
|
|
+trait UsartReadWrite: Deref<Target=crate::stm32::usart1::RegisterBlock> {
|
|
|
|
+ fn read(&self) -> nb::Result<u8, Error> {
|
|
|
|
+ let sr = self.sr.read();
|
|
|
|
+
|
|
|
|
+ // Check for any errors
|
|
|
|
+ let err = if sr.pe().bit_is_set() {
|
|
|
|
+ Some(Error::Parity)
|
|
|
|
+ } else if sr.fe().bit_is_set() {
|
|
|
|
+ Some(Error::Framing)
|
|
|
|
+ } else if sr.ne().bit_is_set() {
|
|
|
|
+ Some(Error::Noise)
|
|
|
|
+ } else if sr.ore().bit_is_set() {
|
|
|
|
+ Some(Error::Overrun)
|
|
|
|
+ } else {
|
|
|
|
+ None
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ if let Some(err) = err {
|
|
|
|
+ // Some error occured. In order to clear that error flag, you have to
|
|
|
|
+ // do a read from the sr register followed by a read from the dr
|
|
|
|
+ // register
|
|
|
|
+ // NOTE(read_volatile) see `write_volatile` below
|
|
|
|
+ unsafe {
|
|
|
|
+ ptr::read_volatile(&self.sr as *const _ as *const _);
|
|
|
|
+ ptr::read_volatile(&self.dr as *const _ as *const _);
|
|
|
|
+ }
|
|
|
|
+ Err(nb::Error::Other(err))
|
|
|
|
+ } else {
|
|
|
|
+ // Check if a byte is available
|
|
|
|
+ if sr.rxne().bit_is_set() {
|
|
|
|
+ // Read the received byte
|
|
|
|
+ // NOTE(read_volatile) see `write_volatile` below
|
|
|
|
+ Ok(unsafe {
|
|
|
|
+ ptr::read_volatile(&self.dr as *const _ as *const _)
|
|
|
|
+ })
|
|
|
|
+ } else {
|
|
|
|
+ Err(nb::Error::WouldBlock)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn write(&self, byte: u8) -> nb::Result<(), Infallible> {
|
|
|
|
+ let sr = self.sr.read();
|
|
|
|
+
|
|
|
|
+ if sr.txe().bit_is_set() {
|
|
|
|
+ // NOTE(unsafe) atomic write to stateless register
|
|
|
|
+ // NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
|
|
|
|
+ unsafe {
|
|
|
|
+ ptr::write_volatile(&self.dr as *const _ as *mut _, byte)
|
|
|
|
+ }
|
|
|
|
+ Ok(())
|
|
|
|
+ } else {
|
|
|
|
+ Err(nb::Error::WouldBlock)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn flush(&self) -> nb::Result<(), Infallible> {
|
|
|
|
+ let sr = self.sr.read();
|
|
|
|
+
|
|
|
|
+ if sr.tc().bit_is_set() {
|
|
|
|
+ Ok(())
|
|
|
|
+ } else {
|
|
|
|
+ Err(nb::Error::WouldBlock)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+impl UsartReadWrite for &crate::stm32::usart1::RegisterBlock {}
|
|
|
|
|
|
pub enum Parity {
|
|
pub enum Parity {
|
|
ParityNone,
|
|
ParityNone,
|
|
@@ -357,81 +417,11 @@ macro_rules! hal {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- impl UsartReadWrite for $USARTX {
|
|
|
|
- fn read() -> nb::Result<u8, Error> {
|
|
|
|
- // NOTE(unsafe) atomic read with no side effects
|
|
|
|
- let sr = unsafe { (*$USARTX::ptr()).sr.read() };
|
|
|
|
-
|
|
|
|
- // Check for any errors
|
|
|
|
- let err = if sr.pe().bit_is_set() {
|
|
|
|
- Some(Error::Parity)
|
|
|
|
- } else if sr.fe().bit_is_set() {
|
|
|
|
- Some(Error::Framing)
|
|
|
|
- } else if sr.ne().bit_is_set() {
|
|
|
|
- Some(Error::Noise)
|
|
|
|
- } else if sr.ore().bit_is_set() {
|
|
|
|
- Some(Error::Overrun)
|
|
|
|
- } else {
|
|
|
|
- None
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- if let Some(err) = err {
|
|
|
|
- // Some error occured. In order to clear that error flag, you have to
|
|
|
|
- // do a read from the sr register followed by a read from the dr
|
|
|
|
- // register
|
|
|
|
- // NOTE(read_volatile) see `write_volatile` below
|
|
|
|
- unsafe {
|
|
|
|
- ptr::read_volatile(&(*$USARTX::ptr()).sr as *const _ as *const _);
|
|
|
|
- ptr::read_volatile(&(*$USARTX::ptr()).dr as *const _ as *const _);
|
|
|
|
- }
|
|
|
|
- Err(nb::Error::Other(err))
|
|
|
|
- } else {
|
|
|
|
- // Check if a byte is available
|
|
|
|
- if sr.rxne().bit_is_set() {
|
|
|
|
- // Read the received byte
|
|
|
|
- // NOTE(read_volatile) see `write_volatile` below
|
|
|
|
- Ok(unsafe {
|
|
|
|
- ptr::read_volatile(&(*$USARTX::ptr()).dr as *const _ as *const _)
|
|
|
|
- })
|
|
|
|
- } else {
|
|
|
|
- Err(nb::Error::WouldBlock)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- fn write(byte: u8) -> nb::Result<(), Infallible> {
|
|
|
|
- // NOTE(unsafe) atomic read with no side effects
|
|
|
|
- let sr = unsafe { (*$USARTX::ptr()).sr.read() };
|
|
|
|
-
|
|
|
|
- if sr.txe().bit_is_set() {
|
|
|
|
- // NOTE(unsafe) atomic write to stateless register
|
|
|
|
- // NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
|
|
|
|
- unsafe {
|
|
|
|
- ptr::write_volatile(&(*$USARTX::ptr()).dr as *const _ as *mut _, byte)
|
|
|
|
- }
|
|
|
|
- Ok(())
|
|
|
|
- } else {
|
|
|
|
- Err(nb::Error::WouldBlock)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- fn flush() -> nb::Result<(), Infallible> {
|
|
|
|
- // NOTE(unsafe) atomic read with no side effects
|
|
|
|
- let sr = unsafe { (*$USARTX::ptr()).sr.read() };
|
|
|
|
-
|
|
|
|
- if sr.tc().bit_is_set() {
|
|
|
|
- Ok(())
|
|
|
|
- } else {
|
|
|
|
- Err(nb::Error::WouldBlock)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
impl crate::hal::serial::Read<u8> for Rx<$USARTX> {
|
|
impl crate::hal::serial::Read<u8> for Rx<$USARTX> {
|
|
type Error = Error;
|
|
type Error = Error;
|
|
|
|
|
|
fn read(&mut self) -> nb::Result<u8, Error> {
|
|
fn read(&mut self) -> nb::Result<u8, Error> {
|
|
- $USARTX::read()
|
|
|
|
|
|
+ unsafe { &*$USARTX::ptr() }.read()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -439,10 +429,10 @@ macro_rules! hal {
|
|
type Error = Infallible;
|
|
type Error = Infallible;
|
|
|
|
|
|
fn flush(&mut self) -> nb::Result<(), Self::Error> {
|
|
fn flush(&mut self) -> nb::Result<(), Self::Error> {
|
|
- $USARTX::flush()
|
|
|
|
|
|
+ unsafe { &*$USARTX::ptr() }.flush()
|
|
}
|
|
}
|
|
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
|
|
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
|
|
- $USARTX::write(byte)
|
|
|
|
|
|
+ unsafe { &*$USARTX::ptr() }.write(byte)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -450,7 +440,7 @@ macro_rules! hal {
|
|
type Error = Error;
|
|
type Error = Error;
|
|
|
|
|
|
fn read(&mut self) -> nb::Result<u8, Error> {
|
|
fn read(&mut self) -> nb::Result<u8, Error> {
|
|
- $USARTX::read()
|
|
|
|
|
|
+ self.usart.deref().read()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -458,11 +448,11 @@ macro_rules! hal {
|
|
type Error = Infallible;
|
|
type Error = Infallible;
|
|
|
|
|
|
fn flush(&mut self) -> nb::Result<(), Self::Error> {
|
|
fn flush(&mut self) -> nb::Result<(), Self::Error> {
|
|
- $USARTX::flush()
|
|
|
|
|
|
+ self.usart.deref().flush()
|
|
}
|
|
}
|
|
|
|
|
|
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
|
|
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
|
|
- $USARTX::write(byte)
|
|
|
|
|
|
+ self.usart.deref().write(byte)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|