diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-06-03 21:26:43 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-06-03 21:26:43 +0000 |
| commit | 9856d216939d9433e840289966e313c9aa377fca (patch) | |
| tree | 18b9ffa6b7dff4f17b304f92e64a89201809e4ca | |
| parent | 039d8ed671c70c4716edd8ffa2d40f3babef9b43 (diff) | |
| parent | f3703ff6bfed6f8342b49cfd9a65d543d1c99c27 (diff) | |
Merge pull request #3006 from honzasp/harmonize-new
stm32: Make initialization of I2C and USART consistent with SPI
| -rw-r--r-- | embassy-stm32/src/i2c/mod.rs | 89 | ||||
| -rw-r--r-- | embassy-stm32/src/i2c/v1.rs | 6 | ||||
| -rw-r--r-- | embassy-stm32/src/i2c/v2.rs | 6 | ||||
| -rw-r--r-- | embassy-stm32/src/spi/mod.rs | 39 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/buffered.rs | 154 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 133 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/ringbuffered.rs | 10 |
7 files changed, 257 insertions, 180 deletions
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 0bf57ef8a..6d12af2cc 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs | |||
| @@ -9,16 +9,16 @@ use core::future::Future; | |||
| 9 | use core::iter; | 9 | use core::iter; |
| 10 | use core::marker::PhantomData; | 10 | use core::marker::PhantomData; |
| 11 | 11 | ||
| 12 | use embassy_hal_internal::{into_ref, Peripheral}; | 12 | use embassy_hal_internal::{Peripheral, PeripheralRef}; |
| 13 | use embassy_sync::waitqueue::AtomicWaker; | 13 | use embassy_sync::waitqueue::AtomicWaker; |
| 14 | #[cfg(feature = "time")] | 14 | #[cfg(feature = "time")] |
| 15 | use embassy_time::{Duration, Instant}; | 15 | use embassy_time::{Duration, Instant}; |
| 16 | 16 | ||
| 17 | use crate::dma::ChannelAndRequest; | 17 | use crate::dma::ChannelAndRequest; |
| 18 | use crate::gpio::{AFType, Pull}; | 18 | use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed}; |
| 19 | use crate::interrupt::typelevel::Interrupt; | 19 | use crate::interrupt::typelevel::Interrupt; |
| 20 | use crate::mode::{Async, Blocking, Mode}; | 20 | use crate::mode::{Async, Blocking, Mode}; |
| 21 | use crate::rcc::{self, RccInfo, SealedRccPeripheral}; | 21 | use crate::rcc::{RccInfo, SealedRccPeripheral}; |
| 22 | use crate::time::Hertz; | 22 | use crate::time::Hertz; |
| 23 | use crate::{interrupt, peripherals}; | 23 | use crate::{interrupt, peripherals}; |
| 24 | 24 | ||
| @@ -72,11 +72,29 @@ impl Default for Config { | |||
| 72 | } | 72 | } |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | impl Config { | ||
| 76 | fn scl_pull_mode(&self) -> Pull { | ||
| 77 | match self.scl_pullup { | ||
| 78 | true => Pull::Up, | ||
| 79 | false => Pull::Down, | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | fn sda_pull_mode(&self) -> Pull { | ||
| 84 | match self.sda_pullup { | ||
| 85 | true => Pull::Up, | ||
| 86 | false => Pull::Down, | ||
| 87 | } | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 75 | /// I2C driver. | 91 | /// I2C driver. |
| 76 | pub struct I2c<'d, M: Mode> { | 92 | pub struct I2c<'d, M: Mode> { |
| 77 | info: &'static Info, | 93 | info: &'static Info, |
| 78 | state: &'static State, | 94 | state: &'static State, |
| 79 | kernel_clock: Hertz, | 95 | kernel_clock: Hertz, |
| 96 | scl: Option<PeripheralRef<'d, AnyPin>>, | ||
| 97 | sda: Option<PeripheralRef<'d, AnyPin>>, | ||
| 80 | tx_dma: Option<ChannelAndRequest<'d>>, | 98 | tx_dma: Option<ChannelAndRequest<'d>>, |
| 81 | rx_dma: Option<ChannelAndRequest<'d>>, | 99 | rx_dma: Option<ChannelAndRequest<'d>>, |
| 82 | #[cfg(feature = "time")] | 100 | #[cfg(feature = "time")] |
| @@ -98,7 +116,15 @@ impl<'d> I2c<'d, Async> { | |||
| 98 | freq: Hertz, | 116 | freq: Hertz, |
| 99 | config: Config, | 117 | config: Config, |
| 100 | ) -> Self { | 118 | ) -> Self { |
| 101 | Self::new_inner(peri, scl, sda, new_dma!(tx_dma), new_dma!(rx_dma), freq, config) | 119 | Self::new_inner( |
| 120 | peri, | ||
| 121 | new_pin!(scl, AFType::OutputOpenDrain, Speed::Medium, config.scl_pull_mode()), | ||
| 122 | new_pin!(sda, AFType::OutputOpenDrain, Speed::Medium, config.sda_pull_mode()), | ||
| 123 | new_dma!(tx_dma), | ||
| 124 | new_dma!(rx_dma), | ||
| 125 | freq, | ||
| 126 | config, | ||
| 127 | ) | ||
| 102 | } | 128 | } |
| 103 | } | 129 | } |
| 104 | 130 | ||
| @@ -111,7 +137,15 @@ impl<'d> I2c<'d, Blocking> { | |||
| 111 | freq: Hertz, | 137 | freq: Hertz, |
| 112 | config: Config, | 138 | config: Config, |
| 113 | ) -> Self { | 139 | ) -> Self { |
| 114 | Self::new_inner(peri, scl, sda, None, None, freq, config) | 140 | Self::new_inner( |
| 141 | peri, | ||
| 142 | new_pin!(scl, AFType::OutputOpenDrain, Speed::Medium, config.scl_pull_mode()), | ||
| 143 | new_pin!(sda, AFType::OutputOpenDrain, Speed::Medium, config.sda_pull_mode()), | ||
| 144 | None, | ||
| 145 | None, | ||
| 146 | freq, | ||
| 147 | config, | ||
| 148 | ) | ||
| 115 | } | 149 | } |
| 116 | } | 150 | } |
| 117 | 151 | ||
| @@ -119,34 +153,13 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 119 | /// Create a new I2C driver. | 153 | /// Create a new I2C driver. |
| 120 | fn new_inner<T: Instance>( | 154 | fn new_inner<T: Instance>( |
| 121 | _peri: impl Peripheral<P = T> + 'd, | 155 | _peri: impl Peripheral<P = T> + 'd, |
| 122 | scl: impl Peripheral<P = impl SclPin<T>> + 'd, | 156 | scl: Option<PeripheralRef<'d, AnyPin>>, |
| 123 | sda: impl Peripheral<P = impl SdaPin<T>> + 'd, | 157 | sda: Option<PeripheralRef<'d, AnyPin>>, |
| 124 | tx_dma: Option<ChannelAndRequest<'d>>, | 158 | tx_dma: Option<ChannelAndRequest<'d>>, |
| 125 | rx_dma: Option<ChannelAndRequest<'d>>, | 159 | rx_dma: Option<ChannelAndRequest<'d>>, |
| 126 | freq: Hertz, | 160 | freq: Hertz, |
| 127 | config: Config, | 161 | config: Config, |
| 128 | ) -> Self { | 162 | ) -> Self { |
| 129 | into_ref!(scl, sda); | ||
| 130 | |||
| 131 | rcc::enable_and_reset::<T>(); | ||
| 132 | |||
| 133 | scl.set_as_af_pull( | ||
| 134 | scl.af_num(), | ||
| 135 | AFType::OutputOpenDrain, | ||
| 136 | match config.scl_pullup { | ||
| 137 | true => Pull::Up, | ||
| 138 | false => Pull::None, | ||
| 139 | }, | ||
| 140 | ); | ||
| 141 | sda.set_as_af_pull( | ||
| 142 | sda.af_num(), | ||
| 143 | AFType::OutputOpenDrain, | ||
| 144 | match config.sda_pullup { | ||
| 145 | true => Pull::Up, | ||
| 146 | false => Pull::None, | ||
| 147 | }, | ||
| 148 | ); | ||
| 149 | |||
| 150 | unsafe { T::EventInterrupt::enable() }; | 163 | unsafe { T::EventInterrupt::enable() }; |
| 151 | unsafe { T::ErrorInterrupt::enable() }; | 164 | unsafe { T::ErrorInterrupt::enable() }; |
| 152 | 165 | ||
| @@ -154,18 +167,23 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 154 | info: T::info(), | 167 | info: T::info(), |
| 155 | state: T::state(), | 168 | state: T::state(), |
| 156 | kernel_clock: T::frequency(), | 169 | kernel_clock: T::frequency(), |
| 170 | scl, | ||
| 171 | sda, | ||
| 157 | tx_dma, | 172 | tx_dma, |
| 158 | rx_dma, | 173 | rx_dma, |
| 159 | #[cfg(feature = "time")] | 174 | #[cfg(feature = "time")] |
| 160 | timeout: config.timeout, | 175 | timeout: config.timeout, |
| 161 | _phantom: PhantomData, | 176 | _phantom: PhantomData, |
| 162 | }; | 177 | }; |
| 163 | 178 | this.enable_and_init(freq, config); | |
| 164 | this.init(freq, config); | ||
| 165 | |||
| 166 | this | 179 | this |
| 167 | } | 180 | } |
| 168 | 181 | ||
| 182 | fn enable_and_init(&mut self, freq: Hertz, config: Config) { | ||
| 183 | self.info.rcc.enable_and_reset(); | ||
| 184 | self.init(freq, config); | ||
| 185 | } | ||
| 186 | |||
| 169 | fn timeout(&self) -> Timeout { | 187 | fn timeout(&self) -> Timeout { |
| 170 | Timeout { | 188 | Timeout { |
| 171 | #[cfg(feature = "time")] | 189 | #[cfg(feature = "time")] |
| @@ -174,6 +192,15 @@ impl<'d, M: Mode> I2c<'d, M> { | |||
| 174 | } | 192 | } |
| 175 | } | 193 | } |
| 176 | 194 | ||
| 195 | impl<'d, M: Mode> Drop for I2c<'d, M> { | ||
| 196 | fn drop(&mut self) { | ||
| 197 | self.scl.as_ref().map(|x| x.set_as_disconnected()); | ||
| 198 | self.sda.as_ref().map(|x| x.set_as_disconnected()); | ||
| 199 | |||
| 200 | self.info.rcc.disable() | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 177 | #[derive(Copy, Clone)] | 204 | #[derive(Copy, Clone)] |
| 178 | struct Timeout { | 205 | struct Timeout { |
| 179 | #[cfg(feature = "time")] | 206 | #[cfg(feature = "time")] |
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index 0e2bd2e40..28026f83c 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs | |||
| @@ -700,12 +700,6 @@ impl<'d> I2c<'d, Async> { | |||
| 700 | } | 700 | } |
| 701 | } | 701 | } |
| 702 | 702 | ||
| 703 | impl<'d, M: PeriMode> Drop for I2c<'d, M> { | ||
| 704 | fn drop(&mut self) { | ||
| 705 | self.info.rcc.disable() | ||
| 706 | } | ||
| 707 | } | ||
| 708 | |||
| 709 | enum Mode { | 703 | enum Mode { |
| 710 | Fast, | 704 | Fast, |
| 711 | Standard, | 705 | Standard, |
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 193f29733..80163c287 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs | |||
| @@ -671,12 +671,6 @@ impl<'d> I2c<'d, Async> { | |||
| 671 | } | 671 | } |
| 672 | } | 672 | } |
| 673 | 673 | ||
| 674 | impl<'d, M: Mode> Drop for I2c<'d, M> { | ||
| 675 | fn drop(&mut self) { | ||
| 676 | self.info.rcc.disable(); | ||
| 677 | } | ||
| 678 | } | ||
| 679 | |||
| 680 | /// I2C Stop Configuration | 674 | /// I2C Stop Configuration |
| 681 | /// | 675 | /// |
| 682 | /// Peripheral options for generating the STOP condition | 676 | /// Peripheral options for generating the STOP condition |
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 720e80e0d..4eaf7777f 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs | |||
| @@ -13,7 +13,7 @@ use crate::dma::{slice_ptr_parts, word, ChannelAndRequest}; | |||
| 13 | use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed}; | 13 | use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed}; |
| 14 | use crate::mode::{Async, Blocking, Mode as PeriMode}; | 14 | use crate::mode::{Async, Blocking, Mode as PeriMode}; |
| 15 | use crate::pac::spi::{regs, vals, Spi as Regs}; | 15 | use crate::pac::spi::{regs, vals, Spi as Regs}; |
| 16 | use crate::rcc::{self, RccInfo, SealedRccPeripheral}; | 16 | use crate::rcc::{RccInfo, SealedRccPeripheral}; |
| 17 | use crate::time::Hertz; | 17 | use crate::time::Hertz; |
| 18 | use crate::Peripheral; | 18 | use crate::Peripheral; |
| 19 | 19 | ||
| @@ -120,17 +120,30 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 120 | rx_dma: Option<ChannelAndRequest<'d>>, | 120 | rx_dma: Option<ChannelAndRequest<'d>>, |
| 121 | config: Config, | 121 | config: Config, |
| 122 | ) -> Self { | 122 | ) -> Self { |
| 123 | let regs = T::info().regs; | 123 | let mut this = Self { |
| 124 | let kernel_clock = T::frequency(); | 124 | info: T::info(), |
| 125 | let br = compute_baud_rate(kernel_clock, config.frequency); | 125 | kernel_clock: T::frequency(), |
| 126 | sck, | ||
| 127 | mosi, | ||
| 128 | miso, | ||
| 129 | tx_dma, | ||
| 130 | rx_dma, | ||
| 131 | current_word_size: <u8 as SealedWord>::CONFIG, | ||
| 132 | _phantom: PhantomData, | ||
| 133 | }; | ||
| 134 | this.enable_and_init(config); | ||
| 135 | this | ||
| 136 | } | ||
| 126 | 137 | ||
| 138 | fn enable_and_init(&mut self, config: Config) { | ||
| 139 | let br = compute_baud_rate(self.kernel_clock, config.frequency); | ||
| 127 | let cpha = config.raw_phase(); | 140 | let cpha = config.raw_phase(); |
| 128 | let cpol = config.raw_polarity(); | 141 | let cpol = config.raw_polarity(); |
| 129 | |||
| 130 | let lsbfirst = config.raw_byte_order(); | 142 | let lsbfirst = config.raw_byte_order(); |
| 131 | 143 | ||
| 132 | rcc::enable_and_reset::<T>(); | 144 | self.info.rcc.enable_and_reset(); |
| 133 | 145 | ||
| 146 | let regs = self.info.regs; | ||
| 134 | #[cfg(any(spi_v1, spi_f1))] | 147 | #[cfg(any(spi_v1, spi_f1))] |
| 135 | { | 148 | { |
| 136 | regs.cr2().modify(|w| { | 149 | regs.cr2().modify(|w| { |
| @@ -209,18 +222,6 @@ impl<'d, M: PeriMode> Spi<'d, M> { | |||
| 209 | w.set_spe(true); | 222 | w.set_spe(true); |
| 210 | }); | 223 | }); |
| 211 | } | 224 | } |
| 212 | |||
| 213 | Self { | ||
| 214 | info: T::info(), | ||
| 215 | kernel_clock, | ||
| 216 | sck, | ||
| 217 | mosi, | ||
| 218 | miso, | ||
| 219 | tx_dma, | ||
| 220 | rx_dma, | ||
| 221 | current_word_size: <u8 as SealedWord>::CONFIG, | ||
| 222 | _phantom: PhantomData, | ||
| 223 | } | ||
| 224 | } | 225 | } |
| 225 | 226 | ||
| 226 | /// Reconfigures it with the supplied config. | 227 | /// Reconfigures it with the supplied config. |
| @@ -611,7 +612,7 @@ impl<'d> Spi<'d, Async> { | |||
| 611 | // see RM0453 rev 1 section 7.2.13 page 291 | 612 | // see RM0453 rev 1 section 7.2.13 page 291 |
| 612 | // The SUBGHZSPI_SCK frequency is obtained by PCLK3 divided by two. | 613 | // The SUBGHZSPI_SCK frequency is obtained by PCLK3 divided by two. |
| 613 | // The SUBGHZSPI_SCK clock maximum speed must not exceed 16 MHz. | 614 | // The SUBGHZSPI_SCK clock maximum speed must not exceed 16 MHz. |
| 614 | let pclk3_freq = <crate::peripherals::SUBGHZSPI as crate::rcc::SealedRccPeripheral>::frequency().0; | 615 | let pclk3_freq = <crate::peripherals::SUBGHZSPI as SealedRccPeripheral>::frequency().0; |
| 615 | let freq = Hertz(core::cmp::min(pclk3_freq / 2, 16_000_000)); | 616 | let freq = Hertz(core::cmp::min(pclk3_freq / 2, 16_000_000)); |
| 616 | let mut config = Config::default(); | 617 | let mut config = Config::default(); |
| 617 | config.mode = MODE_0; | 618 | config.mode = MODE_0; |
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index eacf95002..fd79e035e 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs | |||
| @@ -6,7 +6,7 @@ use core::task::Poll; | |||
| 6 | 6 | ||
| 7 | use embassy_embedded_hal::SetConfig; | 7 | use embassy_embedded_hal::SetConfig; |
| 8 | use embassy_hal_internal::atomic_ring_buffer::RingBuffer; | 8 | use embassy_hal_internal::atomic_ring_buffer::RingBuffer; |
| 9 | use embassy_hal_internal::{into_ref, Peripheral}; | 9 | use embassy_hal_internal::{Peripheral, PeripheralRef}; |
| 10 | use embassy_sync::waitqueue::AtomicWaker; | 10 | use embassy_sync::waitqueue::AtomicWaker; |
| 11 | 11 | ||
| 12 | #[cfg(not(any(usart_v1, usart_v2)))] | 12 | #[cfg(not(any(usart_v1, usart_v2)))] |
| @@ -15,10 +15,8 @@ use super::{ | |||
| 15 | clear_interrupt_flags, configure, rdr, reconfigure, sr, tdr, Config, ConfigError, CtsPin, Error, Info, Instance, | 15 | clear_interrupt_flags, configure, rdr, reconfigure, sr, tdr, Config, ConfigError, CtsPin, Error, Info, Instance, |
| 16 | Regs, RtsPin, RxPin, TxPin, | 16 | Regs, RtsPin, RxPin, TxPin, |
| 17 | }; | 17 | }; |
| 18 | use crate::gpio::AFType; | 18 | use crate::gpio::{AFType, AnyPin, SealedPin as _}; |
| 19 | use crate::interrupt::typelevel::Interrupt as _; | ||
| 20 | use crate::interrupt::{self, InterruptExt}; | 19 | use crate::interrupt::{self, InterruptExt}; |
| 21 | use crate::rcc; | ||
| 22 | use crate::time::Hertz; | 20 | use crate::time::Hertz; |
| 23 | 21 | ||
| 24 | /// Interrupt handler. | 22 | /// Interrupt handler. |
| @@ -156,7 +154,9 @@ pub struct BufferedUartTx<'d> { | |||
| 156 | info: &'static Info, | 154 | info: &'static Info, |
| 157 | state: &'static State, | 155 | state: &'static State, |
| 158 | kernel_clock: Hertz, | 156 | kernel_clock: Hertz, |
| 159 | _phantom: PhantomData<&'d mut ()>, | 157 | tx: Option<PeripheralRef<'d, AnyPin>>, |
| 158 | cts: Option<PeripheralRef<'d, AnyPin>>, | ||
| 159 | de: Option<PeripheralRef<'d, AnyPin>>, | ||
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | /// Rx-only buffered UART | 162 | /// Rx-only buffered UART |
| @@ -166,7 +166,8 @@ pub struct BufferedUartRx<'d> { | |||
| 166 | info: &'static Info, | 166 | info: &'static Info, |
| 167 | state: &'static State, | 167 | state: &'static State, |
| 168 | kernel_clock: Hertz, | 168 | kernel_clock: Hertz, |
| 169 | _phantom: PhantomData<&'d mut ()>, | 169 | rx: Option<PeripheralRef<'d, AnyPin>>, |
| 170 | rts: Option<PeripheralRef<'d, AnyPin>>, | ||
| 170 | } | 171 | } |
| 171 | 172 | ||
| 172 | impl<'d> SetConfig for BufferedUart<'d> { | 173 | impl<'d> SetConfig for BufferedUart<'d> { |
| @@ -207,9 +208,17 @@ impl<'d> BufferedUart<'d> { | |||
| 207 | rx_buffer: &'d mut [u8], | 208 | rx_buffer: &'d mut [u8], |
| 208 | config: Config, | 209 | config: Config, |
| 209 | ) -> Result<Self, ConfigError> { | 210 | ) -> Result<Self, ConfigError> { |
| 210 | rcc::enable_and_reset::<T>(); | 211 | Self::new_inner( |
| 211 | 212 | peri, | |
| 212 | Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) | 213 | new_pin!(rx, AFType::Input), |
| 214 | new_pin!(tx, AFType::OutputPushPull), | ||
| 215 | None, | ||
| 216 | None, | ||
| 217 | None, | ||
| 218 | tx_buffer, | ||
| 219 | rx_buffer, | ||
| 220 | config, | ||
| 221 | ) | ||
| 213 | } | 222 | } |
| 214 | 223 | ||
| 215 | /// Create a new bidirectional buffered UART driver with request-to-send and clear-to-send pins | 224 | /// Create a new bidirectional buffered UART driver with request-to-send and clear-to-send pins |
| @@ -224,18 +233,17 @@ impl<'d> BufferedUart<'d> { | |||
| 224 | rx_buffer: &'d mut [u8], | 233 | rx_buffer: &'d mut [u8], |
| 225 | config: Config, | 234 | config: Config, |
| 226 | ) -> Result<Self, ConfigError> { | 235 | ) -> Result<Self, ConfigError> { |
| 227 | into_ref!(cts, rts); | 236 | Self::new_inner( |
| 228 | 237 | peri, | |
| 229 | rcc::enable_and_reset::<T>(); | 238 | new_pin!(rx, AFType::Input), |
| 230 | 239 | new_pin!(tx, AFType::OutputPushPull), | |
| 231 | rts.set_as_af(rts.af_num(), AFType::OutputPushPull); | 240 | new_pin!(rts, AFType::OutputPushPull), |
| 232 | cts.set_as_af(cts.af_num(), AFType::Input); | 241 | new_pin!(cts, AFType::Input), |
| 233 | T::info().regs.cr3().write(|w| { | 242 | None, |
| 234 | w.set_rtse(true); | 243 | tx_buffer, |
| 235 | w.set_ctse(true); | 244 | rx_buffer, |
| 236 | }); | 245 | config, |
| 237 | 246 | ) | |
| 238 | Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) | ||
| 239 | } | 247 | } |
| 240 | 248 | ||
| 241 | /// Create a new bidirectional buffered UART driver with a driver-enable pin | 249 | /// Create a new bidirectional buffered UART driver with a driver-enable pin |
| @@ -250,66 +258,89 @@ impl<'d> BufferedUart<'d> { | |||
| 250 | rx_buffer: &'d mut [u8], | 258 | rx_buffer: &'d mut [u8], |
| 251 | config: Config, | 259 | config: Config, |
| 252 | ) -> Result<Self, ConfigError> { | 260 | ) -> Result<Self, ConfigError> { |
| 253 | into_ref!(de); | 261 | Self::new_inner( |
| 254 | 262 | peri, | |
| 255 | rcc::enable_and_reset::<T>(); | 263 | new_pin!(rx, AFType::Input), |
| 256 | 264 | new_pin!(tx, AFType::OutputPushPull), | |
| 257 | de.set_as_af(de.af_num(), AFType::OutputPushPull); | 265 | None, |
| 258 | T::info().regs.cr3().write(|w| { | 266 | None, |
| 259 | w.set_dem(true); | 267 | new_pin!(de, AFType::OutputPushPull), |
| 260 | }); | 268 | tx_buffer, |
| 261 | 269 | rx_buffer, | |
| 262 | Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) | 270 | config, |
| 271 | ) | ||
| 263 | } | 272 | } |
| 264 | 273 | ||
| 265 | fn new_inner<T: Instance>( | 274 | fn new_inner<T: Instance>( |
| 266 | _peri: impl Peripheral<P = T> + 'd, | 275 | _peri: impl Peripheral<P = T> + 'd, |
| 267 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 276 | rx: Option<PeripheralRef<'d, AnyPin>>, |
| 268 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 277 | tx: Option<PeripheralRef<'d, AnyPin>>, |
| 278 | rts: Option<PeripheralRef<'d, AnyPin>>, | ||
| 279 | cts: Option<PeripheralRef<'d, AnyPin>>, | ||
| 280 | de: Option<PeripheralRef<'d, AnyPin>>, | ||
| 269 | tx_buffer: &'d mut [u8], | 281 | tx_buffer: &'d mut [u8], |
| 270 | rx_buffer: &'d mut [u8], | 282 | rx_buffer: &'d mut [u8], |
| 271 | config: Config, | 283 | config: Config, |
| 272 | ) -> Result<Self, ConfigError> { | 284 | ) -> Result<Self, ConfigError> { |
| 273 | into_ref!(_peri, rx, tx); | ||
| 274 | |||
| 275 | let info = T::info(); | 285 | let info = T::info(); |
| 276 | let state = T::buffered_state(); | 286 | let state = T::buffered_state(); |
| 277 | let kernel_clock = T::frequency(); | 287 | let kernel_clock = T::frequency(); |
| 278 | let len = tx_buffer.len(); | ||
| 279 | unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) }; | ||
| 280 | let len = rx_buffer.len(); | ||
| 281 | unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) }; | ||
| 282 | |||
| 283 | let r = info.regs; | ||
| 284 | rx.set_as_af(rx.af_num(), AFType::Input); | ||
| 285 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); | ||
| 286 | |||
| 287 | configure(info, kernel_clock, &config, true, true)?; | ||
| 288 | |||
| 289 | r.cr1().modify(|w| { | ||
| 290 | w.set_rxneie(true); | ||
| 291 | w.set_idleie(true); | ||
| 292 | }); | ||
| 293 | |||
| 294 | T::Interrupt::unpend(); | ||
| 295 | unsafe { T::Interrupt::enable() }; | ||
| 296 | 288 | ||
| 297 | state.tx_rx_refcount.store(2, Ordering::Relaxed); | 289 | let mut this = Self { |
| 298 | |||
| 299 | Ok(Self { | ||
| 300 | rx: BufferedUartRx { | 290 | rx: BufferedUartRx { |
| 301 | info, | 291 | info, |
| 302 | state, | 292 | state, |
| 303 | kernel_clock, | 293 | kernel_clock, |
| 304 | _phantom: PhantomData, | 294 | rx, |
| 295 | rts, | ||
| 305 | }, | 296 | }, |
| 306 | tx: BufferedUartTx { | 297 | tx: BufferedUartTx { |
| 307 | info, | 298 | info, |
| 308 | state, | 299 | state, |
| 309 | kernel_clock, | 300 | kernel_clock, |
| 310 | _phantom: PhantomData, | 301 | tx, |
| 302 | cts, | ||
| 303 | de, | ||
| 311 | }, | 304 | }, |
| 312 | }) | 305 | }; |
| 306 | this.enable_and_configure(tx_buffer, rx_buffer, &config)?; | ||
| 307 | Ok(this) | ||
| 308 | } | ||
| 309 | |||
| 310 | fn enable_and_configure( | ||
| 311 | &mut self, | ||
| 312 | tx_buffer: &'d mut [u8], | ||
| 313 | rx_buffer: &'d mut [u8], | ||
| 314 | config: &Config, | ||
| 315 | ) -> Result<(), ConfigError> { | ||
| 316 | let info = self.rx.info; | ||
| 317 | let state = self.rx.state; | ||
| 318 | state.tx_rx_refcount.store(2, Ordering::Relaxed); | ||
| 319 | |||
| 320 | info.rcc.enable_and_reset(); | ||
| 321 | |||
| 322 | let len = tx_buffer.len(); | ||
| 323 | unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) }; | ||
| 324 | let len = rx_buffer.len(); | ||
| 325 | unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) }; | ||
| 326 | |||
| 327 | info.regs.cr3().write(|w| { | ||
| 328 | w.set_rtse(self.rx.rts.is_some()); | ||
| 329 | w.set_ctse(self.tx.cts.is_some()); | ||
| 330 | #[cfg(not(any(usart_v1, usart_v2)))] | ||
| 331 | w.set_dem(self.tx.de.is_some()); | ||
| 332 | }); | ||
| 333 | configure(info, self.rx.kernel_clock, &config, true, true)?; | ||
| 334 | |||
| 335 | info.regs.cr1().modify(|w| { | ||
| 336 | w.set_rxneie(true); | ||
| 337 | w.set_idleie(true); | ||
| 338 | }); | ||
| 339 | |||
| 340 | info.interrupt.unpend(); | ||
| 341 | unsafe { info.interrupt.enable() }; | ||
| 342 | |||
| 343 | Ok(()) | ||
| 313 | } | 344 | } |
| 314 | 345 | ||
| 315 | /// Split the driver into a Tx and Rx part (useful for sending to separate tasks) | 346 | /// Split the driver into a Tx and Rx part (useful for sending to separate tasks) |
| @@ -516,6 +547,8 @@ impl<'d> Drop for BufferedUartRx<'d> { | |||
| 516 | } | 547 | } |
| 517 | } | 548 | } |
| 518 | 549 | ||
| 550 | self.rx.as_ref().map(|x| x.set_as_disconnected()); | ||
| 551 | self.rts.as_ref().map(|x| x.set_as_disconnected()); | ||
| 519 | drop_tx_rx(self.info, state); | 552 | drop_tx_rx(self.info, state); |
| 520 | } | 553 | } |
| 521 | } | 554 | } |
| @@ -533,6 +566,9 @@ impl<'d> Drop for BufferedUartTx<'d> { | |||
| 533 | } | 566 | } |
| 534 | } | 567 | } |
| 535 | 568 | ||
| 569 | self.tx.as_ref().map(|x| x.set_as_disconnected()); | ||
| 570 | self.cts.as_ref().map(|x| x.set_as_disconnected()); | ||
| 571 | self.de.as_ref().map(|x| x.set_as_disconnected()); | ||
| 536 | drop_tx_rx(self.info, state); | 572 | drop_tx_rx(self.info, state); |
| 537 | } | 573 | } |
| 538 | } | 574 | } |
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 2a39c6301..53321391a 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs | |||
| @@ -14,7 +14,7 @@ use embassy_sync::waitqueue::AtomicWaker; | |||
| 14 | use futures_util::future::{select, Either}; | 14 | use futures_util::future::{select, Either}; |
| 15 | 15 | ||
| 16 | use crate::dma::ChannelAndRequest; | 16 | use crate::dma::ChannelAndRequest; |
| 17 | use crate::gpio::{AFType, AnyPin, SealedPin}; | 17 | use crate::gpio::{AFType, AnyPin, SealedPin as _}; |
| 18 | use crate::interrupt::typelevel::Interrupt as _; | 18 | use crate::interrupt::typelevel::Interrupt as _; |
| 19 | use crate::interrupt::{self, Interrupt, InterruptExt}; | 19 | use crate::interrupt::{self, Interrupt, InterruptExt}; |
| 20 | use crate::mode::{Async, Blocking, Mode}; | 20 | use crate::mode::{Async, Blocking, Mode}; |
| @@ -28,7 +28,7 @@ use crate::pac::usart::Lpuart as Regs; | |||
| 28 | #[cfg(any(usart_v1, usart_v2))] | 28 | #[cfg(any(usart_v1, usart_v2))] |
| 29 | use crate::pac::usart::Usart as Regs; | 29 | use crate::pac::usart::Usart as Regs; |
| 30 | use crate::pac::usart::{regs, vals}; | 30 | use crate::pac::usart::{regs, vals}; |
| 31 | use crate::rcc::{self, RccInfo, SealedRccPeripheral}; | 31 | use crate::rcc::{RccInfo, SealedRccPeripheral}; |
| 32 | use crate::time::Hertz; | 32 | use crate::time::Hertz; |
| 33 | use crate::Peripheral; | 33 | use crate::Peripheral; |
| 34 | 34 | ||
| @@ -429,29 +429,33 @@ impl<'d, M: Mode> UartTx<'d, M> { | |||
| 429 | tx_dma: Option<ChannelAndRequest<'d>>, | 429 | tx_dma: Option<ChannelAndRequest<'d>>, |
| 430 | config: Config, | 430 | config: Config, |
| 431 | ) -> Result<Self, ConfigError> { | 431 | ) -> Result<Self, ConfigError> { |
| 432 | rcc::enable_and_reset::<T>(); | 432 | let mut this = Self { |
| 433 | 433 | info: T::info(), | |
| 434 | let info = T::info(); | 434 | state: T::state(), |
| 435 | let state = T::state(); | 435 | kernel_clock: T::frequency(), |
| 436 | let kernel_clock = T::frequency(); | ||
| 437 | let r = info.regs; | ||
| 438 | r.cr3().modify(|w| { | ||
| 439 | w.set_ctse(cts.is_some()); | ||
| 440 | }); | ||
| 441 | configure(info, kernel_clock, &config, false, true)?; | ||
| 442 | |||
| 443 | state.tx_rx_refcount.store(1, Ordering::Relaxed); | ||
| 444 | |||
| 445 | Ok(Self { | ||
| 446 | info, | ||
| 447 | state, | ||
| 448 | kernel_clock, | ||
| 449 | tx, | 436 | tx, |
| 450 | cts, | 437 | cts, |
| 451 | de: None, | 438 | de: None, |
| 452 | tx_dma, | 439 | tx_dma, |
| 453 | _phantom: PhantomData, | 440 | _phantom: PhantomData, |
| 454 | }) | 441 | }; |
| 442 | this.enable_and_configure(&config)?; | ||
| 443 | Ok(this) | ||
| 444 | } | ||
| 445 | |||
| 446 | fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> { | ||
| 447 | let info = self.info; | ||
| 448 | let state = self.state; | ||
| 449 | state.tx_rx_refcount.store(1, Ordering::Relaxed); | ||
| 450 | |||
| 451 | info.rcc.enable_and_reset(); | ||
| 452 | |||
| 453 | info.regs.cr3().modify(|w| { | ||
| 454 | w.set_ctse(self.cts.is_some()); | ||
| 455 | }); | ||
| 456 | configure(info, self.kernel_clock, config, false, true)?; | ||
| 457 | |||
| 458 | Ok(()) | ||
| 455 | } | 459 | } |
| 456 | 460 | ||
| 457 | /// Reconfigure the driver | 461 | /// Reconfigure the driver |
| @@ -775,34 +779,38 @@ impl<'d, M: Mode> UartRx<'d, M> { | |||
| 775 | rx_dma: Option<ChannelAndRequest<'d>>, | 779 | rx_dma: Option<ChannelAndRequest<'d>>, |
| 776 | config: Config, | 780 | config: Config, |
| 777 | ) -> Result<Self, ConfigError> { | 781 | ) -> Result<Self, ConfigError> { |
| 778 | rcc::enable_and_reset::<T>(); | 782 | let mut this = Self { |
| 779 | |||
| 780 | let info = T::info(); | ||
| 781 | let state = T::state(); | ||
| 782 | let kernel_clock = T::frequency(); | ||
| 783 | let r = info.regs; | ||
| 784 | r.cr3().write(|w| { | ||
| 785 | w.set_rtse(rts.is_some()); | ||
| 786 | }); | ||
| 787 | configure(info, kernel_clock, &config, true, false)?; | ||
| 788 | |||
| 789 | T::Interrupt::unpend(); | ||
| 790 | unsafe { T::Interrupt::enable() }; | ||
| 791 | |||
| 792 | state.tx_rx_refcount.store(1, Ordering::Relaxed); | ||
| 793 | |||
| 794 | Ok(Self { | ||
| 795 | _phantom: PhantomData, | 783 | _phantom: PhantomData, |
| 796 | info, | 784 | info: T::info(), |
| 797 | state, | 785 | state: T::state(), |
| 798 | kernel_clock, | 786 | kernel_clock: T::frequency(), |
| 799 | rx, | 787 | rx, |
| 800 | rts, | 788 | rts, |
| 801 | rx_dma, | 789 | rx_dma, |
| 802 | detect_previous_overrun: config.detect_previous_overrun, | 790 | detect_previous_overrun: config.detect_previous_overrun, |
| 803 | #[cfg(any(usart_v1, usart_v2))] | 791 | #[cfg(any(usart_v1, usart_v2))] |
| 804 | buffered_sr: stm32_metapac::usart::regs::Sr(0), | 792 | buffered_sr: stm32_metapac::usart::regs::Sr(0), |
| 805 | }) | 793 | }; |
| 794 | this.enable_and_configure(&config)?; | ||
| 795 | Ok(this) | ||
| 796 | } | ||
| 797 | |||
| 798 | fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> { | ||
| 799 | let info = self.info; | ||
| 800 | let state = self.state; | ||
| 801 | state.tx_rx_refcount.store(1, Ordering::Relaxed); | ||
| 802 | |||
| 803 | info.rcc.enable_and_reset(); | ||
| 804 | |||
| 805 | info.regs.cr3().write(|w| { | ||
| 806 | w.set_rtse(self.rts.is_some()); | ||
| 807 | }); | ||
| 808 | configure(info, self.kernel_clock, &config, true, false)?; | ||
| 809 | |||
| 810 | info.interrupt.unpend(); | ||
| 811 | unsafe { info.interrupt.enable() }; | ||
| 812 | |||
| 813 | Ok(()) | ||
| 806 | } | 814 | } |
| 807 | 815 | ||
| 808 | /// Reconfigure the driver | 816 | /// Reconfigure the driver |
| @@ -1228,27 +1236,11 @@ impl<'d, M: Mode> Uart<'d, M> { | |||
| 1228 | rx_dma: Option<ChannelAndRequest<'d>>, | 1236 | rx_dma: Option<ChannelAndRequest<'d>>, |
| 1229 | config: Config, | 1237 | config: Config, |
| 1230 | ) -> Result<Self, ConfigError> { | 1238 | ) -> Result<Self, ConfigError> { |
| 1231 | rcc::enable_and_reset::<T>(); | ||
| 1232 | |||
| 1233 | let info = T::info(); | 1239 | let info = T::info(); |
| 1234 | let state = T::state(); | 1240 | let state = T::state(); |
| 1235 | let kernel_clock = T::frequency(); | 1241 | let kernel_clock = T::frequency(); |
| 1236 | let r = info.regs; | ||
| 1237 | |||
| 1238 | r.cr3().write(|w| { | ||
| 1239 | w.set_rtse(rts.is_some()); | ||
| 1240 | w.set_ctse(cts.is_some()); | ||
| 1241 | #[cfg(not(any(usart_v1, usart_v2)))] | ||
| 1242 | w.set_dem(de.is_some()); | ||
| 1243 | }); | ||
| 1244 | configure(info, kernel_clock, &config, true, true)?; | ||
| 1245 | |||
| 1246 | T::Interrupt::unpend(); | ||
| 1247 | unsafe { T::Interrupt::enable() }; | ||
| 1248 | 1242 | ||
| 1249 | state.tx_rx_refcount.store(2, Ordering::Relaxed); | 1243 | let mut this = Self { |
| 1250 | |||
| 1251 | Ok(Self { | ||
| 1252 | tx: UartTx { | 1244 | tx: UartTx { |
| 1253 | _phantom: PhantomData, | 1245 | _phantom: PhantomData, |
| 1254 | info, | 1246 | info, |
| @@ -1271,7 +1263,30 @@ impl<'d, M: Mode> Uart<'d, M> { | |||
| 1271 | #[cfg(any(usart_v1, usart_v2))] | 1263 | #[cfg(any(usart_v1, usart_v2))] |
| 1272 | buffered_sr: stm32_metapac::usart::regs::Sr(0), | 1264 | buffered_sr: stm32_metapac::usart::regs::Sr(0), |
| 1273 | }, | 1265 | }, |
| 1274 | }) | 1266 | }; |
| 1267 | this.enable_and_configure(&config)?; | ||
| 1268 | Ok(this) | ||
| 1269 | } | ||
| 1270 | |||
| 1271 | fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> { | ||
| 1272 | let info = self.rx.info; | ||
| 1273 | let state = self.rx.state; | ||
| 1274 | state.tx_rx_refcount.store(2, Ordering::Relaxed); | ||
| 1275 | |||
| 1276 | info.rcc.enable_and_reset(); | ||
| 1277 | |||
| 1278 | info.regs.cr3().write(|w| { | ||
| 1279 | w.set_rtse(self.rx.rts.is_some()); | ||
| 1280 | w.set_ctse(self.tx.cts.is_some()); | ||
| 1281 | #[cfg(not(any(usart_v1, usart_v2)))] | ||
| 1282 | w.set_dem(self.tx.de.is_some()); | ||
| 1283 | }); | ||
| 1284 | configure(info, self.rx.kernel_clock, config, true, true)?; | ||
| 1285 | |||
| 1286 | info.interrupt.unpend(); | ||
| 1287 | unsafe { info.interrupt.enable() }; | ||
| 1288 | |||
| 1289 | Ok(()) | ||
| 1275 | } | 1290 | } |
| 1276 | 1291 | ||
| 1277 | /// Perform a blocking write | 1292 | /// Perform a blocking write |
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index f3a88b93f..8cf75933a 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs | |||
| @@ -4,10 +4,12 @@ use core::sync::atomic::{compiler_fence, Ordering}; | |||
| 4 | use core::task::Poll; | 4 | use core::task::Poll; |
| 5 | 5 | ||
| 6 | use embassy_embedded_hal::SetConfig; | 6 | use embassy_embedded_hal::SetConfig; |
| 7 | use embassy_hal_internal::PeripheralRef; | ||
| 7 | use futures_util::future::{select, Either}; | 8 | use futures_util::future::{select, Either}; |
| 8 | 9 | ||
| 9 | use super::{clear_interrupt_flags, rdr, reconfigure, sr, Config, ConfigError, Error, Info, State, UartRx}; | 10 | use super::{clear_interrupt_flags, rdr, reconfigure, sr, Config, ConfigError, Error, Info, State, UartRx}; |
| 10 | use crate::dma::ReadableRingBuffer; | 11 | use crate::dma::ReadableRingBuffer; |
| 12 | use crate::gpio::{AnyPin, SealedPin as _}; | ||
| 11 | use crate::mode::Async; | 13 | use crate::mode::Async; |
| 12 | use crate::time::Hertz; | 14 | use crate::time::Hertz; |
| 13 | use crate::usart::{Regs, Sr}; | 15 | use crate::usart::{Regs, Sr}; |
| @@ -19,6 +21,8 @@ pub struct RingBufferedUartRx<'d> { | |||
| 19 | info: &'static Info, | 21 | info: &'static Info, |
| 20 | state: &'static State, | 22 | state: &'static State, |
| 21 | kernel_clock: Hertz, | 23 | kernel_clock: Hertz, |
| 24 | rx: Option<PeripheralRef<'d, AnyPin>>, | ||
| 25 | rts: Option<PeripheralRef<'d, AnyPin>>, | ||
| 22 | ring_buf: ReadableRingBuffer<'d, u8>, | 26 | ring_buf: ReadableRingBuffer<'d, u8>, |
| 23 | } | 27 | } |
| 24 | 28 | ||
| @@ -49,6 +53,8 @@ impl<'d> UartRx<'d, Async> { | |||
| 49 | let state = self.state; | 53 | let state = self.state; |
| 50 | let kernel_clock = self.kernel_clock; | 54 | let kernel_clock = self.kernel_clock; |
| 51 | let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(info.regs), dma_buf, opts) }; | 55 | let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(info.regs), dma_buf, opts) }; |
| 56 | let rx = unsafe { self.rx.as_ref().map(|x| x.clone_unchecked()) }; | ||
| 57 | let rts = unsafe { self.rts.as_ref().map(|x| x.clone_unchecked()) }; | ||
| 52 | 58 | ||
| 53 | // Don't disable the clock | 59 | // Don't disable the clock |
| 54 | mem::forget(self); | 60 | mem::forget(self); |
| @@ -57,6 +63,8 @@ impl<'d> UartRx<'d, Async> { | |||
| 57 | info, | 63 | info, |
| 58 | state, | 64 | state, |
| 59 | kernel_clock, | 65 | kernel_clock, |
| 66 | rx, | ||
| 67 | rts, | ||
| 60 | ring_buf, | 68 | ring_buf, |
| 61 | } | 69 | } |
| 62 | } | 70 | } |
| @@ -221,6 +229,8 @@ impl<'d> RingBufferedUartRx<'d> { | |||
| 221 | impl Drop for RingBufferedUartRx<'_> { | 229 | impl Drop for RingBufferedUartRx<'_> { |
| 222 | fn drop(&mut self) { | 230 | fn drop(&mut self) { |
| 223 | self.teardown_uart(); | 231 | self.teardown_uart(); |
| 232 | self.rx.as_ref().map(|x| x.set_as_disconnected()); | ||
| 233 | self.rts.as_ref().map(|x| x.set_as_disconnected()); | ||
| 224 | super::drop_tx_rx(self.info, self.state); | 234 | super::drop_tx_rx(self.info, self.state); |
| 225 | } | 235 | } |
| 226 | } | 236 | } |
