@@ -22,8 +22,34 @@ pub struct RegisterBlock {
22
22
/// Interrupt Active Bit
23
23
pub iabr : [ RO < u32 > ; 16 ] ,
24
24
reserved4 : [ u32 ; 48 ] ,
25
+
26
+ #[ cfg( not( armv6m) ) ]
25
27
/// Interrupt Priority
28
+ ///
29
+ /// On ARMv7-M, 124 word-sized registers are available. Each of those
30
+ /// contains of 4 interrupt priorities of 8 byte each.The architecture
31
+ /// specifically allows accessing those along byte boundaries, so they are
32
+ /// represented as 496 byte-sized registers, for convenience, and to allow
33
+ /// atomic priority updates.
34
+ ///
35
+ /// On ARMv6-M, the registers must only be accessed along word boundaries,
36
+ /// so convenient byte-sized representation wouldn't work on that
37
+ /// architecture.
26
38
pub ipr : [ RW < u8 > ; 496 ] ,
39
+
40
+ #[ cfg( armv6m) ]
41
+ /// Interrupt Priority
42
+ ///
43
+ /// On ARMv7-M, 124 word-sized registers are available. Each of those
44
+ /// contains of 4 interrupt priorities of 8 byte each.The architecture
45
+ /// specifically allows accessing those along byte boundaries, so they are
46
+ /// represented as 496 byte-sized registers, for convenience, and to allow
47
+ /// atomic priority updates.
48
+ ///
49
+ /// On ARMv6-M, the registers must only be accessed along word boundaries,
50
+ /// so convenient byte-sized representation wouldn't work on that
51
+ /// architecture.
52
+ pub ipr : [ RW < u32 > ; 8 ] ,
27
53
}
28
54
29
55
impl RegisterBlock {
@@ -66,9 +92,18 @@ impl RegisterBlock {
66
92
where
67
93
I : Nr ,
68
94
{
69
- let nr = interrupt. nr ( ) ;
70
-
71
- self . ipr [ usize:: from ( nr) ] . read ( )
95
+ #[ cfg( not( armv6m) ) ]
96
+ {
97
+ let nr = interrupt. nr ( ) ;
98
+ self . ipr [ usize:: from ( nr) ] . read ( )
99
+ }
100
+
101
+ #[ cfg( armv6m) ]
102
+ {
103
+ let ipr_n = self . ipr [ Self :: ipr_index ( & interrupt) ] . read ( ) ;
104
+ let prio = ( ipr_n >> Self :: ipr_shift ( & interrupt) ) & 0x000000ff ;
105
+ prio as u8
106
+ }
72
107
}
73
108
74
109
/// Is `interrupt` active or pre-empted and stacked
@@ -118,12 +153,40 @@ impl RegisterBlock {
118
153
///
119
154
/// NOTE See `get_priority` method for an explanation of how NVIC priorities
120
155
/// work.
156
+ ///
157
+ /// On ARMv6-M, updating an interrupt priority requires a read-modify-write
158
+ /// operation, which is not atomic. This is inherently racy, so please
159
+ /// ensure proper access to this method.
160
+ ///
161
+ /// On ARMv7-M, this method is atomic.
121
162
pub unsafe fn set_priority < I > ( & self , interrupt : I , prio : u8 )
122
163
where
123
164
I : Nr ,
124
165
{
125
- let nr = interrupt. nr ( ) ;
166
+ #[ cfg( not( armv6m) ) ]
167
+ {
168
+ let nr = interrupt. nr ( ) ;
169
+ self . ipr [ usize:: from ( nr) ] . write ( prio)
170
+ }
171
+
172
+ #[ cfg( armv6m) ]
173
+ {
174
+ self . ipr [ Self :: ipr_index ( & interrupt) ] . modify ( |value| {
175
+ let mask = 0x000000ff << Self :: ipr_shift ( & interrupt) ;
176
+ let prio = u32:: from ( prio) << Self :: ipr_shift ( & interrupt) ;
177
+
178
+ ( value & !mask) | prio
179
+ } )
180
+ }
181
+ }
182
+
183
+ #[ cfg( armv6m) ]
184
+ fn ipr_index < I > ( interrupt : & I ) -> usize where I : Nr {
185
+ usize:: from ( interrupt. nr ( ) ) / 4
186
+ }
126
187
127
- self . ipr [ usize:: from ( nr) ] . write ( prio)
188
+ #[ cfg( armv6m) ]
189
+ fn ipr_shift < I > ( interrupt : & I ) -> usize where I : Nr {
190
+ ( usize:: from ( interrupt. nr ( ) ) % 4 ) * 8
128
191
}
129
192
}
0 commit comments