1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
bitflags! {
    pub struct Access: u8 {
        const R = 0b00000001;
        const W = 0b00000010;
        const X = 0b00000100;
        const RW = Self::R.bits | Self::W.bits;
        const RX = Self::R.bits | Self::X.bits;
    }
}

pub const PROGRAM_PAGE_WEIGHT: f32 = 0.130;
pub const ERASE_SECTOR_WEIGHT: f32 = 0.048;
pub const ERASE_ALL_WEIGHT: f32 = 0.174;

#[derive(Derivative, Clone)]
#[derivative(Debug, PartialEq, Eq, Hash)]
pub struct FlashRegion {
    pub range: core::ops::Range<u32>,
    pub is_boot_memory: bool,
    pub is_testable: bool,
    pub blocksize: u32,
    pub sector_size: u32,
    pub page_size: u32,
    pub phrase_size: u32,
    #[derivative(PartialEq="ignore")]
    #[derivative(Hash="ignore")]
    pub erase_all_weight: f32,
    #[derivative(PartialEq="ignore")]
    #[derivative(Hash="ignore")]
    pub erase_sector_weight: f32,
    #[derivative(PartialEq="ignore")]
    #[derivative(Hash="ignore")]
    pub program_page_weight: f32,
    pub erased_byte_value: u8,
    pub access: Access,
    pub are_erased_sectors_readable: bool,
}

impl FlashRegion {
    pub fn get_sector_info(&self, address: u32) -> Option<SectorInfo> {
        if !self.range.contains(&address) {
            return None
        }

        Some(SectorInfo {
            base_address: address - (address % self.sector_size),
            erase_weight: self.erase_sector_weight,
            size: self.sector_size,
        })
    }

    pub fn get_page_info(&self, address: u32) -> Option<PageInfo> {
        if !self.range.contains(&address) {
            return None
        }

        Some(PageInfo {
            base_address: address - (address % self.page_size),
            program_weight: self.program_page_weight,
            size: self.page_size,
        })
    }

    pub fn get_flash_info(&self, analyzer_supported: bool) -> FlashInfo {
        FlashInfo {
            rom_start: self.range.start,
            erase_weight: self.erase_all_weight,
            crc_supported: analyzer_supported,
        }
    }

    pub fn is_erased(&self, data: &[u8]) -> bool {
        for b in data {
            if *b != self.erased_byte_value {
                return false;
            }
        }
        true
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct RamRegion {
    pub range: core::ops::Range<u32>,
    pub is_boot_memory: bool,
    pub is_testable: bool,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct RomRegion {
    pub range: core::ops::Range<u32>,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct DeviceRegion {
    pub range: core::ops::Range<u32>,
}

pub struct SectorInfo {
    pub base_address: u32,
    pub erase_weight: f32,
    pub size: u32,
}

pub struct PageInfo {
    pub base_address: u32,
    pub program_weight: f32,
    pub size: u32,
}

pub struct FlashInfo {
    pub rom_start: u32,
    pub erase_weight: f32,
    pub crc_supported: bool,
}

pub trait MemoryRange {
    fn contains_range(&self, range: &std::ops::Range<u32>) -> bool;
    fn intersects_range(&self, range: &std::ops::Range<u32>) -> bool;
}

impl MemoryRange for core::ops::Range<u32> {
    fn contains_range(&self, range: &std::ops::Range<u32>) -> bool {
        self.contains(&range.start) && self.contains(&(range.end - 1))
    }

    fn intersects_range(&self, range: &std::ops::Range<u32>) -> bool {
        self.contains(&range.start) && !self.contains(&(range.end - 1))
     || !self.contains(&range.start) && self.contains(&(range.end - 1))
    }
}

#[derive(Clone, PartialEq, Eq, Hash)]
pub enum MemoryRegion {
    Ram(RamRegion),
    Rom(RomRegion),
    Flash(FlashRegion),
    Device(DeviceRegion)
}