diff --git a/embassy-macros/src/lib.rs b/embassy-macros/src/lib.rs index c46f114a..86140639 100644 --- a/embassy-macros/src/lib.rs +++ b/embassy-macros/src/lib.rs @@ -117,9 +117,9 @@ pub fn interrupt_declare(item: TokenStream) -> TokenStream { fn number(&self) -> u8 { Interrupt::#name as u8 } - unsafe fn __handler(&self) -> &'static ::core::sync::atomic::AtomicPtr { + unsafe fn __handler(&self) -> &'static ::embassy::interrupt::Handler { #[export_name = #name_handler] - static HANDLER: ::core::sync::atomic::AtomicPtr = ::core::sync::atomic::AtomicPtr::new(::core::ptr::null_mut()); + static HANDLER: ::embassy::interrupt::Handler = ::embassy::interrupt::Handler::new(); &HANDLER } } @@ -141,13 +141,14 @@ pub fn interrupt_take(item: TokenStream) -> TokenStream { pub unsafe extern "C" fn trampoline() { extern "C" { #[link_name = #name_handler] - static HANDLER: ::core::sync::atomic::AtomicPtr; + static HANDLER: ::embassy::interrupt::Handler; } - let p = HANDLER.load(::core::sync::atomic::Ordering::Acquire); - if !p.is_null() { - let f: fn() = ::core::mem::transmute(p); - f() + let func = HANDLER.func.load(::core::sync::atomic::Ordering::Acquire); + let ctx = HANDLER.ctx.load(::core::sync::atomic::Ordering::Acquire); + if !func.is_null() { + let func: fn(*mut ()) = ::core::mem::transmute(func); + func(ctx) } } diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index 353f6a94..65a584c7 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs @@ -75,7 +75,7 @@ impl Gpiote { // Enable interrupts gpiote.events_port.write(|w| w); gpiote.intenset.write(|w| w.port().set()); - irq.set_handler(Self::on_irq); + irq.set_handler(Self::on_irq, core::ptr::null_mut()); irq.unpend(); irq.enable(); @@ -296,7 +296,7 @@ impl Gpiote { }) } - unsafe fn on_irq() { + unsafe fn on_irq(_ctx: *mut ()) { let s = &(*INSTANCE); for i in 0..8 { diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs index c9c907cd..753a5985 100644 --- a/embassy-nrf/src/qspi.rs +++ b/embassy-nrf/src/qspi.rs @@ -146,7 +146,7 @@ impl Qspi { SIGNAL.reset(); qspi.intenset.write(|w| w.ready().set()); - irq.set_handler(irq_handler); + irq.set_handler(irq_handler, core::ptr::null_mut()); irq.unpend(); irq.enable(); @@ -347,7 +347,7 @@ impl Flash for Qspi { static SIGNAL: Signal<()> = Signal::new(); -unsafe fn irq_handler() { +unsafe fn irq_handler(_ctx: *mut ()) { let p = crate::pac::Peripherals::steal().QSPI; if p.events_ready.read().events_ready().bit_is_set() { p.events_ready.reset(); diff --git a/embassy-nrf/src/rtc.rs b/embassy-nrf/src/rtc.rs index d65b8d47..fb59faa3 100644 --- a/embassy-nrf/src/rtc.rs +++ b/embassy-nrf/src/rtc.rs @@ -105,8 +105,10 @@ impl RTC { while self.rtc.counter.read().bits() != 0 {} T::set_rtc_instance(self); - self.irq - .set_handler(|| T::get_rtc_instance().on_interrupt()); + self.irq.set_handler( + |_| T::get_rtc_instance().on_interrupt(), + core::ptr::null_mut(), + ); self.irq.unpend(); self.irq.enable(); } diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 648298b8..8aee11c4 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs @@ -119,7 +119,7 @@ where .write(|w| w.endtx().set().txstopped().set().endrx().set().rxto().set()); // Register ISR - irq.set_handler(Self::on_irq); + irq.set_handler(Self::on_irq, core::ptr::null_mut()); irq.unpend(); irq.enable(); @@ -147,7 +147,7 @@ where self.instance.events_rxstarted.read().bits() != 0 } - unsafe fn on_irq() { + unsafe fn on_irq(_ctx: *mut ()) { let uarte = &*pac::UARTE0::ptr(); let mut try_disable = false; diff --git a/embassy-nrf/src/util/peripheral.rs b/embassy-nrf/src/util/peripheral.rs index 85de3419..9b3384e5 100644 --- a/embassy-nrf/src/util/peripheral.rs +++ b/embassy-nrf/src/util/peripheral.rs @@ -55,12 +55,15 @@ impl Registration

{ // - therefore it's safe to overwrite it without dropping the previous contents unsafe { P::store().write(state) } - irq.set_handler(|| { - // safety: - // - If a PeripheralRegistration instance exists, P::storage() is initialized. - // - It's OK to get a &mut to it since the irq is disabled. - unsafe { P::store().as_mut() }.on_interrupt(); - }); + irq.set_handler( + |_| { + // safety: + // - If a PeripheralRegistration instance exists, P::storage() is initialized. + // - It's OK to get a &mut to it since the irq is disabled. + unsafe { P::store().as_mut() }.on_interrupt(); + }, + core::ptr::null_mut(), + ); compiler_fence(Ordering::SeqCst); irq.enable(); @@ -89,7 +92,7 @@ impl Registration

{ pub fn free(self) -> (P::Interrupt, P) { let irq = unsafe { ptr::read(&self.irq) }; irq.disable(); - irq.set_handler(|| ()); + irq.remove_handler(); mem::forget(self); let storage = P::store(); (irq, unsafe { storage.read() }) @@ -99,7 +102,7 @@ impl Registration

{ impl Drop for Registration

{ fn drop(&mut self) { self.irq.disable(); - self.irq.set_handler(|| ()); + self.irq.remove_handler(); let storage = P::store(); unsafe { storage.drop_in_place() }; diff --git a/embassy/src/interrupt.rs b/embassy/src/interrupt.rs index fee52b32..7690bea0 100644 --- a/embassy/src/interrupt.rs +++ b/embassy/src/interrupt.rs @@ -6,6 +6,22 @@ use cortex_m::peripheral::NVIC; pub use embassy_macros::interrupt_declare as declare; pub use embassy_macros::interrupt_take as take; +/// Implementation detail, do not use outside embassy crates. +#[doc(hidden)] +pub struct Handler { + pub func: AtomicPtr<()>, + pub ctx: AtomicPtr<()>, +} + +impl Handler { + pub const fn new() -> Self { + Self { + func: AtomicPtr::new(ptr::null_mut()), + ctx: AtomicPtr::new(ptr::null_mut()), + } + } +} + struct NrWrap(u8); unsafe impl cortex_m::interrupt::Nr for NrWrap { fn nr(&self) -> u8 { @@ -16,11 +32,20 @@ unsafe impl cortex_m::interrupt::Nr for NrWrap { pub unsafe trait OwnedInterrupt { type Priority: From + Into + Copy; fn number(&self) -> u8; - #[doc(hidden)] - unsafe fn __handler(&self) -> &'static AtomicPtr; - fn set_handler(&self, handler: unsafe fn()) { - unsafe { self.__handler() }.store(handler as *mut u32, Ordering::Release); + /// Implementation detail, do not use outside embassy crates. + #[doc(hidden)] + unsafe fn __handler(&self) -> &'static Handler; + + fn set_handler(&self, func: unsafe fn(*mut ()), ctx: *mut ()) { + let handler = unsafe { self.__handler() }; + handler.func.store(func as *mut (), Ordering::Release); + handler.ctx.store(ctx, Ordering::Release); + } + + fn remove_handler(&self) { + let handler = unsafe { self.__handler() }; + handler.func.store(ptr::null_mut(), Ordering::Release); } #[inline]