#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub struct MemoryLayout {
pub regions: &'static [MemoryRegion],
}
impl MemoryLayout {
pub const fn find(&self, name: &str) -> Option<&MemoryRegion> {
let mut i = 0;
while i < self.regions.len() {
if str_eq(self.regions[i].name, name) {
return Some(&self.regions[i]);
}
i += 1;
}
None
}
pub const fn find_by_role(&self, role: MemoryRole) -> Option<&MemoryRegion> {
let mut i = 0;
while i < self.regions.len() {
if self.regions[i].role as u8 == role as u8 {
return Some(&self.regions[i]);
}
i += 1;
}
None
}
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct MemoryRegion {
pub name: &'static str,
pub kind: MemoryRegionKind,
pub role: MemoryRole,
pub address: u32,
pub size: u32,
pub modes: &'static [Mode],
pub access: Option<Access>,
}
impl MemoryRegion {
pub const fn page_program_size(&self) -> Option<u32> {
let mut i = 0;
while i < self.modes.len() {
if let Mode::Fast { page_size, .. } = self.modes[i] {
return Some(page_size);
}
i += 1;
}
None
}
pub const fn fast_load_size(&self) -> Option<u32> {
let mut i = 0;
while i < self.modes.len() {
if let Mode::Fast { load_size, .. } = self.modes[i] {
return Some(load_size);
}
i += 1;
}
None
}
pub const fn erase_size(&self) -> Option<u32> {
let mut i = 0;
while i < self.modes.len() {
if let Mode::Standard { erase_size, .. } = self.modes[i] {
return Some(erase_size);
}
i += 1;
}
None
}
pub const fn write_size(&self) -> Option<u32> {
let mut i = 0;
while i < self.modes.len() {
if let Mode::Standard { write_size, .. } = self.modes[i] {
return Some(write_size);
}
i += 1;
}
None
}
pub const fn end(&self) -> u32 {
self.address + self.size
}
pub const fn contains(&self, addr: u32) -> bool {
addr >= self.address && addr < self.end()
}
pub const fn readable(&self) -> bool {
match &self.access {
Some(a) => a.read,
None => true,
}
}
pub const fn writable(&self) -> bool {
match &self.access {
Some(a) => a.write,
None => true,
}
}
pub const fn executable(&self) -> bool {
match &self.access {
Some(a) => a.execute,
None => true,
}
}
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
#[repr(u8)]
#[non_exhaustive]
pub enum MemoryRole {
Application,
System,
OptionBytes,
Vendor,
Ram,
Tcm,
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum Mode {
Fast { page_size: u32, load_size: u32 },
Standard { erase_size: u32, write_size: u32 },
}
impl Mode {
pub const fn is_fast(&self) -> bool {
matches!(self, Mode::Fast { .. })
}
pub const fn is_standard(&self) -> bool {
matches!(self, Mode::Standard { .. })
}
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Access {
pub read: bool,
pub write: bool,
pub execute: bool,
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum MemoryRegionKind {
Flash,
Ram,
}
const fn str_eq(a: &str, b: &str) -> bool {
let a = a.as_bytes();
let b = b.as_bytes();
if a.len() != b.len() {
return false;
}
let mut i = 0;
while i < a.len() {
if a[i] != b[i] {
return false;
}
i += 1;
}
true
}