use crate::common::{Reg, RO};
use riscv::ExternalInterruptNumber;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(transparent)]
pub struct PENDINGS {
ptr: *mut u32,
}
impl PENDINGS {
#[inline]
pub(crate) const unsafe fn new(address: usize) -> Self {
Self { ptr: address as _ }
}
#[cfg(test)]
#[inline]
pub(crate) fn address(self) -> usize {
self.ptr as _
}
#[inline]
pub fn is_pending<I: ExternalInterruptNumber>(self, source: I) -> bool {
let source = source.number();
let offset = (source / u32::BITS as usize) as _;
let reg: Reg<u32, RO> = unsafe { Reg::new(self.ptr.offset(offset)) };
reg.read_bit(source % u32::BITS as usize)
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::test::Interrupt;
#[test]
fn test_pendings() {
let mut raw_reg = [0u32; 32];
let pendings = unsafe { PENDINGS::new(raw_reg.as_mut_ptr() as _) };
for i in 0..255 {
unsafe { raw_reg.as_mut_ptr().write_volatile(i) };
assert_eq!(pendings.is_pending(Interrupt::I1), i & 0x2 != 0);
assert_eq!(pendings.is_pending(Interrupt::I2), i & 0x4 != 0);
assert_eq!(pendings.is_pending(Interrupt::I3), i & 0x8 != 0);
assert_eq!(pendings.is_pending(Interrupt::I4), i & 0x10 != 0);
}
}
}