use crate::clic;
pub const CPU_INT_LINE_SYSTIMER: u8 = 1;
pub const CPU_INT_LINE_EMAC: u8 = 2;
pub const SYSTIMER_TARGET0_CLIC_INDEX: u8 = clic::clic_idx_for_cpu_line(CPU_INT_LINE_SYSTIMER);
pub const EMAC_SBD_CLIC_INDEX: u8 = clic::clic_idx_for_cpu_line(CPU_INT_LINE_EMAC);
pub const MCAUSE_INTERRUPT_BIT: u32 = 1 << 31;
pub const MCAUSE_CODE_MASK: u32 = 0x0FFF;
#[inline]
pub const fn is_async_irq(mcause: u32) -> bool {
mcause & MCAUSE_INTERRUPT_BIT != 0
}
#[inline]
pub const fn mcause_code(mcause: u32) -> u8 {
(mcause & MCAUSE_CODE_MASK) as u8
}
#[cfg(test)]
mod tests {
use super::*;
use crate::clic::CLIC_EXT_INTR_NUM_OFFSET;
#[test]
fn cpu_int_line_systimer_is_one() {
assert_eq!(CPU_INT_LINE_SYSTIMER, 1);
}
#[test]
fn cpu_int_line_emac_is_two_distinct_from_systimer() {
assert_eq!(CPU_INT_LINE_EMAC, 2);
assert_ne!(CPU_INT_LINE_SYSTIMER, CPU_INT_LINE_EMAC);
}
#[test]
fn systimer_target0_clic_index_is_seventeen() {
assert_eq!(SYSTIMER_TARGET0_CLIC_INDEX, 17);
assert_eq!(
SYSTIMER_TARGET0_CLIC_INDEX,
CPU_INT_LINE_SYSTIMER + CLIC_EXT_INTR_NUM_OFFSET,
);
}
#[test]
fn emac_sbd_clic_index_is_eighteen() {
assert_eq!(EMAC_SBD_CLIC_INDEX, 18);
assert_eq!(
EMAC_SBD_CLIC_INDEX,
CPU_INT_LINE_EMAC + CLIC_EXT_INTR_NUM_OFFSET,
);
}
#[test]
fn clic_indices_for_systimer_and_emac_are_distinct() {
assert_ne!(SYSTIMER_TARGET0_CLIC_INDEX, EMAC_SBD_CLIC_INDEX);
}
#[test]
fn mcause_interrupt_bit_is_msb() {
assert_eq!(MCAUSE_INTERRUPT_BIT, 0x8000_0000);
}
#[test]
fn mcause_code_mask_keeps_low_twelve_bits_only() {
assert_eq!(MCAUSE_CODE_MASK, 0x0000_0FFF);
}
#[test]
fn is_async_irq_recognises_clic_delivery() {
let m = MCAUSE_INTERRUPT_BIT | 17;
assert!(is_async_irq(m));
let m = MCAUSE_INTERRUPT_BIT | 18;
assert!(is_async_irq(m));
}
#[test]
fn is_async_irq_returns_false_for_synchronous_exception() {
assert!(!is_async_irq(2));
assert!(!is_async_irq(11));
assert!(!is_async_irq(0x7FFF_FFFF));
}
#[test]
fn mcause_code_extracts_clic_index() {
assert_eq!(mcause_code(MCAUSE_INTERRUPT_BIT | 17), 17);
assert_eq!(mcause_code(MCAUSE_INTERRUPT_BIT | 18), 18);
assert_eq!(mcause_code(2), 2);
}
#[test]
fn mcause_code_masks_above_byte_range() {
assert_eq!(mcause_code(MCAUSE_INTERRUPT_BIT | 0x123), 0x23);
assert_eq!(mcause_code(MCAUSE_INTERRUPT_BIT | 0xF000), 0);
}
}