aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy/Cargo.toml2
-rw-r--r--embassy/src/util/critical_section.rs30
-rw-r--r--embassy/src/util/mod.rs2
-rw-r--r--embassy/src/util/signal.rs9
4 files changed, 39 insertions, 4 deletions
diff --git a/embassy/Cargo.toml b/embassy/Cargo.toml
index 39ad64a0d..2f3ee453c 100644
--- a/embassy/Cargo.toml
+++ b/embassy/Cargo.toml
@@ -26,3 +26,5 @@ embassy-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" }
28 28
29# Workaround https://github.com/japaric/cast.rs/pull/27
30cast = { version = "=0.2.3", default-features = false }
diff --git a/embassy/src/util/critical_section.rs b/embassy/src/util/critical_section.rs
new file mode 100644
index 000000000..12ad6f20e
--- /dev/null
+++ b/embassy/src/util/critical_section.rs
@@ -0,0 +1,30 @@
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 9f82422dd..25b570cc6 100644
--- a/embassy/src/util/mod.rs
+++ b/embassy/src/util/mod.rs
@@ -5,6 +5,7 @@ mod mutex;
5mod on_drop; 5mod on_drop;
6mod portal; 6mod portal;
7mod signal; 7mod signal;
8mod critical_section;
8 9
9#[cfg_attr(feature = "executor-agnostic", path = "waker_agnostic.rs")] 10#[cfg_attr(feature = "executor-agnostic", path = "waker_agnostic.rs")]
10mod waker; 11mod waker;
@@ -16,6 +17,7 @@ pub use on_drop::*;
16pub use portal::*; 17pub use portal::*;
17pub use signal::*; 18pub use signal::*;
18pub use waker::*; 19pub use waker::*;
20pub use critical_section::*;
19 21
20pub trait PeripheralBorrow { 22pub trait PeripheralBorrow {
21 type Target; 23 type Target;
diff --git a/embassy/src/util/signal.rs b/embassy/src/util/signal.rs
index 2fc86906f..a62abcd55 100644
--- a/embassy/src/util/signal.rs
+++ b/embassy/src/util/signal.rs
@@ -11,6 +11,7 @@ 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;
14 15
15/// Synchronization primitive. Allows creating awaitable signals that may be passed between tasks. 16/// Synchronization primitive. Allows creating awaitable signals that may be passed between tasks.
16/// 17///
@@ -37,7 +38,7 @@ impl<T: Send> Signal<T> {
37 38
38 /// Mark this Signal as completed. 39 /// Mark this Signal as completed.
39 pub fn signal(&self, val: T) { 40 pub fn signal(&self, val: T) {
40 cortex_m::interrupt::free(|_| unsafe { 41 critical_section(|_| unsafe {
41 let state = &mut *self.state.get(); 42 let state = &mut *self.state.get();
42 if let State::Waiting(waker) = mem::replace(state, State::Signaled(val)) { 43 if let State::Waiting(waker) = mem::replace(state, State::Signaled(val)) {
43 waker.wake(); 44 waker.wake();
@@ -46,14 +47,14 @@ impl<T: Send> Signal<T> {
46 } 47 }
47 48
48 pub fn reset(&self) { 49 pub fn reset(&self) {
49 cortex_m::interrupt::free(|_| unsafe { 50 critical_section(|_| unsafe {
50 let state = &mut *self.state.get(); 51 let state = &mut *self.state.get();
51 *state = State::None 52 *state = State::None
52 }) 53 })
53 } 54 }
54 55
55 pub fn poll_wait(&self, cx: &mut Context<'_>) -> Poll<T> { 56 pub fn poll_wait(&self, cx: &mut Context<'_>) -> Poll<T> {
56 cortex_m::interrupt::free(|_| unsafe { 57 critical_section(|_| unsafe {
57 let state = &mut *self.state.get(); 58 let state = &mut *self.state.get();
58 match state { 59 match state {
59 State::None => { 60 State::None => {
@@ -77,7 +78,7 @@ impl<T: Send> Signal<T> {
77 78
78 /// non-blocking method to check whether this signal has been signaled. 79 /// non-blocking method to check whether this signal has been signaled.
79 pub fn signaled(&self) -> bool { 80 pub fn signaled(&self) -> bool {
80 cortex_m::interrupt::free(|_| matches!(unsafe { &*self.state.get() }, State::Signaled(_))) 81 critical_section(|_| matches!(unsafe { &*self.state.get() }, State::Signaled(_)))
81 } 82 }
82} 83}
83 84