pub use super::HartIdNumber;
use crate::common::unsafe_peripheral;
use riscv::register::{sie, sip};
pub unsafe trait Sswi: Copy {
const BASE: usize;
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct SSWI<M> {
_marker: core::marker::PhantomData<M>,
}
impl<S: Sswi> SSWI<S> {
#[inline]
pub const fn new() -> Self {
Self {
_marker: core::marker::PhantomData,
}
}
#[inline]
const fn as_ptr(self) -> *const u32 {
S::BASE as *const u32
}
#[inline]
pub fn is_interrupting(self) -> bool {
sip::read().ssoft()
}
#[inline]
pub fn is_enabled(self) -> bool {
sie::read().ssoft()
}
#[inline]
pub unsafe fn enable(self) {
sie::set_ssoft();
}
#[inline]
pub fn disable(self) {
unsafe { sie::clear_ssoft() };
}
#[inline]
pub fn setssip<H: HartIdNumber>(self, hart_id: H) -> SETSSIP {
unsafe { SETSSIP::new(self.as_ptr().add(hart_id.number()) as _) }
}
#[inline]
pub const fn setssip0(self) -> SETSSIP {
unsafe { SETSSIP::new(S::BASE) }
}
}
unsafe_peripheral!(SETSSIP, u32, RW);
impl SETSSIP {
#[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_sswi() {
let mut raw_reg = 0u32;
let setssip = unsafe { SETSSIP::new(&mut raw_reg as *mut u32 as usize) };
assert!(!setssip.is_pending());
assert_eq!(raw_reg, 0);
setssip.pend();
assert!(setssip.is_pending());
assert_ne!(raw_reg, 0);
setssip.unpend();
assert!(!setssip.is_pending());
assert_eq!(raw_reg, 0);
}
}