@@ -15,19 +15,10 @@ pub fn render(
15
15
) -> Result < TokenStream > {
16
16
let mut mod_items = TokenStream :: new ( ) ;
17
17
18
- let external_interrupts = peripherals
19
- . iter ( )
20
- . flat_map ( |p| p. interrupt . iter ( ) )
21
- . map ( |i| ( i. value , i) )
22
- . collect :: < HashMap < _ , _ > > ( ) ;
23
- let mut external_interrupts = external_interrupts. into_values ( ) . collect :: < Vec < _ > > ( ) ;
24
- external_interrupts. sort_by_key ( |i| i. value ) ;
25
- if !external_interrupts. is_empty ( ) {
26
- writeln ! ( device_x, "/* External interrupt sources */" ) ?;
27
- mod_items. extend ( quote ! { pub use riscv_pac:: ExternalInterruptNumber ; } ) ;
28
-
18
+ if !r. core_interrupts . is_empty ( ) {
19
+ writeln ! ( device_x, "/* Core interrupt sources and trap handlers */" ) ?;
29
20
let mut interrupts = vec ! [ ] ;
30
- for i in external_interrupts . iter ( ) {
21
+ for i in r . core_interrupts . iter ( ) {
31
22
let name = TokenStream :: from_str ( & i. name ) . unwrap ( ) ;
32
23
let value = TokenStream :: from_str ( & format ! ( "{}" , i. value) ) . unwrap ( ) ;
33
24
let description = format ! (
@@ -42,29 +33,43 @@ pub fn render(
42
33
) ;
43
34
44
35
writeln ! ( device_x, "PROVIDE({name} = DefaultHandler);" ) ?;
36
+ writeln ! (
37
+ device_x,
38
+ "PROVIDE(_start_{name}_trap = _start_DefaultHandler_trap);"
39
+ ) ?;
45
40
46
41
interrupts. push ( quote ! {
47
42
#[ doc = #description]
48
43
#name = #value,
49
- } )
44
+ } ) ;
50
45
}
51
46
mod_items. extend ( quote ! {
52
- /// External interrupts. These interrupts are handled by the external peripherals.
53
- #[ repr( usize ) ]
54
- #[ riscv_pac:: pac_enum( unsafe ExternalInterruptNumber ) ]
47
+ /// Core interrupts. These interrupts are handled by the core itself.
48
+ #[ riscv:: pac_enum( unsafe CoreInterruptNumber ) ]
55
49
#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
56
- pub enum ExternalInterrupt {
50
+ pub enum CoreInterrupt {
57
51
#( #interrupts) *
58
52
}
59
53
} ) ;
54
+ } else {
55
+ // when no interrupts are defined, we re-export the standard riscv interrupts
56
+ mod_items. extend ( quote ! { pub use riscv:: interrupt:: Interrupt as CoreInterrupt ; } ) ;
60
57
}
61
58
62
- if !r. core_interrupts . is_empty ( ) {
63
- writeln ! ( device_x, "/* Core interrupt sources and trap handlers */" ) ?;
64
- mod_items. extend ( quote ! { pub use riscv_pac:: CoreInterruptNumber ; } ) ;
59
+ // TODO something similar to core interrupts but for exceptions
60
+ mod_items. extend ( quote ! { pub use riscv:: interrupt:: Exception ; } ) ;
65
61
62
+ let external_interrupts = peripherals
63
+ . iter ( )
64
+ . flat_map ( |p| p. interrupt . iter ( ) )
65
+ . map ( |i| ( i. value , i) )
66
+ . collect :: < HashMap < _ , _ > > ( ) ;
67
+ let mut external_interrupts = external_interrupts. into_values ( ) . collect :: < Vec < _ > > ( ) ;
68
+ external_interrupts. sort_by_key ( |i| i. value ) ;
69
+ if !external_interrupts. is_empty ( ) {
70
+ writeln ! ( device_x, "/* External interrupt sources */" ) ?;
66
71
let mut interrupts = vec ! [ ] ;
67
- for i in r . core_interrupts . iter ( ) {
72
+ for i in external_interrupts . iter ( ) {
68
73
let name = TokenStream :: from_str ( & i. name ) . unwrap ( ) ;
69
74
let value = TokenStream :: from_str ( & format ! ( "{}" , i. value) ) . unwrap ( ) ;
70
75
let description = format ! (
@@ -79,29 +84,23 @@ pub fn render(
79
84
) ;
80
85
81
86
writeln ! ( device_x, "PROVIDE({name} = DefaultHandler);" ) ?;
82
- writeln ! (
83
- device_x,
84
- "PROVIDE(_start_{name}_trap = _start_DefaultHandler_trap);"
85
- ) ?;
86
87
87
88
interrupts. push ( quote ! {
88
89
#[ doc = #description]
89
90
#name = #value,
90
- } ) ;
91
+ } )
91
92
}
92
93
mod_items. extend ( quote ! {
93
- /// Core interrupts. These interrupts are handled by the core itself.
94
- #[ repr( usize ) ]
95
- #[ riscv_pac:: pac_enum( unsafe CoreInterruptNumber ) ]
94
+ /// External interrupts. These interrupts are handled by the external peripherals.
95
+ #[ riscv:: pac_enum( unsafe ExternalInterruptNumber ) ]
96
96
#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
97
- pub enum CoreInterrupt {
97
+ pub enum ExternalInterrupt {
98
98
#( #interrupts) *
99
99
}
100
100
} ) ;
101
101
}
102
102
103
103
if !r. priorities . is_empty ( ) {
104
- mod_items. extend ( quote ! { pub use riscv_pac:: PriorityNumber ; } ) ;
105
104
let priorities = r. priorities . iter ( ) . map ( |p| {
106
105
let name = TokenStream :: from_str ( & p. name ) . unwrap ( ) ;
107
106
let value = TokenStream :: from_str ( & format ! ( "{}" , p. value) ) . unwrap ( ) ;
@@ -123,8 +122,7 @@ pub fn render(
123
122
} ) ;
124
123
mod_items. extend ( quote ! {
125
124
/// Priority levels in the device
126
- #[ repr( u8 ) ]
127
- #[ riscv_pac:: pac_enum( unsafe PriorityNumber ) ]
125
+ #[ riscv:: pac_enum( unsafe PriorityNumber ) ]
128
126
#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
129
127
pub enum Priority {
130
128
#( #priorities) *
@@ -133,7 +131,6 @@ pub fn render(
133
131
}
134
132
135
133
if !r. harts . is_empty ( ) {
136
- mod_items. extend ( quote ! { pub use riscv_pac:: HartIdNumber ; } ) ;
137
134
let harts = r. harts . iter ( ) . map ( |h| {
138
135
let name = TokenStream :: from_str ( & h. name ) . unwrap ( ) ;
139
136
let value = TokenStream :: from_str ( & format ! ( "{}" , h. value) ) . unwrap ( ) ;
@@ -155,15 +152,39 @@ pub fn render(
155
152
} ) ;
156
153
mod_items. extend ( quote ! {
157
154
/// HARTs in the device
158
- #[ repr( u16 ) ]
159
- #[ riscv_pac:: pac_enum( unsafe HartIdNumber ) ]
155
+ #[ riscv:: pac_enum( unsafe HartIdNumber ) ]
160
156
#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
161
157
pub enum Hart {
162
158
#( #harts) *
163
159
}
164
160
} ) ;
165
161
}
166
162
163
+ mod_items. extend ( quote ! {
164
+ pub use riscv:: {
165
+ CoreInterruptNumber , ExceptionNumber , PriorityNumber , HartIdNumber ,
166
+ interrupt:: { enable, disable, free, nested}
167
+ } ;
168
+
169
+ pub type Trap = riscv:: interrupt:: Trap <CoreInterrupt , Exception >;
170
+
171
+ /// Retrieves the cause of a trap in the current hart.
172
+ ///
173
+ /// If the raw cause is not a valid interrupt or exception for the target, it returns an error.
174
+ #[ inline]
175
+ pub fn try_cause( ) -> riscv:: result:: Result <Trap > {
176
+ riscv:: interrupt:: try_cause( )
177
+ }
178
+
179
+ /// Retrieves the cause of a trap in the current hart (machine mode).
180
+ ///
181
+ /// If the raw cause is not a valid interrupt or exception for the target, it panics.
182
+ #[ inline]
183
+ pub fn cause( ) -> Trap {
184
+ try_cause( ) . unwrap( )
185
+ }
186
+ } ) ;
187
+
167
188
Ok ( quote ! {
168
189
/// Interrupt numbers, priority levels, and HART IDs.
169
190
pub mod interrupt {
0 commit comments