riscv/csr/
mcause.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5use kernel::utilities::registers::{register_bitfields, LocalRegisterCopy};
6
7register_bitfields![usize,
8    pub mcause [
9        is_interrupt OFFSET(crate::XLEN - 1) NUMBITS(1) [],
10        reason OFFSET(0) NUMBITS(crate::XLEN - 1) []
11    ],
12];
13
14/// Trap Cause
15#[derive(Copy, Clone, Debug)]
16pub enum Trap {
17    Interrupt(Interrupt),
18    Exception(Exception),
19}
20
21impl From<LocalRegisterCopy<usize, mcause::Register>> for Trap {
22    fn from(val: LocalRegisterCopy<usize, mcause::Register>) -> Self {
23        if val.is_set(mcause::is_interrupt) {
24            Trap::Interrupt(Interrupt::from_reason(val.read(mcause::reason)))
25        } else {
26            Trap::Exception(Exception::from_reason(val.read(mcause::reason)))
27        }
28    }
29}
30
31impl From<usize> for Trap {
32    fn from(csr_val: usize) -> Self {
33        Self::from(LocalRegisterCopy::<usize, mcause::Register>::new(csr_val))
34    }
35}
36
37/// Interrupt
38#[derive(Copy, Clone, Debug)]
39pub enum Interrupt {
40    UserSoft,
41    SupervisorSoft,
42    MachineSoft,
43    UserTimer,
44    SupervisorTimer,
45    MachineTimer,
46    UserExternal,
47    SupervisorExternal,
48    MachineExternal,
49    Unknown(usize),
50}
51
52/// Exception
53#[derive(Copy, Clone, Debug)]
54pub enum Exception {
55    InstructionMisaligned,
56    InstructionFault,
57    IllegalInstruction,
58    Breakpoint,
59    LoadMisaligned,
60    LoadFault,
61    StoreMisaligned,
62    StoreFault,
63    UserEnvCall,
64    SupervisorEnvCall,
65    MachineEnvCall,
66    InstructionPageFault,
67    LoadPageFault,
68    StorePageFault,
69    Unknown,
70}
71
72impl Interrupt {
73    fn from_reason(val: usize) -> Self {
74        let mcause = LocalRegisterCopy::<usize, mcause::Register>::new(val);
75        match mcause.read(mcause::reason) {
76            0 => Interrupt::UserSoft,
77            1 => Interrupt::SupervisorSoft,
78            3 => Interrupt::MachineSoft,
79            4 => Interrupt::UserTimer,
80            5 => Interrupt::SupervisorTimer,
81            7 => Interrupt::MachineTimer,
82            8 => Interrupt::UserExternal,
83            9 => Interrupt::SupervisorExternal,
84            11 => Interrupt::MachineExternal,
85            val => Interrupt::Unknown(val),
86        }
87    }
88}
89
90impl Exception {
91    fn from_reason(val: usize) -> Self {
92        let mcause = LocalRegisterCopy::<usize, mcause::Register>::new(val);
93        match mcause.read(mcause::reason) {
94            0 => Exception::InstructionMisaligned,
95            1 => Exception::InstructionFault,
96            2 => Exception::IllegalInstruction,
97            3 => Exception::Breakpoint,
98            4 => Exception::LoadMisaligned,
99            5 => Exception::LoadFault,
100            6 => Exception::StoreMisaligned,
101            7 => Exception::StoreFault,
102            8 => Exception::UserEnvCall,
103            9 => Exception::SupervisorEnvCall,
104            11 => Exception::MachineEnvCall,
105            12 => Exception::InstructionPageFault,
106            13 => Exception::LoadPageFault,
107            15 => Exception::StorePageFault,
108            _ => Exception::Unknown,
109        }
110    }
111}