Use critical_section
crate
This commit is contained in:
parent
f817f374b6
commit
7fa0e57172
@ -51,7 +51,7 @@ macro_rules! peripherals {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
static mut _EMBASSY_DEVICE_PERIPHERALS: bool = false;
|
static mut _EMBASSY_DEVICE_PERIPHERALS: bool = false;
|
||||||
|
|
||||||
cortex_m::interrupt::free(|_| {
|
critical_section::with(|_| {
|
||||||
if unsafe { _EMBASSY_DEVICE_PERIPHERALS } {
|
if unsafe { _EMBASSY_DEVICE_PERIPHERALS } {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
@ -36,3 +36,4 @@ nrf52811-pac = { version = "0.9.1", optional = true, features = [ "rt" ]}
|
|||||||
nrf52832-pac = { version = "0.9.0", optional = true, features = [ "rt" ]}
|
nrf52832-pac = { version = "0.9.0", optional = true, features = [ "rt" ]}
|
||||||
nrf52833-pac = { version = "0.9.0", optional = true, features = [ "rt" ]}
|
nrf52833-pac = { version = "0.9.0", optional = true, features = [ "rt" ]}
|
||||||
nrf52840-pac = { version = "0.9.0", optional = true, features = [ "rt" ]}
|
nrf52840-pac = { version = "0.9.0", optional = true, features = [ "rt" ]}
|
||||||
|
critical-section = "0.2.0"
|
||||||
|
@ -8,7 +8,6 @@ use core::sync::atomic::{compiler_fence, Ordering};
|
|||||||
use crate::pac::NVIC_PRIO_BITS;
|
use crate::pac::NVIC_PRIO_BITS;
|
||||||
|
|
||||||
// Re-exports
|
// Re-exports
|
||||||
pub use cortex_m::interrupt::{CriticalSection, Mutex};
|
|
||||||
pub use embassy::interrupt::{declare, take, Interrupt};
|
pub use embassy::interrupt::{declare, take, Interrupt};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
@ -47,35 +46,6 @@ impl From<Priority> for u8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn free<F, R>(f: F) -> R
|
|
||||||
where
|
|
||||||
F: FnOnce(&CriticalSection) -> R,
|
|
||||||
{
|
|
||||||
unsafe {
|
|
||||||
// TODO: assert that we're in privileged level
|
|
||||||
// Needed because disabling irqs in non-privileged level is a noop, which would break safety.
|
|
||||||
|
|
||||||
let primask: u32;
|
|
||||||
asm!("mrs {}, PRIMASK", out(reg) primask);
|
|
||||||
|
|
||||||
asm!("cpsid i");
|
|
||||||
|
|
||||||
// Prevent compiler from reordering operations inside/outside the critical section.
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
|
|
||||||
let r = f(&CriticalSection::new());
|
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
|
|
||||||
if primask & 1 == 0 {
|
|
||||||
asm!("cpsie i");
|
|
||||||
}
|
|
||||||
|
|
||||||
r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "52810")]
|
#[cfg(feature = "52810")]
|
||||||
mod irqs {
|
mod irqs {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::sync::atomic::{compiler_fence, AtomicU32, Ordering};
|
use core::sync::atomic::{compiler_fence, AtomicU32, Ordering};
|
||||||
|
use critical_section::CriticalSection;
|
||||||
use embassy::interrupt::InterruptExt;
|
use embassy::interrupt::InterruptExt;
|
||||||
use embassy::time::Clock;
|
use embassy::time::Clock;
|
||||||
|
use embassy::util::CriticalSectionMutex as Mutex;
|
||||||
|
|
||||||
use crate::interrupt::{CriticalSection, Interrupt, Mutex};
|
use crate::interrupt::Interrupt;
|
||||||
use crate::pac;
|
use crate::pac;
|
||||||
use crate::{interrupt, peripherals};
|
use crate::{interrupt, peripherals};
|
||||||
|
|
||||||
@ -134,7 +135,7 @@ impl<T: Instance> RTC<T> {
|
|||||||
for n in 0..ALARM_COUNT {
|
for n in 0..ALARM_COUNT {
|
||||||
if r.events_compare[n].read().bits() == 1 {
|
if r.events_compare[n].read().bits() == 1 {
|
||||||
r.events_compare[n].write(|w| w);
|
r.events_compare[n].write(|w| w);
|
||||||
interrupt::free(|cs| {
|
critical_section::with(|cs| {
|
||||||
self.trigger_alarm(n, cs);
|
self.trigger_alarm(n, cs);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -142,7 +143,7 @@ impl<T: Instance> RTC<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn next_period(&self) {
|
fn next_period(&self) {
|
||||||
interrupt::free(|cs| {
|
critical_section::with(|cs| {
|
||||||
let r = self.rtc.regs();
|
let r = self.rtc.regs();
|
||||||
let period = self.period.fetch_add(1, Ordering::Relaxed) + 1;
|
let period = self.period.fetch_add(1, Ordering::Relaxed) + 1;
|
||||||
let t = (period as u64) << 23;
|
let t = (period as u64) << 23;
|
||||||
@ -160,7 +161,7 @@ impl<T: Instance> RTC<T> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trigger_alarm(&self, n: usize, cs: &CriticalSection) {
|
fn trigger_alarm(&self, n: usize, cs: CriticalSection) {
|
||||||
let r = self.rtc.regs();
|
let r = self.rtc.regs();
|
||||||
r.intenclr.write(|w| unsafe { w.bits(compare_n(n)) });
|
r.intenclr.write(|w| unsafe { w.bits(compare_n(n)) });
|
||||||
|
|
||||||
@ -174,14 +175,14 @@ impl<T: Instance> RTC<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_alarm_callback(&self, n: usize, callback: fn(*mut ()), ctx: *mut ()) {
|
fn set_alarm_callback(&self, n: usize, callback: fn(*mut ()), ctx: *mut ()) {
|
||||||
interrupt::free(|cs| {
|
critical_section::with(|cs| {
|
||||||
let alarm = &self.alarms.borrow(cs)[n];
|
let alarm = &self.alarms.borrow(cs)[n];
|
||||||
alarm.callback.set(Some((callback, ctx)));
|
alarm.callback.set(Some((callback, ctx)));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_alarm(&self, n: usize, timestamp: u64) {
|
fn set_alarm(&self, n: usize, timestamp: u64) {
|
||||||
interrupt::free(|cs| {
|
critical_section::with(|cs| {
|
||||||
let alarm = &self.alarms.borrow(cs)[n];
|
let alarm = &self.alarms.borrow(cs)[n];
|
||||||
alarm.timestamp.set(timestamp);
|
alarm.timestamp.set(timestamp);
|
||||||
|
|
||||||
@ -289,5 +290,5 @@ pub trait Instance: sealed::Instance + 'static {
|
|||||||
|
|
||||||
impl_instance!(RTC0, RTC0);
|
impl_instance!(RTC0, RTC0);
|
||||||
impl_instance!(RTC1, RTC1);
|
impl_instance!(RTC1, RTC1);
|
||||||
#[cfg(any(feature = "52832", feature = "52833", feature = "52840"))]
|
#[cfg(any(feature = "nrf52832", feature = "nrf52833", feature = "nrf52840"))]
|
||||||
impl_instance!(RTC2, RTC2);
|
impl_instance!(RTC2, RTC2);
|
||||||
|
@ -20,6 +20,7 @@ defmt = { version = "0.2.0", optional = true }
|
|||||||
log = { version = "0.4.11", optional = true }
|
log = { version = "0.4.11", optional = true }
|
||||||
cortex-m-rt = "0.6.13"
|
cortex-m-rt = "0.6.13"
|
||||||
cortex-m = "0.7.1"
|
cortex-m = "0.7.1"
|
||||||
|
critical-section = "0.2.0"
|
||||||
|
|
||||||
rp2040-pac2 = { git = "https://github.com/Dirbaio/rp2040-pac", rev="254f4677937801155ca3cb17c7bb9d38eb62683e", features = ["rt"] }
|
rp2040-pac2 = { git = "https://github.com/Dirbaio/rp2040-pac", rev="254f4677937801155ca3cb17c7bb9d38eb62683e", features = ["rt"] }
|
||||||
embedded-hal = { version = "0.2.4", features = [ "unproven" ] }
|
embedded-hal = { version = "0.2.4", features = [ "unproven" ] }
|
||||||
|
@ -8,7 +8,6 @@ use core::sync::atomic::{compiler_fence, Ordering};
|
|||||||
use crate::pac::NVIC_PRIO_BITS;
|
use crate::pac::NVIC_PRIO_BITS;
|
||||||
|
|
||||||
// Re-exports
|
// Re-exports
|
||||||
pub use cortex_m::interrupt::{CriticalSection, Mutex};
|
|
||||||
pub use embassy::interrupt::{declare, take, Interrupt};
|
pub use embassy::interrupt::{declare, take, Interrupt};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
@ -47,35 +46,6 @@ impl From<Priority> for u8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn free<F, R>(f: F) -> R
|
|
||||||
where
|
|
||||||
F: FnOnce(&CriticalSection) -> R,
|
|
||||||
{
|
|
||||||
unsafe {
|
|
||||||
// TODO: assert that we're in privileged level
|
|
||||||
// Needed because disabling irqs in non-privileged level is a noop, which would break safety.
|
|
||||||
|
|
||||||
let primask: u32;
|
|
||||||
asm!("mrs {}, PRIMASK", out(reg) primask);
|
|
||||||
|
|
||||||
asm!("cpsid i");
|
|
||||||
|
|
||||||
// Prevent compiler from reordering operations inside/outside the critical section.
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
|
|
||||||
let r = f(&CriticalSection::new());
|
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
|
|
||||||
if primask & 1 == 0 {
|
|
||||||
asm!("cpsie i");
|
|
||||||
}
|
|
||||||
|
|
||||||
r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod irqs {
|
mod irqs {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["s
|
|||||||
embassy-extras = {version = "0.1.0", path = "../embassy-extras" }
|
embassy-extras = {version = "0.1.0", path = "../embassy-extras" }
|
||||||
|
|
||||||
atomic-polyfill = "0.1.1"
|
atomic-polyfill = "0.1.1"
|
||||||
|
critical-section = "0.2.0"
|
||||||
defmt = { version = "0.2.0", optional = true }
|
defmt = { version = "0.2.0", optional = true }
|
||||||
log = { version = "0.4.11", optional = true }
|
log = { version = "0.4.11", optional = true }
|
||||||
cortex-m-rt = "0.6.13"
|
cortex-m-rt = "0.6.13"
|
||||||
|
@ -44,7 +44,7 @@ pub struct ExtiPin<T: Instance> {
|
|||||||
|
|
||||||
impl<T: Instance> ExtiPin<T> {
|
impl<T: Instance> ExtiPin<T> {
|
||||||
pub fn new(mut pin: T, interrupt: T::Interrupt, syscfg: &mut SysCfg) -> Self {
|
pub fn new(mut pin: T, interrupt: T::Interrupt, syscfg: &mut SysCfg) -> Self {
|
||||||
cortex_m::interrupt::free(|_| {
|
critical_section::with(|_| {
|
||||||
pin.make_source(syscfg);
|
pin.make_source(syscfg);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ impl<T: Instance + digital::InputPin + 'static> ExtiPin<T> {
|
|||||||
async move {
|
async move {
|
||||||
let fut = InterruptFuture::new(&mut self.interrupt);
|
let fut = InterruptFuture::new(&mut self.interrupt);
|
||||||
let pin = &mut self.pin;
|
let pin = &mut self.pin;
|
||||||
cortex_m::interrupt::free(|_| {
|
critical_section::with(|_| {
|
||||||
pin.trigger_edge(if state {
|
pin.trigger_edge(if state {
|
||||||
EdgeOption::Rising
|
EdgeOption::Rising
|
||||||
} else {
|
} else {
|
||||||
@ -126,7 +126,7 @@ impl<T: Instance + 'static> ExtiPin<T> {
|
|||||||
async move {
|
async move {
|
||||||
let fut = InterruptFuture::new(&mut self.interrupt);
|
let fut = InterruptFuture::new(&mut self.interrupt);
|
||||||
let pin = &mut self.pin;
|
let pin = &mut self.pin;
|
||||||
cortex_m::interrupt::free(|_| {
|
critical_section::with(|_| {
|
||||||
pin.trigger_edge(state);
|
pin.trigger_edge(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3,12 +3,13 @@ use crate::hal::rcc::Clocks;
|
|||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
use core::sync::atomic::{compiler_fence, AtomicU32, Ordering};
|
use core::sync::atomic::{compiler_fence, AtomicU32, Ordering};
|
||||||
|
use critical_section::CriticalSection;
|
||||||
use embassy::interrupt::InterruptExt;
|
use embassy::interrupt::InterruptExt;
|
||||||
use embassy::time::{Clock, TICKS_PER_SECOND};
|
use embassy::time::{Clock, TICKS_PER_SECOND};
|
||||||
|
use embassy::util::CriticalSectionMutex as Mutex;
|
||||||
|
|
||||||
use crate::interrupt;
|
use crate::interrupt;
|
||||||
use crate::interrupt::{CriticalSection, Interrupt, Mutex};
|
use crate::interrupt::Interrupt;
|
||||||
|
|
||||||
// RTC timekeeping works with something we call "periods", which are time intervals
|
// RTC timekeeping works with something we call "periods", which are time intervals
|
||||||
// of 2^15 ticks. The RTC counter value is 16 bits, so one "overflow cycle" is 2 periods.
|
// 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> {
|
|||||||
for n in 1..=ALARM_COUNT {
|
for n in 1..=ALARM_COUNT {
|
||||||
if self.rtc.compare_interrupt_status(n) {
|
if self.rtc.compare_interrupt_status(n) {
|
||||||
self.rtc.compare_clear_flag(n);
|
self.rtc.compare_clear_flag(n);
|
||||||
interrupt::free(|cs| self.trigger_alarm(n, cs));
|
critical_section::with(|cs| self.trigger_alarm(n, cs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_period(&self) {
|
fn next_period(&self) {
|
||||||
interrupt::free(|cs| {
|
critical_section::with(|cs| {
|
||||||
let period = self.period.fetch_add(1, Ordering::Relaxed) + 1;
|
let period = self.period.fetch_add(1, Ordering::Relaxed) + 1;
|
||||||
let t = (period as u64) << 15;
|
let t = (period as u64) << 15;
|
||||||
|
|
||||||
@ -142,7 +143,7 @@ impl<T: Instance> RTC<T> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trigger_alarm(&self, n: usize, cs: &CriticalSection) {
|
fn trigger_alarm(&self, n: usize, cs: CriticalSection) {
|
||||||
self.rtc.set_compare_interrupt(n, false);
|
self.rtc.set_compare_interrupt(n, false);
|
||||||
|
|
||||||
let alarm = &self.alarms.borrow(cs)[n - 1];
|
let alarm = &self.alarms.borrow(cs)[n - 1];
|
||||||
@ -155,14 +156,14 @@ impl<T: Instance> RTC<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_alarm_callback(&self, n: usize, callback: fn(*mut ()), ctx: *mut ()) {
|
fn set_alarm_callback(&self, n: usize, callback: fn(*mut ()), ctx: *mut ()) {
|
||||||
interrupt::free(|cs| {
|
critical_section::with(|cs| {
|
||||||
let alarm = &self.alarms.borrow(cs)[n - 1];
|
let alarm = &self.alarms.borrow(cs)[n - 1];
|
||||||
alarm.callback.set(Some((callback, ctx)));
|
alarm.callback.set(Some((callback, ctx)));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_alarm(&self, n: usize, timestamp: u64) {
|
fn set_alarm(&self, n: usize, timestamp: u64) {
|
||||||
interrupt::free(|cs| {
|
critical_section::with(|cs| {
|
||||||
let alarm = &self.alarms.borrow(cs)[n - 1];
|
let alarm = &self.alarms.borrow(cs)[n - 1];
|
||||||
alarm.timestamp.set(timestamp);
|
alarm.timestamp.set(timestamp);
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ use core::sync::atomic::{compiler_fence, Ordering};
|
|||||||
use crate::pac::NVIC_PRIO_BITS;
|
use crate::pac::NVIC_PRIO_BITS;
|
||||||
|
|
||||||
// Re-exports
|
// Re-exports
|
||||||
pub use cortex_m::interrupt::{CriticalSection, Mutex};
|
|
||||||
pub use embassy::interrupt::{declare, take, Interrupt};
|
pub use embassy::interrupt::{declare, take, Interrupt};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
@ -63,35 +62,6 @@ impl From<Priority> for u8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn free<F, R>(f: F) -> R
|
|
||||||
where
|
|
||||||
F: FnOnce(&CriticalSection) -> R,
|
|
||||||
{
|
|
||||||
unsafe {
|
|
||||||
// TODO: assert that we're in privileged level
|
|
||||||
// Needed because disabling irqs in non-privileged level is a noop, which would break safety.
|
|
||||||
|
|
||||||
let primask: u32;
|
|
||||||
asm!("mrs {}, PRIMASK", out(reg) primask);
|
|
||||||
|
|
||||||
asm!("cpsid i");
|
|
||||||
|
|
||||||
// Prevent compiler from reordering operations inside/outside the critical section.
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
|
|
||||||
let r = f(&CriticalSection::new());
|
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
|
|
||||||
if primask & 1 == 0 {
|
|
||||||
asm!("cpsie i");
|
|
||||||
}
|
|
||||||
|
|
||||||
r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "stm32f401")]
|
#[cfg(feature = "stm32f401")]
|
||||||
mod irqs {
|
mod irqs {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -2,12 +2,13 @@ use crate::hal::rcc::Clocks;
|
|||||||
use atomic_polyfill::{compiler_fence, AtomicU32, Ordering};
|
use atomic_polyfill::{compiler_fence, AtomicU32, Ordering};
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
|
use critical_section::CriticalSection;
|
||||||
use embassy::interrupt::InterruptExt;
|
use embassy::interrupt::InterruptExt;
|
||||||
use embassy::time::{Clock, TICKS_PER_SECOND};
|
use embassy::time::{Clock, TICKS_PER_SECOND};
|
||||||
|
use embassy::util::CriticalSectionMutex as Mutex;
|
||||||
|
|
||||||
use crate::interrupt;
|
use crate::interrupt;
|
||||||
use crate::interrupt::{CriticalSection, Interrupt, Mutex};
|
use crate::interrupt::Interrupt;
|
||||||
|
|
||||||
// RTC timekeeping works with something we call "periods", which are time intervals
|
// RTC timekeeping works with something we call "periods", which are time intervals
|
||||||
// of 2^15 ticks. The RTC counter value is 16 bits, so one "overflow cycle" is 2 periods.
|
// 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> {
|
|||||||
for n in 1..=ALARM_COUNT {
|
for n in 1..=ALARM_COUNT {
|
||||||
if self.rtc.compare_interrupt_status(n) {
|
if self.rtc.compare_interrupt_status(n) {
|
||||||
self.rtc.compare_clear_flag(n);
|
self.rtc.compare_clear_flag(n);
|
||||||
interrupt::free(|cs| self.trigger_alarm(n, cs));
|
critical_section::with(|cs| self.trigger_alarm(n, cs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_period(&self) {
|
fn next_period(&self) {
|
||||||
interrupt::free(|cs| {
|
critical_section::with(|cs| {
|
||||||
let period = self.period.fetch_add(1, Ordering::Relaxed) + 1;
|
let period = self.period.fetch_add(1, Ordering::Relaxed) + 1;
|
||||||
let t = (period as u64) << 15;
|
let t = (period as u64) << 15;
|
||||||
|
|
||||||
@ -140,7 +141,7 @@ impl<T: Instance> RTC<T> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trigger_alarm(&self, n: usize, cs: &CriticalSection) {
|
fn trigger_alarm(&self, n: usize, cs: CriticalSection) {
|
||||||
self.rtc.set_compare_interrupt(n, false);
|
self.rtc.set_compare_interrupt(n, false);
|
||||||
|
|
||||||
let alarm = &self.alarms.borrow(cs)[n - 1];
|
let alarm = &self.alarms.borrow(cs)[n - 1];
|
||||||
@ -153,14 +154,14 @@ impl<T: Instance> RTC<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_alarm_callback(&self, n: usize, callback: fn(*mut ()), ctx: *mut ()) {
|
fn set_alarm_callback(&self, n: usize, callback: fn(*mut ()), ctx: *mut ()) {
|
||||||
interrupt::free(|cs| {
|
critical_section::with(|cs| {
|
||||||
let alarm = &self.alarms.borrow(cs)[n - 1];
|
let alarm = &self.alarms.borrow(cs)[n - 1];
|
||||||
alarm.callback.set(Some((callback, ctx)));
|
alarm.callback.set(Some((callback, ctx)));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_alarm(&self, n: usize, timestamp: u64) {
|
fn set_alarm(&self, n: usize, timestamp: u64) {
|
||||||
interrupt::free(|cs| {
|
critical_section::with(|cs| {
|
||||||
let alarm = &self.alarms.borrow(cs)[n - 1];
|
let alarm = &self.alarms.borrow(cs)[n - 1];
|
||||||
alarm.timestamp.set(timestamp);
|
alarm.timestamp.set(timestamp);
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ pin-project = { version = "1.0.2", default-features = false }
|
|||||||
embassy-macros = { version = "0.1.0", path = "../embassy-macros"}
|
embassy-macros = { version = "0.1.0", path = "../embassy-macros"}
|
||||||
embassy-traits = { version = "0.1.0", path = "../embassy-traits"}
|
embassy-traits = { version = "0.1.0", path = "../embassy-traits"}
|
||||||
atomic-polyfill = { version = "0.1.1" }
|
atomic-polyfill = { version = "0.1.1" }
|
||||||
|
critical-section = "0.2.0"
|
||||||
|
|
||||||
# Workaround https://github.com/japaric/cast.rs/pull/27
|
# Workaround https://github.com/japaric/cast.rs/pull/27
|
||||||
cast = { version = "=0.2.3", default-features = false }
|
cast = { version = "=0.2.3", default-features = false }
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
pub use cs::{critical_section, CriticalSection};
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
mod cs {
|
|
||||||
static INIT: std::sync::Once = std::sync::Once::new();
|
|
||||||
static mut BKL: Option<std::sync::Mutex<()>> = None;
|
|
||||||
|
|
||||||
pub type CriticalSection = std::sync::MutexGuard<'static, ()>;
|
|
||||||
pub fn critical_section<F, R>(f: F) -> R
|
|
||||||
where
|
|
||||||
F: FnOnce(&CriticalSection) -> R,
|
|
||||||
{
|
|
||||||
INIT.call_once(|| unsafe {
|
|
||||||
BKL.replace(std::sync::Mutex::new(()));
|
|
||||||
});
|
|
||||||
let guard = unsafe { BKL.as_ref().unwrap().lock().unwrap() };
|
|
||||||
f(&guard)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
|
||||||
mod cs {
|
|
||||||
pub use cortex_m::interrupt::CriticalSection;
|
|
||||||
pub fn critical_section<F, R>(f: F) -> R
|
|
||||||
where
|
|
||||||
F: FnOnce(&CriticalSection) -> R,
|
|
||||||
{
|
|
||||||
cortex_m::interrupt::free(f)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,4 @@
|
|||||||
//! Async utilities
|
//! Async utilities
|
||||||
mod critical_section;
|
|
||||||
mod drop_bomb;
|
mod drop_bomb;
|
||||||
mod forever;
|
mod forever;
|
||||||
mod mutex;
|
mod mutex;
|
||||||
@ -10,7 +9,6 @@ mod signal;
|
|||||||
#[cfg_attr(feature = "executor-agnostic", path = "waker_agnostic.rs")]
|
#[cfg_attr(feature = "executor-agnostic", path = "waker_agnostic.rs")]
|
||||||
mod waker;
|
mod waker;
|
||||||
|
|
||||||
pub use critical_section::*;
|
|
||||||
pub use drop_bomb::*;
|
pub use drop_bomb::*;
|
||||||
pub use forever::*;
|
pub use forever::*;
|
||||||
pub use mutex::*;
|
pub use mutex::*;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use core::cell::UnsafeCell;
|
use core::cell::UnsafeCell;
|
||||||
use cortex_m::interrupt::CriticalSection;
|
use critical_section::CriticalSection;
|
||||||
|
|
||||||
use crate::fmt::assert;
|
use crate::fmt::assert;
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ impl<T> CriticalSectionMutex<T> {
|
|||||||
|
|
||||||
impl<T> CriticalSectionMutex<T> {
|
impl<T> CriticalSectionMutex<T> {
|
||||||
/// Borrows the data for the duration of the critical section
|
/// Borrows the data for the duration of the critical section
|
||||||
pub fn borrow<'cs>(&'cs self, _cs: &'cs CriticalSection) -> &'cs T {
|
pub fn borrow<'cs>(&'cs self, _cs: CriticalSection<'cs>) -> &'cs T {
|
||||||
unsafe { &*self.inner.get() }
|
unsafe { &*self.inner.get() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ use ptr::NonNull;
|
|||||||
use crate::executor;
|
use crate::executor;
|
||||||
use crate::fmt::panic;
|
use crate::fmt::panic;
|
||||||
use crate::interrupt::{Interrupt, InterruptExt};
|
use crate::interrupt::{Interrupt, InterruptExt};
|
||||||
use crate::util::critical_section::critical_section;
|
|
||||||
|
|
||||||
/// Synchronization primitive. Allows creating awaitable signals that may be passed between tasks.
|
/// Synchronization primitive. Allows creating awaitable signals that may be passed between tasks.
|
||||||
///
|
///
|
||||||
@ -38,7 +37,7 @@ impl<T: Send> Signal<T> {
|
|||||||
|
|
||||||
/// Mark this Signal as completed.
|
/// Mark this Signal as completed.
|
||||||
pub fn signal(&self, val: T) {
|
pub fn signal(&self, val: T) {
|
||||||
critical_section(|_| unsafe {
|
critical_section::with(|_| unsafe {
|
||||||
let state = &mut *self.state.get();
|
let state = &mut *self.state.get();
|
||||||
if let State::Waiting(waker) = mem::replace(state, State::Signaled(val)) {
|
if let State::Waiting(waker) = mem::replace(state, State::Signaled(val)) {
|
||||||
waker.wake();
|
waker.wake();
|
||||||
@ -47,14 +46,14 @@ impl<T: Send> Signal<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(&self) {
|
pub fn reset(&self) {
|
||||||
critical_section(|_| unsafe {
|
critical_section::with(|_| unsafe {
|
||||||
let state = &mut *self.state.get();
|
let state = &mut *self.state.get();
|
||||||
*state = State::None
|
*state = State::None
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll_wait(&self, cx: &mut Context<'_>) -> Poll<T> {
|
pub fn poll_wait(&self, cx: &mut Context<'_>) -> Poll<T> {
|
||||||
critical_section(|_| unsafe {
|
critical_section::with(|_| unsafe {
|
||||||
let state = &mut *self.state.get();
|
let state = &mut *self.state.get();
|
||||||
match state {
|
match state {
|
||||||
State::None => {
|
State::None => {
|
||||||
@ -78,7 +77,7 @@ impl<T: Send> Signal<T> {
|
|||||||
|
|
||||||
/// non-blocking method to check whether this signal has been signaled.
|
/// non-blocking method to check whether this signal has been signaled.
|
||||||
pub fn signaled(&self) -> bool {
|
pub fn signaled(&self) -> bool {
|
||||||
critical_section(|_| matches!(unsafe { &*self.state.get() }, State::Signaled(_)))
|
critical_section::with(|_| matches!(unsafe { &*self.state.get() }, State::Signaled(_)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ impl AtomicWaker {
|
|||||||
|
|
||||||
/// Register a waker. Overwrites the previous waker, if any.
|
/// Register a waker. Overwrites the previous waker, if any.
|
||||||
pub fn register(&mut self, w: &Waker) {
|
pub fn register(&mut self, w: &Waker) {
|
||||||
cortex_m::interrupt::free(|cs| {
|
critical_section::with(|cs| {
|
||||||
let cell = self.waker.borrow(cs);
|
let cell = self.waker.borrow(cs);
|
||||||
cell.set(match cell.replace(None) {
|
cell.set(match cell.replace(None) {
|
||||||
Some(w2) if (w2.will_wake(w)) => Some(w2),
|
Some(w2) if (w2.will_wake(w)) => Some(w2),
|
||||||
@ -73,7 +73,7 @@ impl AtomicWaker {
|
|||||||
|
|
||||||
/// Wake the registered waker, if any.
|
/// Wake the registered waker, if any.
|
||||||
pub fn wake(&mut self) {
|
pub fn wake(&mut self) {
|
||||||
cortex_m::interrupt::free(|cs| {
|
critical_section::with(|cs| {
|
||||||
let cell = self.waker.borrow(cs);
|
let cell = self.waker.borrow(cs);
|
||||||
if let Some(w) = cell.replace(None) {
|
if let Some(w) = cell.replace(None) {
|
||||||
w.wake_by_ref();
|
w.wake_by_ref();
|
||||||
|
Loading…
Reference in New Issue
Block a user