aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-09-04 23:37:59 +0200
committerGitHub <[email protected]>2023-09-04 23:37:59 +0200
commita03b6be693293f8a646a96eb3f26c3e79e0882fe (patch)
tree118490c3fcfbe39343795509d239621e84746701
parent87d308653340f050dda5382777c80b373bd203cb (diff)
parentd19e1c1dd1c8c514c375bca3ba69f636a0b19f88 (diff)
Merge pull request #1862 from xoviat/rcc-refcount
stm32: refcount peripheral enable/disable
-rw-r--r--embassy-stm32/build.rs44
-rw-r--r--embassy-stm32/src/i2c/v1.rs6
-rw-r--r--embassy-stm32/src/i2c/v2.rs6
-rw-r--r--embassy-stm32/src/spi/mod.rs2
-rw-r--r--embassy-stm32/src/usart/buffered.rs10
-rw-r--r--embassy-stm32/src/usart/mod.rs18
-rw-r--r--embassy-stm32/src/usart/ringbuffered.rs17
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
342impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> {
343 fn drop(&mut self) {
344 T::disable();
345 }
346}
347
342impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Read for I2c<'d, T> { 348impl<'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
841impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> {
842 fn drop(&mut self) {
843 T::disable();
844 }
845}
846
841mod eh02 { 847mod 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
621impl<'d, T: BasicInstance, TxDma> Drop for UartTx<'d, T, TxDma> {
622 fn drop(&mut self) {
623 T::disable();
624 }
625}
626
627impl<'d, T: BasicInstance, TxDma> Drop for UartRx<'d, T, TxDma> {
628 fn drop(&mut self) {
629 T::disable();
630 }
631}
632
621impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { 633impl<'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 @@
1use core::future::poll_fn; 1use core::future::poll_fn;
2use core::mem;
2use core::sync::atomic::{compiler_fence, Ordering}; 3use core::sync::atomic::{compiler_fence, Ordering};
3use core::task::Poll; 4use 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
186impl<T: BasicInstance, RxDma: super::RxDma<T>> Drop for RingBufferedUartRx<'_, T, RxDma> { 191impl<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