From c608b8e13588a4a6cee611b1c55affc9d521c83c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Sch=C3=A4fer?= Date: Sat, 8 Jan 2022 14:44:44 +0100 Subject: [PATCH] Support reunite in serial::{Rx,Tx} This becomes relevant as more functions like reconfigure are added to the Serial structs. Fixes #386. --- examples/serial.rs | 8 +++++++ src/serial.rs | 58 ++++++++++++++++++++++++++++------------------ 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/examples/serial.rs b/examples/serial.rs index c1b2ef49..95cc78b7 100644 --- a/examples/serial.rs +++ b/examples/serial.rs @@ -88,5 +88,13 @@ fn main() -> ! { assert_eq!(received, sent); asm::bkpt(); + // And later reunite it again + let mut serial = tx.reunite(rx); + let sent = b'Z'; + block!(serial.write(sent)).ok(); + let received = block!(serial.read()).unwrap(); + assert_eq!(received, sent); + asm::bkpt(); + loop {} } diff --git a/src/serial.rs b/src/serial.rs index 1d39d285..b3b11f11 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -190,7 +190,6 @@ pub struct Serial { } pub struct ErasedSerial { - usart: USART, tx: Tx, rx: Rx, } @@ -209,7 +208,7 @@ pub struct Rx { /// Serial transmitter pub struct Tx { - _usart: PhantomData, + usart: USART, } impl Rx { @@ -218,13 +217,21 @@ impl Rx { _usart: PhantomData, } } + + /// Reunite the two halves of a split serial + pub fn reunite(self, tx: Tx) -> ErasedSerial { + ErasedSerial { rx: self, tx } + } } impl Tx { - fn new() -> Self { - Self { - _usart: PhantomData, - } + fn new(usart: USART) -> Self { + Self { usart } + } + + /// Reunite the two halves of a split serial + pub fn reunite(self, rx: Rx) -> ErasedSerial { + ErasedSerial { tx: self, rx } } } @@ -244,7 +251,8 @@ where // UE: enable USART // RE: enable receiver // TE: enable transceiver - self.usart + self.tx + .usart .cr1 .modify(|_r, w| w.ue().set_bit().re().set_bit().te().set_bit()); @@ -255,7 +263,7 @@ where // Configure baud rate let brr = USART::get_frequency(&clocks).0 / config.baudrate.0; assert!(brr >= 16, "impossible baud rate"); - self.usart.brr.write(|w| unsafe { w.bits(brr) }); + self.tx.usart.brr.write(|w| unsafe { w.bits(brr) }); // Configure parity and word length // Unlike most uart devices, the "word length" of this usart device refers to @@ -267,7 +275,7 @@ where Parity::ParityEven => (true, true, false), Parity::ParityOdd => (true, true, true), }; - self.usart.cr1.modify(|_r, w| { + self.tx.usart.cr1.modify(|_r, w| { w.m() .bit(word_length) .ps() @@ -283,7 +291,7 @@ where StopBits::STOP2 => 0b10, StopBits::STOP1P5 => 0b11, }; - self.usart.cr2.modify(|_r, w| w.stop().bits(stop_bits)); + self.tx.usart.cr2.modify(|_r, w| w.stop().bits(stop_bits)); } /// Reconfigure the USART instance. @@ -295,7 +303,7 @@ where config: impl Into, clocks: Clocks, ) -> nb::Result<(), Infallible> { - let sr = self.usart.sr.read(); + let sr = self.tx.usart.sr.read(); // if we're currently busy transmitting, we have to wait until that is // over -- regarding reception, we assume that the caller -- with // exclusive access to the Serial instance due to &mut self -- knows @@ -312,9 +320,9 @@ where /// register empty (TXE)_ interrupt pub fn listen(&mut self, event: Event) { match event { - Event::Rxne => self.usart.cr1.modify(|_, w| w.rxneie().set_bit()), - Event::Txe => self.usart.cr1.modify(|_, w| w.txeie().set_bit()), - Event::Idle => self.usart.cr1.modify(|_, w| w.idleie().set_bit()), + Event::Rxne => self.tx.usart.cr1.modify(|_, w| w.rxneie().set_bit()), + Event::Txe => self.tx.usart.cr1.modify(|_, w| w.txeie().set_bit()), + Event::Idle => self.tx.usart.cr1.modify(|_, w| w.idleie().set_bit()), } } @@ -323,25 +331,25 @@ where /// register empty (TXE)_ interrupt pub fn unlisten(&mut self, event: Event) { match event { - Event::Rxne => self.usart.cr1.modify(|_, w| w.rxneie().clear_bit()), - Event::Txe => self.usart.cr1.modify(|_, w| w.txeie().clear_bit()), - Event::Idle => self.usart.cr1.modify(|_, w| w.idleie().clear_bit()), + Event::Rxne => self.tx.usart.cr1.modify(|_, w| w.rxneie().clear_bit()), + Event::Txe => self.tx.usart.cr1.modify(|_, w| w.txeie().clear_bit()), + Event::Idle => self.tx.usart.cr1.modify(|_, w| w.idleie().clear_bit()), } } /// Returns true if the line idle status is set pub fn is_idle(&self) -> bool { - self.usart.sr.read().idle().bit_is_set() + self.tx.usart.sr.read().idle().bit_is_set() } /// Returns true if the tx register is empty (and can accept data) pub fn is_tx_empty(&self) -> bool { - self.usart.sr.read().txe().bit_is_set() + self.tx.usart.sr.read().txe().bit_is_set() } /// Returns true if the rx register is not empty (and can be read) pub fn is_rx_not_empty(&self) -> bool { - self.usart.sr.read().rxne().bit_is_set() + self.tx.usart.sr.read().rxne().bit_is_set() } /// Clear idle line interrupt flag @@ -365,7 +373,7 @@ where { /// Returns ownership of the borrowed register handles pub fn release(self) -> (USART, PINS) { - (self.inner.usart, self.pins) + (self.inner.tx.usart, self.pins) } /// Erase the pins used for the Serial from the type @@ -385,7 +393,11 @@ where /// If a transmission is currently in progress, this returns /// [`nb::Error::WouldBlock`]. #[inline(always)] - pub fn reconfigure(&mut self, config: impl Into, clocks: Clocks) -> nb::Result<(), ()> { + pub fn reconfigure( + &mut self, + config: impl Into, + clocks: Clocks, + ) -> nb::Result<(), Infallible> { self.inner.reconfigure(config, clocks) } @@ -476,7 +488,7 @@ macro_rules! hal { PINS: Pins<$USARTX>, { #[allow(unused_unsafe)] - Serial { pins, inner: ErasedSerial{ usart, tx: Tx::new(), rx: Rx::new() }.init(config.into(), clocks, || { + Serial { pins, inner: ErasedSerial{ tx: Tx::new(usart), rx: Rx::new() }.init(config.into(), clocks, || { mapr.modify_mapr(|_, w| unsafe { #[allow(clippy::redundant_closure_call)] w.$usartX_remap().$bit(($closure)(PINS::REMAP))