@@ -9,7 +9,11 @@ pub const NUM_L1_PAGE_TABLE_ENTRIES: usize = 4096;
99///
1010/// You should create a static variable of this type, to represent your page table.
1111#[ repr( C , align( 1048576 ) ) ]
12+ #[ derive( Debug ) ]
1213pub struct L1Table {
14+ /// Our mutable list of MMU table entries
15+ ///
16+ /// This table is read by the hardware.
1317 pub entries : core:: cell:: UnsafeCell < [ L1Section ; NUM_L1_PAGE_TABLE_ENTRIES ] > ,
1418}
1519
@@ -24,25 +28,39 @@ unsafe impl Sync for L1Table {}
2428pub struct InvalidL1EntryType ( pub L1EntryType ) ;
2529
2630/// Access permissions for a region of memory
27- #[ bitbybit:: bitenum( u3, exhaustive = true ) ]
31+ #[ bitbybit:: bitenum( u3) ]
2832#[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
2933#[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
3034#[ derive( Debug , PartialEq , Eq ) ]
3135pub enum AccessPermissions {
36+ /// All accesses generate Permission faults
3237 PermissionFault = 0b000 ,
38+ /// Privileged access only
3339 PrivilegedOnly = 0b001 ,
40+ /// Writes in User mode generate Permission faults
3441 NoUserWrite = 0b010 ,
42+ /// Full access
3543 FullAccess = 0b011 ,
36- _Reserved1 = 0b100 ,
44+ /// Privileged read-only
3745 PrivilegedReadOnly = 0b101 ,
38- ReadOnly = 0b110 ,
39- _Reserved2 = 0b111 ,
46+ /// Privileged and User read-only (deprecated in VMSAv7)
47+ ReadOnlyv6 = 0b110 ,
48+ /// Privileged and User read-only
49+ ReadOnly = 0b111 ,
4050}
4151
4252impl AccessPermissions {
53+ /// Create a new [`AccessPermissions`] value from the APX bit at the AP bit
54+ /// pair
55+ ///
56+ /// Will panic if you select an invalid value.
4357 #[ inline]
4458 pub const fn new ( apx : bool , ap : u2 ) -> Self {
45- Self :: new_with_raw_value ( u3:: new ( ( ( apx as u8 ) << 2 ) | ap. value ( ) ) )
59+ let x = u3:: new ( ( ( apx as u8 ) << 2 ) | ap. value ( ) ) ;
60+ let Ok ( ap) = Self :: new_with_raw_value ( x) else {
61+ panic ! ( "Invalid access permissions" ) ;
62+ } ;
63+ ap
4664 }
4765
4866 /// AP bit for the given access permission.
@@ -65,21 +83,25 @@ impl AccessPermissions {
6583#[ derive( Debug , PartialEq , Eq ) ]
6684#[ repr( u8 ) ]
6785pub enum L1EntryType {
68- /// Access generates an abort exception. Indicates an unmapped virtual address.
86+ /// Access generates an abort exception. Indicates an unmapped virtual
87+ /// address.
6988 Fault = 0b00 ,
70- /// Entry points to a L2 translation table, allowing 1 MB of memory to be further divided
89+ /// Entry points to a L2 translation table, allowing 1 MB of memory to be
90+ /// further divided
7191 PageTable = 0b01 ,
7292 /// Maps a 1 MB region to a physical address.
7393 Section = 0b10 ,
74- /// Special 1MB section entry which requires 16 entries in the translation table.
94+ /// Special 1MB section entry which requires 16 entries in the translation
95+ /// table.
7596 Supersection = 0b11 ,
7697}
7798
78- /// The ARM Cortex-A architecture reference manual p.1363 specifies these attributes in more detail.
99+ /// The ARM Cortex-A architecture reference manual p.1363 specifies these
100+ /// attributes in more detail.
79101///
80- /// The B (Bufferable), C (Cacheable), and TEX (Type extension) bit names are inherited from
81- /// earlier versions of the architecture. These names no longer adequately describe the function
82- /// of the B, C, and TEX bits.
102+ /// The B (Bufferable), C (Cacheable), and TEX (Type extension) bit names are
103+ /// inherited from earlier versions of the architecture. These names no longer
104+ /// adequately describe the function of the B, C, and TEX bits.
83105#[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
84106#[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
85107#[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
@@ -91,6 +113,7 @@ pub struct MemoryRegionAttributesRaw {
91113}
92114
93115impl MemoryRegionAttributesRaw {
116+ /// Create a new [`MemoryRegionAttributesRaw`] from constituent parts
94117 #[ inline]
95118 pub const fn new ( type_extensions : u3 , c : bool , b : bool ) -> Self {
96119 Self {
@@ -105,11 +128,15 @@ impl MemoryRegionAttributesRaw {
105128#[ bitbybit:: bitenum( u2, exhaustive = true ) ]
106129#[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
107130#[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
108- #[ derive( Debug ) ]
109- pub enum CacheableMemoryAttribute {
131+ #[ derive( Debug , PartialEq , Eq ) ]
132+ pub enum CachePolicy {
133+ /// Non-cacheable
110134 NonCacheable = 0b00 ,
135+ /// Write-Back Cacheable, Write-Allocate
111136 WriteBackWriteAlloc = 0b01 ,
137+ /// Write-Through Cacheable
112138 WriteThroughNoWriteAlloc = 0b10 ,
139+ /// Write-Back Cacheable, no Write-Allocate
113140 WriteBackNoWriteAlloc = 0b11 ,
114141}
115142
@@ -118,20 +145,43 @@ pub enum CacheableMemoryAttribute {
118145#[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
119146#[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
120147pub enum MemoryRegionAttributes {
148+ /// Strongly- ordered
149+ ///
150+ /// All memory accesses to Strongly-ordered memory occur in program order.
151+ /// All Strongly-ordered regions are assumed to be Shareable.
121152 StronglyOrdered ,
153+ /// Device Shareable
154+ ///
155+ /// Intended to handle memory-mapped peripherals that are shared by several
156+ /// processors.
122157 ShareableDevice ,
158+ /// Normal Memory, Write-Through Cacheable for both Inner and Outer Cache
123159 OuterAndInnerWriteThroughNoWriteAlloc ,
160+ /// Normal Memory, Write-Back no Write-Allocate Cacheable for both Inner and
161+ /// Outer Cache
124162 OuterAndInnerWriteBackNoWriteAlloc ,
163+ /// Normal Memory, Non-cacheable for both Inner and Outer Cache
125164 OuterAndInnerNonCacheable ,
165+ /// Normal Memory, Write-Back Write-Allocate Cacheable for both Inner and
166+ /// Outer Cache
126167 OuterAndInnerWriteBackWriteAlloc ,
168+ /// Device Non-Shareable
169+ ///
170+ /// Intended to handle memory-mapped peripherals that are used only by a
171+ /// single processor.
127172 NonShareableDevice ,
173+ /// Normal Memory, where Inner and Outer cache have different settings
128174 CacheableMemory {
129- inner : CacheableMemoryAttribute ,
130- outer : CacheableMemoryAttribute ,
175+ /// Settings for the Inner Cache
176+ inner : CachePolicy ,
177+ /// Settings for the Outer Cache
178+ outer : CachePolicy ,
131179 } ,
132180}
133181
134182impl MemoryRegionAttributes {
183+ /// Convert the Rust enum type [`MemoryRegionAttributes`] into a raw
184+ /// [`MemoryRegionAttributesRaw`] value for the hardware
135185 pub const fn as_raw ( & self ) -> MemoryRegionAttributesRaw {
136186 match self {
137187 MemoryRegionAttributes :: StronglyOrdered => {
@@ -175,10 +225,13 @@ pub struct SectionAttributes {
175225 pub non_global : bool ,
176226 /// Implementation defined bit.
177227 pub p_bit : bool ,
228+ /// Is memory shareable across multiple CPUs
178229 pub shareable : bool ,
179- /// AP bits
230+ /// Access permissions
180231 pub access : AccessPermissions ,
232+ /// Raw memory attributes
181233 pub memory_attrs : MemoryRegionAttributesRaw ,
234+ /// Domain value for this section
182235 pub domain : u4 ,
183236 /// xN bit.
184237 pub execute_never : bool ,
@@ -195,7 +248,8 @@ impl SectionAttributes {
195248 Ok ( Self :: from_raw_unchecked ( raw) )
196249 }
197250
198- /// Retrieves the corresponding L1 section part without the section base address being set.
251+ /// Retrieves the corresponding L1 section part without the section base
252+ /// address being set.
199253 const fn l1_section_part ( & self ) -> L1Section {
200254 L1Section :: builder ( )
201255 . with_base_addr_upper_bits ( u12:: new ( 0 ) )
@@ -231,8 +285,9 @@ impl SectionAttributes {
231285
232286/// 1 MB section translation entry, mapping a 1 MB region to a physical address.
233287///
234- /// The ARM Cortex-A architecture programmers manual chapter 9.4 (p.163) or the ARMv7-A and ArmV7-R
235- /// architecture reference manual p.1323 specify these attributes in more detail.
288+ /// The ARM Cortex-A architecture programmers manual chapter 9.4 (p.163) or the
289+ /// ARMv7-A and ArmV7-R architecture reference manual p.1323 specify these
290+ /// attributes in more detail.
236291#[ bitbybit:: bitfield( u32 , default = 0 , defmt_fields( feature = "defmt" ) ) ]
237292#[ cfg_attr( feature = "serde" , derive( serde:: Serialize , serde:: Deserialize ) ) ]
238293#[ derive( PartialEq , Eq ) ]
@@ -246,23 +301,31 @@ pub struct L1Section {
246301 /// Shareable bit.
247302 #[ bit( 16 , rw) ]
248303 s : bool ,
304+ /// Part of the access permissions field
249305 #[ bit( 15 , rw) ]
250306 apx : bool ,
251- /// Type extension bits.
307+ /// Memory Region Attribute bit
252308 #[ bits( 12 ..=14 , rw) ]
253309 tex : u3 ,
310+ /// Part of the access permissions field
254311 #[ bits( 10 ..=11 , rw) ]
255312 ap : u2 ,
313+ /// Implementation defined bit
256314 #[ bit( 9 , rw) ]
257315 p_bit : bool ,
316+ /// Domain field
258317 #[ bits( 5 ..=8 , rw) ]
259318 domain : u4 ,
319+ /// Execute-never bit
260320 #[ bit( 4 , rw) ]
261321 xn : bool ,
322+ /// Memory Region Attribute bit
262323 #[ bit( 3 , rw) ]
263324 c : bool ,
325+ /// Memory Region Attribute bit
264326 #[ bit( 2 , rw) ]
265327 b : bool ,
328+ /// Entry Type
266329 #[ bits( 0 ..=1 , rw) ]
267330 entry_type : L1EntryType ,
268331}
@@ -287,11 +350,12 @@ impl core::fmt::Debug for L1Section {
287350}
288351
289352impl L1Section {
290- /// Generates a new L1 section from a physical address and section attributes.
353+ /// Generates a new L1 section from a physical address and section
354+ /// attributes.
291355 ///
292- /// The uppermost 12 bits of the physical address define which 1 MB of virtual address space
293- /// are being accessed. They will be stored in the L1 section table. This address MUST be
294- /// aligned to 1 MB.
356+ /// The uppermost 12 bits of the physical address define which 1 MB of
357+ /// virtual address space are being accessed. They will be stored in the L1
358+ /// section table. This address MUST be aligned to 1 MB.
295359 ///
296360 /// # Panics
297361 ///
@@ -316,7 +380,8 @@ impl L1Section {
316380 * self = Self :: new_with_addr_upper_bits_and_attrs ( self . base_addr_upper_bits ( ) , section_attrs)
317381 }
318382
319- /// Create a new L1 section with the given upper 12 bits of the address and section attributes.
383+ /// Create a new L1 section with the given upper 12 bits of the address and
384+ /// section attributes.
320385 #[ inline]
321386 pub const fn new_with_addr_upper_bits_and_attrs (
322387 addr_upper_twelve_bits : u12 ,
@@ -368,8 +433,8 @@ mod tests {
368433 access : AccessPermissions :: FullAccess ,
369434 // TEX 0b101, c false, b true
370435 memory_attrs : MemoryRegionAttributes :: CacheableMemory {
371- inner : CacheableMemoryAttribute :: WriteBackWriteAlloc ,
372- outer : CacheableMemoryAttribute :: WriteBackWriteAlloc ,
436+ inner : CachePolicy :: WriteBackWriteAlloc ,
437+ outer : CachePolicy :: WriteBackWriteAlloc ,
373438 }
374439 . as_raw ( ) ,
375440 domain : u4:: new ( 0b1010 ) ,
@@ -431,7 +496,7 @@ mod tests {
431496 p_bit : true ,
432497 shareable : false ,
433498 // APX true, AP 0b10
434- access : AccessPermissions :: ReadOnly ,
499+ access : AccessPermissions :: ReadOnlyv6 ,
435500 // TEX 0b000, c false, b false
436501 memory_attrs : MemoryRegionAttributes :: StronglyOrdered . as_raw ( ) ,
437502 domain : u4:: new ( 0b1001 ) ,
0 commit comments