123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- //! scause register
- use bit_field::BitField;
- use core::mem::size_of;
- /// scause register
- #[derive(Clone, Copy)]
- pub struct Scause {
- bits: usize,
- }
- /// Trap Cause
- #[derive(Copy, Clone, Debug, Eq, PartialEq)]
- pub enum Trap {
- Interrupt(Interrupt),
- Exception(Exception),
- }
- /// Interrupt
- #[derive(Copy, Clone, Debug, Eq, PartialEq)]
- pub enum Interrupt {
- UserSoft,
- SupervisorSoft,
- UserTimer,
- SupervisorTimer,
- UserExternal,
- SupervisorExternal,
- Unknown,
- }
- /// Exception
- #[derive(Copy, Clone, Debug, Eq, PartialEq)]
- pub enum Exception {
- InstructionMisaligned,
- InstructionFault,
- IllegalInstruction,
- Breakpoint,
- LoadFault,
- StoreMisaligned,
- StoreFault,
- UserEnvCall,
- InstructionPageFault,
- LoadPageFault,
- StorePageFault,
- Unknown,
- }
- impl Interrupt {
- pub fn from(nr: usize) -> Self {
- match nr {
- 0 => Interrupt::UserSoft,
- 1 => Interrupt::SupervisorSoft,
- 4 => Interrupt::UserTimer,
- 5 => Interrupt::SupervisorTimer,
- 8 => Interrupt::UserExternal,
- 9 => Interrupt::SupervisorExternal,
- _ => Interrupt::Unknown,
- }
- }
- }
- impl Exception {
- pub fn from(nr: usize) -> Self {
- match nr {
- 0 => Exception::InstructionMisaligned,
- 1 => Exception::InstructionFault,
- 2 => Exception::IllegalInstruction,
- 3 => Exception::Breakpoint,
- 5 => Exception::LoadFault,
- 6 => Exception::StoreMisaligned,
- 7 => Exception::StoreFault,
- 8 => Exception::UserEnvCall,
- 12 => Exception::InstructionPageFault,
- 13 => Exception::LoadPageFault,
- 15 => Exception::StorePageFault,
- _ => Exception::Unknown,
- }
- }
- }
- impl Scause {
- /// Returns the contents of the register as raw bits
- #[inline]
- pub fn bits(&self) -> usize {
- self.bits
- }
- /// Returns the code field
- pub fn code(&self) -> usize {
- let bit = 1 << (size_of::<usize>() * 8 - 1);
- self.bits & !bit
- }
- /// Trap Cause
- #[inline]
- pub fn cause(&self) -> Trap {
- if self.is_interrupt() {
- Trap::Interrupt(Interrupt::from(self.code()))
- } else {
- Trap::Exception(Exception::from(self.code()))
- }
- }
- /// Is trap cause an interrupt.
- #[inline]
- pub fn is_interrupt(&self) -> bool {
- self.bits.get_bit(size_of::<usize>() * 8 - 1)
- }
- /// Is trap cause an exception.
- #[inline]
- pub fn is_exception(&self) -> bool {
- !self.is_interrupt()
- }
- }
- read_csr_as!(Scause, 0x142, __read_scause);
- write_csr!(0x142, __write_scause);
- /// Writes the CSR
- #[inline]
- pub unsafe fn write(bits: usize) {
- _write(bits)
- }
- /// Set supervisor cause register to corresponding cause.
- #[inline]
- pub unsafe fn set(cause: Trap) {
- let bits = match cause {
- Trap::Interrupt(i) => match i {
- Interrupt::UserSoft => 0,
- Interrupt::SupervisorSoft => 1,
- Interrupt::UserTimer => 4,
- Interrupt::SupervisorTimer => 5,
- Interrupt::UserExternal => 8,
- Interrupt::SupervisorExternal => 9,
- Interrupt::Unknown => panic!("unknown interrupt"),
- },
- Trap::Exception(e) => {
- (match e {
- Exception::InstructionMisaligned => 0,
- Exception::InstructionFault => 1,
- Exception::IllegalInstruction => 2,
- Exception::Breakpoint => 3,
- Exception::LoadFault => 5,
- Exception::StoreMisaligned => 6,
- Exception::StoreFault => 7,
- Exception::UserEnvCall => 8,
- Exception::InstructionPageFault => 12,
- Exception::LoadPageFault => 13,
- Exception::StorePageFault => 15,
- Exception::Unknown => panic!("unknown exception"),
- } | (1 << (size_of::<usize>() * 8 - 1)))
- }
- };
- _write(bits);
- }
|