Skip to main content

aarch32_rt/
sections.rs

1//! Code to get the memory regions from the linker script
2//!
3//! This is useful if you want to set up the MPU
4
5/// Represents one of the memory regions in the linker script
6#[derive(Debug, Copy, Clone)]
7pub enum Section {
8    /// The .vector_table section
9    ///
10    /// Contains the reset and exception vectors
11    VectorTable,
12    /// The .text section
13    ///
14    /// Contains the executable code
15    Text,
16    /// The .rodata section
17    ///
18    /// Contains read-only static data
19    Rodata,
20    /// The .bss section
21    ///
22    /// Contains zero-initialised static data
23    Bss,
24    /// The .data section
25    ///
26    /// Contains non-zero-initialised static data
27    Data,
28    /// The .uninit section
29    ///
30    /// Contains non-initialised static data
31    Uninit,
32}
33
34impl core::fmt::Display for Section {
35    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
36        f.pad(match self {
37            Section::VectorTable => ".vector_table",
38            Section::Text => ".text",
39            Section::Rodata => ".rodata",
40            Section::Bss => ".bss",
41            Section::Data => ".data",
42            Section::Uninit => ".uninit",
43        })
44    }
45}
46
47impl Section {
48    /// Create an iterator over all the regions
49    pub fn iter() -> impl Iterator<Item = Section> {
50        SectionIter::new()
51    }
52
53    /// Get the highest address of this region
54    ///
55    /// Technically it gets *one past the end* of the region.
56    pub fn top(&self) -> *const u8 {
57        use core::ptr::addr_of;
58        unsafe extern "C" {
59            static __evector: u8;
60            static __etext: u8;
61            static __erodata: u8;
62            static __ebss: u8;
63            static __edata: u8;
64            static __euninit: u8;
65        }
66        match self {
67            Section::VectorTable => addr_of!(__evector),
68            Section::Text => addr_of!(__etext),
69            Section::Rodata => addr_of!(__erodata),
70            Section::Bss => addr_of!(__ebss),
71            Section::Data => addr_of!(__edata),
72            Section::Uninit => addr_of!(__euninit),
73        }
74    }
75
76    /// Get the lowest address of this region
77    pub fn bottom(&self) -> *const u8 {
78        use core::ptr::addr_of;
79        unsafe extern "C" {
80            static __svector: u8;
81            static __stext: u8;
82            static __srodata: u8;
83            static __sbss: u8;
84            static __sdata: u8;
85            static __suninit: u8;
86        }
87        match self {
88            Section::VectorTable => addr_of!(__svector),
89            Section::Text => addr_of!(__stext),
90            Section::Rodata => addr_of!(__srodata),
91            Section::Bss => addr_of!(__sbss),
92            Section::Data => addr_of!(__sdata),
93            Section::Uninit => addr_of!(__suninit),
94        }
95    }
96
97    /// Get the range of this region.
98    pub fn range(&self) -> Option<core::ops::Range<*const u8>> {
99        let bottom = self.bottom();
100        let top = self.top();
101        if bottom != top {
102            Some(bottom..top)
103        } else {
104            None
105        }
106    }
107
108    /// Get the inclusive range of this region.
109    ///
110    /// This is the range you need to give to the PMSAv8 MPU code.
111    pub fn mpu_range(&self) -> Option<core::ops::RangeInclusive<*const u8>> {
112        let bottom = self.bottom();
113        let top = self.top();
114        let top_under = unsafe { top.offset(-1) };
115        if bottom != top {
116            Some(bottom..=top_under)
117        } else {
118            None
119        }
120    }
121}
122
123/// Iterator over all the [`Region`] variants
124pub struct SectionIter {
125    next: Option<Section>,
126}
127
128impl SectionIter {
129    /// Create a new [`RegionIter`]
130    pub fn new() -> Self {
131        Self {
132            next: Some(Section::VectorTable),
133        }
134    }
135}
136
137impl Default for SectionIter {
138    fn default() -> Self {
139        SectionIter::new()
140    }
141}
142
143impl Iterator for SectionIter {
144    type Item = Section;
145
146    fn next(&mut self) -> Option<Self::Item> {
147        let current = self.next;
148        self.next = match self.next {
149            Some(Section::VectorTable) => Some(Section::Text),
150            Some(Section::Text) => Some(Section::Rodata),
151            Some(Section::Rodata) => Some(Section::Bss),
152            Some(Section::Bss) => Some(Section::Data),
153            Some(Section::Data) => Some(Section::Uninit),
154            Some(Section::Uninit) | None => None,
155        };
156        current
157    }
158}