aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-extras/src/macros.rs2
-rw-r--r--embassy-nrf/Cargo.toml1
-rw-r--r--embassy-nrf/src/interrupt.rs30
-rw-r--r--embassy-nrf/src/rtc.rs17
-rw-r--r--embassy-rp/Cargo.toml1
-rw-r--r--embassy-rp/src/interrupt.rs30
-rw-r--r--embassy-stm32/Cargo.toml1
-rw-r--r--embassy-stm32/src/exti.rs6
-rw-r--r--embassy-stm32/src/f4/rtc.rs15
-rw-r--r--embassy-stm32/src/interrupt.rs30
-rw-r--r--embassy-stm32/src/l0/rtc.rs15
-rw-r--r--embassy/Cargo.toml1
-rw-r--r--embassy/src/util/critical_section.rs30
-rw-r--r--embassy/src/util/mod.rs2
-rw-r--r--embassy/src/util/mutex.rs4
-rw-r--r--embassy/src/util/signal.rs9
-rw-r--r--embassy/src/util/waker_agnostic.rs4
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" ]}
36nrf52832-pac = { version = "0.9.0", optional = true, features = [ "rt" ]} 36nrf52832-pac = { version = "0.9.0", optional = true, features = [ "rt" ]}
37nrf52833-pac = { version = "0.9.0", optional = true, features = [ "rt" ]} 37nrf52833-pac = { version = "0.9.0", optional = true, features = [ "rt" ]}
38nrf52840-pac = { version = "0.9.0", optional = true, features = [ "rt" ]} 38nrf52840-pac = { version = "0.9.0", optional = true, features = [ "rt" ]}
39critical-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};
8use crate::pac::NVIC_PRIO_BITS; 8use crate::pac::NVIC_PRIO_BITS;
9 9
10// Re-exports 10// Re-exports
11pub use cortex_m::interrupt::{CriticalSection, Mutex};
12pub use embassy::interrupt::{declare, take, Interrupt}; 11pub 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]
51pub fn free<F, R>(f: F) -> R
52where
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")]
80mod irqs { 50mod 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 @@
1use core::cell::Cell; 1use core::cell::Cell;
2use core::sync::atomic::{compiler_fence, AtomicU32, Ordering}; 2use core::sync::atomic::{compiler_fence, AtomicU32, Ordering};
3 3use critical_section::CriticalSection;
4use embassy::interrupt::InterruptExt; 4use embassy::interrupt::InterruptExt;
5use embassy::time::Clock; 5use embassy::time::Clock;
6use embassy::util::CriticalSectionMutex as Mutex;
6 7
7use crate::interrupt::{CriticalSection, Interrupt, Mutex}; 8use crate::interrupt::Interrupt;
8use crate::pac; 9use crate::pac;
9use crate::{interrupt, peripherals}; 10use 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
290impl_instance!(RTC0, RTC0); 291impl_instance!(RTC0, RTC0);
291impl_instance!(RTC1, RTC1); 292impl_instance!(RTC1, RTC1);
292#[cfg(any(feature = "52832", feature = "52833", feature = "52840"))] 293#[cfg(any(feature = "nrf52832", feature = "nrf52833", feature = "nrf52840"))]
293impl_instance!(RTC2, RTC2); 294impl_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 }
20log = { version = "0.4.11", optional = true } 20log = { version = "0.4.11", optional = true }
21cortex-m-rt = "0.6.13" 21cortex-m-rt = "0.6.13"
22cortex-m = "0.7.1" 22cortex-m = "0.7.1"
23critical-section = "0.2.0"
23 24
24rp2040-pac2 = { git = "https://github.com/Dirbaio/rp2040-pac", rev="254f4677937801155ca3cb17c7bb9d38eb62683e", features = ["rt"] } 25rp2040-pac2 = { git = "https://github.com/Dirbaio/rp2040-pac", rev="254f4677937801155ca3cb17c7bb9d38eb62683e", features = ["rt"] }
25embedded-hal = { version = "0.2.4", features = [ "unproven" ] } 26embedded-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};
8use crate::pac::NVIC_PRIO_BITS; 8use crate::pac::NVIC_PRIO_BITS;
9 9
10// Re-exports 10// Re-exports
11pub use cortex_m::interrupt::{CriticalSection, Mutex};
12pub use embassy::interrupt::{declare, take, Interrupt}; 11pub 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]
51pub fn free<F, R>(f: F) -> R
52where
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
79mod irqs { 49mod 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
39embassy-extras = {version = "0.1.0", path = "../embassy-extras" } 39embassy-extras = {version = "0.1.0", path = "../embassy-extras" }
40 40
41atomic-polyfill = "0.1.1" 41atomic-polyfill = "0.1.1"
42critical-section = "0.2.0"
42defmt = { version = "0.2.0", optional = true } 43defmt = { version = "0.2.0", optional = true }
43log = { version = "0.4.11", optional = true } 44log = { version = "0.4.11", optional = true }
44cortex-m-rt = "0.6.13" 45cortex-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
45impl<T: Instance> ExtiPin<T> { 45impl<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;
3use core::cell::Cell; 3use core::cell::Cell;
4use core::convert::TryInto; 4use core::convert::TryInto;
5use core::sync::atomic::{compiler_fence, AtomicU32, Ordering}; 5use core::sync::atomic::{compiler_fence, AtomicU32, Ordering};
6 6use critical_section::CriticalSection;
7use embassy::interrupt::InterruptExt; 7use embassy::interrupt::InterruptExt;
8use embassy::time::{Clock, TICKS_PER_SECOND}; 8use embassy::time::{Clock, TICKS_PER_SECOND};
9use embassy::util::CriticalSectionMutex as Mutex;
9 10
10use crate::interrupt; 11use crate::interrupt;
11use crate::interrupt::{CriticalSection, Interrupt, Mutex}; 12use 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};
8use crate::pac::NVIC_PRIO_BITS; 8use crate::pac::NVIC_PRIO_BITS;
9 9
10// Re-exports 10// Re-exports
11pub use cortex_m::interrupt::{CriticalSection, Mutex};
12pub use embassy::interrupt::{declare, take, Interrupt}; 11pub 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]
67pub fn free<F, R>(f: F) -> R
68where
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")]
96mod irqs { 66mod 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;
2use atomic_polyfill::{compiler_fence, AtomicU32, Ordering}; 2use atomic_polyfill::{compiler_fence, AtomicU32, Ordering};
3use core::cell::Cell; 3use core::cell::Cell;
4use core::convert::TryInto; 4use core::convert::TryInto;
5 5use critical_section::CriticalSection;
6use embassy::interrupt::InterruptExt; 6use embassy::interrupt::InterruptExt;
7use embassy::time::{Clock, TICKS_PER_SECOND}; 7use embassy::time::{Clock, TICKS_PER_SECOND};
8use embassy::util::CriticalSectionMutex as Mutex;
8 9
9use crate::interrupt; 10use crate::interrupt;
10use crate::interrupt::{CriticalSection, Interrupt, Mutex}; 11use 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 }
25embassy-macros = { version = "0.1.0", path = "../embassy-macros"} 25embassy-macros = { version = "0.1.0", path = "../embassy-macros"}
26embassy-traits = { version = "0.1.0", path = "../embassy-traits"} 26embassy-traits = { version = "0.1.0", path = "../embassy-traits"}
27atomic-polyfill = { version = "0.1.1" } 27atomic-polyfill = { version = "0.1.1" }
28critical-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
30cast = { version = "=0.2.3", default-features = false } 31cast = { 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 @@
1pub use cs::{critical_section, CriticalSection};
2
3#[cfg(feature = "std")]
4mod 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"))]
22mod 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
2mod critical_section;
3mod drop_bomb; 2mod drop_bomb;
4mod forever; 3mod forever;
5mod mutex; 4mod 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")]
11mod waker; 10mod waker;
12 11
13pub use critical_section::*;
14pub use drop_bomb::*; 12pub use drop_bomb::*;
15pub use forever::*; 13pub use forever::*;
16pub use mutex::*; 14pub 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 @@
1use core::cell::UnsafeCell; 1use core::cell::UnsafeCell;
2use cortex_m::interrupt::CriticalSection; 2use critical_section::CriticalSection;
3 3
4use crate::fmt::assert; 4use crate::fmt::assert;
5 5
@@ -30,7 +30,7 @@ impl<T> CriticalSectionMutex<T> {
30 30
31impl<T> CriticalSectionMutex<T> { 31impl<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;
11use crate::executor; 11use crate::executor;
12use crate::fmt::panic; 12use crate::fmt::panic;
13use crate::interrupt::{Interrupt, InterruptExt}; 13use crate::interrupt::{Interrupt, InterruptExt};
14use 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();