From 3bc7c7f214c24f65e7b80eaf9b366e23a40c479f Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Mon, 15 Aug 2022 23:21:21 +0300 Subject: [PATCH 1/2] Deref for UTx --- CHANGELOG.md | 5 +- src/serial.rs | 228 ++++++++++++------------------------------- src/serial/hal_02.rs | 68 +------------ src/serial/hal_1.rs | 54 +--------- 4 files changed, 67 insertions(+), 288 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66be2745..37271e91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added -- Serial Tx, Rx containing pins [#514] +- Serial Tx, Rx containing pins [#514] [#515] - Implementation of From trait for Pin-to-PartiallyErasedPin [#507] - Implementation of From trait for Pin-to-ErasedPin [#507] - Implementation of From trait for PartiallyErasedPin-to-ErasedPin [#507] @@ -39,7 +39,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). [#507]: https://github.com/stm32-rs/stm32f4xx-hal/pull/507 [#508]: https://github.com/stm32-rs/stm32f4xx-hal/pull/508 [#510]: https://github.com/stm32-rs/stm32f4xx-hal/pull/510 -[#510]: https://github.com/stm32-rs/stm32f4xx-hal/pull/514 +[#514]: https://github.com/stm32-rs/stm32f4xx-hal/pull/514 +[#515]: https://github.com/stm32-rs/stm32f4xx-hal/pull/515 ## [v0.13.2] - 2022-05-16 diff --git a/src/serial.rs b/src/serial.rs index fa463333..8b6d9eac 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -18,6 +18,7 @@ use core::fmt; use core::marker::PhantomData; +use core::ops::{Deref, DerefMut}; use crate::rcc; use nb::block; @@ -334,24 +335,22 @@ impl AsMut> for Serial { /// Serial receiver containing RX pin pub struct URx { - _usart: PhantomData, + inner: Rx, pin: RX, - _word: PhantomData, } /// Serial transmitter containing TX pin pub struct UTx { + inner: Tx, usart: USART, pin: TX, - _word: PhantomData, } impl URx { fn new(pin: RX) -> Self { Self { - _usart: PhantomData, + inner: Rx::new(), pin, - _word: PhantomData, } } @@ -359,47 +358,15 @@ impl URx { Rx::new() } - /// Start listening for an rx not empty interrupt event - /// - /// Note, you will also have to enable the corresponding interrupt - /// in the NVIC to start receiving events. - pub fn listen(&mut self) { - unsafe { (*USART::ptr()).cr1.modify(|_, w| w.rxneie().set_bit()) } - } - - /// Stop listening for the rx not empty interrupt event - pub fn unlisten(&mut self) { - unsafe { (*USART::ptr()).cr1.modify(|_, w| w.rxneie().clear_bit()) } - } - - /// Start listening for a line idle interrupt event - /// - /// Note, you will also have to enable the corresponding interrupt - /// in the NVIC to start receiving events. - pub fn listen_idle(&mut self) { - unsafe { (*USART::ptr()).cr1.modify(|_, w| w.idleie().set_bit()) } - } - - /// Stop listening for the line idle interrupt event - pub fn unlisten_idle(&mut self) { - unsafe { (*USART::ptr()).cr1.modify(|_, w| w.idleie().clear_bit()) } - } - - /// Return true if the line idle status is set - pub fn is_idle(&self) -> bool { - unsafe { (*USART::ptr()).sr.read().idle().bit_is_set() } - } - - /// Return true if the rx register is not empty (and can be read) - pub fn is_rx_not_empty(&self) -> bool { - unsafe { (*USART::ptr()).sr.read().rxne().bit_is_set() } - } - - /// Clear idle line interrupt flag - pub fn clear_idle_interrupt(&self) { - unsafe { - let _ = (*USART::ptr()).sr.read(); - let _ = (*USART::ptr()).dr.read(); + pub fn join(self, tx: UTx) -> Serial + where + (TX, RX): Pins, + { + Serial { + usart: tx.usart, + pins: (tx.pin, self.pin), + tx: tx.inner, + rx: self.inner, } } } @@ -407,9 +374,9 @@ impl URx { impl UTx { fn new(usart: USART, pin: TX) -> Self { Self { + inner: Tx::new(), usart, pin, - _word: PhantomData, } } @@ -424,28 +391,59 @@ impl UTx { Serial { usart: self.usart, pins: (self.pin, rx.pin), - tx: Tx::new(), - rx: Rx::new(), + tx: self.inner, + rx: rx.inner, } } +} - /// Start listening for a tx empty interrupt event - /// - /// Note, you will also have to enable the corresponding interrupt - /// in the NVIC to start receiving events. - // TODO: replace with "self.usart" - pub fn listen(&mut self) { - unsafe { (*USART::ptr()).cr1.modify(|_, w| w.txeie().set_bit()) } +impl AsRef> for UTx { + fn as_ref(&self) -> &Tx { + &self.inner } +} - /// Stop listening for the tx empty interrupt event - pub fn unlisten(&mut self) { - unsafe { (*USART::ptr()).cr1.modify(|_, w| w.txeie().clear_bit()) } +impl Deref for UTx { + type Target = Tx; + fn deref(&self) -> &Self::Target { + &self.inner } +} - /// Return true if the tx register is empty (and can accept data) - pub fn is_tx_empty(&self) -> bool { - unsafe { (*USART::ptr()).sr.read().txe().bit_is_set() } +impl AsRef> for URx { + fn as_ref(&self) -> &Rx { + &self.inner + } +} + +impl Deref for URx { + type Target = Rx; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl AsMut> for UTx { + fn as_mut(&mut self) -> &mut Tx { + &mut self.inner + } +} + +impl DerefMut for UTx { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} + +impl AsMut> for URx { + fn as_mut(&mut self) -> &mut Rx { + &mut self.inner + } +} + +impl DerefMut for URx { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner } } @@ -1035,109 +1033,3 @@ impl Tx { nb::block!(self.flush()) } } - -impl fmt::Write for UTx { - fn write_str(&mut self, s: &str) -> fmt::Result { - s.bytes() - .try_for_each(|c| block!(self.write(c))) - .map_err(|_| fmt::Error) - } -} - -impl URx { - fn read(&mut self) -> nb::Result { - // Delegate to the Read implementation, then truncate to 8 bits - Rx::::new().read().map(|word16| word16 as u8) - } -} - -impl URx { - fn read(&mut self) -> nb::Result { - // NOTE(unsafe) atomic read with no side effects - let sr = unsafe { (*USART::ptr()).sr.read() }; - - // Any error requires the dr to be read to clear - if sr.pe().bit_is_set() - || sr.fe().bit_is_set() - || sr.nf().bit_is_set() - || sr.ore().bit_is_set() - { - unsafe { (*USART::ptr()).dr.read() }; - } - - Err(if sr.pe().bit_is_set() { - Error::Parity.into() - } else if sr.fe().bit_is_set() { - Error::FrameFormat.into() - } else if sr.nf().bit_is_set() { - Error::Noise.into() - } else if sr.ore().bit_is_set() { - Error::Overrun.into() - } else if sr.rxne().bit_is_set() { - // NOTE(unsafe) atomic read from stateless register - return Ok(unsafe { &*USART::ptr() }.dr.read().dr().bits()); - } else { - nb::Error::WouldBlock - }) - } -} - -impl UTx { - fn write(&mut self, word: u8) -> nb::Result<(), Error> { - // Delegate to u16 version - Tx::::new().write(u16::from(word)) - } - - fn flush(&mut self) -> nb::Result<(), Error> { - // Delegate to u16 version - Tx::::new().flush() - } - - fn bwrite_all(&mut self, bytes: &[u8]) -> Result<(), Error> { - for &b in bytes { - nb::block!(self.write(b))?; - } - Ok(()) - } - - fn bflush(&mut self) -> Result<(), Error> { - nb::block!(self.flush()) - } -} - -impl UTx { - fn write(&mut self, word: u16) -> nb::Result<(), Error> { - // NOTE(unsafe) atomic read with no side effects - let sr = unsafe { (*USART::ptr()).sr.read() }; - - if sr.txe().bit_is_set() { - // NOTE(unsafe) atomic write to stateless register - unsafe { &*USART::ptr() }.dr.write(|w| w.dr().bits(word)); - Ok(()) - } else { - Err(nb::Error::WouldBlock) - } - } - - fn flush(&mut self) -> nb::Result<(), Error> { - // NOTE(unsafe) atomic read with no side effects - let sr = unsafe { (*USART::ptr()).sr.read() }; - - if sr.tc().bit_is_set() { - Ok(()) - } else { - Err(nb::Error::WouldBlock) - } - } - - fn bwrite_all(&mut self, buffer: &[u16]) -> Result<(), Error> { - for &b in buffer { - nb::block!(self.write(b))?; - } - Ok(()) - } - - fn bflush(&mut self) -> Result<(), Error> { - nb::block!(self.flush()) - } -} diff --git a/src/serial/hal_02.rs b/src/serial/hal_02.rs index c58b7bc5..80b47373 100644 --- a/src/serial/hal_02.rs +++ b/src/serial/hal_02.rs @@ -1,5 +1,5 @@ mod nb { - use super::super::{Error, Instance, Rx, Serial, Tx, URx, UTx}; + use super::super::{Error, Instance, Rx, Serial, Tx}; use embedded_hal::serial::{Read, Write}; impl Read for Serial @@ -22,14 +22,6 @@ mod nb { } } - impl Read for URx { - type Error = Error; - - fn read(&mut self) -> nb::Result { - self.read() - } - } - /// Reads 9-bit words from the UART/USART /// /// If the UART/USART was configured with `WordLength::DataBits9`, the returned value will contain @@ -43,14 +35,6 @@ mod nb { } } - impl Read for URx { - type Error = Error; - - fn read(&mut self) -> nb::Result { - self.read() - } - } - impl Write for Serial where USART: Instance, @@ -67,18 +51,6 @@ mod nb { } } - impl Write for UTx { - type Error = Error; - - fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { - self.write(word) - } - - fn flush(&mut self) -> nb::Result<(), Self::Error> { - self.flush() - } - } - /// Writes 9-bit words to the UART/USART /// /// If the UART/USART was configured with `WordLength::DataBits9`, the 9 least significant bits will @@ -95,22 +67,10 @@ mod nb { self.flush() } } - - impl Write for UTx { - type Error = Error; - - fn write(&mut self, word: u16) -> nb::Result<(), Self::Error> { - self.write(word) - } - - fn flush(&mut self) -> nb::Result<(), Self::Error> { - self.flush() - } - } } mod blocking { - use super::super::{Error, Instance, Serial, Tx, UTx}; + use super::super::{Error, Instance, Serial, Tx}; use embedded_hal::blocking::serial::Write; impl Write for Tx { @@ -125,18 +85,6 @@ mod blocking { } } - impl Write for UTx { - type Error = Error; - - fn bwrite_all(&mut self, bytes: &[u8]) -> Result<(), Self::Error> { - self.bwrite_all(bytes) - } - - fn bflush(&mut self) -> Result<(), Self::Error> { - self.bflush() - } - } - impl Write for Serial { type Error = Error; @@ -161,18 +109,6 @@ mod blocking { } } - impl Write for UTx { - type Error = Error; - - fn bwrite_all(&mut self, slice: &[u16]) -> Result<(), Self::Error> { - self.bwrite_all(slice) - } - - fn bflush(&mut self) -> Result<(), Self::Error> { - self.bflush() - } - } - impl Write for Serial { type Error = Error; diff --git a/src/serial/hal_1.rs b/src/serial/hal_1.rs index e44c1cbc..4647952d 100644 --- a/src/serial/hal_1.rs +++ b/src/serial/hal_1.rs @@ -12,16 +12,8 @@ impl ErrorType for super::Tx { type Error = super::Error; } -impl ErrorType for super::URx { - type Error = super::Error; -} - -impl ErrorType for super::UTx { - type Error = super::Error; -} - mod nb { - use super::super::{Error, Instance, Rx, Serial, Tx, URx, UTx}; + use super::super::{Error, Instance, Rx, Serial, Tx}; use embedded_hal_one::serial::{ nb::{Read, Write}, ErrorType, @@ -43,12 +35,6 @@ mod nb { } } - impl Read for URx { - fn read(&mut self) -> nb::Result { - self.read() - } - } - /// Reads 9-bit words from the UART/USART /// /// If the UART/USART was configured with `WordLength::DataBits9`, the returned value will contain @@ -60,12 +46,6 @@ mod nb { } } - impl Read for URx { - fn read(&mut self) -> nb::Result { - self.read() - } - } - impl Write for Serial where USART: Instance, @@ -90,16 +70,6 @@ mod nb { } } - impl Write for UTx { - fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> { - self.write(word) - } - - fn flush(&mut self) -> nb::Result<(), Self::Error> { - self.flush() - } - } - /// Writes 9-bit words to the UART/USART /// /// If the UART/USART was configured with `WordLength::DataBits9`, the 9 least significant bits will @@ -117,7 +87,7 @@ mod nb { } mod blocking { - use super::super::{Instance, Serial, Tx, UTx}; + use super::super::{Instance, Serial, Tx}; use super::ErrorType; use embedded_hal_one::serial::blocking::Write; @@ -145,16 +115,6 @@ mod blocking { } } - impl Write for UTx { - fn write(&mut self, bytes: &[u8]) -> Result<(), Self::Error> { - self.bwrite_all(bytes) - } - - fn flush(&mut self) -> Result<(), Self::Error> { - self.bflush() - } - } - impl Write for Tx { fn write(&mut self, slice: &[u16]) -> Result<(), Self::Error> { self.bwrite_all(slice) @@ -164,14 +124,4 @@ mod blocking { self.bflush() } } - - impl Write for UTx { - fn write(&mut self, slice: &[u16]) -> Result<(), Self::Error> { - self.bwrite_all(slice) - } - - fn flush(&mut self) -> Result<(), Self::Error> { - self.bflush() - } - } } From 3dcfeebbe0deb5415d472ad108706a2de6319262 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Mon, 15 Aug 2022 23:37:03 +0300 Subject: [PATCH 2/2] inline --- src/serial.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/serial.rs b/src/serial.rs index 8b6d9eac..9ad4714c 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -310,24 +310,28 @@ impl Tx { } impl AsRef> for Serial { + #[inline(always)] fn as_ref(&self) -> &Tx { &self.tx } } impl AsRef> for Serial { + #[inline(always)] fn as_ref(&self) -> &Rx { &self.rx } } impl AsMut> for Serial { + #[inline(always)] fn as_mut(&mut self) -> &mut Tx { &mut self.tx } } impl AsMut> for Serial { + #[inline(always)] fn as_mut(&mut self) -> &mut Rx { &mut self.rx } @@ -398,6 +402,7 @@ impl UTx { } impl AsRef> for UTx { + #[inline(always)] fn as_ref(&self) -> &Tx { &self.inner } @@ -405,12 +410,14 @@ impl AsRef> for UTx { impl Deref for UTx { type Target = Tx; + #[inline(always)] fn deref(&self) -> &Self::Target { &self.inner } } impl AsRef> for URx { + #[inline(always)] fn as_ref(&self) -> &Rx { &self.inner } @@ -418,30 +425,35 @@ impl AsRef> for URx { impl Deref for URx { type Target = Rx; + #[inline(always)] fn deref(&self) -> &Self::Target { &self.inner } } impl AsMut> for UTx { + #[inline(always)] fn as_mut(&mut self) -> &mut Tx { &mut self.inner } } impl DerefMut for UTx { + #[inline(always)] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } } impl AsMut> for URx { + #[inline(always)] fn as_mut(&mut self) -> &mut Rx { &mut self.inner } } impl DerefMut for URx { + #[inline(always)] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner }