pub use super::{Clint, HartIdNumber};
use crate::common::safe_peripheral;
use riscv::register::{mhartid, mie, mip};
pub unsafe trait Mtimer: Copy {
const MTIMECMP_BASE: usize;
const MTIME_BASE: usize;
const MTIME_FREQ: usize;
}
unsafe impl<C: Clint> Mtimer for C {
const MTIMECMP_BASE: usize = C::BASE + 0x4000;
const MTIME_BASE: usize = C::BASE + 0xBFF8;
const MTIME_FREQ: usize = C::MTIME_FREQ;
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct MTIMER<M> {
_marker: core::marker::PhantomData<M>,
}
impl<M: Mtimer> MTIMER<M> {
#[inline]
pub const fn new() -> Self {
Self {
_marker: core::marker::PhantomData,
}
}
#[inline]
const fn mtimecmp_as_ptr(self) -> *const u64 {
M::MTIMECMP_BASE as *const u64
}
#[inline]
pub const fn mtime_freq(self) -> usize {
M::MTIME_FREQ
}
#[inline]
pub fn is_interrupting(self) -> bool {
mip::read().mtimer()
}
#[inline]
pub fn is_enabled(self) -> bool {
mie::read().mtimer()
}
#[inline]
pub unsafe fn enable(self) {
mie::set_mtimer();
}
#[inline]
pub fn disable(self) {
unsafe { mie::clear_mtimer() };
}
#[inline]
pub const fn mtime(self) -> MTIME {
unsafe { MTIME::new(M::MTIME_BASE) }
}
#[inline]
pub fn mtimecmp<H: HartIdNumber>(self, hart_id: H) -> MTIMECMP {
unsafe { MTIMECMP::new(self.mtimecmp_as_ptr().add(hart_id.number()) as _) }
}
#[inline]
pub const fn mtimecmp0(self) -> MTIMECMP {
unsafe { MTIMECMP::new(M::MTIMECMP_BASE) }
}
#[inline]
pub fn mtimecmp_mhartid(self) -> MTIMECMP {
let hart_id = mhartid::read();
unsafe { MTIMECMP::new(self.mtimecmp_as_ptr().add(hart_id) as _) }
}
}
safe_peripheral!(MTIMECMP, u64, RW);
safe_peripheral!(MTIME, u64, RW);