#![cfg_attr(docsrs, procmacros::doc_replace)]
use core::marker::PhantomData;
use crate::{
interrupt::{self, InterruptConfigurable, InterruptHandler},
peripherals::Interrupt,
system::Cpu,
};
#[non_exhaustive]
pub struct SoftwareInterrupt<'d, const NUM: u8> {
_lifetime: PhantomData<&'d mut ()>,
}
impl<const NUM: u8> SoftwareInterrupt<'_, NUM> {
#[inline]
pub unsafe fn steal() -> Self {
Self {
_lifetime: PhantomData,
}
}
pub fn reborrow(&mut self) -> SoftwareInterrupt<'_, NUM> {
unsafe { SoftwareInterrupt::steal() }
}
#[instability::unstable]
pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
let interrupt;
for_each_sw_interrupt! {
(all $( ($n:literal, $interrupt_name:ident, $f:ident) ),*) => {
interrupt = match NUM {
$($n => Interrupt::$interrupt_name,)*
_ => unreachable!(),
};
};
}
for core in Cpu::other() {
interrupt::disable(core, interrupt);
}
interrupt::bind_handler(interrupt, handler);
}
pub fn raise(&self) {
cfg_if::cfg_if! {
if #[cfg(soc_has_intpri)] {
let regs = crate::peripherals::INTPRI::regs();
} else {
let regs = crate::peripherals::SYSTEM::regs();
}
}
let reg;
for_each_sw_interrupt! {
(all $( ($n:literal, $i:ident, $f:ident) ),*) => {
reg = match NUM {
$($n => regs.cpu_intr_from_cpu($n),)*
_ => unreachable!(),
};
};
}
reg.write(|w| w.cpu_intr().set_bit());
_ = reg.read();
sw_interrupt_delay!();
}
pub fn reset(&self) {
cfg_if::cfg_if! {
if #[cfg(soc_has_intpri)] {
let regs = crate::peripherals::INTPRI::regs();
} else {
let regs = crate::peripherals::SYSTEM::regs();
}
}
let reg;
for_each_sw_interrupt! {
(all $( ($n:literal, $i:ident, $f:ident) ),*) => {
reg = match NUM {
$($n => regs.cpu_intr_from_cpu($n),)*
_ => unreachable!(),
};
};
}
reg.write(|w| w.cpu_intr().clear_bit());
}
}
impl<const NUM: u8> crate::private::Sealed for SoftwareInterrupt<'_, NUM> {}
impl<const NUM: u8> InterruptConfigurable for SoftwareInterrupt<'_, NUM> {
fn set_interrupt_handler(&mut self, handler: interrupt::InterruptHandler) {
SoftwareInterrupt::set_interrupt_handler(self, handler);
}
}
for_each_sw_interrupt! {
(all $( ($n:literal, $i:ident, $field:ident) ),*) => {
#[non_exhaustive]
pub struct SoftwareInterruptControl<'d> {
$(
#[doc = concat!("Software interrupt ", stringify!($n), ".")]
pub $field: SoftwareInterrupt<'d, $n>,
)*
}
impl<'d> SoftwareInterruptControl<'d> {
pub fn new(_peripheral: crate::peripherals::SW_INTERRUPT<'d>) -> Self {
SoftwareInterruptControl {
$(
$field: SoftwareInterrupt {
_lifetime: PhantomData,
},
)*
}
}
}
};
}