33use riscv_pac:: CoreInterruptNumber ;
44pub use riscv_pac:: { ExceptionNumber , InterruptNumber } ; // re-export useful riscv-pac traits
55
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
277#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
288#[ repr( usize ) ]
299pub enum Interrupt {
@@ -33,10 +13,32 @@ pub enum Interrupt {
3313 MachineTimer = 7 ,
3414 SupervisorExternal = 9 ,
3515 MachineExternal = 11 ,
36- Unknown ,
3716}
3817
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
4042#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
4143#[ repr( usize ) ]
4244pub enum Exception {
@@ -54,93 +56,52 @@ pub enum Exception {
5456 InstructionPageFault = 12 ,
5557 LoadPageFault = 13 ,
5658 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- }
8259}
8360
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 ;
8764
8865 #[ inline]
89- fn number ( self ) -> u16 {
90- self as u16
66+ fn number ( self ) -> usize {
67+ self as usize
9168 }
9269
9370 #[ 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)
11074 } else {
11175 // SAFETY: valid exception number
112- unsafe { core:: mem:: transmute :: < usize , Self > ( nr ) }
76+ unsafe { Ok ( core:: mem:: transmute :: < usize , Self > ( value ) ) }
11377 }
11478 }
11579}
11680
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 ) ,
12786}
12887
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+ }
13294
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+ }
137100
101+ impl From < usize > for Mcause {
138102 #[ 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 }
144105 }
145106}
146107
@@ -157,16 +118,32 @@ impl Mcause {
157118 self . bits & !( 1 << ( usize:: BITS as usize - 1 ) )
158119 }
159120
160- /// Trap Cause
121+ /// Try to get the trap cause
161122 #[ 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+ {
163128 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+ }
165133 } 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+ }
167138 }
168139 }
169140
141+ /// Trap Cause
142+ #[ inline]
143+ pub fn cause < I : CoreInterruptNumber , E : ExceptionNumber > ( & self ) -> Trap < I , E > {
144+ self . try_cause ( ) . unwrap ( )
145+ }
146+
170147 /// Is trap cause an interrupt.
171148 #[ inline]
172149 pub fn is_interrupt ( & self ) -> bool {
0 commit comments