pub mod state;
use crate::reg;
use bitfield::bitfield;
use core::marker::PhantomData;
use reg::AccessRegisterBlock as _;
#[derive(Copy, Clone)]
pub enum InterruptLine {
Line0,
Line1,
}
bitfield! {
#[derive(Copy, Clone)]
pub struct InterruptSet(u32);
pub ara, set_ara: 29;
pub ped, set_ped: 28;
pub pea, set_pea: 27;
pub wdi, set_wdi: 26;
pub bo, set_bo: 25;
pub ew, set_ew: 24;
pub ep, set_ep: 23;
pub elo, set_elo: 22;
pub beu, set_beu: 21;
pub bec, set_bec: 20;
pub drx, set_drx: 19;
pub too, set_too: 18;
pub mraf, set_mraf: 17;
pub tsw, set_tsw: 16;
pub tefl, set_tefl: 15;
pub teff, set_teff: 14;
pub tefw, set_tefw: 13;
pub tefn, set_tefn: 12;
pub tfe, set_tfe: 11;
pub tcf, set_tcf: 10;
pub tc, set_tc: 9;
pub hpm, set_hpm: 8;
pub rf1l, set_rf1l: 7;
pub rf1f, set_rf1f: 6;
pub rf1w, set_rf1w: 5;
pub rf1n, set_rf1n: 4;
pub rf0l, set_rf0l: 3;
pub rf0f, set_rf0f: 2;
pub rf0w, set_rf0w: 1;
pub rf0n, set_rf0n: 0;
}
impl FromIterator<Interrupt> for InterruptSet {
fn from_iter<T: IntoIterator<Item = Interrupt>>(iter: T) -> Self {
let mut set = 0_u32;
for int in iter.into_iter() {
set |= u32::from(int);
}
InterruptSet(set)
}
}
impl From<Interrupt> for InterruptSet {
fn from(value: Interrupt) -> Self {
Self(value.into())
}
}
impl core::fmt::Debug for InterruptSet {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "InterruptSet {{ ")?;
if self.ara() {
write!(f, "ARA ")?;
}
if self.ped() {
write!(f, "PED ")?;
}
if self.pea() {
write!(f, "PEA ")?;
}
if self.wdi() {
write!(f, "WDI ")?;
}
if self.bo() {
write!(f, "BO ")?;
}
if self.ew() {
write!(f, "EW ")?;
}
if self.ep() {
write!(f, "EP ")?;
}
if self.elo() {
write!(f, "ELO ")?;
}
if self.beu() {
write!(f, "BEU ")?;
}
if self.bec() {
write!(f, "BEC ")?;
}
if self.drx() {
write!(f, "DRX ")?;
}
if self.too() {
write!(f, "TOO ")?;
}
if self.mraf() {
write!(f, "MRAF ")?;
}
if self.tsw() {
write!(f, "TSW ")?;
}
if self.tefl() {
write!(f, "TEFL ")?;
}
if self.teff() {
write!(f, "TEFF ")?;
}
if self.tefw() {
write!(f, "TEFW ")?;
}
if self.tefn() {
write!(f, "TEFN ")?;
}
if self.tfe() {
write!(f, "TFE ")?;
}
if self.tcf() {
write!(f, "TCF ")?;
}
if self.tc() {
write!(f, "TC ")?;
}
if self.hpm() {
write!(f, "HPM ")?;
}
if self.rf1l() {
write!(f, "RF1L ")?;
}
if self.rf1f() {
write!(f, "RF1F ")?;
}
if self.rf1w() {
write!(f, "RF1W ")?;
}
if self.rf1n() {
write!(f, "RF1N ")?;
}
if self.rf0l() {
write!(f, "RF0L ")?;
}
if self.rf0f() {
write!(f, "RF0F ")?;
}
if self.rf0w() {
write!(f, "RF0W ")?;
}
if self.rf0n() {
write!(f, "RF0N ")?;
}
write!(f, "}}")
}
}
#[derive(Debug, Copy, Clone)]
pub enum Interrupt {
RxFifo0NewMessage = 0,
RxFifo0WatermarkReached = 1,
RxFifo0Full = 2,
RxFifo0MessageLost = 3,
RxFifo1NewMessage = 4,
RxFifo1WatermarkReached = 5,
RxFifo1Full = 6,
RxFifo1MessageLost = 7,
HighPriorityMessage = 8,
TransmissionCompleted = 9,
TransmissionCancellationFinished = 10,
TxFifoEmpty = 11,
TxEventFifoNewEntry = 12,
TxEventFifoWatermarkReached = 13,
TxEventFifoFull = 14,
TxEventFifoElementLost = 15,
TimestampWraparound = 16,
MessageRamAccessFailure = 17,
TimeoutOccured = 18,
MessageStoredToDedicatedRxBuffer = 19,
BitErrorCorrected = 20,
BitErrorUncorrected = 21,
ErrorLoggingOverflow = 22,
ErrorPassive = 23,
WarningStatusChanged = 24,
BusOff = 25,
Watchdog = 26,
ProtocolErrorArbitration = 27,
ProtocolErrorData = 28,
AccessToReservedAddress = 29,
}
impl From<Interrupt> for u32 {
fn from(x: Interrupt) -> Self {
1 << x as u32
}
}
pub struct InvalidInterruptNumber;
impl TryFrom<u8> for Interrupt {
type Error = InvalidInterruptNumber;
fn try_from(value: u8) -> Result<Self, Self::Error> {
use Interrupt::*;
let ret = match value {
0 => RxFifo0NewMessage,
1 => RxFifo0WatermarkReached,
2 => RxFifo0Full,
3 => RxFifo0MessageLost,
4 => RxFifo1NewMessage,
5 => RxFifo1WatermarkReached,
6 => RxFifo1Full,
7 => RxFifo1MessageLost,
8 => HighPriorityMessage,
9 => TransmissionCompleted,
10 => TransmissionCancellationFinished,
11 => TxFifoEmpty,
12 => TxEventFifoNewEntry,
13 => TxEventFifoWatermarkReached,
14 => TxEventFifoFull,
15 => TxEventFifoElementLost,
16 => TimestampWraparound,
17 => MessageRamAccessFailure,
18 => TimeoutOccured,
19 => MessageStoredToDedicatedRxBuffer,
20 => BitErrorCorrected,
21 => BitErrorUncorrected,
22 => ErrorLoggingOverflow,
23 => ErrorPassive,
24 => WarningStatusChanged,
25 => BusOff,
26 => Watchdog,
27 => ProtocolErrorArbitration,
28 => ProtocolErrorData,
29 => AccessToReservedAddress,
30.. => Err(InvalidInterruptNumber)?,
};
Ok(ret)
}
}
impl InterruptSet {
pub fn iter(&self) -> Iter {
Iter {
flags: *self,
index: 0,
}
}
pub fn is_empty(&self) -> bool {
self.0 == 0
}
}
pub struct Iter {
flags: InterruptSet,
index: u8,
}
impl Iterator for Iter {
type Item = Interrupt;
fn next(&mut self) -> Option<Self::Item> {
let i = self.index;
self.index = self.index.saturating_add(1);
let int = i.try_into().ok()?;
if self.flags.0 & (1 << i) != 0 {
Some(int)
} else {
self.next()
}
}
}
#[must_use]
pub struct OwnedInterruptSet<Id, State = state::Dynamic>(InterruptSet, PhantomData<(Id, State)>);
impl<Id: mcan_core::CanId, State: state::Static> From<OwnedInterruptSet<Id, State>>
for OwnedInterruptSet<Id>
{
fn from(value: OwnedInterruptSet<Id, State>) -> Self {
unsafe { value.convert() }
}
}
impl<Id: mcan_core::CanId, State> Default for OwnedInterruptSet<Id, State> {
fn default() -> Self {
Self::empty()
}
}
#[derive(Debug)]
pub struct MaskError(pub InterruptSet);
impl<Id: mcan_core::CanId, State> OwnedInterruptSet<Id, State> {
unsafe fn new(interrupts: InterruptSet) -> Self {
Self(interrupts, PhantomData)
}
pub fn empty() -> Self {
unsafe { Self::new(InterruptSet(0)) }
}
pub fn split(&mut self, subset: InterruptSet) -> Result<Self, MaskError> {
let missing = !self.0 .0 & subset.0;
if missing != 0 {
Err(MaskError(InterruptSet(missing)))
} else {
Ok(self.split_leniently(subset))
}
}
pub fn join(&mut self, other: Self) {
debug_assert!(self.0 .0 & other.0 .0 == 0);
self.0 .0 |= other.0 .0;
}
fn split_leniently(&mut self, subset: InterruptSet) -> Self {
let remaining = self.0 .0 & !subset.0;
let split_out = self.0 .0 & subset.0;
self.0 .0 = remaining;
unsafe { Self::new(InterruptSet(split_out)) }
}
unsafe fn convert<NewState>(self) -> OwnedInterruptSet<Id, NewState> {
unsafe { OwnedInterruptSet::new(self.0) }
}
}
impl<Id: mcan_core::CanId, State: state::MaybeEnabled> OwnedInterruptSet<Id, State> {
pub fn split_flagged(&mut self) -> Self {
self.split_leniently(self.interrupt_flags())
}
pub fn iter_flagged(&self) -> Iter {
let interrupts = self.interrupt_flags();
self.clear_interrupts(interrupts);
interrupts.iter()
}
pub fn interrupt_flags(&self) -> InterruptSet {
let masked = unsafe { self.ir().read().bits() & self.0 .0 };
InterruptSet(masked)
}
pub fn clear_interrupts(&self, interrupts: InterruptSet) {
let masked = interrupts.0 & self.0 .0;
unsafe {
self.ir().write(|w| w.bits(masked));
}
}
unsafe fn ir(&self) -> ®::IR {
&(*Id::register_block()).ir
}
}
pub struct InterruptConfiguration<P>(PhantomData<P>);
impl<Id: mcan_core::CanId> InterruptConfiguration<Id> {
pub fn enable_line_0<State>(
&mut self,
interrupt: OwnedInterruptSet<Id, State>,
) -> OwnedInterruptSet<Id, state::EnabledLine0> {
unsafe { self.raw_enable(interrupt, InterruptLine::Line0) }
}
pub fn enable_line_1<State>(
&mut self,
interrupt: OwnedInterruptSet<Id, State>,
) -> OwnedInterruptSet<Id, state::EnabledLine1> {
unsafe { self.raw_enable(interrupt, InterruptLine::Line1) }
}
pub fn enable<State>(
&mut self,
interrupt: OwnedInterruptSet<Id, State>,
line: InterruptLine,
) -> OwnedInterruptSet<Id> {
match line {
InterruptLine::Line0 => self.enable_line_0(interrupt).into(),
InterruptLine::Line1 => self.enable_line_1(interrupt).into(),
}
}
pub fn disable<State>(
&mut self,
interrupt: OwnedInterruptSet<Id, State>,
) -> OwnedInterruptSet<Id, state::Disabled> {
let interrupt = unsafe { interrupt.convert() };
self.set_enabled(&interrupt, false);
unsafe { interrupt.convert() }
}
unsafe fn raw_enable<In, Out: state::MaybeEnabled>(
&mut self,
interrupt: OwnedInterruptSet<Id, In>,
line: InterruptLine,
) -> OwnedInterruptSet<Id, Out> {
let interrupt = unsafe { interrupt.convert() };
self.set_line(&interrupt, line);
self.set_enabled(&interrupt, true);
unsafe { interrupt.convert() }
}
pub(crate) unsafe fn new() -> (Self, OwnedInterruptSet<Id, state::Disabled>) {
const RESERVED_BITS: u32 = 0x3fff_ffff;
let v = Self(PhantomData);
v.ils().write(|w| w);
(v, unsafe {
OwnedInterruptSet::<_, state::Disabled>::new(InterruptSet(RESERVED_BITS))
})
}
fn ils(&self) -> ®::ILS {
&unsafe { &*Id::register_block() }.ils
}
fn ile(&self) -> ®::ILE {
&unsafe { &*Id::register_block() }.ile
}
fn ie(&self) -> ®::IE {
&unsafe { &*Id::register_block() }.ie
}
fn set_line(&mut self, interrupts: &OwnedInterruptSet<Id>, line: InterruptLine) {
self.enable_line(line);
let mask = interrupts.0 .0;
self.ils().modify(|r, w| unsafe {
w.bits(match line {
InterruptLine::Line0 => r.bits() & !mask,
InterruptLine::Line1 => r.bits() | mask,
})
});
}
fn enable_line(&mut self, line: InterruptLine) {
self.ile().modify(|_, w| match line {
InterruptLine::Line0 => w.eint0().set_bit(),
InterruptLine::Line1 => w.eint1().set_bit(),
});
}
fn set_enabled(&mut self, interrupts: &OwnedInterruptSet<Id>, enabled: bool) {
let mask = interrupts.0 .0;
self.ie().modify(|r, w| unsafe {
w.bits(if enabled {
r.bits() | mask
} else {
r.bits() & !mask
})
});
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn iter_preserves_length() {
assert_eq!(InterruptSet(0).iter().count(), 0);
assert_eq!(InterruptSet(1).iter().count(), 1);
assert_eq!(InterruptSet(0x1555_5555).iter().count(), 15);
assert_eq!(InterruptSet(0x2aaa_aaaa).iter().count(), 15);
assert_eq!(InterruptSet(0x3fff_ffff).iter().count(), 30);
assert_eq!(InterruptSet(0xffff_ffff).iter().count(), 30);
}
fn iter_collect(int: u32) -> u32 {
InterruptSet::from_iter(InterruptSet(int).iter()).0
}
#[test]
fn iter_collect_preserves_interrupts() {
assert_eq!(iter_collect(0), 0);
assert_eq!(iter_collect(1), 1);
assert_eq!(iter_collect(0x1555_5555), 0x1555_5555);
assert_eq!(iter_collect(0x2aaa_aaaa), 0x2aaa_aaaa);
}
#[test]
fn iter_collect_drops_reserved_bits() {
assert_eq!(iter_collect(0xffff_ffff), 0x3fff_ffff);
}
}