riscv_peripheral/
aclint.rs1pub mod mswi;
7pub mod mtimer;
8pub mod sswi;
9
10pub use riscv_pac::HartIdNumber; pub unsafe trait Clint: Copy {
19 const BASE: usize;
21}
22
23#[allow(clippy::upper_case_acronyms)]
33#[derive(Clone, Copy, Debug, Eq, PartialEq)]
34pub struct CLINT<C: Clint> {
35 _marker: core::marker::PhantomData<C>,
36}
37
38impl<C: Clint> CLINT<C> {
39 const MTIMECMP_OFFSET: usize = 0x4000;
40
41 const MTIME_OFFSET: usize = 0xBFF8;
42
43 #[inline]
45 pub const fn mswi() -> mswi::MSWI {
46 unsafe { mswi::MSWI::new(C::BASE) }
48 }
49
50 #[inline]
52 pub const fn mtimer() -> mtimer::MTIMER {
53 unsafe {
55 mtimer::MTIMER::new(
56 C::BASE + Self::MTIMECMP_OFFSET,
57 C::BASE + Self::MTIME_OFFSET,
58 )
59 }
60 }
61}
62
63#[cfg(test)]
64pub(crate) mod test {
65 use super::HartIdNumber;
66 use riscv_pac::result::{Error, Result};
67
68 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
69 #[repr(usize)]
70 pub(crate) enum HartId {
71 H0 = 0,
72 H1 = 1,
73 H2 = 2,
74 }
75
76 unsafe impl HartIdNumber for HartId {
77 const MAX_HART_ID_NUMBER: usize = Self::H2 as usize;
78
79 #[inline]
80 fn number(self) -> usize {
81 self as _
82 }
83
84 #[inline]
85 fn from_number(number: usize) -> Result<Self> {
86 if number > Self::MAX_HART_ID_NUMBER {
87 Err(Error::InvalidVariant(number))
88 } else {
89 Ok(unsafe { core::mem::transmute::<usize, HartId>(number) })
91 }
92 }
93 }
94
95 #[test]
96 fn check_hart_id_enum() {
97 assert_eq!(HartId::H0.number(), 0);
98 assert_eq!(HartId::H1.number(), 1);
99 assert_eq!(HartId::H2.number(), 2);
100
101 assert_eq!(HartId::from_number(0), Ok(HartId::H0));
102 assert_eq!(HartId::from_number(1), Ok(HartId::H1));
103 assert_eq!(HartId::from_number(2), Ok(HartId::H2));
104
105 assert_eq!(HartId::from_number(3), Err(Error::InvalidVariant(3)));
106 }
107
108 #[allow(dead_code)]
109 #[test]
110 fn check_clint() {
111 crate::clint_codegen!(
113 base 0x0200_0000,
114 mtimecmps [mtimecmp0=(HartId::H0,"`H0`"), mtimecmp1=(HartId::H1,"`H1`"), mtimecmp2=(HartId::H2,"`H2`")],
115 msips [msip0=(HartId::H0,"`H0`"), msip1=(HartId::H1,"`H1`"), msip2=(HartId::H2,"`H2`")],
116 );
117
118 let mswi = CLINT::mswi();
119 let mtimer = CLINT::mtimer();
120
121 assert_eq!(mswi.msip0.get_ptr() as usize, 0x0200_0000);
122 assert_eq!(mtimer.mtimecmp0.get_ptr() as usize, 0x0200_4000);
123 assert_eq!(mtimer.mtime.get_ptr() as usize, 0x0200_bff8);
124
125 let mtimecmp0 = mtimer.mtimecmp(HartId::H0);
126 let mtimecmp1 = mtimer.mtimecmp(HartId::H1);
127 let mtimecmp2 = mtimer.mtimecmp(HartId::H2);
128
129 assert_eq!(mtimecmp0.get_ptr() as usize, 0x0200_4000);
130 assert_eq!(mtimecmp1.get_ptr() as usize, 0x0200_4000 + 8); assert_eq!(mtimecmp2.get_ptr() as usize, 0x0200_4000 + 2 * 8);
132
133 assert_eq!(CLINT::mtime(), mtimer.mtime);
134 assert_eq!(CLINT::mtimecmp0(), mtimer.mtimecmp(HartId::H0));
135 assert_eq!(CLINT::mtimecmp1(), mtimer.mtimecmp(HartId::H1));
136 assert_eq!(CLINT::mtimecmp2(), mtimer.mtimecmp(HartId::H2));
137
138 assert_eq!(CLINT::msip0(), mswi.msip(HartId::H0));
139 assert_eq!(CLINT::msip1(), mswi.msip(HartId::H1));
140 assert_eq!(CLINT::msip2(), mswi.msip(HartId::H2));
141 }
142}