Skip to content

Commit

Permalink
riscv: define mtvec CSR with macro helpers
Browse files Browse the repository at this point in the history
Uses the CSR macro helpers to define the `mtvec` CSR register.

Authored-by: rmsyn <github@weathered-steel.dev>
Reviewed-by: romancardenas <rcardenas.rod@gmail.com>
  • Loading branch information
rmsyn committed Dec 26, 2024
1 parent 6e91134 commit b343fbe
Showing 1 changed file with 48 additions and 33 deletions.
81 changes: 48 additions & 33 deletions riscv/src/register/mtvec.rs
Original file line number Diff line number Diff line change
@@ -1,50 +1,65 @@
//! mtvec register
/// mtvec register
#[derive(Clone, Copy, Debug)]
pub struct Mtvec {
bits: usize,
use crate::result::{Error, Result};

const MASK: usize = usize::MAX;
const TRAP_MASK: usize = 0b11;

read_write_csr! {
/// mtvec register
Mtvec: 0x305,
mask: MASK,
}

csr_field_enum! {
/// Trap mode
TrapMode {
default: Direct,
Direct = 0,
Vectored = 1,
}
}

/// Trap mode
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum TrapMode {
Direct = 0,
Vectored = 1,
read_write_csr_field! {
Mtvec,
/// Accesses the trap-vector mode.
trap_mode,
TrapMode: [0:1],
}

impl Mtvec {
/// Returns the contents of the register as raw bits
/// Returns the trap-vector base-address
#[inline]
pub fn bits(&self) -> usize {
self.bits
pub const fn address(&self) -> usize {
self.bits & !TRAP_MASK
}

/// Returns the trap-vector base-address
/// Sets the trap-vector base-address.
///
/// # Note
///
/// Panics if the address is not aligned to 4-bytes.
#[inline]
pub fn address(&self) -> usize {
self.bits - (self.bits & 0b11)
pub fn set_address(&mut self, address: usize) {
self.try_set_address(address).unwrap();
}

/// Returns the trap-vector mode
/// Attempts to set the trap-vector base-address.
///
/// # Note
///
/// Returns an error if the address is not aligned to 4-bytes.
#[inline]
pub fn trap_mode(&self) -> Option<TrapMode> {
let mode = self.bits & 0b11;
match mode {
0 => Some(TrapMode::Direct),
1 => Some(TrapMode::Vectored),
_ => None,
pub fn try_set_address(&mut self, address: usize) -> Result<()> {
// check for four-byte alignment
if (address & TRAP_MASK) != 0 {
Err(Error::InvalidFieldVariant {
field: "mtvec::address",
value: address,
})
} else {
self.bits = address | (self.bits & TRAP_MASK);
Ok(())
}
}
}

read_csr_as!(Mtvec, 0x305);

write_csr!(0x305);

/// Writes the CSR
#[inline]
pub unsafe fn write(addr: usize, mode: TrapMode) {
let bits = addr + mode as usize;
_write(bits);
}

0 comments on commit b343fbe

Please sign in to comment.