use cortex_m::interrupt::InterruptNumber;
use crate::{
module_stop::ModuleStop as _,
pac::{self, icu::regs::Ielsr},
peripherals::ELC,
};
#[cfg(trust_zone)]
use pac::{
cpscu::vals::SecurityAttribution,
system::vals::{Prc4, Prkey},
};
pub unsafe trait IcuInterrupt: InterruptNumber + Copy {
#[inline(always)]
fn icu_disable(&self) {
let icu = pac::ICU;
icu.ielsr(self.number() as _).modify(|w| w.set_iels(0));
trace!("IEL{}: disable", self.number());
}
#[inline(always)]
unsafe fn icu_enable(&self, mask: InterruptEvent) {
let icu = pac::ICU;
trace!("IEL{}: enable={}", self.number(), mask);
icu.ielsr(self.number() as _).modify(|w| {
w.set_iels(mask as _);
});
}
#[inline(always)]
fn icu_enabled(&self) -> bool {
self.icu_event() != InterruptEvent::None
}
#[inline(always)]
fn icu_event(&self) -> InterruptEvent {
let icu = pac::ICU;
let event = icu.ielsr(self.number() as _).read().iels();
let event: InterruptEvent = unsafe { core::mem::transmute(event) };
trace!("IEL{}: event={}", self.number(), event);
event
}
#[inline(always)]
fn dtc_disable(&self) {
let icu = pac::ICU;
icu.ielsr(self.number() as _).write_value(Ielsr(0));
}
#[inline(always)]
fn dtc_enable(&self, mask: InterruptEvent) {
let icu = pac::ICU;
trace!("IEL{}: enable={}, dtc=true", self.number(), mask);
icu.ielsr(self.number() as _).write(|r| {
r.set_dtce(true);
r.set_iels(mask as _);
});
}
#[inline(always)]
fn is_dtc(&self) -> bool {
let icu = pac::ICU;
icu.ielsr(self.number() as _).read().dtce()
}
#[inline(always)]
fn icu_unpend(&self) {
let icu = pac::ICU;
icu.ielsr(self.number() as _).modify(|w| w.set_ir(false));
}
#[inline(always)]
fn icu_pend(&self) {
let icu = pac::ICU;
icu.ielsr(self.number() as _).modify(|w| w.set_ir(true));
}
fn icu_is_pending(&self) -> bool {
let icu = pac::ICU;
icu.ielsr(self.number() as _).read().ir()
}
fn icu_status(&self) {
let icu = pac::ICU;
let number = self.number();
let ielsr = icu.ielsr(number as _);
let status = ielsr.read();
trace!("IEL{}: ir={}, dtce={}", number, status.ir(), status.dtce());
}
#[cfg(trust_zone)]
fn set_security_attribution(&self, attribution: SecurityAttribution) {
let cpscu = pac::CPSCU;
let system = pac::SYSTEM;
let prcr = cfg_select! {
all(trust_zone_v2, secure) => system.prcr_s(),
_ => system.prcr()
};
prcr.modify(|r| {
r.set_prkey(Prkey::ProtectKey);
r.set_prc4(Prc4::NotProtected);
});
cpscu
.icusarg()
.modify(|r| r.set_saielsr(self.number() as _, attribution));
info!(
"ICUSARG: {}",
cpscu.icusarg().read().saielsr(self.number() as _)
);
prcr.modify(|r| {
r.set_prkey(Prkey::ProtectKey);
r.set_prc4(Prc4::Protected);
});
}
}
unsafe impl<T: InterruptNumber + Copy> IcuInterrupt for T {}
#[allow(private_bounds)]
pub trait SoftwareEventGenerator<const N: u8>: SealedSoftwareEventGenerator<N> {
fn event(&self) -> InterruptEvent;
#[inline(always)]
fn fire(&self) {
let elc = crate::pac::ELC;
elc.elsegr(self.index() as _).write(|r| r.set_wi(false));
elc.elsegr(self.index() as _).write(|r| r.set_we(true));
elc.elsegr(self.index() as _).write(|r| r.set_seg(true));
}
}
trait SealedSoftwareEventGenerator<const N: u8> {
fn index(&self) -> u8;
}
pub struct SoftwareEvent<const N: u8> {}
impl<const N: u8> SoftwareEvent<N> {
pub const fn new() -> Self {
Self {}
}
}
impl SoftwareEventGenerator<0> for SoftwareEvent<0> {
#[inline(always)]
fn event(&self) -> InterruptEvent {
InterruptEvent::ElcSoftwareEvent0
}
}
impl SealedSoftwareEventGenerator<0> for SoftwareEvent<0> {
#[inline(always)]
fn index(&self) -> u8 {
0
}
}
impl SoftwareEventGenerator<1> for SoftwareEvent<1> {
#[inline(always)]
fn event(&self) -> InterruptEvent {
InterruptEvent::ElcSoftwareEvent1
}
}
impl SealedSoftwareEventGenerator<1> for SoftwareEvent<1> {
#[inline(always)]
fn index(&self) -> u8 {
1
}
}
#[allow(unused, missing_docs)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u8)]
pub enum EventSignal {
PortIrq0 = 0x01,
PortIrq1 = 0x02,
PortIrq2 = 0x03,
PortIrq3 = 0x04,
PortIrq4 = 0x05,
PortIrq5 = 0x06,
PortIrq6 = 0x07,
PortIrq7 = 0x08,
PortIrq8 = 0x09,
PortIrq9 = 0x0a,
PortIrq10 = 0x0b,
PortIrq11 = 0x0c,
PortIrq12 = 0x0d,
PortIrq13 = 0x0e,
PortIrq14 = 0x0f,
PortIrq15 = 0x10,
Dmac0Int = 0x11,
Dmac1Int = 0x12,
Dmac2Int = 0x13,
Dmac3Int = 0x14,
DtcEnd = 0x16,
Lvd1 = 0x19,
Lvd2 = 0x1A,
MoscStop = 0x1C,
SnoozeRequest = 0x1D,
Agt0Agti = 0x1E,
Agt0AgtCmAi = 0x1F,
Agt0AgtCmBi = 0x20,
Agt1Agti = 0x21,
Agt1AgtCmAi = 0x22,
Agt1AgtCmBi = 0x23,
IwdtNmi = 0x24,
WdtNmi = 0x25,
RtcPrd = 0x27,
AdcAdi = 0x29,
AdcWcmpM = 0x2D,
AdcWcmpUm = 0x2E,
AcmpLp0 = 0x2F,
AcmpLp1 = 0x30,
Iic0Rxi = 0x35,
Iic0Txi = 0x36,
Iic0Tei = 0x37,
Iic0Eei = 0x38,
Iic1Rxi = 0x3A,
Iic1Txi = 0x3B,
Iic1Tei = 0x3C,
Iic1Eei = 0x3D,
DocDopci = 0x46,
IoportGroup1 = 0x4F,
IoportGroup2 = 0x50,
IoportGroup3 = 0x51,
IoportGroup4 = 0x52,
ElcSwEvt0 = 0x53,
ElcSwEvt1 = 0x54,
Gpt0CcmpA = 0x57,
Gpt0CcmpB = 0x58,
Gpt0CmpC = 0x59,
Gpt0CmpD = 0x5A,
Gpt0CmpE = 0x5B,
Gpt0CmpF = 0x5C,
Gpt0Ovf = 0x5D,
Gpt0Udf = 0x5E,
Gpt1CcmpA = 0x5F,
Gpt1CcmpB = 0x60,
Gpt1CmpC = 0x61,
Gpt1CmpD = 0x62,
Gpt1CmpE = 0x63,
Gpt1CmpF = 0x64,
Gpt1Ovf = 0x65,
Gpt1Udf = 0x66,
Gpt2CcmpA = 0x67,
Gpt2CcmpB = 0x68,
Gpt2CmpC = 0x69,
Gpt2CmpD = 0x6A,
Gpt2CmpE = 0x6B,
Gpt2CmpF = 0x6C,
Gpt2Ovf = 0x6D,
Gpt2Udf = 0x6E,
Gpt3CcmpA = 0x6F,
Gpt3CcmpB = 0x70,
Gpt3CmpC = 0x71,
Gpt3CmpD = 0x72,
Gpt3CmpE = 0x73,
Gpt3CmpF = 0x74,
Gpt3Ovf = 0x75,
Gpt3Udf = 0x76,
Gpt4CcmpA = 0x77,
Gpt4CcmpB = 0x78,
Gpt4CmpC = 0x79,
Gpt4CmpD = 0x7A,
Gpt4CmpE = 0x7B,
Gpt4CmpF = 0x7C,
Gpt4Ovf = 0x7D,
Gpt4Udf = 0x7E,
Gpt5CcmpA = 0x7F,
Gpt5CcmpB = 0x80,
Gpt5CmpC = 0x81,
Gpt5CmpD = 0x82,
Gpt5CmpE = 0x83,
Gpt5CmpF = 0x84,
Gpt5Ovf = 0x85,
Gpt5Udf = 0x86,
Gpt6CcmpA = 0x87,
Gpt6CcmpB = 0x88,
Gpt6CmpC = 0x89,
Gpt6CmpD = 0x8A,
Gpt6CmpE = 0x8B,
Gpt6CmpF = 0x8C,
Gpt6Ovf = 0x8D,
Gpt6Udf = 0x8E,
Gpt7CcmpA = 0x8F,
Gpt7CcmpB = 0x90,
Gpt7CmpC = 0x91,
Gpt7CmpD = 0x92,
Gpt7CmpE = 0x93,
Gpt7CmpF = 0x94,
Gpt7Ovf = 0x95,
Gpt7Udf = 0x96,
GptUvwEdge = 0x97,
Sci0Rxi = 0x98,
Sci0Txi = 0x99,
Sci0Tei = 0x9A,
Sci0Eri = 0x9B,
Sci0Am = 0x9C,
Sci1Rxi = 0x9E,
Sci1Txi = 0x9F,
Sci1Tei = 0xA0,
Sci1Eri = 0xA1,
Sci1Am = 0xA2,
Sci2Rxi = 0xA3,
Sci2Txi = 0xA4,
Sci2Tei = 0xA5,
Sci2Eri = 0xA6,
Sci2Am = 0xA7,
Sci9Rxi = 0xA8,
Sci9Txi = 0xA9,
Sci9Tei = 0xAA,
Sci9Eri = 0xAB,
Sci9Am = 0xAC,
Spi0SpRi = 0xAD,
Spi0SpTi = 0xAE,
Spi0SpIi = 0xAF,
Spi0SpEi = 0xB0,
Spi0SpTend = 0xB1,
Spi1SpRi = 0xB2,
Spi1SpTi = 0xB3,
Spi1SpIi = 0xB4,
Spi1SpEi = 0xB5,
Spi1SpTend = 0xB6,
}
include!(concat!(env!("OUT_DIR"), "/event_link.rs"));
pub(crate) fn init() {
ELC::start_module();
}