pub use super::{Clint, HartIdNumber};
use crate::common::unsafe_peripheral;
use riscv::register::{mhartid, mie, mip};
pub unsafe trait Mswi: Copy {
const BASE: usize;
}
unsafe impl<C: Clint> Mswi for C {
const BASE: usize = C::BASE;
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct MSWI<M> {
_marker: core::marker::PhantomData<M>,
}
impl<M: Mswi> MSWI<M> {
#[inline]
pub const fn new() -> Self {
Self {
_marker: core::marker::PhantomData,
}
}
#[inline]
const fn as_ptr(self) -> *const u32 {
M::BASE as *const u32
}
#[inline]
pub fn is_interrupting(self) -> bool {
mip::read().msoft()
}
#[inline]
pub fn is_enabled(self) -> bool {
mie::read().msoft()
}
#[inline]
pub unsafe fn enable(self) {
mie::set_msoft();
}
#[inline]
pub fn disable(self) {
unsafe { mie::clear_msoft() };
}
#[inline]
pub fn msip<H: HartIdNumber>(self, hart_id: H) -> MSIP {
unsafe { MSIP::new(self.as_ptr().add(hart_id.number()) as _) }
}
#[inline]
pub const fn msip0(self) -> MSIP {
unsafe { MSIP::new(M::BASE) }
}
#[inline]
pub fn msip_mhartid(self) -> MSIP {
let hart_id = mhartid::read();
unsafe { MSIP::new(self.as_ptr().add(hart_id) as _) }
}
}
unsafe_peripheral!(MSIP, u32, RW);
impl MSIP {
#[inline]
pub fn is_pending(self) -> bool {
self.register.read() != 0
}
#[inline]
pub fn pend(self) {
self.register.write(1);
}
#[inline]
pub fn unpend(self) {
self.register.write(0);
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_mswi() {
let mut raw_reg = 0u32;
let msip = unsafe { MSIP::new(&mut raw_reg as *mut u32 as usize) };
assert!(!msip.is_pending());
assert_eq!(raw_reg, 0);
msip.pend();
assert!(msip.is_pending());
assert_ne!(raw_reg, 0);
msip.unpend();
assert!(!msip.is_pending());
assert_eq!(raw_reg, 0);
}
}