diff options
| -rw-r--r-- | embassy-stm32/build.rs | 44 | ||||
| -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 | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/buffered.rs | 10 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 18 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/ringbuffered.rs | 17 |
7 files changed, 98 insertions, 5 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 6c364f7bb..aef0668a2 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -308,6 +308,10 @@ fn main() { | |||
| 308 | // ======== | 308 | // ======== |
| 309 | // Generate RccPeripheral impls | 309 | // Generate RccPeripheral impls |
| 310 | 310 | ||
| 311 | // TODO: maybe get this from peripheral kind? Not sure | ||
| 312 | let refcounted_peripherals = HashSet::from(["USART"]); | ||
| 313 | let mut refcount_statics = HashSet::new(); | ||
| 314 | |||
| 311 | for p in METADATA.peripherals { | 315 | for p in METADATA.peripherals { |
| 312 | // generating RccPeripheral impl for H7 ADC3 would result in bad frequency | 316 | // generating RccPeripheral impl for H7 ADC3 would result in bad frequency |
| 313 | if !singletons.contains(&p.name.to_string()) | 317 | if !singletons.contains(&p.name.to_string()) |
| @@ -344,11 +348,36 @@ fn main() { | |||
| 344 | TokenStream::new() | 348 | TokenStream::new() |
| 345 | }; | 349 | }; |
| 346 | 350 | ||
| 351 | let ptype = (if let Some(reg) = &p.registers { reg.kind } else { "" }).to_ascii_uppercase(); | ||
| 347 | let pname = format_ident!("{}", p.name); | 352 | let pname = format_ident!("{}", p.name); |
| 348 | let clk = format_ident!("{}", rcc.clock.to_ascii_lowercase()); | 353 | let clk = format_ident!("{}", rcc.clock.to_ascii_lowercase()); |
| 349 | let en_reg = format_ident!("{}", en.register.to_ascii_lowercase()); | 354 | let en_reg = format_ident!("{}", en.register.to_ascii_lowercase()); |
| 350 | let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase()); | 355 | let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase()); |
| 351 | 356 | ||
| 357 | let (before_enable, before_disable) = if refcounted_peripherals.contains(ptype.as_str()) { | ||
| 358 | let refcount_static = | ||
| 359 | format_ident!("{}_{}", en.register.to_ascii_uppercase(), en.field.to_ascii_uppercase()); | ||
| 360 | |||
| 361 | refcount_statics.insert(refcount_static.clone()); | ||
| 362 | |||
| 363 | ( | ||
| 364 | quote! { | ||
| 365 | unsafe { refcount_statics::#refcount_static += 1 }; | ||
| 366 | if unsafe { refcount_statics::#refcount_static } > 1 { | ||
| 367 | return; | ||
| 368 | } | ||
| 369 | }, | ||
| 370 | quote! { | ||
| 371 | unsafe { refcount_statics::#refcount_static -= 1 }; | ||
| 372 | if unsafe { refcount_statics::#refcount_static } > 0 { | ||
| 373 | return; | ||
| 374 | } | ||
| 375 | }, | ||
| 376 | ) | ||
| 377 | } else { | ||
| 378 | (TokenStream::new(), TokenStream::new()) | ||
| 379 | }; | ||
| 380 | |||
| 352 | g.extend(quote! { | 381 | g.extend(quote! { |
| 353 | impl crate::rcc::sealed::RccPeripheral for peripherals::#pname { | 382 | impl crate::rcc::sealed::RccPeripheral for peripherals::#pname { |
| 354 | fn frequency() -> crate::time::Hertz { | 383 | fn frequency() -> crate::time::Hertz { |
| @@ -356,6 +385,7 @@ fn main() { | |||
| 356 | } | 385 | } |
| 357 | fn enable() { | 386 | fn enable() { |
| 358 | critical_section::with(|_| { | 387 | critical_section::with(|_| { |
| 388 | #before_enable | ||
| 359 | #[cfg(feature = "low-power")] | 389 | #[cfg(feature = "low-power")] |
| 360 | crate::rcc::clock_refcount_add(); | 390 | crate::rcc::clock_refcount_add(); |
| 361 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); | 391 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); |
| @@ -364,6 +394,7 @@ fn main() { | |||
| 364 | } | 394 | } |
| 365 | fn disable() { | 395 | fn disable() { |
| 366 | critical_section::with(|_| { | 396 | critical_section::with(|_| { |
| 397 | #before_disable | ||
| 367 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); | 398 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); |
| 368 | #[cfg(feature = "low-power")] | 399 | #[cfg(feature = "low-power")] |
| 369 | crate::rcc::clock_refcount_sub(); | 400 | crate::rcc::clock_refcount_sub(); |
| @@ -379,6 +410,19 @@ fn main() { | |||
| 379 | } | 410 | } |
| 380 | } | 411 | } |
| 381 | 412 | ||
| 413 | let mut refcount_mod = TokenStream::new(); | ||
| 414 | for refcount_static in refcount_statics { | ||
| 415 | refcount_mod.extend(quote! { | ||
| 416 | pub(crate) static mut #refcount_static: u8 = 0; | ||
| 417 | }); | ||
| 418 | } | ||
| 419 | |||
| 420 | g.extend(quote! { | ||
| 421 | mod refcount_statics { | ||
| 422 | #refcount_mod | ||
| 423 | } | ||
| 424 | }); | ||
| 425 | |||
| 382 | // ======== | 426 | // ======== |
| 383 | // Generate fns to enable GPIO, DMA in RCC | 427 | // Generate fns to enable GPIO, DMA in RCC |
| 384 | 428 | ||
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index 618d85af2..f32dd0f0c 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs | |||
| @@ -339,6 +339,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 339 | } | 339 | } |
| 340 | } | 340 | } |
| 341 | 341 | ||
| 342 | impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> { | ||
| 343 | fn drop(&mut self) { | ||
| 344 | T::disable(); | ||
| 345 | } | ||
| 346 | } | ||
| 347 | |||
| 342 | impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Read for I2c<'d, T> { | 348 | impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Read for I2c<'d, T> { |
| 343 | type Error = Error; | 349 | type Error = Error; |
| 344 | 350 | ||
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 4327899bb..36f70e32e 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs | |||
| @@ -838,6 +838,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { | |||
| 838 | } | 838 | } |
| 839 | } | 839 | } |
| 840 | 840 | ||
| 841 | impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> { | ||
| 842 | fn drop(&mut self) { | ||
| 843 | T::disable(); | ||
| 844 | } | ||
| 845 | } | ||
| 846 | |||
| 841 | mod eh02 { | 847 | mod eh02 { |
| 842 | use super::*; | 848 | use super::*; |
| 843 | 849 | ||
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index e2bc8d7f2..853de98f9 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs | |||
| @@ -646,6 +646,8 @@ impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> { | |||
| 646 | self.sck.as_ref().map(|x| x.set_as_disconnected()); | 646 | self.sck.as_ref().map(|x| x.set_as_disconnected()); |
| 647 | self.mosi.as_ref().map(|x| x.set_as_disconnected()); | 647 | self.mosi.as_ref().map(|x| x.set_as_disconnected()); |
| 648 | self.miso.as_ref().map(|x| x.set_as_disconnected()); | 648 | self.miso.as_ref().map(|x| x.set_as_disconnected()); |
| 649 | |||
| 650 | T::disable(); | ||
| 649 | } | 651 | } |
| 650 | } | 652 | } |
| 651 | 653 | ||
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 596d40bf9..989c88205 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs | |||
| @@ -124,6 +124,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { | |||
| 124 | rx_buffer: &'d mut [u8], | 124 | rx_buffer: &'d mut [u8], |
| 125 | config: Config, | 125 | config: Config, |
| 126 | ) -> BufferedUart<'d, T> { | 126 | ) -> BufferedUart<'d, T> { |
| 127 | // UartRx and UartTx have one refcount ea. | ||
| 128 | T::enable(); | ||
| 127 | T::enable(); | 129 | T::enable(); |
| 128 | T::reset(); | 130 | T::reset(); |
| 129 | 131 | ||
| @@ -143,6 +145,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { | |||
| 143 | ) -> BufferedUart<'d, T> { | 145 | ) -> BufferedUart<'d, T> { |
| 144 | into_ref!(cts, rts); | 146 | into_ref!(cts, rts); |
| 145 | 147 | ||
| 148 | // UartRx and UartTx have one refcount ea. | ||
| 149 | T::enable(); | ||
| 146 | T::enable(); | 150 | T::enable(); |
| 147 | T::reset(); | 151 | T::reset(); |
| 148 | 152 | ||
| @@ -169,6 +173,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> { | |||
| 169 | ) -> BufferedUart<'d, T> { | 173 | ) -> BufferedUart<'d, T> { |
| 170 | into_ref!(de); | 174 | into_ref!(de); |
| 171 | 175 | ||
| 176 | // UartRx and UartTx have one refcount ea. | ||
| 177 | T::enable(); | ||
| 172 | T::enable(); | 178 | T::enable(); |
| 173 | T::reset(); | 179 | T::reset(); |
| 174 | 180 | ||
| @@ -382,6 +388,8 @@ impl<'d, T: BasicInstance> Drop for BufferedUartRx<'d, T> { | |||
| 382 | T::Interrupt::disable(); | 388 | T::Interrupt::disable(); |
| 383 | } | 389 | } |
| 384 | } | 390 | } |
| 391 | |||
| 392 | T::disable(); | ||
| 385 | } | 393 | } |
| 386 | } | 394 | } |
| 387 | 395 | ||
| @@ -397,6 +405,8 @@ impl<'d, T: BasicInstance> Drop for BufferedUartTx<'d, T> { | |||
| 397 | T::Interrupt::disable(); | 405 | T::Interrupt::disable(); |
| 398 | } | 406 | } |
| 399 | } | 407 | } |
| 408 | |||
| 409 | T::disable(); | ||
| 400 | } | 410 | } |
| 401 | } | 411 | } |
| 402 | 412 | ||
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 255ddfd4b..bfb056718 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs | |||
| @@ -618,6 +618,18 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { | |||
| 618 | } | 618 | } |
| 619 | } | 619 | } |
| 620 | 620 | ||
| 621 | impl<'d, T: BasicInstance, TxDma> Drop for UartTx<'d, T, TxDma> { | ||
| 622 | fn drop(&mut self) { | ||
| 623 | T::disable(); | ||
| 624 | } | ||
| 625 | } | ||
| 626 | |||
| 627 | impl<'d, T: BasicInstance, TxDma> Drop for UartRx<'d, T, TxDma> { | ||
| 628 | fn drop(&mut self) { | ||
| 629 | T::disable(); | ||
| 630 | } | ||
| 631 | } | ||
| 632 | |||
| 621 | impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | 633 | impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { |
| 622 | pub fn new( | 634 | pub fn new( |
| 623 | peri: impl Peripheral<P = T> + 'd, | 635 | peri: impl Peripheral<P = T> + 'd, |
| @@ -628,6 +640,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 628 | rx_dma: impl Peripheral<P = RxDma> + 'd, | 640 | rx_dma: impl Peripheral<P = RxDma> + 'd, |
| 629 | config: Config, | 641 | config: Config, |
| 630 | ) -> Self { | 642 | ) -> Self { |
| 643 | // UartRx and UartTx have one refcount ea. | ||
| 644 | T::enable(); | ||
| 631 | T::enable(); | 645 | T::enable(); |
| 632 | T::reset(); | 646 | T::reset(); |
| 633 | 647 | ||
| @@ -647,6 +661,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 647 | ) -> Self { | 661 | ) -> Self { |
| 648 | into_ref!(cts, rts); | 662 | into_ref!(cts, rts); |
| 649 | 663 | ||
| 664 | // UartRx and UartTx have one refcount ea. | ||
| 665 | T::enable(); | ||
| 650 | T::enable(); | 666 | T::enable(); |
| 651 | T::reset(); | 667 | T::reset(); |
| 652 | 668 | ||
| @@ -672,6 +688,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 672 | ) -> Self { | 688 | ) -> Self { |
| 673 | into_ref!(de); | 689 | into_ref!(de); |
| 674 | 690 | ||
| 691 | // UartRx and UartTx have one refcount ea. | ||
| 692 | T::enable(); | ||
| 675 | T::enable(); | 693 | T::enable(); |
| 676 | T::reset(); | 694 | T::reset(); |
| 677 | 695 | ||
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index b3f570624..e990eaca8 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | use core::future::poll_fn; | 1 | use core::future::poll_fn; |
| 2 | use core::mem; | ||
| 2 | use core::sync::atomic::{compiler_fence, Ordering}; | 3 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 3 | use core::task::Poll; | 4 | use core::task::Poll; |
| 4 | 5 | ||
| @@ -24,12 +25,16 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> { | |||
| 24 | let request = self.rx_dma.request(); | 25 | let request = self.rx_dma.request(); |
| 25 | let opts = Default::default(); | 26 | let opts = Default::default(); |
| 26 | 27 | ||
| 27 | let ring_buf = unsafe { ReadableRingBuffer::new_read(self.rx_dma, request, rdr(T::regs()), dma_buf, opts) }; | 28 | // Safety: we forget the struct before this function returns. |
| 29 | let rx_dma = unsafe { self.rx_dma.clone_unchecked() }; | ||
| 30 | let _peri = unsafe { self._peri.clone_unchecked() }; | ||
| 28 | 31 | ||
| 29 | RingBufferedUartRx { | 32 | let ring_buf = unsafe { ReadableRingBuffer::new_read(rx_dma, request, rdr(T::regs()), dma_buf, opts) }; |
| 30 | _peri: self._peri, | 33 | |
| 31 | ring_buf, | 34 | // Don't disable the clock |
| 32 | } | 35 | mem::forget(self); |
| 36 | |||
| 37 | RingBufferedUartRx { _peri, ring_buf } | ||
| 33 | } | 38 | } |
| 34 | } | 39 | } |
| 35 | 40 | ||
| @@ -186,6 +191,8 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxD | |||
| 186 | impl<T: BasicInstance, RxDma: super::RxDma<T>> Drop for RingBufferedUartRx<'_, T, RxDma> { | 191 | impl<T: BasicInstance, RxDma: super::RxDma<T>> Drop for RingBufferedUartRx<'_, T, RxDma> { |
| 187 | fn drop(&mut self) { | 192 | fn drop(&mut self) { |
| 188 | self.teardown_uart(); | 193 | self.teardown_uart(); |
| 194 | |||
| 195 | T::disable(); | ||
| 189 | } | 196 | } |
| 190 | } | 197 | } |
| 191 | /// Return an error result if the Sr register has errors | 198 | /// Return an error result if the Sr register has errors |
