1
1
//! Peripheral definitions for the E310x chip.
2
+ //!
2
3
//! This is a simple example of how to use the `riscv-peripheral` crate to generate
3
4
//! peripheral definitions for a target.
4
5
5
- use riscv_pac:: {
6
- result:: { Error , Result } ,
7
- ExternalInterruptNumber , HartIdNumber , InterruptNumber , PriorityNumber ,
8
- } ;
9
-
10
6
#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
7
+ #[ riscv:: pac_enum( unsafe HartIdNumber ) ]
11
8
pub enum HartId {
12
9
H0 = 0 ,
13
10
}
14
11
15
- unsafe impl HartIdNumber for HartId {
16
- const MAX_HART_ID_NUMBER : usize = Self :: H0 as usize ;
17
-
18
- #[ inline]
19
- fn number ( self ) -> usize {
20
- self as _
21
- }
22
-
23
- #[ inline]
24
- fn from_number ( number : usize ) -> Result < Self > {
25
- match number {
26
- 0 => Ok ( Self :: H0 ) ,
27
- _ => Err ( Error :: InvalidVariant ( number) ) ,
28
- }
29
- }
30
- }
31
-
32
12
#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
33
- #[ repr ( usize ) ]
13
+ #[ riscv :: pac_enum ( unsafe ExternalInterruptNumber ) ]
34
14
pub enum Interrupt {
35
15
WATCHDOG = 1 ,
36
16
RTC = 2 ,
@@ -86,29 +66,8 @@ pub enum Interrupt {
86
66
I2C0 = 52 ,
87
67
}
88
68
89
- unsafe impl InterruptNumber for Interrupt {
90
- const MAX_INTERRUPT_NUMBER : usize = Self :: I2C0 as usize ;
91
-
92
- #[ inline]
93
- fn number ( self ) -> usize {
94
- self as _
95
- }
96
-
97
- #[ inline]
98
- fn from_number ( number : usize ) -> Result < Self > {
99
- if number == 0 || number > Self :: MAX_INTERRUPT_NUMBER {
100
- Err ( Error :: InvalidVariant ( number) )
101
- } else {
102
- // SAFETY: valid interrupt number
103
- Ok ( unsafe { core:: mem:: transmute :: < usize , Interrupt > ( number) } )
104
- }
105
- }
106
- }
107
-
108
- unsafe impl ExternalInterruptNumber for Interrupt { }
109
-
110
69
#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
111
- #[ repr ( usize ) ]
70
+ #[ riscv :: pac_enum ( unsafe PriorityNumber ) ]
112
71
pub enum Priority {
113
72
P0 = 0 ,
114
73
P1 = 1 ,
@@ -120,87 +79,30 @@ pub enum Priority {
120
79
P7 = 7 ,
121
80
}
122
81
123
- unsafe impl PriorityNumber for Priority {
124
- const MAX_PRIORITY_NUMBER : usize = Self :: P7 as usize ;
125
-
126
- #[ inline]
127
- fn number ( self ) -> usize {
128
- self as _
129
- }
130
-
131
- #[ inline]
132
- fn from_number ( number : usize ) -> Result < Self > {
133
- if number > Self :: MAX_PRIORITY_NUMBER {
134
- Err ( Error :: InvalidVariant ( number) )
135
- } else {
136
- // SAFETY: valid priority number
137
- Ok ( unsafe { core:: mem:: transmute :: < usize , Priority > ( number) } )
138
- }
139
- }
140
- }
141
-
142
- #[ cfg( feature = "aclint-hal-async" ) ]
143
- riscv_peripheral:: clint_codegen!(
144
- base 0x0200_0000 ,
145
- freq 32_768 ,
146
- async_delay,
147
- mtimecmps [ mtimecmp0=( HartId :: H0 , "`H0`" ) ] ,
148
- msips [ msip0=( HartId :: H0 , "`H0`" ) ] ,
149
- ) ;
150
-
151
- #[ cfg( not( feature = "aclint-hal-async" ) ) ]
82
+ // We can define CLINT::new() as a public, safe function
152
83
riscv_peripheral:: clint_codegen!(
84
+ pub CLINT ,
153
85
base 0x0200_0000 ,
154
- freq 32_768 ,
155
- mtimecmps [ mtimecmp0=( HartId :: H0 , "`H0`" ) ] ,
156
- msips [ msip0=( HartId :: H0 , "`H0`" ) ] ,
86
+ mtime_freq 32_768 ,
87
+ harts [ HartId :: H0 => 0 ]
157
88
) ;
158
89
90
+ // We can define PLIC::new() as a private, safe function...
159
91
riscv_peripheral:: plic_codegen!(
92
+ PLIC ,
160
93
base 0x0C00_0000 ,
161
- ctxs [ ctx0= ( HartId :: H0 , "`H0`" ) ] ,
94
+ harts [ HartId :: H0 => 0 ]
162
95
) ;
163
96
164
- #[ cfg( feature = "aclint-hal-async" ) ]
165
- /// extern functions needed by the `riscv-peripheral` crate for the `async` feature.
166
- ///
167
- /// # Note
168
- ///
169
- /// The functionality in this module is just to illustrate how to enable the `async` feature
170
- /// The timer queue used here, while functional, is unsound and should not be used in production.
171
- /// In this case, you should protect the timer queue with a mutex or critical section.
172
- /// For a more robust implementation, use proper timer queues such as the ones provided by `embassy-time`
173
- mod async_no_mangle {
174
- use super :: CLINT ;
175
- use heapless:: binary_heap:: { BinaryHeap , Min } ;
176
- use riscv_peripheral:: { aclint:: mtimer:: MTIMER , hal_async:: aclint:: Timer } ;
177
-
178
- const N_TIMERS : usize = 16 ;
179
- static mut TIMER_QUEUE : BinaryHeap < Timer , Min , N_TIMERS > = BinaryHeap :: new ( ) ;
180
-
181
- #[ no_mangle]
182
- fn _riscv_peripheral_aclint_mtimer ( ) -> MTIMER {
183
- CLINT :: mtimer ( )
184
- }
185
-
186
- #[ no_mangle]
187
- fn _riscv_peripheral_aclint_push_timer ( t : Timer ) -> Result < ( ) , Timer > {
188
- unsafe { TIMER_QUEUE . push ( t) }
189
- }
190
-
191
- #[ no_mangle]
192
- fn _riscv_peripheral_aclint_wake_timers ( current_tick : u64 ) -> Option < u64 > {
193
- let mut next_expires = None ;
194
- while let Some ( t) = unsafe { TIMER_QUEUE . peek ( ) } {
195
- if t. expires ( ) > current_tick {
196
- next_expires = Some ( t. expires ( ) ) ;
197
- break ;
198
- }
199
- let t = unsafe { TIMER_QUEUE . pop ( ) } . unwrap ( ) ;
200
- t. waker ( ) . wake_by_ref ( ) ;
201
- }
202
- next_expires
97
+ // ... and then implement a public, unsafe function to steal the PLIC instance
98
+ // Usually, this function is implemented by svd2rust, but we do it manually here
99
+ impl PLIC {
100
+ pub unsafe fn steal ( ) -> Self {
101
+ PLIC :: new ( )
203
102
}
204
103
}
205
104
206
- fn main ( ) { }
105
+ fn main ( ) {
106
+ let _clint = CLINT :: new ( ) ;
107
+ let _plic = unsafe { PLIC :: steal ( ) } ;
108
+ }
0 commit comments