aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-10-12 00:34:47 +0200
committerDario Nieuwenhuis <[email protected]>2023-10-12 16:20:34 +0200
commit97ca0e77bf6e6f36aae18cb57fbfa8e583597327 (patch)
tree20f7a2f1e27e0d30e530047e819b6efeaf2bd9cc /embassy-stm32
parent66e399b5c61653f1f66cd3fd1592936e4085d6b5 (diff)
stm32: avoid creating many tiny critical sections in init.
Saves 292 bytes on stm32f0 bilnky with max optimizations (from 3132 to 2840).
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/build.rs28
-rw-r--r--embassy-stm32/src/dac/mod.rs16
-rw-r--r--embassy-stm32/src/dma/bdma.rs4
-rw-r--r--embassy-stm32/src/dma/dma.rs4
-rw-r--r--embassy-stm32/src/dma/dmamux.rs2
-rw-r--r--embassy-stm32/src/dma/gpdma.rs4
-rw-r--r--embassy-stm32/src/dma/mod.rs9
-rw-r--r--embassy-stm32/src/exti.rs2
-rw-r--r--embassy-stm32/src/gpio.rs5
-rw-r--r--embassy-stm32/src/lib.rs145
-rw-r--r--embassy-stm32/src/rcc/mod.rs13
-rw-r--r--embassy-stm32/src/time_driver.rs56
12 files changed, 145 insertions, 143 deletions
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 {
77static STATE: State = State::new(); 77static STATE: State = State::new();
78 78
79/// safety: must be called only once 79/// safety: must be called only once
80pub(crate) unsafe fn init(irq_priority: Priority) { 80pub(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 {
154static STATE: State = State::new(); 154static STATE: State = State::new();
155 155
156/// safety: must be called only once 156/// safety: must be called only once
157pub(crate) unsafe fn init(irq_priority: Priority) { 157pub(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
50pub(crate) unsafe fn init() { 50pub(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 {
53static STATE: State = State::new(); 53static STATE: State = State::new();
54 54
55/// safety: must be called only once 55/// safety: must be called only once
56pub(crate) unsafe fn init(irq_priority: Priority) { 56pub(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
58pub(crate) unsafe fn init( 58pub(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
370pub(crate) unsafe fn init() { 370pub(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]
2use core::convert::Infallible; 2use core::convert::Infallible;
3 3
4use critical_section::CriticalSection;
4use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; 5use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef};
5 6
6use crate::pac::gpio::{self, vals}; 7use crate::pac::gpio::{self, vals};
@@ -757,9 +758,9 @@ foreach_pin!(
757 }; 758 };
758); 759);
759 760
760pub(crate) unsafe fn init() { 761pub(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.
157pub fn init(config: Config) -> Peripherals { 157pub 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
231pub(crate) mod sealed { 231pub(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
154impl RtcDriver { 154impl 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
465pub(crate) fn init() { 463pub(crate) fn init(cs: CriticalSection) {
466 DRIVER.init() 464 DRIVER.init(cs)
467} 465}