11//! Peripheral definitions for the E310x chip.
2+ //!
23//! This is a simple example of how to use the `riscv-peripheral` crate to generate
34//! peripheral definitions for a target.
45
5- use riscv_pac:: {
6- result:: { Error , Result } ,
7- ExternalInterruptNumber , HartIdNumber , InterruptNumber , PriorityNumber ,
8- } ;
9-
106#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
7+ #[ riscv:: pac_enum( unsafe HartIdNumber ) ]
118pub enum HartId {
129 H0 = 0 ,
1310}
1411
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-
3212#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
33- #[ repr ( usize ) ]
13+ #[ riscv :: pac_enum ( unsafe ExternalInterruptNumber ) ]
3414pub enum Interrupt {
3515 WATCHDOG = 1 ,
3616 RTC = 2 ,
@@ -86,29 +66,8 @@ pub enum Interrupt {
8666 I2C0 = 52 ,
8767}
8868
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-
11069#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
111- #[ repr ( usize ) ]
70+ #[ riscv :: pac_enum ( unsafe PriorityNumber ) ]
11271pub enum Priority {
11372 P0 = 0 ,
11473 P1 = 1 ,
@@ -120,87 +79,30 @@ pub enum Priority {
12079 P7 = 7 ,
12180}
12281
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
15283riscv_peripheral:: clint_codegen!(
84+ pub CLINT ,
15385 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 ]
15788) ;
15889
90+ // We can define PLIC::new() as a private, safe function...
15991riscv_peripheral:: plic_codegen!(
92+ PLIC ,
16093 base 0x0C00_0000 ,
161- ctxs [ ctx0= ( HartId :: H0 , "`H0`" ) ] ,
94+ harts [ HartId :: H0 => 0 ]
16295) ;
16396
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 ( )
203102 }
204103}
205104
206- fn main ( ) { }
105+ fn main ( ) {
106+ let _clint = CLINT :: new ( ) ;
107+ let _plic = unsafe { PLIC :: steal ( ) } ;
108+ }
0 commit comments