1
1
use arbitrary_int:: { u12, u2, u3, u4} ;
2
2
3
- #[ derive( Debug , Copy , Clone ) ]
4
- #[ repr( u8 ) ]
3
+ #[ derive( Debug , thiserror:: Error ) ]
4
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
5
+ #[ error( "invalid L1 entry type {0:?}" ) ]
6
+ pub struct InvalidL1EntryType ( pub L1EntryType ) ;
7
+
8
+ #[ bitbybit:: bitenum( u3, exhaustive = true ) ]
9
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
10
+ #[ derive( Debug ) ]
5
11
pub enum AccessPermissions {
6
12
PermissionFault = 0b000 ,
7
13
PrivilegedOnly = 0b001 ,
@@ -14,18 +20,23 @@ pub enum AccessPermissions {
14
20
}
15
21
16
22
impl AccessPermissions {
17
- const fn ap ( & self ) -> u8 {
23
+ /// AP bit for the given access permission.
24
+ #[ inline]
25
+ pub const fn ap ( & self ) -> u8 {
18
26
( * self as u8 ) & 0b11
19
27
}
20
28
21
- const fn apx ( & self ) -> bool {
29
+ /// APX bit for the given access permission.
30
+ #[ inline]
31
+ pub const fn apx ( & self ) -> bool {
22
32
( * self as u8 ) > ( AccessPermissions :: FullAccess as u8 )
23
33
}
24
34
}
25
35
26
- #[ derive( Debug ) ]
27
- #[ repr( u8 ) ]
28
36
#[ bitbybit:: bitenum( u2, exhaustive = true ) ]
37
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
38
+ #[ derive( Debug , PartialEq , Eq ) ]
39
+ #[ repr( u8 ) ]
29
40
pub enum L1EntryType {
30
41
/// Access generates an abort exception. Indicates an unmapped virtual address.
31
42
Fault = 0b00 ,
@@ -43,15 +54,17 @@ pub enum L1EntryType {
43
54
/// earlier versions of the architecture. These names no longer adequately describe the function
44
55
/// of the B, C, and TEX bits.
45
56
#[ derive( Debug , Copy , Clone ) ]
57
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
46
58
pub struct MemoryRegionAttributesRaw {
47
59
/// TEX bits
48
- type_extensions : u8 ,
60
+ type_extensions : u3 ,
49
61
c : bool ,
50
62
b : bool ,
51
63
}
52
64
53
65
impl MemoryRegionAttributesRaw {
54
- pub const fn new ( type_extensions : u8 , c : bool , b : bool ) -> Self {
66
+ #[ inline]
67
+ pub const fn new ( type_extensions : u3 , c : bool , b : bool ) -> Self {
55
68
Self {
56
69
type_extensions,
57
70
c,
@@ -60,7 +73,9 @@ impl MemoryRegionAttributesRaw {
60
73
}
61
74
}
62
75
63
- #[ derive( Debug , Copy , Clone ) ]
76
+ #[ bitbybit:: bitenum( u2, exhaustive = true ) ]
77
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
78
+ #[ derive( Debug ) ]
64
79
pub enum CacheableMemoryAttribute {
65
80
NonCacheable = 0b00 ,
66
81
WriteBackWriteAlloc = 0b01 ,
@@ -69,6 +84,7 @@ pub enum CacheableMemoryAttribute {
69
84
}
70
85
71
86
#[ derive( Debug , Copy , Clone ) ]
87
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
72
88
pub enum MemoryRegionAttributes {
73
89
StronglyOrdered ,
74
90
ShareableDevice ,
@@ -87,29 +103,29 @@ impl MemoryRegionAttributes {
87
103
pub const fn as_raw ( & self ) -> MemoryRegionAttributesRaw {
88
104
match self {
89
105
MemoryRegionAttributes :: StronglyOrdered => {
90
- MemoryRegionAttributesRaw :: new ( 0b000 , false , false )
106
+ MemoryRegionAttributesRaw :: new ( u3 :: new ( 0b000 ) , false , false )
91
107
}
92
108
MemoryRegionAttributes :: ShareableDevice => {
93
- MemoryRegionAttributesRaw :: new ( 0b000 , false , true )
109
+ MemoryRegionAttributesRaw :: new ( u3 :: new ( 0b000 ) , false , true )
94
110
}
95
111
MemoryRegionAttributes :: OuterAndInnerWriteThroughNoWriteAlloc => {
96
- MemoryRegionAttributesRaw :: new ( 0b000 , true , false )
112
+ MemoryRegionAttributesRaw :: new ( u3 :: new ( 0b000 ) , true , false )
97
113
}
98
114
MemoryRegionAttributes :: OuterAndInnerWriteBackNoWriteAlloc => {
99
- MemoryRegionAttributesRaw :: new ( 0b000 , true , true )
115
+ MemoryRegionAttributesRaw :: new ( u3 :: new ( 0b000 ) , true , true )
100
116
}
101
117
MemoryRegionAttributes :: OuterAndInnerNonCacheable => {
102
- MemoryRegionAttributesRaw :: new ( 0b001 , false , false )
118
+ MemoryRegionAttributesRaw :: new ( u3 :: new ( 0b001 ) , false , false )
103
119
}
104
120
MemoryRegionAttributes :: OuterAndInnerWriteBackWriteAlloc => {
105
- MemoryRegionAttributesRaw :: new ( 0b001 , true , true )
121
+ MemoryRegionAttributesRaw :: new ( u3 :: new ( 0b001 ) , true , true )
106
122
}
107
123
MemoryRegionAttributes :: NonShareableDevice => {
108
- MemoryRegionAttributesRaw :: new ( 0b010 , false , false )
124
+ MemoryRegionAttributesRaw :: new ( u3 :: new ( 0b010 ) , false , false )
109
125
}
110
126
MemoryRegionAttributes :: CacheableMemory { inner, outer } => {
111
127
MemoryRegionAttributesRaw :: new (
112
- ( 1 << 2 ) | ( * outer as u8 ) ,
128
+ u3 :: new ( ( 1 << 2 ) | ( outer. raw_value ( ) . value ( ) ) ) ,
113
129
( * inner as u8 & 0b10 ) != 0 ,
114
130
( * inner as u8 & 0b01 ) != 0 ,
115
131
)
@@ -118,7 +134,9 @@ impl MemoryRegionAttributes {
118
134
}
119
135
}
120
136
137
+ /// Individual section attributes for a L1 section.
121
138
#[ derive( Debug , Copy , Clone ) ]
139
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
122
140
pub struct SectionAttributes {
123
141
/// NG bit
124
142
pub non_global : bool ,
@@ -128,16 +146,65 @@ pub struct SectionAttributes {
128
146
/// AP bits
129
147
pub access : AccessPermissions ,
130
148
pub memory_attrs : MemoryRegionAttributesRaw ,
131
- pub domain : u8 ,
149
+ pub domain : u4 ,
132
150
/// xN bit.
133
151
pub execute_never : bool ,
134
152
}
135
153
154
+ impl SectionAttributes {
155
+ /// Lower 18 bits of the L1 section entry.
156
+ #[ inline]
157
+ pub const fn raw ( & self ) -> u32 {
158
+ ( ( self . non_global as u32 ) << 17 )
159
+ | ( ( self . shareable as u32 ) << 16 )
160
+ | ( ( self . access . apx ( ) as u32 ) << 15 )
161
+ | ( ( self . memory_attrs . type_extensions . value ( ) as u32 ) << 12 )
162
+ | ( ( self . access . ap ( ) as u32 ) << 10 )
163
+ | ( ( self . p_bit as u32 ) << 9 )
164
+ | ( ( self . domain . value ( ) as u32 ) << 5 )
165
+ | ( ( self . execute_never as u32 ) << 4 )
166
+ | ( ( self . memory_attrs . c as u32 ) << 3 )
167
+ | ( ( self . memory_attrs . b as u32 ) << 2 )
168
+ | L1EntryType :: Section as u32
169
+ }
170
+
171
+ /// Extract the section attributes from a raw L1 section entry.
172
+ #[ inline]
173
+ pub fn from_raw ( raw : u32 ) -> Result < Self , InvalidL1EntryType > {
174
+ let section_type = L1EntryType :: new_with_raw_value ( u2:: new ( ( raw & 0b11 ) as u8 ) ) ;
175
+ if section_type != L1EntryType :: Section {
176
+ return Err ( InvalidL1EntryType ( section_type) ) ;
177
+ }
178
+ Ok ( Self :: from_raw_unchecked ( raw) )
179
+ }
180
+
181
+ /// Extract the section attributes without checking the entry type bits.
182
+ #[ inline]
183
+ pub const fn from_raw_unchecked ( raw : u32 ) -> Self {
184
+ Self {
185
+ non_global : ( raw >> 17 ) & 0x1 != 0 ,
186
+ shareable : ( raw >> 16 ) & 0x1 != 0 ,
187
+ p_bit : ( raw >> 9 ) & 0x1 != 0 ,
188
+ access : AccessPermissions :: new_with_raw_value ( u3:: new (
189
+ ( ( ( ( raw >> 15 ) & 0b1 ) as u8 ) << 2 ) | ( ( ( raw >> 10 ) & 0b11 ) as u8 ) ,
190
+ ) ) ,
191
+ memory_attrs : MemoryRegionAttributesRaw :: new (
192
+ u3:: new ( ( ( raw >> 12 ) & 0b111 ) as u8 ) ,
193
+ ( ( raw >> 3 ) & 0b1 ) != 0 ,
194
+ ( ( raw >> 2 ) & 0b1 ) as u8 != 0 ,
195
+ ) ,
196
+ domain : u4:: new ( ( ( raw >> 5 ) & 0b1111 ) as u8 ) ,
197
+ execute_never : ( ( raw >> 4 ) & 0b1 ) != 0 ,
198
+ }
199
+ }
200
+ }
201
+
136
202
/// 1 MB section translation entry, mapping a 1 MB region to a physical address.
137
203
///
138
204
/// The ARM Cortex-A architecture programmers manual chapter 9.4 (p.163) specifies these attributes
139
205
/// in more detail.
140
206
#[ bitbybit:: bitfield( u32 ) ]
207
+ #[ derive( PartialEq , Eq ) ]
141
208
pub struct L1Section {
142
209
/// Section base address.
143
210
#[ bits( 20 ..=31 , rw) ]
@@ -204,18 +271,6 @@ impl L1Section {
204
271
panic ! ( "physical base address for L1 section must be aligned to 1 MB" ) ;
205
272
}
206
273
let higher_bits = phys_addr >> 20 ;
207
- let raw = ( higher_bits << 20 )
208
- | ( ( section_attrs. non_global as u32 ) << 17 )
209
- | ( ( section_attrs. shareable as u32 ) << 16 )
210
- | ( ( section_attrs. access . apx ( ) as u32 ) << 15 )
211
- | ( ( section_attrs. memory_attrs . type_extensions as u32 ) << 12 )
212
- | ( ( section_attrs. access . ap ( ) as u32 ) << 10 )
213
- | ( ( section_attrs. p_bit as u32 ) << 9 )
214
- | ( ( section_attrs. domain as u32 ) << 5 )
215
- | ( ( section_attrs. execute_never as u32 ) << 4 )
216
- | ( ( section_attrs. memory_attrs . c as u32 ) << 3 )
217
- | ( ( section_attrs. memory_attrs . b as u32 ) << 2 )
218
- | L1EntryType :: Section as u32 ;
219
- Self :: new_with_raw_value ( raw)
274
+ Self :: new_with_raw_value ( ( higher_bits << 20 ) | section_attrs. raw ( ) )
220
275
}
221
276
}
0 commit comments