3
3
use riscv_pac:: CoreInterruptNumber ;
4
4
pub use riscv_pac:: { ExceptionNumber , InterruptNumber } ; // re-export useful riscv-pac traits
5
5
6
- /// mcause register
7
- #[ derive( Clone , Copy , Debug ) ]
8
- pub struct Mcause {
9
- bits : usize ,
10
- }
11
-
12
- impl From < usize > for Mcause {
13
- #[ inline]
14
- fn from ( bits : usize ) -> Self {
15
- Self { bits }
16
- }
17
- }
18
-
19
- /// Trap Cause
20
- #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
21
- pub enum Trap {
22
- Interrupt ( Interrupt ) ,
23
- Exception ( Exception ) ,
24
- }
25
-
26
- /// Interrupt
6
+ /// Standard M-mode RISC-V interrupts
27
7
#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
28
8
#[ repr( usize ) ]
29
9
pub enum Interrupt {
@@ -33,10 +13,32 @@ pub enum Interrupt {
33
13
MachineTimer = 7 ,
34
14
SupervisorExternal = 9 ,
35
15
MachineExternal = 11 ,
36
- Unknown ,
37
16
}
38
17
39
- /// Exception
18
+ /// SAFETY: `Interrupt` represents the standard RISC-V interrupts
19
+ unsafe impl InterruptNumber for Interrupt {
20
+ const MAX_INTERRUPT_NUMBER : usize = Self :: MachineExternal as usize ;
21
+
22
+ #[ inline]
23
+ fn number ( self ) -> usize {
24
+ self as usize
25
+ }
26
+
27
+ #[ inline]
28
+ fn from_number ( value : usize ) -> Result < Self , usize > {
29
+ if value > 11 || value % 2 == 0 {
30
+ Err ( value)
31
+ } else {
32
+ // SAFETY: valid interrupt number
33
+ unsafe { Ok ( core:: mem:: transmute :: < usize , Self > ( value) ) }
34
+ }
35
+ }
36
+ }
37
+
38
+ /// SAFETY: `Interrupt` represents the standard RISC-V core interrupts
39
+ unsafe impl CoreInterruptNumber for Interrupt { }
40
+
41
+ /// Standard M-mode RISC-V exceptions
40
42
#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
41
43
#[ repr( usize ) ]
42
44
pub enum Exception {
@@ -54,93 +56,52 @@ pub enum Exception {
54
56
InstructionPageFault = 12 ,
55
57
LoadPageFault = 13 ,
56
58
StorePageFault = 15 ,
57
- Unknown ,
58
- }
59
-
60
- impl From < usize > for Interrupt {
61
- #[ inline]
62
- fn from ( nr : usize ) -> Self {
63
- if nr > 11 || nr % 2 == 0 {
64
- Self :: Unknown
65
- } else {
66
- // SAFETY: valid interrupt number
67
- unsafe { core:: mem:: transmute :: < usize , Self > ( nr) }
68
- }
69
- }
70
- }
71
-
72
- impl TryFrom < Interrupt > for usize {
73
- type Error = Interrupt ;
74
-
75
- #[ inline]
76
- fn try_from ( value : Interrupt ) -> Result < Self , Self :: Error > {
77
- match value {
78
- Interrupt :: Unknown => Err ( Self :: Error :: Unknown ) ,
79
- _ => Ok ( value as Self ) ,
80
- }
81
- }
82
59
}
83
60
84
- /// SAFETY: `Interrupt ` represents the standard RISC-V interrupts
85
- unsafe impl InterruptNumber for Interrupt {
86
- const MAX_INTERRUPT_NUMBER : u16 = Self :: MachineExternal as u16 ;
61
+ /// SAFETY: `Exception ` represents the standard RISC-V exceptions
62
+ unsafe impl ExceptionNumber for Exception {
63
+ const MAX_EXCEPTION_NUMBER : usize = Self :: StorePageFault as usize ;
87
64
88
65
#[ inline]
89
- fn number ( self ) -> u16 {
90
- self as u16
66
+ fn number ( self ) -> usize {
67
+ self as usize
91
68
}
92
69
93
70
#[ inline]
94
- fn from_number ( value : u16 ) -> Result < Self , u16 > {
95
- match ( value as usize ) . into ( ) {
96
- Self :: Unknown => Err ( value) ,
97
- value => Ok ( value) ,
98
- }
99
- }
100
- }
101
-
102
- /// SAFETY: `Interrupt` represents the standard RISC-V core interrupts
103
- unsafe impl CoreInterruptNumber for Interrupt { }
104
-
105
- impl From < usize > for Exception {
106
- #[ inline]
107
- fn from ( nr : usize ) -> Self {
108
- if nr == 10 || nr == 14 || nr > 15 {
109
- Self :: Unknown
71
+ fn from_number ( value : usize ) -> Result < Self , usize > {
72
+ if value == 10 || value == 14 || value > 15 {
73
+ Err ( value)
110
74
} else {
111
75
// SAFETY: valid exception number
112
- unsafe { core:: mem:: transmute :: < usize , Self > ( nr ) }
76
+ unsafe { Ok ( core:: mem:: transmute :: < usize , Self > ( value ) ) }
113
77
}
114
78
}
115
79
}
116
80
117
- impl TryFrom < Exception > for usize {
118
- type Error = Exception ;
119
-
120
- #[ inline]
121
- fn try_from ( value : Exception ) -> Result < Self , Self :: Error > {
122
- match value {
123
- Exception :: Unknown => Err ( Self :: Error :: Unknown ) ,
124
- _ => Ok ( value as Self ) ,
125
- }
126
- }
81
+ /// Trap Cause
82
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
83
+ pub enum Trap < I , E > {
84
+ Interrupt ( I ) ,
85
+ Exception ( E ) ,
127
86
}
128
87
129
- /// SAFETY: `Exception` represents the standard RISC-V exceptions
130
- unsafe impl ExceptionNumber for Exception {
131
- const MAX_EXCEPTION_NUMBER : u16 = Self :: StorePageFault as u16 ;
88
+ /// Trap Error
89
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
90
+ pub enum TrapError {
91
+ InvalidInterrupt ( usize ) ,
92
+ InvalidException ( usize ) ,
93
+ }
132
94
133
- #[ inline]
134
- fn number ( self ) -> u16 {
135
- self as u16
136
- }
95
+ /// mcause register
96
+ #[ derive( Clone , Copy , Debug ) ]
97
+ pub struct Mcause {
98
+ bits : usize ,
99
+ }
137
100
101
+ impl From < usize > for Mcause {
138
102
#[ inline]
139
- fn from_number ( value : u16 ) -> Result < Self , u16 > {
140
- match ( value as usize ) . into ( ) {
141
- Self :: Unknown => Err ( value) ,
142
- value => Ok ( value) ,
143
- }
103
+ fn from ( bits : usize ) -> Self {
104
+ Self { bits }
144
105
}
145
106
}
146
107
@@ -157,16 +118,32 @@ impl Mcause {
157
118
self . bits & !( 1 << ( usize:: BITS as usize - 1 ) )
158
119
}
159
120
160
- /// Trap Cause
121
+ /// Try to get the trap cause
161
122
#[ inline]
162
- pub fn cause ( & self ) -> Trap {
123
+ pub fn try_cause < I , E > ( & self ) -> Result < Trap < I , E > , TrapError >
124
+ where
125
+ I : CoreInterruptNumber ,
126
+ E : ExceptionNumber ,
127
+ {
163
128
if self . is_interrupt ( ) {
164
- Trap :: Interrupt ( Interrupt :: from ( self . code ( ) ) )
129
+ match I :: from_number ( self . code ( ) ) {
130
+ Ok ( interrupt) => Ok ( Trap :: Interrupt ( interrupt) ) ,
131
+ Err ( code) => Err ( TrapError :: InvalidInterrupt ( code) ) ,
132
+ }
165
133
} else {
166
- Trap :: Exception ( Exception :: from ( self . code ( ) ) )
134
+ match E :: from_number ( self . code ( ) ) {
135
+ Ok ( exception) => Ok ( Trap :: Exception ( exception) ) ,
136
+ Err ( code) => Err ( TrapError :: InvalidException ( code) ) ,
137
+ }
167
138
}
168
139
}
169
140
141
+ /// Trap Cause
142
+ #[ inline]
143
+ pub fn cause < I : CoreInterruptNumber , E : ExceptionNumber > ( & self ) -> Trap < I , E > {
144
+ self . try_cause ( ) . unwrap ( )
145
+ }
146
+
170
147
/// Is trap cause an interrupt.
171
148
#[ inline]
172
149
pub fn is_interrupt ( & self ) -> bool {
0 commit comments