3
3
pub use crate :: interrupt:: Trap ;
4
4
pub use riscv_pac:: { CoreInterruptNumber , ExceptionNumber , InterruptNumber } ; // re-export useful riscv-pac traits
5
5
6
- /// scause register
7
- # [ derive ( Clone , Copy ) ]
8
- pub struct Scause {
9
- bits : usize ,
6
+ read_write_csr ! {
7
+ /// scause register
8
+ Scause : 0x142 ,
9
+ mask : usize :: MAX ,
10
10
}
11
11
12
- impl Scause {
13
- /// Returns the contents of the register as raw bits
14
- #[ inline]
15
- pub fn bits ( & self ) -> usize {
16
- self . bits
17
- }
12
+ #[ cfg( target_arch = "riscv32" ) ]
13
+ read_write_csr_field ! {
14
+ Scause ,
15
+ /// Returns the type of the trap:
16
+ ///
17
+ /// - `true`: an interrupt caused the trap
18
+ /// - `false`: an exception caused the trap
19
+ interrupt: 31 ,
20
+ }
21
+
22
+ #[ cfg( not( target_arch = "riscv32" ) ) ]
23
+ read_write_csr_field ! {
24
+ Scause ,
25
+ /// Returns the type of the trap:
26
+ ///
27
+ /// - `true`: an interrupt caused the trap
28
+ /// - `false`: an exception caused the trap
29
+ interrupt: 63 ,
30
+ }
18
31
32
+ #[ cfg( target_arch = "riscv32" ) ]
33
+ read_write_csr_field ! {
34
+ Scause ,
19
35
/// Returns the code field
20
- #[ inline]
21
- pub fn code ( & self ) -> usize {
22
- self . bits & !( 1 << ( usize:: BITS as usize - 1 ) )
23
- }
36
+ code: [ 0 : 30 ] ,
37
+ }
38
+
39
+ #[ cfg( not( target_arch = "riscv32" ) ) ]
40
+ read_write_csr_field ! {
41
+ Scause ,
42
+ /// Returns the code field
43
+ code: [ 0 : 62 ] ,
44
+ }
24
45
46
+ impl Scause {
25
47
/// Returns the trap cause represented by this register.
26
48
///
27
49
/// # Note
@@ -40,25 +62,16 @@ impl Scause {
40
62
/// Is trap cause an interrupt.
41
63
#[ inline]
42
64
pub fn is_interrupt ( & self ) -> bool {
43
- self . bits & ( 1 << ( usize :: BITS as usize - 1 ) ) != 0
65
+ self . interrupt ( )
44
66
}
45
67
46
68
/// Is trap cause an exception.
47
69
#[ inline]
48
70
pub fn is_exception ( & self ) -> bool {
49
- !self . is_interrupt ( )
71
+ !self . interrupt ( )
50
72
}
51
73
}
52
74
53
- read_csr_as ! ( Scause , 0x142 ) ;
54
- write_csr ! ( 0x142 ) ;
55
-
56
- /// Writes the CSR
57
- #[ inline]
58
- pub unsafe fn write ( bits : usize ) {
59
- _write ( bits)
60
- }
61
-
62
75
/// Set supervisor cause register to corresponding cause.
63
76
#[ inline]
64
77
pub unsafe fn set < I : CoreInterruptNumber , E : ExceptionNumber > ( cause : Trap < I , E > ) {
@@ -70,3 +83,58 @@ pub unsafe fn set<I: CoreInterruptNumber, E: ExceptionNumber>(cause: Trap<I, E>)
70
83
} ;
71
84
_write ( bits) ;
72
85
}
86
+
87
+ #[ cfg( test) ]
88
+ mod tests {
89
+ use super :: * ;
90
+
91
+ #[ test]
92
+ fn test_scause ( ) {
93
+ let new_code = 0 ;
94
+ ( 1usize ..=usize:: BITS as usize )
95
+ . map ( |r| ( ( 1u128 << r) - 1 ) as usize )
96
+ . for_each ( |raw| {
97
+ let exp_interrupt = ( raw >> ( usize:: BITS - 1 ) ) != 0 ;
98
+ let exp_code = raw & ( ( 1usize << ( usize:: BITS - 1 ) ) - 1 ) ;
99
+ let exp_cause = if exp_interrupt {
100
+ Trap :: Interrupt ( exp_code)
101
+ } else {
102
+ Trap :: Exception ( exp_code)
103
+ } ;
104
+
105
+ let mut scause = Scause :: from_bits ( raw) ;
106
+
107
+ assert_eq ! ( scause. interrupt( ) , exp_interrupt) ;
108
+ assert_eq ! ( scause. is_interrupt( ) , exp_interrupt) ;
109
+ assert_eq ! ( scause. is_exception( ) , !exp_interrupt) ;
110
+
111
+ assert_eq ! ( scause. code( ) , exp_code) ;
112
+ assert_eq ! ( scause. cause( ) , exp_cause) ;
113
+
114
+ scause. set_interrupt ( !exp_interrupt) ;
115
+
116
+ assert_eq ! ( scause. is_interrupt( ) , !exp_interrupt) ;
117
+ assert_eq ! ( scause. is_exception( ) , exp_interrupt) ;
118
+
119
+ scause. set_code ( new_code) ;
120
+ let new_cause = if scause. interrupt ( ) {
121
+ Trap :: Interrupt ( new_code)
122
+ } else {
123
+ Trap :: Exception ( new_code)
124
+ } ;
125
+
126
+ assert_eq ! ( scause. code( ) , new_code) ;
127
+ assert_eq ! ( scause. cause( ) , new_cause) ;
128
+
129
+ scause. set_code ( exp_code) ;
130
+ let exp_cause = if scause. interrupt ( ) {
131
+ Trap :: Interrupt ( exp_code)
132
+ } else {
133
+ Trap :: Exception ( exp_code)
134
+ } ;
135
+
136
+ assert_eq ! ( scause. code( ) , exp_code) ;
137
+ assert_eq ! ( scause. cause( ) , exp_cause) ;
138
+ } ) ;
139
+ }
140
+ }
0 commit comments