Add "context" pointer to owned interrupt handlers.
This commit is contained in:
parent
39ca8b8ded
commit
9e88718fbd
@ -117,9 +117,9 @@ pub fn interrupt_declare(item: TokenStream) -> TokenStream {
|
|||||||
fn number(&self) -> u8 {
|
fn number(&self) -> u8 {
|
||||||
Interrupt::#name as u8
|
Interrupt::#name as u8
|
||||||
}
|
}
|
||||||
unsafe fn __handler(&self) -> &'static ::core::sync::atomic::AtomicPtr<u32> {
|
unsafe fn __handler(&self) -> &'static ::embassy::interrupt::Handler {
|
||||||
#[export_name = #name_handler]
|
#[export_name = #name_handler]
|
||||||
static HANDLER: ::core::sync::atomic::AtomicPtr<u32> = ::core::sync::atomic::AtomicPtr::new(::core::ptr::null_mut());
|
static HANDLER: ::embassy::interrupt::Handler = ::embassy::interrupt::Handler::new();
|
||||||
&HANDLER
|
&HANDLER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,13 +141,14 @@ pub fn interrupt_take(item: TokenStream) -> TokenStream {
|
|||||||
pub unsafe extern "C" fn trampoline() {
|
pub unsafe extern "C" fn trampoline() {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#[link_name = #name_handler]
|
#[link_name = #name_handler]
|
||||||
static HANDLER: ::core::sync::atomic::AtomicPtr<u32>;
|
static HANDLER: ::embassy::interrupt::Handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
let p = HANDLER.load(::core::sync::atomic::Ordering::Acquire);
|
let func = HANDLER.func.load(::core::sync::atomic::Ordering::Acquire);
|
||||||
if !p.is_null() {
|
let ctx = HANDLER.ctx.load(::core::sync::atomic::Ordering::Acquire);
|
||||||
let f: fn() = ::core::mem::transmute(p);
|
if !func.is_null() {
|
||||||
f()
|
let func: fn(*mut ()) = ::core::mem::transmute(func);
|
||||||
|
func(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ impl Gpiote {
|
|||||||
// Enable interrupts
|
// Enable interrupts
|
||||||
gpiote.events_port.write(|w| w);
|
gpiote.events_port.write(|w| w);
|
||||||
gpiote.intenset.write(|w| w.port().set());
|
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.unpend();
|
||||||
irq.enable();
|
irq.enable();
|
||||||
|
|
||||||
@ -296,7 +296,7 @@ impl Gpiote {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn on_irq() {
|
unsafe fn on_irq(_ctx: *mut ()) {
|
||||||
let s = &(*INSTANCE);
|
let s = &(*INSTANCE);
|
||||||
|
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
|
@ -146,7 +146,7 @@ impl Qspi {
|
|||||||
SIGNAL.reset();
|
SIGNAL.reset();
|
||||||
qspi.intenset.write(|w| w.ready().set());
|
qspi.intenset.write(|w| w.ready().set());
|
||||||
|
|
||||||
irq.set_handler(irq_handler);
|
irq.set_handler(irq_handler, core::ptr::null_mut());
|
||||||
irq.unpend();
|
irq.unpend();
|
||||||
irq.enable();
|
irq.enable();
|
||||||
|
|
||||||
@ -347,7 +347,7 @@ impl Flash for Qspi {
|
|||||||
|
|
||||||
static SIGNAL: Signal<()> = Signal::new();
|
static SIGNAL: Signal<()> = Signal::new();
|
||||||
|
|
||||||
unsafe fn irq_handler() {
|
unsafe fn irq_handler(_ctx: *mut ()) {
|
||||||
let p = crate::pac::Peripherals::steal().QSPI;
|
let p = crate::pac::Peripherals::steal().QSPI;
|
||||||
if p.events_ready.read().events_ready().bit_is_set() {
|
if p.events_ready.read().events_ready().bit_is_set() {
|
||||||
p.events_ready.reset();
|
p.events_ready.reset();
|
||||||
|
@ -105,8 +105,10 @@ impl<T: Instance> RTC<T> {
|
|||||||
while self.rtc.counter.read().bits() != 0 {}
|
while self.rtc.counter.read().bits() != 0 {}
|
||||||
|
|
||||||
T::set_rtc_instance(self);
|
T::set_rtc_instance(self);
|
||||||
self.irq
|
self.irq.set_handler(
|
||||||
.set_handler(|| T::get_rtc_instance().on_interrupt());
|
|_| T::get_rtc_instance().on_interrupt(),
|
||||||
|
core::ptr::null_mut(),
|
||||||
|
);
|
||||||
self.irq.unpend();
|
self.irq.unpend();
|
||||||
self.irq.enable();
|
self.irq.enable();
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ where
|
|||||||
.write(|w| w.endtx().set().txstopped().set().endrx().set().rxto().set());
|
.write(|w| w.endtx().set().txstopped().set().endrx().set().rxto().set());
|
||||||
|
|
||||||
// Register ISR
|
// Register ISR
|
||||||
irq.set_handler(Self::on_irq);
|
irq.set_handler(Self::on_irq, core::ptr::null_mut());
|
||||||
irq.unpend();
|
irq.unpend();
|
||||||
irq.enable();
|
irq.enable();
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ where
|
|||||||
self.instance.events_rxstarted.read().bits() != 0
|
self.instance.events_rxstarted.read().bits() != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn on_irq() {
|
unsafe fn on_irq(_ctx: *mut ()) {
|
||||||
let uarte = &*pac::UARTE0::ptr();
|
let uarte = &*pac::UARTE0::ptr();
|
||||||
|
|
||||||
let mut try_disable = false;
|
let mut try_disable = false;
|
||||||
|
@ -55,12 +55,15 @@ impl<P: State> Registration<P> {
|
|||||||
// - therefore it's safe to overwrite it without dropping the previous contents
|
// - therefore it's safe to overwrite it without dropping the previous contents
|
||||||
unsafe { P::store().write(state) }
|
unsafe { P::store().write(state) }
|
||||||
|
|
||||||
irq.set_handler(|| {
|
irq.set_handler(
|
||||||
// safety:
|
|_| {
|
||||||
// - If a PeripheralRegistration instance exists, P::storage() is initialized.
|
// safety:
|
||||||
// - It's OK to get a &mut to it since the irq is disabled.
|
// - If a PeripheralRegistration instance exists, P::storage() is initialized.
|
||||||
unsafe { P::store().as_mut() }.on_interrupt();
|
// - 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);
|
compiler_fence(Ordering::SeqCst);
|
||||||
irq.enable();
|
irq.enable();
|
||||||
@ -89,7 +92,7 @@ impl<P: State> Registration<P> {
|
|||||||
pub fn free(self) -> (P::Interrupt, P) {
|
pub fn free(self) -> (P::Interrupt, P) {
|
||||||
let irq = unsafe { ptr::read(&self.irq) };
|
let irq = unsafe { ptr::read(&self.irq) };
|
||||||
irq.disable();
|
irq.disable();
|
||||||
irq.set_handler(|| ());
|
irq.remove_handler();
|
||||||
mem::forget(self);
|
mem::forget(self);
|
||||||
let storage = P::store();
|
let storage = P::store();
|
||||||
(irq, unsafe { storage.read() })
|
(irq, unsafe { storage.read() })
|
||||||
@ -99,7 +102,7 @@ impl<P: State> Registration<P> {
|
|||||||
impl<P: State> Drop for Registration<P> {
|
impl<P: State> Drop for Registration<P> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.irq.disable();
|
self.irq.disable();
|
||||||
self.irq.set_handler(|| ());
|
self.irq.remove_handler();
|
||||||
|
|
||||||
let storage = P::store();
|
let storage = P::store();
|
||||||
unsafe { storage.drop_in_place() };
|
unsafe { storage.drop_in_place() };
|
||||||
|
@ -6,6 +6,22 @@ use cortex_m::peripheral::NVIC;
|
|||||||
pub use embassy_macros::interrupt_declare as declare;
|
pub use embassy_macros::interrupt_declare as declare;
|
||||||
pub use embassy_macros::interrupt_take as take;
|
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);
|
struct NrWrap(u8);
|
||||||
unsafe impl cortex_m::interrupt::Nr for NrWrap {
|
unsafe impl cortex_m::interrupt::Nr for NrWrap {
|
||||||
fn nr(&self) -> u8 {
|
fn nr(&self) -> u8 {
|
||||||
@ -16,11 +32,20 @@ unsafe impl cortex_m::interrupt::Nr for NrWrap {
|
|||||||
pub unsafe trait OwnedInterrupt {
|
pub unsafe trait OwnedInterrupt {
|
||||||
type Priority: From<u8> + Into<u8> + Copy;
|
type Priority: From<u8> + Into<u8> + Copy;
|
||||||
fn number(&self) -> u8;
|
fn number(&self) -> u8;
|
||||||
#[doc(hidden)]
|
|
||||||
unsafe fn __handler(&self) -> &'static AtomicPtr<u32>;
|
|
||||||
|
|
||||||
fn set_handler(&self, handler: unsafe fn()) {
|
/// Implementation detail, do not use outside embassy crates.
|
||||||
unsafe { self.__handler() }.store(handler as *mut u32, Ordering::Release);
|
#[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]
|
#[inline]
|
||||||
|
Loading…
Reference in New Issue
Block a user