11//! Nested Vector Interrupt Controller
2-
3- use volatile_register:: RW ;
4- #[ cfg( not( armv6m) ) ]
5- use volatile_register:: { RO , WO } ;
6-
72use crate :: interrupt:: InterruptNumber ;
83use crate :: peripheral:: NVIC ;
94
10- /// Register block
5+ /// NVIC register block.
6+ #[ derive( derive_mmio:: Mmio ) ]
117#[ repr( C ) ]
128pub struct RegisterBlock {
139 /// Interrupt Set-Enable
14- pub iser : [ RW < u32 > ; 16 ] ,
10+ iser : [ u32 ; 16 ] ,
1511
1612 _reserved0 : [ u32 ; 16 ] ,
1713
1814 /// Interrupt Clear-Enable
19- pub icer : [ RW < u32 > ; 16 ] ,
15+ icer : [ u32 ; 16 ] ,
2016
2117 _reserved1 : [ u32 ; 16 ] ,
2218
2319 /// Interrupt Set-Pending
24- pub ispr : [ RW < u32 > ; 16 ] ,
20+ ispr : [ u32 ; 16 ] ,
2521
2622 _reserved2 : [ u32 ; 16 ] ,
2723
2824 /// Interrupt Clear-Pending
29- pub icpr : [ RW < u32 > ; 16 ] ,
25+ icpr : [ u32 ; 16 ] ,
3026
3127 _reserved3 : [ u32 ; 16 ] ,
3228
3329 /// Interrupt Active Bit (not present on Cortex-M0 variants)
3430 #[ cfg( not( armv6m) ) ]
35- pub iabr : [ RO < u32 > ; 16 ] ,
31+ iabr : [ u32 ; 16 ] ,
3632 #[ cfg( armv6m) ]
3733 _reserved4 : [ u32 ; 16 ] ,
3834
3935 _reserved5 : [ u32 ; 16 ] ,
4036
4137 #[ cfg( armv8m) ]
4238 /// Interrupt Target Non-secure (only present on Arm v8-M)
43- pub itns : [ RW < u32 > ; 16 ] ,
39+ itns : [ u32 ; 16 ] ,
4440 #[ cfg( not( armv8m) ) ]
4541 _reserved6 : [ u32 ; 16 ] ,
4642
@@ -58,7 +54,7 @@ pub struct RegisterBlock {
5854 /// so convenient byte-sized representation wouldn't work on that
5955 /// architecture.
6056 #[ cfg( not( armv6m) ) ]
61- pub ipr : [ RW < u8 > ; 496 ] ,
57+ ipr : [ u32 ; 124 ] ,
6258
6359 /// Interrupt Priority
6460 ///
@@ -72,14 +68,26 @@ pub struct RegisterBlock {
7268 /// so convenient byte-sized representation wouldn't work on that
7369 /// architecture.
7470 #[ cfg( armv6m) ]
75- pub ipr : [ RW < u32 > ; 8 ] ,
71+ ipr : [ u32 ; 8 ] ,
7672
7773 #[ cfg( not( armv6m) ) ]
7874 _reserved8 : [ u32 ; 580 ] ,
7975
8076 /// Software Trigger Interrupt
8177 #[ cfg( not( armv6m) ) ]
82- pub stir : WO < u32 > ,
78+ stir : u32 ,
79+ }
80+
81+ impl RegisterBlock {
82+ /// Creates a new instance of the NVIC register block.
83+ ///
84+ /// # Safety
85+ ///
86+ /// This potentially allows to create multiple instances of the NVIC register block, which
87+ /// might only be valid in certain multi-core environments.
88+ pub const unsafe fn new ( ) -> MmioRegisterBlock < ' static > {
89+ unsafe { RegisterBlock :: new_mmio_at ( 0xE000_E100 ) }
90+ }
8391}
8492
8593impl NVIC {
@@ -100,9 +108,7 @@ impl NVIC {
100108 {
101109 let nr = interrupt. number ( ) ;
102110
103- unsafe {
104- self . stir . write ( u32:: from ( nr) ) ;
105- }
111+ self . write_stir ( u32:: from ( nr) ) ;
106112 }
107113
108114 /// Disables `interrupt`
@@ -113,7 +119,8 @@ impl NVIC {
113119 {
114120 let nr = interrupt. number ( ) ;
115121 // NOTE(unsafe) this is a write to a stateless register
116- unsafe { ( * Self :: PTR ) . icer [ usize:: from ( nr / 32 ) ] . write ( 1 << ( nr % 32 ) ) }
122+ let mut nvic = unsafe { Self :: steal ( ) } ;
123+ nvic. write_icer ( usize:: from ( nr / 32 ) , 1 << ( nr % 32 ) ) . expect ( "invalid interrupt number" ) ;
117124 }
118125
119126 /// Enables `interrupt`
@@ -124,11 +131,10 @@ impl NVIC {
124131 where
125132 I : InterruptNumber ,
126133 {
127- unsafe {
128- let nr = interrupt. number ( ) ;
129- // NOTE(ptr) this is a write to a stateless register
130- ( * Self :: PTR ) . iser [ usize:: from ( nr / 32 ) ] . write ( 1 << ( nr % 32 ) )
131- }
134+ let nr = interrupt. number ( ) ;
135+ // NOTE(ptr) this is a write to a stateless register
136+ let mut nvic = unsafe { Self :: steal ( ) } ;
137+ nvic. write_iser ( usize:: from ( nr / 32 ) , 1 << ( nr % 32 ) ) . expect ( "invalid interrupt number" ) ;
132138 }
133139
134140 /// Returns the NVIC priority of `interrupt`
@@ -144,16 +150,26 @@ impl NVIC {
144150 #[ cfg( not( armv6m) ) ]
145151 {
146152 let nr = interrupt. number ( ) ;
147- // NOTE(unsafe) atomic read with no side effects
148- unsafe { ( * Self :: PTR ) . ipr [ usize:: from ( nr) ] . read ( ) }
153+ // note(unsafe) atomic read with no side effects
154+ let nvic = unsafe { Self :: steal ( ) } ;
155+ let ipr_ptr = nvic. pointer_to_ipr_start ( ) as * const u8 ;
156+ // This should never happen for correct `InterruptNumber` implementations.
157+ if nr >= 124 {
158+ panic ! ( "unexpected interrupt number" ) ;
159+ }
160+ // note(unsafe) atomic read with no side effects
161+ unsafe { core:: ptr:: read_volatile ( ipr_ptr. offset ( nr as isize ) ) }
149162 }
150163
151164 #[ cfg( armv6m) ]
152165 {
153- // NOTE(unsafe) atomic read with no side effects
154- let ipr_n = unsafe { ( * Self :: PTR ) . ipr [ Self :: ipr_index ( interrupt) ] . read ( ) } ;
155- let prio = ( ipr_n >> Self :: ipr_shift ( interrupt) ) & 0x0000_00ff ;
156- prio as u8
166+ // note(unsafe) atomic read with no side effects
167+ let nvic = unsafe { Self :: steal ( ) } ;
168+ let ipr_index = Self :: ipr_index ( ) ;
169+ let iprn_n = nvic
170+ . read_ipr ( Self :: ipr_index ( interrupt) )
171+ . expect ( "unexpected interrupt number" ) ;
172+ let prio = ( ( ipr_n >> Self :: ipr_shift ( interrupt) ) & 0x0000_00ff ) as u8 ;
157173 }
158174 }
159175
@@ -167,8 +183,12 @@ impl NVIC {
167183 let nr = interrupt. number ( ) ;
168184 let mask = 1 << ( nr % 32 ) ;
169185
170- // NOTE(unsafe) atomic read with no side effects
171- unsafe { ( ( * Self :: PTR ) . iabr [ usize:: from ( nr / 32 ) ] . read ( ) & mask) == mask }
186+ // note(unsafe) atomic read with no side effects
187+ let nvic = unsafe { Self :: steal ( ) } ;
188+ nvic. read_iabr ( usize:: from ( nr / 32 ) )
189+ . expect ( "unexpected interrupt number" )
190+ & mask
191+ == mask
172192 }
173193
174194 /// Checks if `interrupt` is enabled
@@ -180,8 +200,12 @@ impl NVIC {
180200 let nr = interrupt. number ( ) ;
181201 let mask = 1 << ( nr % 32 ) ;
182202
183- // NOTE(unsafe) atomic read with no side effects
184- unsafe { ( ( * Self :: PTR ) . iser [ usize:: from ( nr / 32 ) ] . read ( ) & mask) == mask }
203+ // note(unsafe) atomic read with no side effects
204+ let nvic = unsafe { Self :: steal ( ) } ;
205+ nvic. read_iser ( usize:: from ( nr / 32 ) )
206+ . expect ( "unexpected interrupt number" )
207+ & mask
208+ == mask
185209 }
186210
187211 /// Checks if `interrupt` is pending
@@ -193,8 +217,12 @@ impl NVIC {
193217 let nr = interrupt. number ( ) ;
194218 let mask = 1 << ( nr % 32 ) ;
195219
196- // NOTE(unsafe) atomic read with no side effects
197- unsafe { ( ( * Self :: PTR ) . ispr [ usize:: from ( nr / 32 ) ] . read ( ) & mask) == mask }
220+ // note(unsafe) atomic read with no side effects
221+ let nvic = unsafe { Self :: steal ( ) } ;
222+ nvic. read_ispr ( usize:: from ( nr / 32 ) )
223+ . expect ( "unexpected interrupt number" )
224+ & mask
225+ == mask
198226 }
199227
200228 /// Forces `interrupt` into pending state
@@ -206,7 +234,9 @@ impl NVIC {
206234 let nr = interrupt. number ( ) ;
207235
208236 // NOTE(unsafe) atomic stateless write; ICPR doesn't store any state
209- unsafe { ( * Self :: PTR ) . ispr [ usize:: from ( nr / 32 ) ] . write ( 1 << ( nr % 32 ) ) }
237+ let mut nvic = unsafe { Self :: steal ( ) } ;
238+ nvic. write_ispr ( usize:: from ( nr / 32 ) , 1 << ( nr % 32 ) )
239+ . expect ( "unexpected interrupt number" )
210240 }
211241
212242 /// Sets the "priority" of `interrupt` to `prio`
@@ -226,22 +256,31 @@ impl NVIC {
226256 where
227257 I : InterruptNumber ,
228258 {
229- unsafe {
230- #[ cfg( not( armv6m) ) ]
231- {
232- let nr = interrupt. number ( ) ;
233- self . ipr [ usize:: from ( nr) ] . write ( prio)
259+ #[ cfg( not( armv6m) ) ]
260+ {
261+ let nr = interrupt. number ( ) ;
262+ // NOTE(unsafe) atomic stateless write; IPR doesn't store any state
263+ let nvic = unsafe { Self :: steal ( ) } ;
264+ let ipr_ptr = nvic. pointer_to_ipr_start ( ) as * mut u8 ;
265+ // This should never happen for correct `InterruptNumber` implementations.
266+ if nr >= 124 {
267+ panic ! ( "unexpected interrupt number" ) ;
234268 }
269+ // NOTE(unsafe) atomic stateless write; IPR doesn't store any state
270+ unsafe { core:: ptr:: write_volatile ( ipr_ptr. offset ( nr as isize ) , prio) }
271+ }
235272
236- #[ cfg( armv6m) ]
237- {
238- self . ipr [ Self :: ipr_index ( interrupt) ] . modify ( |value| {
239- let mask = 0x0000_00ff << Self :: ipr_shift ( interrupt) ;
240- let prio = u32:: from ( prio) << Self :: ipr_shift ( interrupt) ;
241-
242- ( value & !mask) | prio
243- } )
244- }
273+ #[ cfg( armv6m) ]
274+ {
275+ // NOTE(unsafe) atomic stateless write; IPR doesn't store any state
276+ let nvic = unsafe { Self :: steal ( ) } ;
277+ nvic. modify_ipr ( Self :: ipr_index ( interrupt) , |mut val| {
278+ let mask = 0x0000_00ff << Self :: ipr_shift ( interrupt) ;
279+ let prio = u32:: from ( prio) << Self :: ipr_shift ( interrupt) ;
280+
281+ ( value & !mask) | prio
282+ } )
283+ . expect ( "unexpected interrupt number" ) ;
245284 }
246285 }
247286
@@ -254,7 +293,9 @@ impl NVIC {
254293 let nr = interrupt. number ( ) ;
255294
256295 // NOTE(unsafe) atomic stateless write; ICPR doesn't store any state
257- unsafe { ( * Self :: PTR ) . icpr [ usize:: from ( nr / 32 ) ] . write ( 1 << ( nr % 32 ) ) }
296+ let mut nvic = unsafe { Self :: steal ( ) } ;
297+ nvic. write_icpr ( usize:: from ( nr / 32 ) , 1 << ( nr % 32 ) )
298+ . expect ( "unexpected interrupt number" )
258299 }
259300
260301 #[ cfg( armv6m) ]
0 commit comments