Skip to content

Commit

Permalink
Merge pull request #139 from rust-embedded/interrupts-exceptions
Browse files Browse the repository at this point in the history
Rework of mcause and scause registers
  • Loading branch information
almindor authored Aug 11, 2023
2 parents c884f7e + 6ba456a commit 622f6fe
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 140 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
Cargo.lock
target/

.vscode/
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Add generic implementation of a PLIC peripheral
- Add `asm::fence()`, a wrapper for implementing a `fence` instruction
- Add `asm::fence_i()`, a wrapper for implementing a `fence.i` instruction
- Add `TryFrom` implementation for `mcause::{Interrupt, Exception}` and `scause::{Interrupt, Exception}`

### Changed

- CI actions updated. They now use `checkout@v3` and `dtolnay/rust-toolchain`.
- `mcause::{Interrupt, Exception}` and `scause::{Interrupt, Exception}` now implement `From` trait for `usize`

### Fixed

- Fix `scause::Exception` missing `LoadMisaligned`
- Fix `scause::Exception` missing `SupervisorEnvCall`
- Removed user-level interrupts from `mcause::Interrupt` and `scause::Interrupt`

## [v0.10.1] - 2023-01-18

Expand Down
143 changes: 75 additions & 68 deletions src/register/mcause.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,79 +15,100 @@ pub enum Trap {

/// Interrupt
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(usize)]
pub enum Interrupt {
UserSoft,
SupervisorSoft,
MachineSoft,
UserTimer,
SupervisorTimer,
MachineTimer,
UserExternal,
SupervisorExternal,
MachineExternal,
SupervisorSoft = 1,
MachineSoft = 3,
SupervisorTimer = 5,
MachineTimer = 7,
SupervisorExternal = 9,
MachineExternal = 11,
Unknown,
}

/// Exception
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(usize)]
pub enum Exception {
InstructionMisaligned,
InstructionFault,
IllegalInstruction,
Breakpoint,
LoadMisaligned,
LoadFault,
StoreMisaligned,
StoreFault,
UserEnvCall,
SupervisorEnvCall,
MachineEnvCall,
InstructionPageFault,
LoadPageFault,
StorePageFault,
InstructionMisaligned = 0,
InstructionFault = 1,
IllegalInstruction = 2,
Breakpoint = 3,
LoadMisaligned = 4,
LoadFault = 5,
StoreMisaligned = 6,
StoreFault = 7,
UserEnvCall = 8,
SupervisorEnvCall = 9,
MachineEnvCall = 11,
InstructionPageFault = 12,
LoadPageFault = 13,
StorePageFault = 15,
Unknown,
}

impl Interrupt {
impl From<usize> for Interrupt {
#[inline]
pub fn from(nr: usize) -> Self {
fn from(nr: usize) -> Self {
match nr {
0 => Interrupt::UserSoft,
1 => Interrupt::SupervisorSoft,
3 => Interrupt::MachineSoft,
4 => Interrupt::UserTimer,
5 => Interrupt::SupervisorTimer,
7 => Interrupt::MachineTimer,
8 => Interrupt::UserExternal,
9 => Interrupt::SupervisorExternal,
11 => Interrupt::MachineExternal,
_ => Interrupt::Unknown,
1 => Self::SupervisorSoft,
3 => Self::MachineSoft,
5 => Self::SupervisorTimer,
7 => Self::MachineTimer,
9 => Self::SupervisorExternal,
11 => Self::MachineExternal,
_ => Self::Unknown,
}
}
}

impl Exception {
impl TryFrom<Interrupt> for usize {
type Error = Interrupt;

#[inline]
fn try_from(value: Interrupt) -> Result<Self, Self::Error> {
match value {
Interrupt::Unknown => Err(Self::Error::Unknown),
_ => Ok(value as Self),
}
}
}

impl From<usize> for Exception {
#[inline]
pub fn from(nr: usize) -> Self {
fn from(nr: usize) -> Self {
match nr {
0 => Exception::InstructionMisaligned,
1 => Exception::InstructionFault,
2 => Exception::IllegalInstruction,
3 => Exception::Breakpoint,
4 => Exception::LoadMisaligned,
5 => Exception::LoadFault,
6 => Exception::StoreMisaligned,
7 => Exception::StoreFault,
8 => Exception::UserEnvCall,
9 => Exception::SupervisorEnvCall,
11 => Exception::MachineEnvCall,
12 => Exception::InstructionPageFault,
13 => Exception::LoadPageFault,
15 => Exception::StorePageFault,
_ => Exception::Unknown,
0 => Self::InstructionMisaligned,
1 => Self::InstructionFault,
2 => Self::IllegalInstruction,
3 => Self::Breakpoint,
4 => Self::LoadMisaligned,
5 => Self::LoadFault,
6 => Self::StoreMisaligned,
7 => Self::StoreFault,
8 => Self::UserEnvCall,
9 => Self::SupervisorEnvCall,
11 => Self::MachineEnvCall,
12 => Self::InstructionPageFault,
13 => Self::LoadPageFault,
15 => Self::StorePageFault,
_ => Self::Unknown,
}
}
}

impl TryFrom<Exception> for usize {
type Error = Exception;

#[inline]
fn try_from(value: Exception) -> Result<Self, Self::Error> {
match value {
Exception::Unknown => Err(Self::Error::Unknown),
_ => Ok(value as Self),
}
}
}

impl Mcause {
/// Returns the contents of the register as raw bits
#[inline]
Expand All @@ -98,14 +119,7 @@ impl Mcause {
/// Returns the code field
#[inline]
pub fn code(&self) -> usize {
match () {
#[cfg(target_pointer_width = "32")]
() => self.bits & !(1 << 31),
#[cfg(target_pointer_width = "64")]
() => self.bits & !(1 << 63),
#[cfg(target_pointer_width = "128")]
() => self.bits & !(1 << 127),
}
self.bits & !(1 << (usize::BITS as usize - 1))
}

/// Trap Cause
Expand All @@ -121,14 +135,7 @@ impl Mcause {
/// Is trap cause an interrupt.
#[inline]
pub fn is_interrupt(&self) -> bool {
match () {
#[cfg(target_pointer_width = "32")]
() => self.bits & (1 << 31) == 1 << 31,
#[cfg(target_pointer_width = "64")]
() => self.bits & (1 << 63) == 1 << 63,
#[cfg(target_pointer_width = "128")]
() => self.bits & (1 << 127) == 1 << 127,
}
self.bits & (1 << (usize::BITS as usize - 1)) != 0
}

/// Is trap cause an exception.
Expand Down
Loading

0 comments on commit 622f6fe

Please sign in to comment.