diff options
| -rw-r--r-- | embassy-extras/src/macros.rs | 2 | ||||
| -rw-r--r-- | embassy-nrf/Cargo.toml | 1 | ||||
| -rw-r--r-- | embassy-nrf/src/interrupt.rs | 30 | ||||
| -rw-r--r-- | embassy-nrf/src/rtc.rs | 17 | ||||
| -rw-r--r-- | embassy-rp/Cargo.toml | 1 | ||||
| -rw-r--r-- | embassy-rp/src/interrupt.rs | 30 | ||||
| -rw-r--r-- | embassy-stm32/Cargo.toml | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/exti.rs | 6 | ||||
| -rw-r--r-- | embassy-stm32/src/f4/rtc.rs | 15 | ||||
| -rw-r--r-- | embassy-stm32/src/interrupt.rs | 30 | ||||
| -rw-r--r-- | embassy-stm32/src/l0/rtc.rs | 15 | ||||
| -rw-r--r-- | embassy/Cargo.toml | 1 | ||||
| -rw-r--r-- | embassy/src/util/critical_section.rs | 30 | ||||
| -rw-r--r-- | embassy/src/util/mod.rs | 2 | ||||
| -rw-r--r-- | embassy/src/util/mutex.rs | 4 | ||||
| -rw-r--r-- | embassy/src/util/signal.rs | 9 | ||||
| -rw-r--r-- | embassy/src/util/waker_agnostic.rs | 4 |
17 files changed, 41 insertions, 157 deletions
diff --git a/embassy-extras/src/macros.rs b/embassy-extras/src/macros.rs index d85439358..860c0795a 100644 --- a/embassy-extras/src/macros.rs +++ b/embassy-extras/src/macros.rs | |||
| @@ -51,7 +51,7 @@ macro_rules! peripherals { | |||
| 51 | #[no_mangle] | 51 | #[no_mangle] |
| 52 | static mut _EMBASSY_DEVICE_PERIPHERALS: bool = false; | 52 | static mut _EMBASSY_DEVICE_PERIPHERALS: bool = false; |
| 53 | 53 | ||
| 54 | cortex_m::interrupt::free(|_| { | 54 | critical_section::with(|_| { |
| 55 | if unsafe { _EMBASSY_DEVICE_PERIPHERALS } { | 55 | if unsafe { _EMBASSY_DEVICE_PERIPHERALS } { |
| 56 | None | 56 | None |
| 57 | } else { | 57 | } else { |
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 8ec5b0878..b8b63bbb1 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml | |||
| @@ -36,3 +36,4 @@ nrf52811-pac = { version = "0.9.1", optional = true, features = [ "rt" ]} | |||
| 36 | nrf52832-pac = { version = "0.9.0", optional = true, features = [ "rt" ]} | 36 | nrf52832-pac = { version = "0.9.0", optional = true, features = [ "rt" ]} |
| 37 | nrf52833-pac = { version = "0.9.0", optional = true, features = [ "rt" ]} | 37 | nrf52833-pac = { version = "0.9.0", optional = true, features = [ "rt" ]} |
| 38 | nrf52840-pac = { version = "0.9.0", optional = true, features = [ "rt" ]} | 38 | nrf52840-pac = { version = "0.9.0", optional = true, features = [ "rt" ]} |
| 39 | critical-section = "0.2.0" | ||
diff --git a/embassy-nrf/src/interrupt.rs b/embassy-nrf/src/interrupt.rs index 741dbaee2..8d069e329 100644 --- a/embassy-nrf/src/interrupt.rs +++ b/embassy-nrf/src/interrupt.rs | |||
| @@ -8,7 +8,6 @@ use core::sync::atomic::{compiler_fence, Ordering}; | |||
| 8 | use crate::pac::NVIC_PRIO_BITS; | 8 | use crate::pac::NVIC_PRIO_BITS; |
| 9 | 9 | ||
| 10 | // Re-exports | 10 | // Re-exports |
| 11 | pub use cortex_m::interrupt::{CriticalSection, Mutex}; | ||
| 12 | pub use embassy::interrupt::{declare, take, Interrupt}; | 11 | pub use embassy::interrupt::{declare, take, Interrupt}; |
| 13 | 12 | ||
| 14 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] | 13 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] |
| @@ -47,35 +46,6 @@ impl From<Priority> for u8 { | |||
| 47 | } | 46 | } |
| 48 | } | 47 | } |
| 49 | 48 | ||
| 50 | #[inline] | ||
| 51 | pub fn free<F, R>(f: F) -> R | ||
| 52 | where | ||
| 53 | F: FnOnce(&CriticalSection) -> R, | ||
| 54 | { | ||
| 55 | unsafe { | ||
| 56 | // TODO: assert that we're in privileged level | ||
| 57 | // Needed because disabling irqs in non-privileged level is a noop, which would break safety. | ||
| 58 | |||
| 59 | let primask: u32; | ||
| 60 | asm!("mrs {}, PRIMASK", out(reg) primask); | ||
| 61 | |||
| 62 | asm!("cpsid i"); | ||
| 63 | |||
| 64 | // Prevent compiler from reordering operations inside/outside the critical section. | ||
| 65 | compiler_fence(Ordering::SeqCst); | ||
| 66 | |||
| 67 | let r = f(&CriticalSection::new()); | ||
| 68 | |||
| 69 | compiler_fence(Ordering::SeqCst); | ||
| 70 | |||
| 71 | if primask & 1 == 0 { | ||
| 72 | asm!("cpsie i"); | ||
| 73 | } | ||
| 74 | |||
| 75 | r | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | #[cfg(feature = "52810")] | 49 | #[cfg(feature = "52810")] |
| 80 | mod irqs { | 50 | mod irqs { |
| 81 | use super::*; | 51 | use super::*; |
diff --git a/embassy-nrf/src/rtc.rs b/embassy-nrf/src/rtc.rs index cbb5a87ef..dc0e3ceb6 100644 --- a/embassy-nrf/src/rtc.rs +++ b/embassy-nrf/src/rtc.rs | |||
| @@ -1,10 +1,11 @@ | |||
| 1 | use core::cell::Cell; | 1 | use core::cell::Cell; |
| 2 | use core::sync::atomic::{compiler_fence, AtomicU32, Ordering}; | 2 | use core::sync::atomic::{compiler_fence, AtomicU32, Ordering}; |
| 3 | 3 | use critical_section::CriticalSection; | |
| 4 | use embassy::interrupt::InterruptExt; | 4 | use embassy::interrupt::InterruptExt; |
| 5 | use embassy::time::Clock; | 5 | use embassy::time::Clock; |
| 6 | use embassy::util::CriticalSectionMutex as Mutex; | ||
| 6 | 7 | ||
| 7 | use crate::interrupt::{CriticalSection, Interrupt, Mutex}; | 8 | use crate::interrupt::Interrupt; |
| 8 | use crate::pac; | 9 | use crate::pac; |
| 9 | use crate::{interrupt, peripherals}; | 10 | use crate::{interrupt, peripherals}; |
| 10 | 11 | ||
| @@ -134,7 +135,7 @@ impl<T: Instance> RTC<T> { | |||
| 134 | for n in 0..ALARM_COUNT { | 135 | for n in 0..ALARM_COUNT { |
| 135 | if r.events_compare[n].read().bits() == 1 { | 136 | if r.events_compare[n].read().bits() == 1 { |
| 136 | r.events_compare[n].write(|w| w); | 137 | r.events_compare[n].write(|w| w); |
| 137 | interrupt::free(|cs| { | 138 | critical_section::with(|cs| { |
| 138 | self.trigger_alarm(n, cs); | 139 | self.trigger_alarm(n, cs); |
| 139 | }) | 140 | }) |
| 140 | } | 141 | } |
| @@ -142,7 +143,7 @@ impl<T: Instance> RTC<T> { | |||
| 142 | } | 143 | } |
| 143 | 144 | ||
| 144 | fn next_period(&self) { | 145 | fn next_period(&self) { |
| 145 | interrupt::free(|cs| { | 146 | critical_section::with(|cs| { |
| 146 | let r = self.rtc.regs(); | 147 | let r = self.rtc.regs(); |
| 147 | let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; | 148 | let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; |
| 148 | let t = (period as u64) << 23; | 149 | let t = (period as u64) << 23; |
| @@ -160,7 +161,7 @@ impl<T: Instance> RTC<T> { | |||
| 160 | }) | 161 | }) |
| 161 | } | 162 | } |
| 162 | 163 | ||
| 163 | fn trigger_alarm(&self, n: usize, cs: &CriticalSection) { | 164 | fn trigger_alarm(&self, n: usize, cs: CriticalSection) { |
| 164 | let r = self.rtc.regs(); | 165 | let r = self.rtc.regs(); |
| 165 | r.intenclr.write(|w| unsafe { w.bits(compare_n(n)) }); | 166 | r.intenclr.write(|w| unsafe { w.bits(compare_n(n)) }); |
| 166 | 167 | ||
| @@ -174,14 +175,14 @@ impl<T: Instance> RTC<T> { | |||
| 174 | } | 175 | } |
| 175 | 176 | ||
| 176 | fn set_alarm_callback(&self, n: usize, callback: fn(*mut ()), ctx: *mut ()) { | 177 | fn set_alarm_callback(&self, n: usize, callback: fn(*mut ()), ctx: *mut ()) { |
| 177 | interrupt::free(|cs| { | 178 | critical_section::with(|cs| { |
| 178 | let alarm = &self.alarms.borrow(cs)[n]; | 179 | let alarm = &self.alarms.borrow(cs)[n]; |
| 179 | alarm.callback.set(Some((callback, ctx))); | 180 | alarm.callback.set(Some((callback, ctx))); |
| 180 | }) | 181 | }) |
| 181 | } | 182 | } |
| 182 | 183 | ||
| 183 | fn set_alarm(&self, n: usize, timestamp: u64) { | 184 | fn set_alarm(&self, n: usize, timestamp: u64) { |
| 184 | interrupt::free(|cs| { | 185 | critical_section::with(|cs| { |
| 185 | let alarm = &self.alarms.borrow(cs)[n]; | 186 | let alarm = &self.alarms.borrow(cs)[n]; |
| 186 | alarm.timestamp.set(timestamp); | 187 | alarm.timestamp.set(timestamp); |
| 187 | 188 | ||
| @@ -289,5 +290,5 @@ pub trait Instance: sealed::Instance + 'static { | |||
| 289 | 290 | ||
| 290 | impl_instance!(RTC0, RTC0); | 291 | impl_instance!(RTC0, RTC0); |
| 291 | impl_instance!(RTC1, RTC1); | 292 | impl_instance!(RTC1, RTC1); |
| 292 | #[cfg(any(feature = "52832", feature = "52833", feature = "52840"))] | 293 | #[cfg(any(feature = "nrf52832", feature = "nrf52833", feature = "nrf52840"))] |
| 293 | impl_instance!(RTC2, RTC2); | 294 | impl_instance!(RTC2, RTC2); |
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index 1d11fb0d7..59331dd1d 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml | |||
| @@ -20,6 +20,7 @@ defmt = { version = "0.2.0", optional = true } | |||
| 20 | log = { version = "0.4.11", optional = true } | 20 | log = { version = "0.4.11", optional = true } |
| 21 | cortex-m-rt = "0.6.13" | 21 | cortex-m-rt = "0.6.13" |
| 22 | cortex-m = "0.7.1" | 22 | cortex-m = "0.7.1" |
| 23 | critical-section = "0.2.0" | ||
| 23 | 24 | ||
| 24 | rp2040-pac2 = { git = "https://github.com/Dirbaio/rp2040-pac", rev="254f4677937801155ca3cb17c7bb9d38eb62683e", features = ["rt"] } | 25 | rp2040-pac2 = { git = "https://github.com/Dirbaio/rp2040-pac", rev="254f4677937801155ca3cb17c7bb9d38eb62683e", features = ["rt"] } |
| 25 | embedded-hal = { version = "0.2.4", features = [ "unproven" ] } | 26 | embedded-hal = { version = "0.2.4", features = [ "unproven" ] } |
diff --git a/embassy-rp/src/interrupt.rs b/embassy-rp/src/interrupt.rs index a913ea60c..cb9f36546 100644 --- a/embassy-rp/src/interrupt.rs +++ b/embassy-rp/src/interrupt.rs | |||
| @@ -8,7 +8,6 @@ use core::sync::atomic::{compiler_fence, Ordering}; | |||
| 8 | use crate::pac::NVIC_PRIO_BITS; | 8 | use crate::pac::NVIC_PRIO_BITS; |
| 9 | 9 | ||
| 10 | // Re-exports | 10 | // Re-exports |
| 11 | pub use cortex_m::interrupt::{CriticalSection, Mutex}; | ||
| 12 | pub use embassy::interrupt::{declare, take, Interrupt}; | 11 | pub use embassy::interrupt::{declare, take, Interrupt}; |
| 13 | 12 | ||
| 14 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] | 13 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] |
| @@ -47,35 +46,6 @@ impl From<Priority> for u8 { | |||
| 47 | } | 46 | } |
| 48 | } | 47 | } |
| 49 | 48 | ||
| 50 | #[inline] | ||
| 51 | pub fn free<F, R>(f: F) -> R | ||
| 52 | where | ||
| 53 | F: FnOnce(&CriticalSection) -> R, | ||
| 54 | { | ||
| 55 | unsafe { | ||
| 56 | // TODO: assert that we're in privileged level | ||
| 57 | // Needed because disabling irqs in non-privileged level is a noop, which would break safety. | ||
| 58 | |||
| 59 | let primask: u32; | ||
| 60 | asm!("mrs {}, PRIMASK", out(reg) primask); | ||
| 61 | |||
| 62 | asm!("cpsid i"); | ||
| 63 | |||
| 64 | // Prevent compiler from reordering operations inside/outside the critical section. | ||
| 65 | compiler_fence(Ordering::SeqCst); | ||
| 66 | |||
| 67 | let r = f(&CriticalSection::new()); | ||
| 68 | |||
| 69 | compiler_fence(Ordering::SeqCst); | ||
| 70 | |||
| 71 | if primask & 1 == 0 { | ||
| 72 | asm!("cpsie i"); | ||
| 73 | } | ||
| 74 | |||
| 75 | r | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | mod irqs { | 49 | mod irqs { |
| 80 | use super::*; | 50 | use super::*; |
| 81 | 51 | ||
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index af30f1aae..36bc0f25e 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -39,6 +39,7 @@ embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["s | |||
| 39 | embassy-extras = {version = "0.1.0", path = "../embassy-extras" } | 39 | embassy-extras = {version = "0.1.0", path = "../embassy-extras" } |
| 40 | 40 | ||
| 41 | atomic-polyfill = "0.1.1" | 41 | atomic-polyfill = "0.1.1" |
| 42 | critical-section = "0.2.0" | ||
| 42 | defmt = { version = "0.2.0", optional = true } | 43 | defmt = { version = "0.2.0", optional = true } |
| 43 | log = { version = "0.4.11", optional = true } | 44 | log = { version = "0.4.11", optional = true } |
| 44 | cortex-m-rt = "0.6.13" | 45 | cortex-m-rt = "0.6.13" |
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index 9a12f8115..3d83c2d53 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs | |||
| @@ -44,7 +44,7 @@ pub struct ExtiPin<T: Instance> { | |||
| 44 | 44 | ||
| 45 | impl<T: Instance> ExtiPin<T> { | 45 | impl<T: Instance> ExtiPin<T> { |
| 46 | pub fn new(mut pin: T, interrupt: T::Interrupt, syscfg: &mut SysCfg) -> Self { | 46 | pub fn new(mut pin: T, interrupt: T::Interrupt, syscfg: &mut SysCfg) -> Self { |
| 47 | cortex_m::interrupt::free(|_| { | 47 | critical_section::with(|_| { |
| 48 | pin.make_source(syscfg); | 48 | pin.make_source(syscfg); |
| 49 | }); | 49 | }); |
| 50 | 50 | ||
| @@ -99,7 +99,7 @@ impl<T: Instance + digital::InputPin + 'static> ExtiPin<T> { | |||
| 99 | async move { | 99 | async move { |
| 100 | let fut = InterruptFuture::new(&mut self.interrupt); | 100 | let fut = InterruptFuture::new(&mut self.interrupt); |
| 101 | let pin = &mut self.pin; | 101 | let pin = &mut self.pin; |
| 102 | cortex_m::interrupt::free(|_| { | 102 | critical_section::with(|_| { |
| 103 | pin.trigger_edge(if state { | 103 | pin.trigger_edge(if state { |
| 104 | EdgeOption::Rising | 104 | EdgeOption::Rising |
| 105 | } else { | 105 | } else { |
| @@ -126,7 +126,7 @@ impl<T: Instance + 'static> ExtiPin<T> { | |||
| 126 | async move { | 126 | async move { |
| 127 | let fut = InterruptFuture::new(&mut self.interrupt); | 127 | let fut = InterruptFuture::new(&mut self.interrupt); |
| 128 | let pin = &mut self.pin; | 128 | let pin = &mut self.pin; |
| 129 | cortex_m::interrupt::free(|_| { | 129 | critical_section::with(|_| { |
| 130 | pin.trigger_edge(state); | 130 | pin.trigger_edge(state); |
| 131 | }); | 131 | }); |
| 132 | 132 | ||
diff --git a/embassy-stm32/src/f4/rtc.rs b/embassy-stm32/src/f4/rtc.rs index b1abba325..df7a82d87 100644 --- a/embassy-stm32/src/f4/rtc.rs +++ b/embassy-stm32/src/f4/rtc.rs | |||
| @@ -3,12 +3,13 @@ use crate::hal::rcc::Clocks; | |||
| 3 | use core::cell::Cell; | 3 | use core::cell::Cell; |
| 4 | use core::convert::TryInto; | 4 | use core::convert::TryInto; |
| 5 | use core::sync::atomic::{compiler_fence, AtomicU32, Ordering}; | 5 | use core::sync::atomic::{compiler_fence, AtomicU32, Ordering}; |
| 6 | 6 | use critical_section::CriticalSection; | |
| 7 | use embassy::interrupt::InterruptExt; | 7 | use embassy::interrupt::InterruptExt; |
| 8 | use embassy::time::{Clock, TICKS_PER_SECOND}; | 8 | use embassy::time::{Clock, TICKS_PER_SECOND}; |
| 9 | use embassy::util::CriticalSectionMutex as Mutex; | ||
| 9 | 10 | ||
| 10 | use crate::interrupt; | 11 | use crate::interrupt; |
| 11 | use crate::interrupt::{CriticalSection, Interrupt, Mutex}; | 12 | use crate::interrupt::Interrupt; |
| 12 | 13 | ||
| 13 | // RTC timekeeping works with something we call "periods", which are time intervals | 14 | // RTC timekeeping works with something we call "periods", which are time intervals |
| 14 | // of 2^15 ticks. The RTC counter value is 16 bits, so one "overflow cycle" is 2 periods. | 15 | // of 2^15 ticks. The RTC counter value is 16 bits, so one "overflow cycle" is 2 periods. |
| @@ -119,13 +120,13 @@ impl<T: Instance> RTC<T> { | |||
| 119 | for n in 1..=ALARM_COUNT { | 120 | for n in 1..=ALARM_COUNT { |
| 120 | if self.rtc.compare_interrupt_status(n) { | 121 | if self.rtc.compare_interrupt_status(n) { |
| 121 | self.rtc.compare_clear_flag(n); | 122 | self.rtc.compare_clear_flag(n); |
| 122 | interrupt::free(|cs| self.trigger_alarm(n, cs)); | 123 | critical_section::with(|cs| self.trigger_alarm(n, cs)); |
| 123 | } | 124 | } |
| 124 | } | 125 | } |
| 125 | } | 126 | } |
| 126 | 127 | ||
| 127 | fn next_period(&self) { | 128 | fn next_period(&self) { |
| 128 | interrupt::free(|cs| { | 129 | critical_section::with(|cs| { |
| 129 | let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; | 130 | let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; |
| 130 | let t = (period as u64) << 15; | 131 | let t = (period as u64) << 15; |
| 131 | 132 | ||
| @@ -142,7 +143,7 @@ impl<T: Instance> RTC<T> { | |||
| 142 | }) | 143 | }) |
| 143 | } | 144 | } |
| 144 | 145 | ||
| 145 | fn trigger_alarm(&self, n: usize, cs: &CriticalSection) { | 146 | fn trigger_alarm(&self, n: usize, cs: CriticalSection) { |
| 146 | self.rtc.set_compare_interrupt(n, false); | 147 | self.rtc.set_compare_interrupt(n, false); |
| 147 | 148 | ||
| 148 | let alarm = &self.alarms.borrow(cs)[n - 1]; | 149 | let alarm = &self.alarms.borrow(cs)[n - 1]; |
| @@ -155,14 +156,14 @@ impl<T: Instance> RTC<T> { | |||
| 155 | } | 156 | } |
| 156 | 157 | ||
| 157 | fn set_alarm_callback(&self, n: usize, callback: fn(*mut ()), ctx: *mut ()) { | 158 | fn set_alarm_callback(&self, n: usize, callback: fn(*mut ()), ctx: *mut ()) { |
| 158 | interrupt::free(|cs| { | 159 | critical_section::with(|cs| { |
| 159 | let alarm = &self.alarms.borrow(cs)[n - 1]; | 160 | let alarm = &self.alarms.borrow(cs)[n - 1]; |
| 160 | alarm.callback.set(Some((callback, ctx))); | 161 | alarm.callback.set(Some((callback, ctx))); |
| 161 | }) | 162 | }) |
| 162 | } | 163 | } |
| 163 | 164 | ||
| 164 | fn set_alarm(&self, n: usize, timestamp: u64) { | 165 | fn set_alarm(&self, n: usize, timestamp: u64) { |
| 165 | interrupt::free(|cs| { | 166 | critical_section::with(|cs| { |
| 166 | let alarm = &self.alarms.borrow(cs)[n - 1]; | 167 | let alarm = &self.alarms.borrow(cs)[n - 1]; |
| 167 | alarm.timestamp.set(timestamp); | 168 | alarm.timestamp.set(timestamp); |
| 168 | 169 | ||
diff --git a/embassy-stm32/src/interrupt.rs b/embassy-stm32/src/interrupt.rs index 63b80a6c9..1d48dc584 100644 --- a/embassy-stm32/src/interrupt.rs +++ b/embassy-stm32/src/interrupt.rs | |||
| @@ -8,7 +8,6 @@ use core::sync::atomic::{compiler_fence, Ordering}; | |||
| 8 | use crate::pac::NVIC_PRIO_BITS; | 8 | use crate::pac::NVIC_PRIO_BITS; |
| 9 | 9 | ||
| 10 | // Re-exports | 10 | // Re-exports |
| 11 | pub use cortex_m::interrupt::{CriticalSection, Mutex}; | ||
| 12 | pub use embassy::interrupt::{declare, take, Interrupt}; | 11 | pub use embassy::interrupt::{declare, take, Interrupt}; |
| 13 | 12 | ||
| 14 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] | 13 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] |
| @@ -63,35 +62,6 @@ impl From<Priority> for u8 { | |||
| 63 | } | 62 | } |
| 64 | } | 63 | } |
| 65 | 64 | ||
| 66 | #[inline] | ||
| 67 | pub fn free<F, R>(f: F) -> R | ||
| 68 | where | ||
| 69 | F: FnOnce(&CriticalSection) -> R, | ||
| 70 | { | ||
| 71 | unsafe { | ||
| 72 | // TODO: assert that we're in privileged level | ||
| 73 | // Needed because disabling irqs in non-privileged level is a noop, which would break safety. | ||
| 74 | |||
| 75 | let primask: u32; | ||
| 76 | asm!("mrs {}, PRIMASK", out(reg) primask); | ||
| 77 | |||
| 78 | asm!("cpsid i"); | ||
| 79 | |||
| 80 | // Prevent compiler from reordering operations inside/outside the critical section. | ||
| 81 | compiler_fence(Ordering::SeqCst); | ||
| 82 | |||
| 83 | let r = f(&CriticalSection::new()); | ||
| 84 | |||
| 85 | compiler_fence(Ordering::SeqCst); | ||
| 86 | |||
| 87 | if primask & 1 == 0 { | ||
| 88 | asm!("cpsie i"); | ||
| 89 | } | ||
| 90 | |||
| 91 | r | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | #[cfg(feature = "stm32f401")] | 65 | #[cfg(feature = "stm32f401")] |
| 96 | mod irqs { | 66 | mod irqs { |
| 97 | use super::*; | 67 | use super::*; |
diff --git a/embassy-stm32/src/l0/rtc.rs b/embassy-stm32/src/l0/rtc.rs index 9a1342044..fa5011d3a 100644 --- a/embassy-stm32/src/l0/rtc.rs +++ b/embassy-stm32/src/l0/rtc.rs | |||
| @@ -2,12 +2,13 @@ use crate::hal::rcc::Clocks; | |||
| 2 | use atomic_polyfill::{compiler_fence, AtomicU32, Ordering}; | 2 | use atomic_polyfill::{compiler_fence, AtomicU32, Ordering}; |
| 3 | use core::cell::Cell; | 3 | use core::cell::Cell; |
| 4 | use core::convert::TryInto; | 4 | use core::convert::TryInto; |
| 5 | 5 | use critical_section::CriticalSection; | |
| 6 | use embassy::interrupt::InterruptExt; | 6 | use embassy::interrupt::InterruptExt; |
| 7 | use embassy::time::{Clock, TICKS_PER_SECOND}; | 7 | use embassy::time::{Clock, TICKS_PER_SECOND}; |
| 8 | use embassy::util::CriticalSectionMutex as Mutex; | ||
| 8 | 9 | ||
| 9 | use crate::interrupt; | 10 | use crate::interrupt; |
| 10 | use crate::interrupt::{CriticalSection, Interrupt, Mutex}; | 11 | use crate::interrupt::Interrupt; |
| 11 | 12 | ||
| 12 | // RTC timekeeping works with something we call "periods", which are time intervals | 13 | // RTC timekeeping works with something we call "periods", which are time intervals |
| 13 | // of 2^15 ticks. The RTC counter value is 16 bits, so one "overflow cycle" is 2 periods. | 14 | // of 2^15 ticks. The RTC counter value is 16 bits, so one "overflow cycle" is 2 periods. |
| @@ -117,13 +118,13 @@ impl<T: Instance> RTC<T> { | |||
| 117 | for n in 1..=ALARM_COUNT { | 118 | for n in 1..=ALARM_COUNT { |
| 118 | if self.rtc.compare_interrupt_status(n) { | 119 | if self.rtc.compare_interrupt_status(n) { |
| 119 | self.rtc.compare_clear_flag(n); | 120 | self.rtc.compare_clear_flag(n); |
| 120 | interrupt::free(|cs| self.trigger_alarm(n, cs)); | 121 | critical_section::with(|cs| self.trigger_alarm(n, cs)); |
| 121 | } | 122 | } |
| 122 | } | 123 | } |
| 123 | } | 124 | } |
| 124 | 125 | ||
| 125 | fn next_period(&self) { | 126 | fn next_period(&self) { |
| 126 | interrupt::free(|cs| { | 127 | critical_section::with(|cs| { |
| 127 | let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; | 128 | let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; |
| 128 | let t = (period as u64) << 15; | 129 | let t = (period as u64) << 15; |
| 129 | 130 | ||
| @@ -140,7 +141,7 @@ impl<T: Instance> RTC<T> { | |||
| 140 | }) | 141 | }) |
| 141 | } | 142 | } |
| 142 | 143 | ||
| 143 | fn trigger_alarm(&self, n: usize, cs: &CriticalSection) { | 144 | fn trigger_alarm(&self, n: usize, cs: CriticalSection) { |
| 144 | self.rtc.set_compare_interrupt(n, false); | 145 | self.rtc.set_compare_interrupt(n, false); |
| 145 | 146 | ||
| 146 | let alarm = &self.alarms.borrow(cs)[n - 1]; | 147 | let alarm = &self.alarms.borrow(cs)[n - 1]; |
| @@ -153,14 +154,14 @@ impl<T: Instance> RTC<T> { | |||
| 153 | } | 154 | } |
| 154 | 155 | ||
| 155 | fn set_alarm_callback(&self, n: usize, callback: fn(*mut ()), ctx: *mut ()) { | 156 | fn set_alarm_callback(&self, n: usize, callback: fn(*mut ()), ctx: *mut ()) { |
| 156 | interrupt::free(|cs| { | 157 | critical_section::with(|cs| { |
| 157 | let alarm = &self.alarms.borrow(cs)[n - 1]; | 158 | let alarm = &self.alarms.borrow(cs)[n - 1]; |
| 158 | alarm.callback.set(Some((callback, ctx))); | 159 | alarm.callback.set(Some((callback, ctx))); |
| 159 | }) | 160 | }) |
| 160 | } | 161 | } |
| 161 | 162 | ||
| 162 | fn set_alarm(&self, n: usize, timestamp: u64) { | 163 | fn set_alarm(&self, n: usize, timestamp: u64) { |
| 163 | interrupt::free(|cs| { | 164 | critical_section::with(|cs| { |
| 164 | let alarm = &self.alarms.borrow(cs)[n - 1]; | 165 | let alarm = &self.alarms.borrow(cs)[n - 1]; |
| 165 | alarm.timestamp.set(timestamp); | 166 | alarm.timestamp.set(timestamp); |
| 166 | 167 | ||
diff --git a/embassy/Cargo.toml b/embassy/Cargo.toml index 2f3ee453c..2395eeae7 100644 --- a/embassy/Cargo.toml +++ b/embassy/Cargo.toml | |||
| @@ -25,6 +25,7 @@ pin-project = { version = "1.0.2", default-features = false } | |||
| 25 | embassy-macros = { version = "0.1.0", path = "../embassy-macros"} | 25 | embassy-macros = { version = "0.1.0", path = "../embassy-macros"} |
| 26 | embassy-traits = { version = "0.1.0", path = "../embassy-traits"} | 26 | embassy-traits = { version = "0.1.0", path = "../embassy-traits"} |
| 27 | atomic-polyfill = { version = "0.1.1" } | 27 | atomic-polyfill = { version = "0.1.1" } |
| 28 | critical-section = "0.2.0" | ||
| 28 | 29 | ||
| 29 | # Workaround https://github.com/japaric/cast.rs/pull/27 | 30 | # Workaround https://github.com/japaric/cast.rs/pull/27 |
| 30 | cast = { version = "=0.2.3", default-features = false } | 31 | cast = { version = "=0.2.3", default-features = false } |
diff --git a/embassy/src/util/critical_section.rs b/embassy/src/util/critical_section.rs deleted file mode 100644 index 12ad6f20e..000000000 --- a/embassy/src/util/critical_section.rs +++ /dev/null | |||
| @@ -1,30 +0,0 @@ | |||
| 1 | pub use cs::{critical_section, CriticalSection}; | ||
| 2 | |||
| 3 | #[cfg(feature = "std")] | ||
| 4 | mod cs { | ||
| 5 | static INIT: std::sync::Once = std::sync::Once::new(); | ||
| 6 | static mut BKL: Option<std::sync::Mutex<()>> = None; | ||
| 7 | |||
| 8 | pub type CriticalSection = std::sync::MutexGuard<'static, ()>; | ||
| 9 | pub fn critical_section<F, R>(f: F) -> R | ||
| 10 | where | ||
| 11 | F: FnOnce(&CriticalSection) -> R, | ||
| 12 | { | ||
| 13 | INIT.call_once(|| unsafe { | ||
| 14 | BKL.replace(std::sync::Mutex::new(())); | ||
| 15 | }); | ||
| 16 | let guard = unsafe { BKL.as_ref().unwrap().lock().unwrap() }; | ||
| 17 | f(&guard) | ||
| 18 | } | ||
| 19 | } | ||
| 20 | |||
| 21 | #[cfg(not(feature = "std"))] | ||
| 22 | mod cs { | ||
| 23 | pub use cortex_m::interrupt::CriticalSection; | ||
| 24 | pub fn critical_section<F, R>(f: F) -> R | ||
| 25 | where | ||
| 26 | F: FnOnce(&CriticalSection) -> R, | ||
| 27 | { | ||
| 28 | cortex_m::interrupt::free(f) | ||
| 29 | } | ||
| 30 | } | ||
diff --git a/embassy/src/util/mod.rs b/embassy/src/util/mod.rs index cace0d190..6aa3a7330 100644 --- a/embassy/src/util/mod.rs +++ b/embassy/src/util/mod.rs | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | //! Async utilities | 1 | //! Async utilities |
| 2 | mod critical_section; | ||
| 3 | mod drop_bomb; | 2 | mod drop_bomb; |
| 4 | mod forever; | 3 | mod forever; |
| 5 | mod mutex; | 4 | mod mutex; |
| @@ -10,7 +9,6 @@ mod signal; | |||
| 10 | #[cfg_attr(feature = "executor-agnostic", path = "waker_agnostic.rs")] | 9 | #[cfg_attr(feature = "executor-agnostic", path = "waker_agnostic.rs")] |
| 11 | mod waker; | 10 | mod waker; |
| 12 | 11 | ||
| 13 | pub use critical_section::*; | ||
| 14 | pub use drop_bomb::*; | 12 | pub use drop_bomb::*; |
| 15 | pub use forever::*; | 13 | pub use forever::*; |
| 16 | pub use mutex::*; | 14 | pub use mutex::*; |
diff --git a/embassy/src/util/mutex.rs b/embassy/src/util/mutex.rs index ed2fd7852..86ab070a3 100644 --- a/embassy/src/util/mutex.rs +++ b/embassy/src/util/mutex.rs | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | use core::cell::UnsafeCell; | 1 | use core::cell::UnsafeCell; |
| 2 | use cortex_m::interrupt::CriticalSection; | 2 | use critical_section::CriticalSection; |
| 3 | 3 | ||
| 4 | use crate::fmt::assert; | 4 | use crate::fmt::assert; |
| 5 | 5 | ||
| @@ -30,7 +30,7 @@ impl<T> CriticalSectionMutex<T> { | |||
| 30 | 30 | ||
| 31 | impl<T> CriticalSectionMutex<T> { | 31 | impl<T> CriticalSectionMutex<T> { |
| 32 | /// Borrows the data for the duration of the critical section | 32 | /// Borrows the data for the duration of the critical section |
| 33 | pub fn borrow<'cs>(&'cs self, _cs: &'cs CriticalSection) -> &'cs T { | 33 | pub fn borrow<'cs>(&'cs self, _cs: CriticalSection<'cs>) -> &'cs T { |
| 34 | unsafe { &*self.inner.get() } | 34 | unsafe { &*self.inner.get() } |
| 35 | } | 35 | } |
| 36 | } | 36 | } |
diff --git a/embassy/src/util/signal.rs b/embassy/src/util/signal.rs index a62abcd55..2eefe658b 100644 --- a/embassy/src/util/signal.rs +++ b/embassy/src/util/signal.rs | |||
| @@ -11,7 +11,6 @@ use ptr::NonNull; | |||
| 11 | use crate::executor; | 11 | use crate::executor; |
| 12 | use crate::fmt::panic; | 12 | use crate::fmt::panic; |
| 13 | use crate::interrupt::{Interrupt, InterruptExt}; | 13 | use crate::interrupt::{Interrupt, InterruptExt}; |
| 14 | use crate::util::critical_section::critical_section; | ||
| 15 | 14 | ||
| 16 | /// Synchronization primitive. Allows creating awaitable signals that may be passed between tasks. | 15 | /// Synchronization primitive. Allows creating awaitable signals that may be passed between tasks. |
| 17 | /// | 16 | /// |
| @@ -38,7 +37,7 @@ impl<T: Send> Signal<T> { | |||
| 38 | 37 | ||
| 39 | /// Mark this Signal as completed. | 38 | /// Mark this Signal as completed. |
| 40 | pub fn signal(&self, val: T) { | 39 | pub fn signal(&self, val: T) { |
| 41 | critical_section(|_| unsafe { | 40 | critical_section::with(|_| unsafe { |
| 42 | let state = &mut *self.state.get(); | 41 | let state = &mut *self.state.get(); |
| 43 | if let State::Waiting(waker) = mem::replace(state, State::Signaled(val)) { | 42 | if let State::Waiting(waker) = mem::replace(state, State::Signaled(val)) { |
| 44 | waker.wake(); | 43 | waker.wake(); |
| @@ -47,14 +46,14 @@ impl<T: Send> Signal<T> { | |||
| 47 | } | 46 | } |
| 48 | 47 | ||
| 49 | pub fn reset(&self) { | 48 | pub fn reset(&self) { |
| 50 | critical_section(|_| unsafe { | 49 | critical_section::with(|_| unsafe { |
| 51 | let state = &mut *self.state.get(); | 50 | let state = &mut *self.state.get(); |
| 52 | *state = State::None | 51 | *state = State::None |
| 53 | }) | 52 | }) |
| 54 | } | 53 | } |
| 55 | 54 | ||
| 56 | pub fn poll_wait(&self, cx: &mut Context<'_>) -> Poll<T> { | 55 | pub fn poll_wait(&self, cx: &mut Context<'_>) -> Poll<T> { |
| 57 | critical_section(|_| unsafe { | 56 | critical_section::with(|_| unsafe { |
| 58 | let state = &mut *self.state.get(); | 57 | let state = &mut *self.state.get(); |
| 59 | match state { | 58 | match state { |
| 60 | State::None => { | 59 | State::None => { |
| @@ -78,7 +77,7 @@ impl<T: Send> Signal<T> { | |||
| 78 | 77 | ||
| 79 | /// non-blocking method to check whether this signal has been signaled. | 78 | /// non-blocking method to check whether this signal has been signaled. |
| 80 | pub fn signaled(&self) -> bool { | 79 | pub fn signaled(&self) -> bool { |
| 81 | critical_section(|_| matches!(unsafe { &*self.state.get() }, State::Signaled(_))) | 80 | critical_section::with(|_| matches!(unsafe { &*self.state.get() }, State::Signaled(_))) |
| 82 | } | 81 | } |
| 83 | } | 82 | } |
| 84 | 83 | ||
diff --git a/embassy/src/util/waker_agnostic.rs b/embassy/src/util/waker_agnostic.rs index 3f6ad373a..53f1ec135 100644 --- a/embassy/src/util/waker_agnostic.rs +++ b/embassy/src/util/waker_agnostic.rs | |||
| @@ -62,7 +62,7 @@ impl AtomicWaker { | |||
| 62 | 62 | ||
| 63 | /// Register a waker. Overwrites the previous waker, if any. | 63 | /// Register a waker. Overwrites the previous waker, if any. |
| 64 | pub fn register(&mut self, w: &Waker) { | 64 | pub fn register(&mut self, w: &Waker) { |
| 65 | cortex_m::interrupt::free(|cs| { | 65 | critical_section::with(|cs| { |
| 66 | let cell = self.waker.borrow(cs); | 66 | let cell = self.waker.borrow(cs); |
| 67 | cell.set(match cell.replace(None) { | 67 | cell.set(match cell.replace(None) { |
| 68 | Some(w2) if (w2.will_wake(w)) => Some(w2), | 68 | Some(w2) if (w2.will_wake(w)) => Some(w2), |
| @@ -73,7 +73,7 @@ impl AtomicWaker { | |||
| 73 | 73 | ||
| 74 | /// Wake the registered waker, if any. | 74 | /// Wake the registered waker, if any. |
| 75 | pub fn wake(&mut self) { | 75 | pub fn wake(&mut self) { |
| 76 | cortex_m::interrupt::free(|cs| { | 76 | critical_section::with(|cs| { |
| 77 | let cell = self.waker.borrow(cs); | 77 | let cell = self.waker.borrow(cs); |
| 78 | if let Some(w) = cell.replace(None) { | 78 | if let Some(w) = cell.replace(None) { |
| 79 | w.wake_by_ref(); | 79 | w.wake_by_ref(); |
