From 5d23ebc177c4b34ea5bee14a6e61ebc2b185efa6 Mon Sep 17 00:00:00 2001 From: Marwan SMOUNI Date: Fri, 11 Feb 2022 16:12:26 +0100 Subject: [PATCH 1/2] allow to configure: +UsartInversion +WordLength +ParityControl --- examples/serial_delay.rs | 3 ++ examples/serial_dma.rs | 3 ++ examples/serial_echo.rs | 3 ++ src/serial.rs | 82 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 87 insertions(+), 4 deletions(-) diff --git a/examples/serial_delay.rs b/examples/serial_delay.rs index 0c1ff94..a74ee06 100644 --- a/examples/serial_delay.rs +++ b/examples/serial_delay.rs @@ -43,6 +43,9 @@ fn main() -> ! { baud_rate: 115_200.Bps(), oversampling: serial::Oversampling::By16, character_match: None, + active_level_inversion: serial::UsartInversion::Standard, + word_length: serial::WordLength::DataBits8, + parity_control: None, }, ); let (mut tx, _) = serial.split(); diff --git a/examples/serial_dma.rs b/examples/serial_dma.rs index cc8b025..6dbdb9d 100644 --- a/examples/serial_dma.rs +++ b/examples/serial_dma.rs @@ -50,6 +50,9 @@ fn main() -> ! { baud_rate: 115_200.Bps(), oversampling: serial::Oversampling::By16, character_match: None, + active_level_inversion: serial::UsartInversion::Standard, + word_length: serial::WordLength::DataBits8, + parity_control: None, }, ); let (mut tx, mut rx) = serial.split(); diff --git a/examples/serial_echo.rs b/examples/serial_echo.rs index ddae8fa..b13ee69 100644 --- a/examples/serial_echo.rs +++ b/examples/serial_echo.rs @@ -39,6 +39,9 @@ fn main() -> ! { baud_rate: 115_200.Bps(), oversampling: serial::Oversampling::By16, character_match: None, + active_level_inversion: serial::UsartInversion::Standard, + word_length: serial::WordLength::DataBits8, + parity_control: None, }, ); diff --git a/src/serial.rs b/src/serial.rs index c86013f..73536d6 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -184,10 +184,62 @@ where let ch = config.character_match.unwrap_or(0); usart.cr2.write(|w| w.add().bits(ch)); - // Enable transmission and receiving - usart - .cr1 - .modify(|_, w| w.te().enabled().re().enabled().ue().enabled()); + // TXINV | RXINV: TX/RX pin active level inversion + match config.active_level_inversion { + UsartInversion::Standard => { + usart + .cr2 + .modify(|_r, w| w.rxinv().clear_bit().txinv().clear_bit()); + } + UsartInversion::Inverted => { + usart + .cr2 + .modify(|_r, w| w.rxinv().set_bit().txinv().set_bit()); + } + } + + usart.cr1.modify(|_r, w| { + match config.word_length { + // M[1:0] + WordLength::DataBits7 => { + // 10: 1 Start bit, 7 data bits + w.m0().clear_bit().m1().set_bit(); + } + WordLength::DataBits8 => { + // 00: 1 Start bit, 9 data bits + w.m0().clear_bit().m1().clear_bit(); + } + WordLength::DataBits9 => { + // 01: 1 Start bit, 9 data bits + w.m0().set_bit().m1().clear_bit(); + } + } + + if let Some(parity) = config.parity_control { + // Parity control enable + w.pce().set_bit(); + match parity { + ParityControl::Even => { + // Parity selection: Even + w.ps().clear_bit(); + } + ParityControl::Odd => { + // Parity selection: Odd + w.ps().set_bit(); + } + } + } + + // USART enable + w.ue() + .set_bit() + // Enable receiving + .re() + .set_bit() + // Enable transmission + .te() + .set_bit() + }); // Enable DMA usart.cr3.write(|w| w.dmat().enabled().dmar().enabled()); @@ -434,9 +486,28 @@ where pub struct Config { pub baud_rate: BytesPerSecond, pub oversampling: Oversampling, + pub active_level_inversion: UsartInversion, + pub word_length: WordLength, + pub parity_control: Option, pub character_match: Option, } +pub enum UsartInversion { + Standard, + Inverted, +} + +pub enum WordLength { + DataBits7, + DataBits8, + DataBits9, +} + +pub enum ParityControl { + Even, + Odd, +} + pub enum Oversampling { By8, By16, @@ -447,6 +518,9 @@ impl Default for Config { Self { baud_rate: 115_200.Bps(), oversampling: Oversampling::By16, + active_level_inversion: UsartInversion::Standard, + word_length: WordLength::DataBits8, + parity_control: None, character_match: None, } } From 1155be105afb24fa5e8798091ea9037eb97dd340 Mon Sep 17 00:00:00 2001 From: Marwan SMOUNI Date: Fri, 11 Feb 2022 16:12:49 +0100 Subject: [PATCH 2/2] allow struct Serial to do DMA Transfer, without calling split(), in order to allow releasing the ressources after using DMA transfers --- src/serial.rs | 88 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 13 deletions(-) diff --git a/src/serial.rs b/src/serial.rs index 73536d6..6cced82 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -46,6 +46,10 @@ pub enum Error { Overrun, /// Parity check error Parity, + /// UsartRx Moved + RxMoved, + /// UsartTx Moved + TxMoved, } pub trait Pins {} @@ -143,12 +147,16 @@ impl PinRx for PF6> {} pub struct Serial { usart: USART, pins: PINS, + tx: Option>, + rx: Option>, } impl Serial where PINS: Pins, USART: Instance, + Rx: dma::Target, + Tx: dma::Target, { pub fn new(usart: USART, pins: PINS, clocks: Clocks, config: Config) -> Self { // NOTE(unsafe) This executes only during initialisation @@ -244,7 +252,16 @@ where // Enable DMA usart.cr3.write(|w| w.dmat().enabled().dmar().enabled()); - Serial { usart, pins } + Serial { + usart, + pins, + tx: Some(Tx { + _usart: PhantomData, + }), + rx: Some(Rx { + _usart: PhantomData, + }), + } } /// Starts listening for an interrupt event @@ -281,6 +298,48 @@ where pub fn release(self) -> (USART, PINS) { (self.usart, self.pins) } + + pub fn read_all( + &mut self, + buffer: Pin, + dma: &dma::Handle< as dma::Target>::Instance, state::Enabled>, + stream: as dma::Target>::Stream, + ) -> Result, B, dma::Ready>, Error> + where + B: DerefMut + 'static, + B::Target: AsMutSlice, + { + if let Some(usart_rx) = self.rx.take() { + Ok(usart_rx.read_all(buffer, dma, stream)) + } else { + Err(Error::RxMoved) + } + } + + pub fn return_rx(&mut self, usart_rx: Rx) { + self.rx.replace(usart_rx); + } + + pub fn write_all( + &mut self, + data: Pin, + dma: &dma::Handle< as dma::Target>::Instance, state::Enabled>, + stream: as dma::Target>::Stream, + ) -> Result, B, dma::Ready>, Error> + where + B: Deref + 'static, + B::Target: AsSlice, + { + if let Some(usart_tx) = self.tx.take() { + Ok(usart_tx.write_all(data, dma, stream)) + } else { + Err(Error::RxMoved) + } + } + + pub fn return_tx(&mut self, usart_tx: Tx) { + self.tx.replace(usart_tx); + } } impl serial::Read for Serial @@ -290,10 +349,11 @@ where type Error = Error; fn read(&mut self) -> nb::Result { - let mut rx: Rx = Rx { - _usart: PhantomData, - }; - rx.read() + if let Some(usart_rx) = &mut self.rx { + usart_rx.read() + } else { + Err(nb::Error::Other(Error::RxMoved)) + } } } @@ -304,17 +364,19 @@ where type Error = Error; fn flush(&mut self) -> nb::Result<(), Self::Error> { - let mut tx: Tx = Tx { - _usart: PhantomData, - }; - tx.flush() + if let Some(usart_tx) = &mut self.tx { + usart_tx.flush() + } else { + Err(nb::Error::Other(Error::TxMoved)) + } } fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> { - let mut tx: Tx = Tx { - _usart: PhantomData, - }; - tx.write(byte) + if let Some(usart_tx) = &mut self.tx { + usart_tx.write(byte) + } else { + Err(nb::Error::Other(Error::TxMoved)) + } } }