1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//! CLIC extended machine trap-handler base address register.
use core::arch::asm;
/// Machine trap-handler base address register with CLIC extension.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct Mtvec {
bits: usize,
}
impl Mtvec {
/// Returns the contents of the register as raw bits.
#[inline]
pub const fn bits(self) -> usize {
self.bits
}
/// Returns the trap handler base-address.
///
/// This function returns `OBASE` in specification under CLINT trap modes,
/// `NBASE` if under CLIC trap mode, `None` if current trap mode is reserved.
#[inline]
pub const fn base_address(self) -> Option<usize> {
match self.trap_mode() {
Some(TrapMode::Direct | TrapMode::Vectored) => Some(self.bits & !0b11),
Some(TrapMode::Clic) => Some(self.bits & !0b111111),
None => None,
}
}
/// Returns the trap-vector mode, `None` if reserved under CLIC.
#[inline]
pub const fn trap_mode(self) -> Option<TrapMode> {
let mode = self.bits & 0b11;
let submode = (self.bits & 0b111100) >> 2;
match (mode, submode) {
(0, _) => Some(TrapMode::Direct),
(1, _) => Some(TrapMode::Vectored),
(3, 0b0000) => Some(TrapMode::Vectored),
_ => None,
}
}
}
/// Trap mode with CLIC extension.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum TrapMode {
/// CLINT non-vectored basic mode.
Direct = 0,
/// CLINT vectored basic mode.
Vectored = 1,
/// CLIC mode.
Clic = 3,
}
/// Writes the CLIC extended `mtvec` CSR.
#[inline]
pub unsafe fn write(addr: usize, mode: TrapMode) {
match mode {
TrapMode::Direct | TrapMode::Vectored => {
assert!(addr & 0b11 == 0, "base address must align to 4 bytes")
}
TrapMode::Clic => assert!(
addr & 0b111111 == 0,
"CLIC base address must align to 64 bytes"
),
}
asm!("csrw mtvec, {}", in(reg) addr | mode as usize)
}
/// Reads the CLIC extended `mtvec` CSR.
#[inline]
pub fn read() -> Mtvec {
let bits: usize;
unsafe { asm!("csrr {}, mtvec", out(reg) bits) };
Mtvec { bits }
}