From b865df4e2a88956d0a2192b1fc60df1975c8ed92 Mon Sep 17 00:00:00 2001 From: Denys Rtveliashvili Date: Mon, 2 Oct 2023 21:12:01 +0100 Subject: [PATCH 1/5] Hardware flow control for serial interfaces --- src/serial.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/serial.rs b/src/serial.rs index f097bb9..bf43b2f 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -192,6 +192,9 @@ where // Enable DMA usart.cr3.write(|w| w.dmat().enabled().dmar().enabled()); + // Configure hardware flow control + usart.cr3.write(|w| w.ctse().bit(config.cts_enabled).rtse().bit(config.rts_enabled)); + Serial { usart, pins } } @@ -438,7 +441,8 @@ pub struct Config { pub sysclock: bool, pub parity: Parity, pub data_bits: DataBits, - + pub cts_enabled: bool, + pub rts_enabled: bool, } pub enum Oversampling { @@ -479,6 +483,8 @@ impl Default for Config { sysclock: false, parity: Parity::ParityNone, data_bits: DataBits::Bits8, + cts_enabled: false, + rts_enabled: false, } } } From 6605f737c85918957480f85adad7f04ca2475747 Mon Sep 17 00:00:00 2001 From: Denys Rtveliashvili Date: Thu, 26 Oct 2023 06:34:30 +0100 Subject: [PATCH 2/5] An alternative approach to configuring CTS/RTS This is a draft. --- src/serial.rs | 195 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 146 insertions(+), 49 deletions(-) diff --git a/src/serial.rs b/src/serial.rs index bf43b2f..69843ab 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -41,11 +41,13 @@ pub enum Error { pub trait Pins {} pub trait PinTx {} pub trait PinRx {} +pub trait PinCts {} +pub trait PinRts {} -impl Pins for (TX, RX) +impl Pins for (TX, RX) where - TX: PinTx, - RX: PinRx, + TX: PinTx, + RX: PinRx, { } @@ -113,34 +115,119 @@ impl PinRx for gpio::PC7> {} impl PinRx for gpio::PG9> {} impl PinRx for gpio::PE7> {} impl PinRx for gpio::PF6> {} +// TODO where is UART8? + +impl PinCts for gpio::PA11> {} +impl PinCts for gpio::PA0> {} +impl PinCts for gpio::PB13> {} +impl PinCts for gpio::PD11> {} +impl PinCts for gpio::PA15> {} +impl PinCts for gpio::PC9> {} +impl PinCts for gpio::PG13> {} +impl PinCts for gpio::PG15> {} +impl PinCts for gpio::PE10> {} +impl PinCts for gpio::PF9> {} + +impl PinRts for gpio::PA12> {} +impl PinRts for gpio::PA1> {} +impl PinRts for gpio::PB14> {} +impl PinRts for gpio::PD12> {} +impl PinRts for gpio::PB0> {} +impl PinRts for gpio::PC8> {} +impl PinRts for gpio::PG8> {} +impl PinRts for gpio::PG12> {} +impl PinRts for gpio::PE9> {} +impl PinRts for gpio::PF8> {} + + +enum AsyncFlowControl { + Rs232None, + Rs232CtsRts, + Rs232Cts, + Rs232Rts, + // TODO add Rs485 +} + +enum SerialMode { + Async(AsyncFlowControl), + // TODO add SingleWire, IrDA, ModbusCommunication, LIN, SnartCard, etc. +} /// Serial abstraction -pub struct Serial { - usart: USART, +pub struct Serial { + usart: U, pins: PINS, } -impl Serial +pub trait UART { + fn new_async_uart_no_flwctl>( + usart: U, pins: PINS, clocks: &Clocks, config: Config, + ) -> Serial { + Serial::new(usart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232None)) + } + + fn new_async_uart_rs232_cts_rts, CTS: PinCts, RTS: PinRts>( + usart: U, pins: PINS, clocks: &Clocks, config: Config, cts: CTS, rts: RTS, + ) -> Serial { + // TODO Clarify if we can borrow cts and rts and keep them borrowed. + // TODO Note that at the moment any CTS and RTS pin of this U(S)ART would be accepted + // This may be too flexible. + Serial::new(usart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232CtsRts)) + } + + fn new_async_uart_rs232_cts, CTS: PinCts, RTS: PinRts>( + usart: U, pins: PINS, clocks: &Clocks, config: Config, cts: CTS, + ) -> Serial { + Serial::new(usart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232Cts)) + } + + fn new_async_uart_rs232_rts, RTS: PinRts>( + usart: U, pins: PINS, clocks: &Clocks, config: Config, rts: RTS, + ) -> Serial { + Serial::new(usart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232Rts)) + } + + // TODO Add constructors for other modes of operation +} +impl UART for Serial where PINS: Pins {} +impl UART for Serial where PINS: Pins {} +impl UART for Serial where PINS: Pins {} +// TODO where is UART8? +impl UART for Serial where PINS: Pins {} +impl UART for Serial where PINS: Pins {} +impl UART for Serial where PINS: Pins {} +impl UART for Serial where PINS: Pins {} + +// TODO add USART trait which would have USART-specific modes like "Synchronous" and "SmartCard" +// TOOD add add implementation of those traits for all USART* + +impl Serial where - PINS: Pins, - USART: Instance, + PINS: Pins, + U: Instance, { - pub fn new(usart: USART, pins: PINS, clocks: &Clocks, config: Config) -> Self { + fn new( + usart: U, + pins: PINS, + clocks: &Clocks, + config: Config, + mode: SerialMode + ) -> Self { // TODO remove "pub" // NOTE(unsafe) This executes only during initialisation let rcc = unsafe { &(*RCC::ptr()) }; // TODO: The unsafe calls below should be replaced with accessing // the correct registers directly. - USART::select_sysclock(rcc, config.sysclock); + U::select_sysclock(rcc, config.sysclock); unsafe { - USART::enable_unchecked(); + U::enable_unchecked(); } let clk = if config.sysclock { clocks.sysclk() } else { - USART::clock(clocks) + U::clock(clocks) }; // Calculate correct baudrate divisor on the fly @@ -192,8 +279,22 @@ where // Enable DMA usart.cr3.write(|w| w.dmat().enabled().dmar().enabled()); - // Configure hardware flow control - usart.cr3.write(|w| w.ctse().bit(config.cts_enabled).rtse().bit(config.rts_enabled)); + match mode { + SerialMode::Async(flow_control) => match flow_control { + AsyncFlowControl::Rs232None => { + usart.cr3.write(|w| w.ctse().disabled().rtse().disabled()); + }, + AsyncFlowControl::Rs232CtsRts => { + usart.cr3.write(|w| w.ctse().enabled().rtse().enabled()); + }, + AsyncFlowControl::Rs232Cts => { + usart.cr3.write(|w| w.ctse().enabled().rtse().disabled()); + }, + AsyncFlowControl::Rs232Rts => { + usart.cr3.write(|w| w.ctse().disabled().rtse().enabled()); + }, + } + } Serial { usart, pins } } @@ -218,7 +319,7 @@ where } } - pub fn split(self) -> (Tx, Rx) { + pub fn split(self) -> (Tx, Rx) { ( Tx { _usart: PhantomData, @@ -229,40 +330,40 @@ where ) } - pub fn release(self) -> (USART, PINS) { + pub fn release(self) -> (U, PINS) { (self.usart, self.pins) } } -impl serial::Read for Serial +impl serial::Read for Serial where - USART: Instance, + U: Instance, { type Error = Error; fn read(&mut self) -> nb::Result { - let mut rx: Rx = Rx { + let mut rx: Rx = Rx { _usart: PhantomData, }; rx.read() } } -impl serial::Write for Serial +impl serial::Write for Serial where - USART: Instance, + U: Instance, { type Error = Error; fn flush(&mut self) -> nb::Result<(), Self::Error> { - let mut tx: Tx = Tx { + let mut tx: Tx = Tx { _usart: PhantomData, }; tx.flush() } fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> { - let mut tx: Tx = Tx { + let mut tx: Tx = Tx { _usart: PhantomData, }; tx.write(byte) @@ -270,13 +371,13 @@ where } /// Serial receiver -pub struct Rx { - _usart: PhantomData, +pub struct Rx { + _usart: PhantomData, } -impl Rx +impl Rx where - USART: Instance, + U: Instance, Self: dma::Target, { /// Reads data using DMA until `buffer` is full @@ -295,7 +396,7 @@ where { // This is safe, as we're only using the USART instance to access the // address of one register. - let address = &unsafe { &*USART::ptr() }.rdr as *const _ as _; + let address = &unsafe { &*U::ptr() }.rdr as *const _ as _; // Safe, because the trait bounds on this method guarantee that `buffer` // can be written to safely. @@ -312,18 +413,18 @@ where } } -impl serial::Read for Rx +impl serial::Read for Rx where - USART: Instance, + U: Instance, { type Error = Error; fn read(&mut self) -> nb::Result { // NOTE(unsafe) atomic read with no side effects - let isr = unsafe { (*USART::ptr()).isr.read() }; + let isr = unsafe { (*U::ptr()).isr.read() }; // NOTE(unsafe): Only used for atomic writes, to clear error flags. - let icr = unsafe { &(*USART::ptr()).icr }; + let icr = unsafe { &(*U::ptr()).icr }; if isr.pe().bit_is_set() { icr.write(|w| w.pecf().clear()); @@ -347,7 +448,7 @@ where return Ok(unsafe { // Casting to `u8` should be fine, as we've configured the USART // to use 8 data bits. - (*USART::ptr()).rdr.read().rdr().bits() as u8 + (*U::ptr()).rdr.read().rdr().bits() as u8 }); } @@ -356,14 +457,14 @@ where } /// Serial transmitter -pub struct Tx { - _usart: PhantomData, +pub struct Tx { + _usart: PhantomData, } -impl Tx +impl Tx where Self: dma::Target, - USART: Instance, + U: Instance, { /// Writes data using DMA /// @@ -383,7 +484,7 @@ where // STM32F74xxx, section 31.5.15. // // This is safe, as we're doing just one atomic write. - let usart = unsafe { &*USART::ptr() }; + let usart = unsafe { &*U::ptr() }; usart.icr.write(|w| w.tccf().clear()); // Safe, because the trait bounds on this method guarantee that `buffer` @@ -401,15 +502,15 @@ where } } -impl serial::Write for Tx +impl serial::Write for Tx where - USART: Instance, + U: Instance, { type Error = Error; fn flush(&mut self) -> nb::Result<(), Self::Error> { // NOTE(unsafe) atomic read with no side effects - let isr = unsafe { (*USART::ptr()).isr.read() }; + let isr = unsafe { (*U::ptr()).isr.read() }; if isr.tc().bit_is_set() { Ok(()) @@ -420,12 +521,12 @@ where fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> { // NOTE(unsafe) atomic read with no side effects - let isr = unsafe { (*USART::ptr()).isr.read() }; + let isr = unsafe { (*U::ptr()).isr.read() }; if isr.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(&(*USART::ptr()).tdr as *const _ as *mut _, byte) } + unsafe { ptr::write_volatile(&(*U::ptr()).tdr as *const _ as *mut _, byte) } Ok(()) } else { Err(nb::Error::WouldBlock) @@ -441,8 +542,6 @@ pub struct Config { pub sysclock: bool, pub parity: Parity, pub data_bits: DataBits, - pub cts_enabled: bool, - pub rts_enabled: bool, } pub enum Oversampling { @@ -483,8 +582,6 @@ impl Default for Config { sysclock: false, parity: Parity::ParityNone, data_bits: DataBits::Bits8, - cts_enabled: false, - rts_enabled: false, } } } @@ -537,9 +634,9 @@ impl_instance! { UART7: (uart7sel), } -impl fmt::Write for Tx +impl fmt::Write for Tx where - Tx: serial::Write, + Tx: serial::Write, { fn write_str(&mut self, s: &str) -> fmt::Result { let _ = s.as_bytes().iter().map(|c| block!(self.write(*c))).last(); From e5f70e369d8f783e46c8335946da246be3aaf466 Mon Sep 17 00:00:00 2001 From: Denys Rtveliashvili Date: Thu, 26 Oct 2023 07:04:44 +0100 Subject: [PATCH 3/5] One more attempt --- examples/serial_echo.rs | 4 ++-- src/serial.rs | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/serial_echo.rs b/examples/serial_echo.rs index 5a51185..f97c4d6 100644 --- a/examples/serial_echo.rs +++ b/examples/serial_echo.rs @@ -15,7 +15,7 @@ use cortex_m_rt::entry; use stm32f7xx_hal::{ pac, prelude::*, - serial::{self, Serial}, + serial::{self, Serial, UART}, }; #[entry] @@ -31,7 +31,7 @@ fn main() -> ! { let tx = gpioa.pa9.into_alternate(); let rx = gpiob.pb7.into_alternate(); - let serial = Serial::new( + let serial = Serial::new_async_uart_no_flwctl( p.USART1, (tx, rx), &clocks, diff --git a/src/serial.rs b/src/serial.rs index 69843ab..cc67f7c 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -161,35 +161,35 @@ pub struct Serial { pub trait UART { fn new_async_uart_no_flwctl>( - usart: U, pins: PINS, clocks: &Clocks, config: Config, + uart: U, pins: PINS, clocks: &Clocks, config: Config, ) -> Serial { - Serial::new(usart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232None)) + Serial::new(uart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232None)) } fn new_async_uart_rs232_cts_rts, CTS: PinCts, RTS: PinRts>( - usart: U, pins: PINS, clocks: &Clocks, config: Config, cts: CTS, rts: RTS, + uart: U, pins: PINS, clocks: &Clocks, config: Config, cts: CTS, rts: RTS, ) -> Serial { // TODO Clarify if we can borrow cts and rts and keep them borrowed. // TODO Note that at the moment any CTS and RTS pin of this U(S)ART would be accepted // This may be too flexible. - Serial::new(usart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232CtsRts)) + Serial::new(uart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232CtsRts)) } fn new_async_uart_rs232_cts, CTS: PinCts, RTS: PinRts>( - usart: U, pins: PINS, clocks: &Clocks, config: Config, cts: CTS, + uart: U, pins: PINS, clocks: &Clocks, config: Config, cts: CTS, ) -> Serial { - Serial::new(usart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232Cts)) + Serial::new(uart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232Cts)) } fn new_async_uart_rs232_rts, RTS: PinRts>( - usart: U, pins: PINS, clocks: &Clocks, config: Config, rts: RTS, + uart: U, pins: PINS, clocks: &Clocks, config: Config, rts: RTS, ) -> Serial { - Serial::new(usart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232Rts)) + Serial::new(uart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232Rts)) } // TODO Add constructors for other modes of operation } -impl UART for Serial where PINS: Pins {} +impl UART for Serial where PINS: Pins {} impl UART for Serial where PINS: Pins {} impl UART for Serial where PINS: Pins {} // TODO where is UART8? From c160ab5dab0771c7cca4817e7bcb7d464e06d53b Mon Sep 17 00:00:00 2001 From: Denys Rtveliashvili Date: Thu, 26 Oct 2023 08:10:59 +0100 Subject: [PATCH 4/5] Made it build serial_echo.rs --- examples/serial_echo.rs | 2 +- src/serial.rs | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/serial_echo.rs b/examples/serial_echo.rs index f97c4d6..a6e485c 100644 --- a/examples/serial_echo.rs +++ b/examples/serial_echo.rs @@ -31,7 +31,7 @@ fn main() -> ! { let tx = gpioa.pa9.into_alternate(); let rx = gpiob.pb7.into_alternate(); - let serial = Serial::new_async_uart_no_flwctl( + let serial = Serial::new_async_no_flwctl( p.USART1, (tx, rx), &clocks, diff --git a/src/serial.rs b/src/serial.rs index cc67f7c..063f4d2 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -159,14 +159,14 @@ pub struct Serial { pins: PINS, } -pub trait UART { - fn new_async_uart_no_flwctl>( +pub trait UART> { + fn new_async_no_flwctl<>( uart: U, pins: PINS, clocks: &Clocks, config: Config, ) -> Serial { Serial::new(uart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232None)) } - fn new_async_uart_rs232_cts_rts, CTS: PinCts, RTS: PinRts>( + fn new_async_rs232_cts_rts, RTS: PinRts>( uart: U, pins: PINS, clocks: &Clocks, config: Config, cts: CTS, rts: RTS, ) -> Serial { // TODO Clarify if we can borrow cts and rts and keep them borrowed. @@ -175,13 +175,13 @@ pub trait UART { Serial::new(uart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232CtsRts)) } - fn new_async_uart_rs232_cts, CTS: PinCts, RTS: PinRts>( + fn new_async_rs232_cts>( uart: U, pins: PINS, clocks: &Clocks, config: Config, cts: CTS, ) -> Serial { Serial::new(uart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232Cts)) } - fn new_async_uart_rs232_rts, RTS: PinRts>( + fn new_async_rs232_rts>( uart: U, pins: PINS, clocks: &Clocks, config: Config, rts: RTS, ) -> Serial { Serial::new(uart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232Rts)) @@ -189,14 +189,14 @@ pub trait UART { // TODO Add constructors for other modes of operation } -impl UART for Serial where PINS: Pins {} -impl UART for Serial where PINS: Pins {} -impl UART for Serial where PINS: Pins {} +impl > UART for Serial {} +impl > UART for Serial {} +impl > UART for Serial {} // TODO where is UART8? -impl UART for Serial where PINS: Pins {} -impl UART for Serial where PINS: Pins {} -impl UART for Serial where PINS: Pins {} -impl UART for Serial where PINS: Pins {} +impl > UART for Serial {} +impl > UART for Serial {} +impl > UART for Serial {} +impl > UART for Serial {} // TODO add USART trait which would have USART-specific modes like "Synchronous" and "SmartCard" // TOOD add add implementation of those traits for all USART* From 6eac0a2df59bc8c9e8cd4f29be112b82f0e094c0 Mon Sep 17 00:00:00 2001 From: Denys Rtveliashvili Date: Thu, 26 Oct 2023 19:13:53 +0100 Subject: [PATCH 5/5] Added a few more bits to show the overall idea --- src/serial.rs | 127 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 106 insertions(+), 21 deletions(-) diff --git a/src/serial.rs b/src/serial.rs index 063f4d2..cc5a1de 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -139,18 +139,37 @@ impl PinRts for gpio::PG12> {} impl PinRts for gpio::PE9> {} impl PinRts for gpio::PF8> {} +pub enum IrDAPower { + Normal, + Low, +} + +pub enum Rs485Polarity { + High, + Low, +} enum AsyncFlowControl { Rs232None, Rs232CtsRts, Rs232Cts, Rs232Rts, - // TODO add Rs485 + Rs485(Rs485Polarity), } enum SerialMode { - Async(AsyncFlowControl), - // TODO add SingleWire, IrDA, ModbusCommunication, LIN, SnartCard, etc. + // These options are for any UART, including USART + Asynchronous(AsyncFlowControl), + SingleWire, + MultiprocessorCommunication, + IrDA(IrDAPower), + ModbusCommunication, + LIN, + + // The following options are for USART only + Synchronous, + SmartCard, + SmartCardWithCardLock, } /// Serial abstraction @@ -163,7 +182,8 @@ pub trait UART> { fn new_async_no_flwctl<>( uart: U, pins: PINS, clocks: &Clocks, config: Config, ) -> Serial { - Serial::new(uart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232None)) + Serial::new(uart, pins, clocks, config, + SerialMode::Asynchronous(AsyncFlowControl::Rs232None)) } fn new_async_rs232_cts_rts, RTS: PinRts>( @@ -172,19 +192,36 @@ pub trait UART> { // TODO Clarify if we can borrow cts and rts and keep them borrowed. // TODO Note that at the moment any CTS and RTS pin of this U(S)ART would be accepted // This may be too flexible. - Serial::new(uart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232CtsRts)) + Serial::new(uart, pins, clocks, config, + SerialMode::Asynchronous(AsyncFlowControl::Rs232CtsRts)) } fn new_async_rs232_cts>( uart: U, pins: PINS, clocks: &Clocks, config: Config, cts: CTS, ) -> Serial { - Serial::new(uart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232Cts)) + Serial::new(uart, pins, clocks, config, + SerialMode::Asynchronous(AsyncFlowControl::Rs232Cts)) } fn new_async_rs232_rts>( uart: U, pins: PINS, clocks: &Clocks, config: Config, rts: RTS, ) -> Serial { - Serial::new(uart, pins, clocks, config, SerialMode::Async(AsyncFlowControl::Rs232Rts)) + Serial::new(uart, pins, clocks, config, + SerialMode::Asynchronous(AsyncFlowControl::Rs232Rts)) + } + + fn new_async_rs458>( + uart: U, pins: PINS, clocks: &Clocks, config: Config, polarity: Rs485Polarity, + ) -> Serial { + Serial::new(uart, pins, clocks, config, + SerialMode::Asynchronous(AsyncFlowControl::Rs485(polarity))) + } + + fn new_irda>( + uart: U, pins: PINS, clocks: &Clocks, config: Config, irda_power: IrDAPower, + ) -> Serial { + Serial::new(uart, pins, clocks, config, + SerialMode::IrDA(irda_power)) } // TODO Add constructors for other modes of operation @@ -280,20 +317,68 @@ where usart.cr3.write(|w| w.dmat().enabled().dmar().enabled()); match mode { - SerialMode::Async(flow_control) => match flow_control { - AsyncFlowControl::Rs232None => { - usart.cr3.write(|w| w.ctse().disabled().rtse().disabled()); - }, - AsyncFlowControl::Rs232CtsRts => { - usart.cr3.write(|w| w.ctse().enabled().rtse().enabled()); - }, - AsyncFlowControl::Rs232Cts => { - usart.cr3.write(|w| w.ctse().enabled().rtse().disabled()); - }, - AsyncFlowControl::Rs232Rts => { - usart.cr3.write(|w| w.ctse().disabled().rtse().enabled()); - }, - } + SerialMode::Asynchronous(flow_control) => { + usart.cr2.write(|w| w.linen().clear_bit().clken().clear_bit()); + usart.cr3.write(|w| w.scen().clear_bit().iren().clear_bit().hdsel().clear_bit()); + match flow_control { + AsyncFlowControl::Rs232None => { + usart.cr3.write(|w| w.ctse().disabled().rtse().disabled()); + }, + AsyncFlowControl::Rs232CtsRts => { + usart.cr3.write(|w| w.ctse().enabled().rtse().enabled()); + }, + AsyncFlowControl::Rs232Cts => { + usart.cr3.write(|w| w.ctse().enabled().rtse().disabled()); + }, + AsyncFlowControl::Rs232Rts => { + usart.cr3.write(|w| w.ctse().disabled().rtse().enabled()); + }, + AsyncFlowControl::Rs485(polarity) => { + usart.cr3.write(|w| w.dem().enabled()); // drive-enabled mode ON + usart.cr3.write(|w| w.dep().bit(match polarity { + Rs485Polarity::High => false, + Rs485Polarity::Low => true, + })); + usart.cr1.write(|w| w.deat().bits(0)); // setting the assertion time + usart.cr1.write(|w| w.dedt().bits(0)); // setting the de-assertion time + // TODO ^ make the times be configurable? + }, + } + }, + SerialMode::SingleWire => { + usart.cr2.write(|w| w.linen().clear_bit().clken().clear_bit()); + usart.cr3.write(|w| w.scen().clear_bit().iren().clear_bit()); + usart.cr3.write(|w| w.hdsel().set_bit()); + }, + SerialMode::MultiprocessorCommunication => { + // TODO implement this + }, + SerialMode::IrDA(power) => { + usart.cr3.write(|w| w.irlp().bit(match power { + IrDAPower::Normal => false, + IrDAPower::Low => true, + })); + usart.gtpr.write(|w| w.gt().bits(1)); // setting the prescaler + + usart.cr2.write(|w| w.linen().clear_bit().clken().clear_bit().stop().bits(0)); + usart.cr3.write(|w| w.scen().clear_bit().hdsel().clear_bit()); + usart.cr3.write(|w| w.iren().set_bit()); + }, + SerialMode::ModbusCommunication => { + // TODO implement this + }, + SerialMode::LIN => { + // TODO implement this + }, + SerialMode::Synchronous => { + // TODO implement this + }, + SerialMode::SmartCard => { + // TODO implement this + }, + SerialMode::SmartCardWithCardLock => { + // TODO implement this + }, } Serial { usart, pins }