diff options
| -rw-r--r-- | embassy/Cargo.toml | 2 | ||||
| -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/signal.rs | 9 |
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"} | |||
| 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 | 28 | ||
| 29 | # Workaround https://github.com/japaric/cast.rs/pull/27 | ||
| 30 | cast = { 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 @@ | |||
| 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 9f82422dd..25b570cc6 100644 --- a/embassy/src/util/mod.rs +++ b/embassy/src/util/mod.rs | |||
| @@ -5,6 +5,7 @@ mod mutex; | |||
| 5 | mod on_drop; | 5 | mod on_drop; |
| 6 | mod portal; | 6 | mod portal; |
| 7 | mod signal; | 7 | mod signal; |
| 8 | mod critical_section; | ||
| 8 | 9 | ||
| 9 | #[cfg_attr(feature = "executor-agnostic", path = "waker_agnostic.rs")] | 10 | #[cfg_attr(feature = "executor-agnostic", path = "waker_agnostic.rs")] |
| 10 | mod waker; | 11 | mod waker; |
| @@ -16,6 +17,7 @@ pub use on_drop::*; | |||
| 16 | pub use portal::*; | 17 | pub use portal::*; |
| 17 | pub use signal::*; | 18 | pub use signal::*; |
| 18 | pub use waker::*; | 19 | pub use waker::*; |
| 20 | pub use critical_section::*; | ||
| 19 | 21 | ||
| 20 | pub trait PeripheralBorrow { | 22 | pub 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; | |||
| 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; | ||
| 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 | ||
