From 88eb5cca71a470cca93001943e962b63e15168af Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Sat, 16 Sep 2023 22:32:14 +0100 Subject: [PATCH] stm32: Implement `set_config` for Uart structs --- embassy-stm32/src/spi/mod.rs | 4 +- embassy-stm32/src/usart/buffered.rs | 36 ++++++++++++++++++ embassy-stm32/src/usart/mod.rs | 49 +++++++++++++++++++++++++ embassy-stm32/src/usart/ringbuffered.rs | 16 +++++++- 4 files changed, 102 insertions(+), 3 deletions(-) diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 853de98f..f40bce78 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -323,7 +323,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { } /// Reconfigures it with the supplied config. - pub fn reconfigure(&mut self, config: Config) { + pub fn set_config(&mut self, config: Config) { let cpha = config.raw_phase(); let cpol = config.raw_polarity(); @@ -1062,6 +1062,6 @@ foreach_peripheral!( impl<'d, T: Instance, Tx, Rx> SetConfig for Spi<'d, T, Tx, Rx> { type Config = Config; fn set_config(&mut self, config: &Self::Config) { - self.reconfigure(*config); + self.set_config(*config); } } diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index b88eebc7..323d8381 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -114,6 +114,30 @@ pub struct BufferedUartRx<'d, T: BasicInstance> { phantom: PhantomData<&'d mut T>, } +impl<'d, T: BasicInstance> SetConfig for BufferedUart<'d, T> { + type Config = Config; + + fn set_config(&mut self, config: &Self::Config) { + self.set_config(config) + } +} + +impl<'d, T: BasicInstance> SetConfig for BufferedUartRx<'d, T> { + type Config = Config; + + fn set_config(&mut self, config: &Self::Config) { + self.set_config(config) + } +} + +impl<'d, T: BasicInstance> SetConfig for BufferedUartTx<'d, T> { + type Config = Config; + + fn set_config(&mut self, config: &Self::Config) { + self.set_config(config) + } +} + impl<'d, T: BasicInstance> BufferedUart<'d, T> { pub fn new( peri: impl Peripheral

+ 'd, @@ -228,6 +252,10 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { pub fn split(self) -> (BufferedUartTx<'d, T>, BufferedUartRx<'d, T>) { (self.tx, self.rx) } + + pub fn set_config(&mut self, config: &Config) { + reconfigure::(config) + } } impl<'d, T: BasicInstance> BufferedUartRx<'d, T> { @@ -304,6 +332,10 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> { T::Interrupt::pend(); } } + + pub fn set_config(&mut self, config: &Config) { + reconfigure::(config) + } } impl<'d, T: BasicInstance> BufferedUartTx<'d, T> { @@ -374,6 +406,10 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> { } } } + + pub fn set_config(&mut self, config: &Config) { + reconfigure::(config) + } } impl<'d, T: BasicInstance> Drop for BufferedUartRx<'d, T> { diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index c6d6cc59..ff02d0a6 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -5,6 +5,7 @@ use core::marker::PhantomData; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; +use embassy_embedded_hal::SetConfig; use embassy_hal_internal::drop::OnDrop; use embassy_hal_internal::{into_ref, PeripheralRef}; use futures::future::{select, Either}; @@ -168,11 +169,28 @@ pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> { rx: UartRx<'d, T, RxDma>, } +impl<'d, T: BasicInstance, TxDma, RxDma> SetConfig for Uart<'d, T, TxDma, RxDma> { + type Config = Config; + + fn set_config(&mut self, config: &Self::Config) { + self.tx.set_config(config); + self.rx.set_config(config); + } +} + pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> { phantom: PhantomData<&'d mut T>, tx_dma: PeripheralRef<'d, TxDma>, } +impl<'d, T: BasicInstance, TxDma> SetConfig for UartTx<'d, T, TxDma> { + type Config = Config; + + fn set_config(&mut self, config: &Self::Config) { + self.set_config(config); + } +} + pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> { _peri: PeripheralRef<'d, T>, rx_dma: PeripheralRef<'d, RxDma>, @@ -181,6 +199,14 @@ pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> { buffered_sr: stm32_metapac::usart::regs::Sr, } +impl<'d, T: BasicInstance, RxDma> SetConfig for UartRx<'d, T, RxDma> { + type Config = Config; + + fn set_config(&mut self, config: &Self::Config) { + self.set_config(config); + } +} + impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. pub fn new( @@ -237,6 +263,10 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { } } + pub fn set_config(&mut self, config: &Config) { + reconfigure::(config) + } + pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> where TxDma: crate::usart::TxDma, @@ -334,6 +364,10 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { } } + pub fn set_config(&mut self, config: &Config) { + reconfigure::(config) + } + #[cfg(any(usart_v1, usart_v2))] fn check_rx_flags(&mut self) -> Result { let r = T::regs(); @@ -759,6 +793,10 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { } } + pub fn set_config(&mut self, config: &Config) { + reconfigure::(config) + } + pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> where TxDma: crate::usart::TxDma, @@ -804,6 +842,17 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { } } +fn reconfigure(config: &Config) { + T::Interrupt::disable(); + let r = T::regs(); + + let cr = r.cr1().read(); + configure(r, config, T::frequency(), T::KIND, cr.re(), cr.te()); + + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; +} + fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx: bool, enable_tx: bool) { if !enable_rx && !enable_tx { panic!("USART: At least one of RX or TX should be enabled"); diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index e990eaca..eed5ef5d 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs @@ -3,10 +3,11 @@ use core::mem; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; +use embassy_embedded_hal::SetConfig; use embassy_hal_internal::PeripheralRef; use futures::future::{select, Either}; -use super::{clear_interrupt_flags, rdr, sr, BasicInstance, Error, UartRx}; +use super::{clear_interrupt_flags, rdr, reconfigure, sr, BasicInstance, Config, Error, UartRx}; use crate::dma::ReadableRingBuffer; use crate::usart::{Regs, Sr}; @@ -15,6 +16,14 @@ pub struct RingBufferedUartRx<'d, T: BasicInstance, RxDma: super::RxDma> { ring_buf: ReadableRingBuffer<'d, RxDma, u8>, } +impl<'d, T: BasicInstance, RxDma: super::RxDma> SetConfig for RingBufferedUartRx<'d, T, RxDma> { + type Config = Config; + + fn set_config(&mut self, config: &Self::Config) { + self.set_config(config); + } +} + impl<'d, T: BasicInstance, RxDma: super::RxDma> UartRx<'d, T, RxDma> { /// Turn the `UartRx` into a buffered uart which can continously receive in the background /// without the possibility of loosing bytes. The `dma_buf` is a buffer registered to the @@ -54,6 +63,11 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma> RingBufferedUartRx<'d, T, RxD Err(err) } + pub fn set_config(&mut self, config: &Config) { + self.teardown_uart(); + reconfigure::(config) + } + /// Start uart background receive fn setup_uart(&mut self) { // fence before starting DMA.