diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-10-12 00:34:47 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-10-12 16:20:34 +0200 |
| commit | 97ca0e77bf6e6f36aae18cb57fbfa8e583597327 (patch) | |
| tree | 20f7a2f1e27e0d30e530047e819b6efeaf2bd9cc | |
| parent | 66e399b5c61653f1f66cd3fd1592936e4085d6b5 (diff) | |
stm32: avoid creating many tiny critical sections in init.
Saves 292 bytes on stm32f0 bilnky with max optimizations (from 3132 to 2840).
| -rw-r--r-- | embassy-hal-internal/src/interrupt.rs | 32 | ||||
| -rw-r--r-- | embassy-hal-internal/src/macros.rs | 10 | ||||
| -rw-r--r-- | embassy-stm32/build.rs | 28 | ||||
| -rw-r--r-- | embassy-stm32/src/dac/mod.rs | 16 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/bdma.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/dma.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/dmamux.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/gpdma.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/mod.rs | 9 | ||||
| -rw-r--r-- | embassy-stm32/src/exti.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/gpio.rs | 5 | ||||
| -rw-r--r-- | embassy-stm32/src/lib.rs | 145 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 13 | ||||
| -rw-r--r-- | embassy-stm32/src/time_driver.rs | 56 |
14 files changed, 182 insertions, 148 deletions
diff --git a/embassy-hal-internal/src/interrupt.rs b/embassy-hal-internal/src/interrupt.rs index b970aa2cd..19dabcf6f 100644 --- a/embassy-hal-internal/src/interrupt.rs +++ b/embassy-hal-internal/src/interrupt.rs | |||
| @@ -4,6 +4,7 @@ use core::sync::atomic::{compiler_fence, Ordering}; | |||
| 4 | 4 | ||
| 5 | use cortex_m::interrupt::InterruptNumber; | 5 | use cortex_m::interrupt::InterruptNumber; |
| 6 | use cortex_m::peripheral::NVIC; | 6 | use cortex_m::peripheral::NVIC; |
| 7 | use critical_section::CriticalSection; | ||
| 7 | 8 | ||
| 8 | /// Generate a standard `mod interrupt` for a HAL. | 9 | /// Generate a standard `mod interrupt` for a HAL. |
| 9 | #[macro_export] | 10 | #[macro_export] |
| @@ -91,6 +92,12 @@ macro_rules! interrupt_mod { | |||
| 91 | fn set_priority(prio: crate::interrupt::Priority) { | 92 | fn set_priority(prio: crate::interrupt::Priority) { |
| 92 | Self::IRQ.set_priority(prio) | 93 | Self::IRQ.set_priority(prio) |
| 93 | } | 94 | } |
| 95 | |||
| 96 | /// Set the interrupt priority with an already-acquired critical section | ||
| 97 | #[inline] | ||
| 98 | fn set_priority_with_cs(cs: critical_section::CriticalSection, prio: crate::interrupt::Priority) { | ||
| 99 | Self::IRQ.set_priority_with_cs(cs, prio) | ||
| 100 | } | ||
| 94 | } | 101 | } |
| 95 | 102 | ||
| 96 | $( | 103 | $( |
| @@ -195,10 +202,29 @@ pub unsafe trait InterruptExt: InterruptNumber + Copy { | |||
| 195 | /// Set the interrupt priority. | 202 | /// Set the interrupt priority. |
| 196 | #[inline] | 203 | #[inline] |
| 197 | fn set_priority(self, prio: Priority) { | 204 | fn set_priority(self, prio: Priority) { |
| 198 | critical_section::with(|_| unsafe { | 205 | unsafe { |
| 206 | let mut nvic: cortex_m::peripheral::NVIC = mem::transmute(()); | ||
| 207 | |||
| 208 | // On thumbv6, set_priority must do a RMW to change 8bit in a 32bit reg. | ||
| 209 | #[cfg(armv6m)] | ||
| 210 | critical_section::with(|_| nvic.set_priority(self, prio.into())); | ||
| 211 | // On thumbv7+, set_priority does an atomic 8bit write, so no CS needed. | ||
| 212 | #[cfg(not(armv6m))] | ||
| 213 | nvic.set_priority(self, prio.into()); | ||
| 214 | } | ||
| 215 | } | ||
| 216 | |||
| 217 | /// Set the interrupt priority with an already-acquired critical section | ||
| 218 | /// | ||
| 219 | /// Equivalent to `set_priority`, except you pass a `CriticalSection` to prove | ||
| 220 | /// you've already acquired a critical section. This prevents acquiring another | ||
| 221 | /// one, which saves code size. | ||
| 222 | #[inline] | ||
| 223 | fn set_priority_with_cs(self, _cs: CriticalSection, prio: Priority) { | ||
| 224 | unsafe { | ||
| 199 | let mut nvic: cortex_m::peripheral::NVIC = mem::transmute(()); | 225 | let mut nvic: cortex_m::peripheral::NVIC = mem::transmute(()); |
| 200 | nvic.set_priority(self, prio.into()) | 226 | nvic.set_priority(self, prio.into()); |
| 201 | }) | 227 | } |
| 202 | } | 228 | } |
| 203 | } | 229 | } |
| 204 | 230 | ||
diff --git a/embassy-hal-internal/src/macros.rs b/embassy-hal-internal/src/macros.rs index 0eea4b667..97df38954 100644 --- a/embassy-hal-internal/src/macros.rs +++ b/embassy-hal-internal/src/macros.rs | |||
| @@ -48,17 +48,23 @@ macro_rules! peripherals_struct { | |||
| 48 | ///Returns all the peripherals *once* | 48 | ///Returns all the peripherals *once* |
| 49 | #[inline] | 49 | #[inline] |
| 50 | pub(crate) fn take() -> Self { | 50 | pub(crate) fn take() -> Self { |
| 51 | critical_section::with(Self::take_with_cs) | ||
| 52 | } | ||
| 51 | 53 | ||
| 54 | ///Returns all the peripherals *once* | ||
| 55 | #[inline] | ||
| 56 | pub(crate) fn take_with_cs(_cs: critical_section::CriticalSection) -> Self { | ||
| 52 | #[no_mangle] | 57 | #[no_mangle] |
| 53 | static mut _EMBASSY_DEVICE_PERIPHERALS: bool = false; | 58 | static mut _EMBASSY_DEVICE_PERIPHERALS: bool = false; |
| 54 | 59 | ||
| 55 | critical_section::with(|_| unsafe { | 60 | // safety: OK because we're inside a CS. |
| 61 | unsafe { | ||
| 56 | if _EMBASSY_DEVICE_PERIPHERALS { | 62 | if _EMBASSY_DEVICE_PERIPHERALS { |
| 57 | panic!("init called more than once!") | 63 | panic!("init called more than once!") |
| 58 | } | 64 | } |
| 59 | _EMBASSY_DEVICE_PERIPHERALS = true; | 65 | _EMBASSY_DEVICE_PERIPHERALS = true; |
| 60 | Self::steal() | 66 | Self::steal() |
| 61 | }) | 67 | } |
| 62 | } | 68 | } |
| 63 | } | 69 | } |
| 64 | 70 | ||
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index bbdb1250c..8e680fb60 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -554,23 +554,19 @@ fn main() { | |||
| 554 | fn frequency() -> crate::time::Hertz { | 554 | fn frequency() -> crate::time::Hertz { |
| 555 | #clock_frequency | 555 | #clock_frequency |
| 556 | } | 556 | } |
| 557 | fn enable_and_reset() { | 557 | fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) { |
| 558 | critical_section::with(|_cs| { | 558 | #before_enable |
| 559 | #before_enable | 559 | #[cfg(feature = "low-power")] |
| 560 | #[cfg(feature = "low-power")] | 560 | crate::rcc::clock_refcount_add(_cs); |
| 561 | crate::rcc::clock_refcount_add(_cs); | 561 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); |
| 562 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); | 562 | #after_enable |
| 563 | #after_enable | 563 | #rst |
| 564 | #rst | ||
| 565 | }) | ||
| 566 | } | 564 | } |
| 567 | fn disable() { | 565 | fn disable_with_cs(_cs: critical_section::CriticalSection) { |
| 568 | critical_section::with(|_cs| { | 566 | #before_disable |
| 569 | #before_disable | 567 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); |
| 570 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); | 568 | #[cfg(feature = "low-power")] |
| 571 | #[cfg(feature = "low-power")] | 569 | crate::rcc::clock_refcount_sub(_cs); |
| 572 | crate::rcc::clock_refcount_sub(_cs); | ||
| 573 | }) | ||
| 574 | } | 570 | } |
| 575 | } | 571 | } |
| 576 | 572 | ||
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs index 6458572f2..a3c7823cf 100644 --- a/embassy-stm32/src/dac/mod.rs +++ b/embassy-stm32/src/dac/mod.rs | |||
| @@ -567,18 +567,14 @@ foreach_peripheral!( | |||
| 567 | critical_section::with(|_| unsafe { crate::rcc::get_freqs().apb1 }) | 567 | critical_section::with(|_| unsafe { crate::rcc::get_freqs().apb1 }) |
| 568 | } | 568 | } |
| 569 | 569 | ||
| 570 | fn enable_and_reset() { | 570 | fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) { |
| 571 | critical_section::with(|_| { | 571 | crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(true)); |
| 572 | crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(true)); | 572 | crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(false)); |
| 573 | crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(false)); | 573 | crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true)); |
| 574 | crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true)); | ||
| 575 | }) | ||
| 576 | } | 574 | } |
| 577 | 575 | ||
| 578 | fn disable() { | 576 | fn disable_with_cs(_cs: critical_section::CriticalSection) { |
| 579 | critical_section::with(|_| { | 577 | crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(false)) |
| 580 | crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(false)) | ||
| 581 | }) | ||
| 582 | } | 578 | } |
| 583 | } | 579 | } |
| 584 | 580 | ||
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs index 62eb65b1c..a7422f66b 100644 --- a/embassy-stm32/src/dma/bdma.rs +++ b/embassy-stm32/src/dma/bdma.rs | |||
| @@ -77,10 +77,10 @@ impl State { | |||
| 77 | static STATE: State = State::new(); | 77 | static STATE: State = State::new(); |
| 78 | 78 | ||
| 79 | /// safety: must be called only once | 79 | /// safety: must be called only once |
| 80 | pub(crate) unsafe fn init(irq_priority: Priority) { | 80 | pub(crate) unsafe fn init(cs: critical_section::CriticalSection, irq_priority: Priority) { |
| 81 | foreach_interrupt! { | 81 | foreach_interrupt! { |
| 82 | ($peri:ident, bdma, $block:ident, $signal_name:ident, $irq:ident) => { | 82 | ($peri:ident, bdma, $block:ident, $signal_name:ident, $irq:ident) => { |
| 83 | crate::interrupt::typelevel::$irq::set_priority(irq_priority); | 83 | crate::interrupt::typelevel::$irq::set_priority_with_cs(cs, irq_priority); |
| 84 | crate::interrupt::typelevel::$irq::enable(); | 84 | crate::interrupt::typelevel::$irq::enable(); |
| 85 | }; | 85 | }; |
| 86 | } | 86 | } |
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs index 5033ae477..cce0407c1 100644 --- a/embassy-stm32/src/dma/dma.rs +++ b/embassy-stm32/src/dma/dma.rs | |||
| @@ -154,10 +154,10 @@ impl State { | |||
| 154 | static STATE: State = State::new(); | 154 | static STATE: State = State::new(); |
| 155 | 155 | ||
| 156 | /// safety: must be called only once | 156 | /// safety: must be called only once |
| 157 | pub(crate) unsafe fn init(irq_priority: Priority) { | 157 | pub(crate) unsafe fn init(cs: critical_section::CriticalSection, irq_priority: Priority) { |
| 158 | foreach_interrupt! { | 158 | foreach_interrupt! { |
| 159 | ($peri:ident, dma, $block:ident, $signal_name:ident, $irq:ident) => { | 159 | ($peri:ident, dma, $block:ident, $signal_name:ident, $irq:ident) => { |
| 160 | interrupt::typelevel::$irq::set_priority(irq_priority); | 160 | interrupt::typelevel::$irq::set_priority_with_cs(cs, irq_priority); |
| 161 | interrupt::typelevel::$irq::enable(); | 161 | interrupt::typelevel::$irq::enable(); |
| 162 | }; | 162 | }; |
| 163 | } | 163 | } |
diff --git a/embassy-stm32/src/dma/dmamux.rs b/embassy-stm32/src/dma/dmamux.rs index 36fc03403..20601dc86 100644 --- a/embassy-stm32/src/dma/dmamux.rs +++ b/embassy-stm32/src/dma/dmamux.rs | |||
| @@ -47,6 +47,6 @@ foreach_dma_channel! { | |||
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | /// safety: must be called only once | 49 | /// safety: must be called only once |
| 50 | pub(crate) unsafe fn init() { | 50 | pub(crate) unsafe fn init(_cs: critical_section::CriticalSection) { |
| 51 | crate::_generated::init_dmamux(); | 51 | crate::_generated::init_dmamux(); |
| 52 | } | 52 | } |
diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs index 97cc200d7..b811da1fb 100644 --- a/embassy-stm32/src/dma/gpdma.rs +++ b/embassy-stm32/src/dma/gpdma.rs | |||
| @@ -53,10 +53,10 @@ impl State { | |||
| 53 | static STATE: State = State::new(); | 53 | static STATE: State = State::new(); |
| 54 | 54 | ||
| 55 | /// safety: must be called only once | 55 | /// safety: must be called only once |
| 56 | pub(crate) unsafe fn init(irq_priority: Priority) { | 56 | pub(crate) unsafe fn init(cs: critical_section::CriticalSection, irq_priority: Priority) { |
| 57 | foreach_interrupt! { | 57 | foreach_interrupt! { |
| 58 | ($peri:ident, gpdma, $block:ident, $signal_name:ident, $irq:ident) => { | 58 | ($peri:ident, gpdma, $block:ident, $signal_name:ident, $irq:ident) => { |
| 59 | crate::interrupt::typelevel::$irq::set_priority(irq_priority); | 59 | crate::interrupt::typelevel::$irq::set_priority_with_cs(cs, irq_priority); |
| 60 | crate::interrupt::typelevel::$irq::enable(); | 60 | crate::interrupt::typelevel::$irq::enable(); |
| 61 | }; | 61 | }; |
| 62 | } | 62 | } |
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index 4f1a58ae2..29fced8fc 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs | |||
| @@ -56,16 +56,17 @@ pub(crate) fn slice_ptr_parts_mut<T>(slice: *mut [T]) -> (usize, usize) { | |||
| 56 | 56 | ||
| 57 | // safety: must be called only once at startup | 57 | // safety: must be called only once at startup |
| 58 | pub(crate) unsafe fn init( | 58 | pub(crate) unsafe fn init( |
| 59 | cs: critical_section::CriticalSection, | ||
| 59 | #[cfg(bdma)] bdma_priority: Priority, | 60 | #[cfg(bdma)] bdma_priority: Priority, |
| 60 | #[cfg(dma)] dma_priority: Priority, | 61 | #[cfg(dma)] dma_priority: Priority, |
| 61 | #[cfg(gpdma)] gpdma_priority: Priority, | 62 | #[cfg(gpdma)] gpdma_priority: Priority, |
| 62 | ) { | 63 | ) { |
| 63 | #[cfg(bdma)] | 64 | #[cfg(bdma)] |
| 64 | bdma::init(bdma_priority); | 65 | bdma::init(cs, bdma_priority); |
| 65 | #[cfg(dma)] | 66 | #[cfg(dma)] |
| 66 | dma::init(dma_priority); | 67 | dma::init(cs, dma_priority); |
| 67 | #[cfg(gpdma)] | 68 | #[cfg(gpdma)] |
| 68 | gpdma::init(gpdma_priority); | 69 | gpdma::init(cs, gpdma_priority); |
| 69 | #[cfg(dmamux)] | 70 | #[cfg(dmamux)] |
| 70 | dmamux::init(); | 71 | dmamux::init(cs); |
| 71 | } | 72 | } |
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index 62f321709..538791a51 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs | |||
| @@ -367,7 +367,7 @@ macro_rules! enable_irq { | |||
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | /// safety: must be called only once | 369 | /// safety: must be called only once |
| 370 | pub(crate) unsafe fn init() { | 370 | pub(crate) unsafe fn init(_cs: critical_section::CriticalSection) { |
| 371 | use crate::interrupt::typelevel::Interrupt; | 371 | use crate::interrupt::typelevel::Interrupt; |
| 372 | 372 | ||
| 373 | foreach_exti_irq!(enable_irq); | 373 | foreach_exti_irq!(enable_irq); |
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index 37fedf8e1..e1702b008 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #![macro_use] | 1 | #![macro_use] |
| 2 | use core::convert::Infallible; | 2 | use core::convert::Infallible; |
| 3 | 3 | ||
| 4 | use critical_section::CriticalSection; | ||
| 4 | use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; | 5 | use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; |
| 5 | 6 | ||
| 6 | use crate::pac::gpio::{self, vals}; | 7 | use crate::pac::gpio::{self, vals}; |
| @@ -757,9 +758,9 @@ foreach_pin!( | |||
| 757 | }; | 758 | }; |
| 758 | ); | 759 | ); |
| 759 | 760 | ||
| 760 | pub(crate) unsafe fn init() { | 761 | pub(crate) unsafe fn init(_cs: CriticalSection) { |
| 761 | #[cfg(afio)] | 762 | #[cfg(afio)] |
| 762 | <crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable_and_reset(); | 763 | <crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(_cs); |
| 763 | 764 | ||
| 764 | crate::_generated::init_gpio(); | 765 | crate::_generated::init_gpio(); |
| 765 | } | 766 | } |
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index b93e5ee87..372246f87 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs | |||
| @@ -155,81 +155,82 @@ impl Default for Config { | |||
| 155 | 155 | ||
| 156 | /// Initialize embassy. | 156 | /// Initialize embassy. |
| 157 | pub fn init(config: Config) -> Peripherals { | 157 | pub fn init(config: Config) -> Peripherals { |
| 158 | let p = Peripherals::take(); | 158 | critical_section::with(|cs| { |
| 159 | 159 | let p = Peripherals::take_with_cs(cs); | |
| 160 | #[cfg(dbgmcu)] | 160 | |
| 161 | if config.enable_debug_during_sleep { | 161 | #[cfg(dbgmcu)] |
| 162 | crate::pac::DBGMCU.cr().modify(|cr| { | 162 | if config.enable_debug_during_sleep { |
| 163 | #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5, dbgmcu_wba))] | 163 | crate::pac::DBGMCU.cr().modify(|cr| { |
| 164 | { | 164 | #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5, dbgmcu_wba))] |
| 165 | cr.set_dbg_stop(true); | 165 | { |
| 166 | cr.set_dbg_standby(true); | 166 | cr.set_dbg_stop(true); |
| 167 | } | 167 | cr.set_dbg_standby(true); |
| 168 | #[cfg(any( | 168 | } |
| 169 | dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1, | 169 | #[cfg(any( |
| 170 | dbgmcu_l4, dbgmcu_wb, dbgmcu_wl | 170 | dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1, |
| 171 | ))] | 171 | dbgmcu_l4, dbgmcu_wb, dbgmcu_wl |
| 172 | { | 172 | ))] |
| 173 | cr.set_dbg_sleep(true); | 173 | { |
| 174 | cr.set_dbg_stop(true); | 174 | cr.set_dbg_sleep(true); |
| 175 | cr.set_dbg_standby(true); | 175 | cr.set_dbg_stop(true); |
| 176 | } | 176 | cr.set_dbg_standby(true); |
| 177 | #[cfg(dbgmcu_h7)] | 177 | } |
| 178 | { | 178 | #[cfg(dbgmcu_h7)] |
| 179 | cr.set_d1dbgcken(true); | 179 | { |
| 180 | cr.set_d3dbgcken(true); | 180 | cr.set_d1dbgcken(true); |
| 181 | cr.set_dbgsleep_d1(true); | 181 | cr.set_d3dbgcken(true); |
| 182 | cr.set_dbgstby_d1(true); | 182 | cr.set_dbgsleep_d1(true); |
| 183 | cr.set_dbgstop_d1(true); | 183 | cr.set_dbgstby_d1(true); |
| 184 | } | 184 | cr.set_dbgstop_d1(true); |
| 185 | }); | 185 | } |
| 186 | } | 186 | }); |
| 187 | 187 | } | |
| 188 | #[cfg(not(any(stm32f1, stm32wb, stm32wl)))] | ||
| 189 | peripherals::SYSCFG::enable_and_reset(); | ||
| 190 | #[cfg(not(any(stm32h5, stm32h7, stm32wb, stm32wl)))] | ||
| 191 | peripherals::PWR::enable_and_reset(); | ||
| 192 | #[cfg(not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7)))] | ||
| 193 | peripherals::FLASH::enable_and_reset(); | ||
| 194 | |||
| 195 | unsafe { | ||
| 196 | #[cfg(feature = "_split-pins-enabled")] | ||
| 197 | crate::pac::SYSCFG.pmcr().modify(|pmcr| { | ||
| 198 | #[cfg(feature = "split-pa0")] | ||
| 199 | pmcr.set_pa0so(true); | ||
| 200 | #[cfg(feature = "split-pa1")] | ||
| 201 | pmcr.set_pa1so(true); | ||
| 202 | #[cfg(feature = "split-pc2")] | ||
| 203 | pmcr.set_pc2so(true); | ||
| 204 | #[cfg(feature = "split-pc3")] | ||
| 205 | pmcr.set_pc3so(true); | ||
| 206 | }); | ||
| 207 | |||
| 208 | gpio::init(); | ||
| 209 | dma::init( | ||
| 210 | #[cfg(bdma)] | ||
| 211 | config.bdma_interrupt_priority, | ||
| 212 | #[cfg(dma)] | ||
| 213 | config.dma_interrupt_priority, | ||
| 214 | #[cfg(gpdma)] | ||
| 215 | config.gpdma_interrupt_priority, | ||
| 216 | ); | ||
| 217 | #[cfg(feature = "exti")] | ||
| 218 | exti::init(); | ||
| 219 | |||
| 220 | rcc::init(config.rcc); | ||
| 221 | 188 | ||
| 222 | // must be after rcc init | 189 | #[cfg(not(any(stm32f1, stm32wb, stm32wl)))] |
| 223 | #[cfg(feature = "_time-driver")] | 190 | peripherals::SYSCFG::enable_and_reset_with_cs(cs); |
| 224 | time_driver::init(); | 191 | #[cfg(not(any(stm32h5, stm32h7, stm32wb, stm32wl)))] |
| 192 | peripherals::PWR::enable_and_reset_with_cs(cs); | ||
| 193 | #[cfg(not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7)))] | ||
| 194 | peripherals::FLASH::enable_and_reset_with_cs(cs); | ||
| 195 | |||
| 196 | unsafe { | ||
| 197 | #[cfg(feature = "_split-pins-enabled")] | ||
| 198 | crate::pac::SYSCFG.pmcr().modify(|pmcr| { | ||
| 199 | #[cfg(feature = "split-pa0")] | ||
| 200 | pmcr.set_pa0so(true); | ||
| 201 | #[cfg(feature = "split-pa1")] | ||
| 202 | pmcr.set_pa1so(true); | ||
| 203 | #[cfg(feature = "split-pc2")] | ||
| 204 | pmcr.set_pc2so(true); | ||
| 205 | #[cfg(feature = "split-pc3")] | ||
| 206 | pmcr.set_pc3so(true); | ||
| 207 | }); | ||
| 225 | 208 | ||
| 226 | #[cfg(feature = "low-power")] | 209 | gpio::init(cs); |
| 227 | while !crate::rcc::low_power_ready() { | 210 | dma::init( |
| 228 | critical_section::with(|cs| { | 211 | cs, |
| 212 | #[cfg(bdma)] | ||
| 213 | config.bdma_interrupt_priority, | ||
| 214 | #[cfg(dma)] | ||
| 215 | config.dma_interrupt_priority, | ||
| 216 | #[cfg(gpdma)] | ||
| 217 | config.gpdma_interrupt_priority, | ||
| 218 | ); | ||
| 219 | #[cfg(feature = "exti")] | ||
| 220 | exti::init(cs); | ||
| 221 | |||
| 222 | rcc::init(config.rcc); | ||
| 223 | |||
| 224 | // must be after rcc init | ||
| 225 | #[cfg(feature = "_time-driver")] | ||
| 226 | time_driver::init(cs); | ||
| 227 | |||
| 228 | #[cfg(feature = "low-power")] | ||
| 229 | while !crate::rcc::low_power_ready() { | ||
| 229 | crate::rcc::clock_refcount_sub(cs); | 230 | crate::rcc::clock_refcount_sub(cs); |
| 230 | }); | 231 | } |
| 231 | } | 232 | } |
| 232 | } | ||
| 233 | 233 | ||
| 234 | p | 234 | p |
| 235 | }) | ||
| 235 | } | 236 | } |
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 0263c97aa..edbae30de 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs | |||
| @@ -229,10 +229,19 @@ pub mod low_level { | |||
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | pub(crate) mod sealed { | 231 | pub(crate) mod sealed { |
| 232 | use critical_section::CriticalSection; | ||
| 233 | |||
| 232 | pub trait RccPeripheral { | 234 | pub trait RccPeripheral { |
| 233 | fn frequency() -> crate::time::Hertz; | 235 | fn frequency() -> crate::time::Hertz; |
| 234 | fn enable_and_reset(); | 236 | fn enable_and_reset_with_cs(cs: CriticalSection); |
| 235 | fn disable(); | 237 | fn disable_with_cs(cs: CriticalSection); |
| 238 | |||
| 239 | fn enable_and_reset() { | ||
| 240 | critical_section::with(|cs| Self::enable_and_reset_with_cs(cs)) | ||
| 241 | } | ||
| 242 | fn disable() { | ||
| 243 | critical_section::with(|cs| Self::disable_with_cs(cs)) | ||
| 244 | } | ||
| 236 | } | 245 | } |
| 237 | } | 246 | } |
| 238 | 247 | ||
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index baea20aef..add8be831 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs | |||
| @@ -152,45 +152,43 @@ embassy_time::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver { | |||
| 152 | }); | 152 | }); |
| 153 | 153 | ||
| 154 | impl RtcDriver { | 154 | impl RtcDriver { |
| 155 | fn init(&'static self) { | 155 | fn init(&'static self, cs: critical_section::CriticalSection) { |
| 156 | let r = T::regs_gp16(); | 156 | let r = T::regs_gp16(); |
| 157 | 157 | ||
| 158 | <T as RccPeripheral>::enable_and_reset(); | 158 | <T as RccPeripheral>::enable_and_reset_with_cs(cs); |
| 159 | 159 | ||
| 160 | let timer_freq = T::frequency(); | 160 | let timer_freq = T::frequency(); |
| 161 | 161 | ||
| 162 | critical_section::with(|_| { | 162 | r.cr1().modify(|w| w.set_cen(false)); |
| 163 | r.cr1().modify(|w| w.set_cen(false)); | 163 | r.cnt().write(|w| w.set_cnt(0)); |
| 164 | r.cnt().write(|w| w.set_cnt(0)); | ||
| 165 | 164 | ||
| 166 | let psc = timer_freq.0 / TICK_HZ as u32 - 1; | 165 | let psc = timer_freq.0 / TICK_HZ as u32 - 1; |
| 167 | let psc: u16 = match psc.try_into() { | 166 | let psc: u16 = match psc.try_into() { |
| 168 | Err(_) => panic!("psc division overflow: {}", psc), | 167 | Err(_) => panic!("psc division overflow: {}", psc), |
| 169 | Ok(n) => n, | 168 | Ok(n) => n, |
| 170 | }; | 169 | }; |
| 171 | 170 | ||
| 172 | r.psc().write(|w| w.set_psc(psc)); | 171 | r.psc().write(|w| w.set_psc(psc)); |
| 173 | r.arr().write(|w| w.set_arr(u16::MAX)); | 172 | r.arr().write(|w| w.set_arr(u16::MAX)); |
| 174 | 173 | ||
| 175 | // Set URS, generate update and clear URS | 174 | // Set URS, generate update and clear URS |
| 176 | r.cr1().modify(|w| w.set_urs(vals::Urs::COUNTERONLY)); | 175 | r.cr1().modify(|w| w.set_urs(vals::Urs::COUNTERONLY)); |
| 177 | r.egr().write(|w| w.set_ug(true)); | 176 | r.egr().write(|w| w.set_ug(true)); |
| 178 | r.cr1().modify(|w| w.set_urs(vals::Urs::ANYEVENT)); | 177 | r.cr1().modify(|w| w.set_urs(vals::Urs::ANYEVENT)); |
| 179 | 178 | ||
| 180 | // Mid-way point | 179 | // Mid-way point |
| 181 | r.ccr(0).write(|w| w.set_ccr(0x8000)); | 180 | r.ccr(0).write(|w| w.set_ccr(0x8000)); |
| 182 | 181 | ||
| 183 | // Enable overflow and half-overflow interrupts | 182 | // Enable overflow and half-overflow interrupts |
| 184 | r.dier().write(|w| { | 183 | r.dier().write(|w| { |
| 185 | w.set_uie(true); | 184 | w.set_uie(true); |
| 186 | w.set_ccie(0, true); | 185 | w.set_ccie(0, true); |
| 187 | }); | 186 | }); |
| 188 | 187 | ||
| 189 | <T as BasicInstance>::Interrupt::unpend(); | 188 | <T as BasicInstance>::Interrupt::unpend(); |
| 190 | unsafe { <T as BasicInstance>::Interrupt::enable() }; | 189 | unsafe { <T as BasicInstance>::Interrupt::enable() }; |
| 191 | 190 | ||
| 192 | r.cr1().modify(|w| w.set_cen(true)); | 191 | r.cr1().modify(|w| w.set_cen(true)); |
| 193 | }) | ||
| 194 | } | 192 | } |
| 195 | 193 | ||
| 196 | fn on_interrupt(&self) { | 194 | fn on_interrupt(&self) { |
| @@ -462,6 +460,6 @@ pub(crate) fn get_driver() -> &'static RtcDriver { | |||
| 462 | &DRIVER | 460 | &DRIVER |
| 463 | } | 461 | } |
| 464 | 462 | ||
| 465 | pub(crate) fn init() { | 463 | pub(crate) fn init(cs: CriticalSection) { |
| 466 | DRIVER.init() | 464 | DRIVER.init(cs) |
| 467 | } | 465 | } |
