Merge pull request #176 from rmja/flash-blocks
Support multiple flash regions, including OTP
This commit is contained in:
commit
d69e9e27bf
@ -1003,17 +1003,31 @@ fn process_chip(
|
|||||||
cores: &[stm32_data_serde::chip::Core],
|
cores: &[stm32_data_serde::chip::Core],
|
||||||
) -> Result<(), anyhow::Error> {
|
) -> Result<(), anyhow::Error> {
|
||||||
let chip = chips.get(chip_name).unwrap();
|
let chip = chips.get(chip_name).unwrap();
|
||||||
let flash_total = chip.flash * 1024;
|
let flash_size = chip.flash * 1024;
|
||||||
let ram_total = chip.ram * 1024;
|
let ram_total = chip.ram * 1024;
|
||||||
|
let memory = memories.get(group.die.as_ref().unwrap());
|
||||||
|
let mut flash_remaining = flash_size;
|
||||||
let mut memory_regions = Vec::new();
|
let mut memory_regions = Vec::new();
|
||||||
let mut found = HashSet::<&str>::new();
|
let mut found = HashSet::<&str>::new();
|
||||||
for each in ["FLASH", "FLASH_BANK1", "FLASH_BANK2", "D1_AXIFLASH", "D1_AXIICP"] {
|
for each in [
|
||||||
|
// We test FLASH_BANKx _before_ FLASH as we prefer their definition over the legacy one
|
||||||
|
"FLASH_BANK1",
|
||||||
|
"FLASH_BANK2",
|
||||||
|
"FLASH",
|
||||||
|
"FLASH_OTP",
|
||||||
|
"D1_AXIFLASH",
|
||||||
|
"D1_AXIICP",
|
||||||
|
] {
|
||||||
if let Some(address) = h.defines.get("all").unwrap().0.get(&format!("{each}_BASE")) {
|
if let Some(address) = h.defines.get("all").unwrap().0.get(&format!("{each}_BASE")) {
|
||||||
let key = match each {
|
let (key, banks) = match each {
|
||||||
"FLASH" => "BANK_1",
|
"FLASH" => (
|
||||||
"FLASH_BANK1" => "BANK_1",
|
"BANK_1",
|
||||||
"FLASH_BANK2" => "BANK_2",
|
Some([memory::FlashBank::Bank1, memory::FlashBank::Bank2].as_ref()),
|
||||||
each => each,
|
),
|
||||||
|
"FLASH_BANK1" => ("BANK_1", Some([memory::FlashBank::Bank1].as_ref())),
|
||||||
|
"FLASH_BANK2" => ("BANK_2", Some([memory::FlashBank::Bank2].as_ref())),
|
||||||
|
"FLASH_OTP" => ("OTP", Some([memory::FlashBank::Otp].as_ref())),
|
||||||
|
each => (each, None),
|
||||||
};
|
};
|
||||||
|
|
||||||
if found.contains(key) {
|
if found.contains(key) {
|
||||||
@ -1021,20 +1035,61 @@ fn process_chip(
|
|||||||
}
|
}
|
||||||
found.insert(key);
|
found.insert(key);
|
||||||
|
|
||||||
let size = if key == "BANK_1" || key == "BANK_2" {
|
if let Some(banks) = banks {
|
||||||
let size = memories.determine_flash_size(chip_name);
|
for bank in banks {
|
||||||
std::cmp::min(size, flash_total)
|
let bank_name = match bank {
|
||||||
|
memory::FlashBank::Bank1 => "BANK_1",
|
||||||
|
memory::FlashBank::Bank2 => "BANK_2",
|
||||||
|
memory::FlashBank::Otp => "OTP",
|
||||||
|
};
|
||||||
|
let regions: Vec<_> = memory
|
||||||
|
.flash_regions
|
||||||
|
.iter()
|
||||||
|
.filter(|region| region.bank == *bank)
|
||||||
|
.enumerate()
|
||||||
|
.map_while(|(index, region)| {
|
||||||
|
let size = if *bank == memory::FlashBank::Bank1 || *bank == memory::FlashBank::Bank2 {
|
||||||
|
// Truncate region to the total amount of remaining chip flash
|
||||||
|
let size = std::cmp::min(region.bytes, flash_remaining);
|
||||||
|
flash_remaining -= size;
|
||||||
|
if size == 0 {
|
||||||
|
// No more regions are present on this chip
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
size
|
||||||
} else {
|
} else {
|
||||||
0
|
region.bytes
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Some((index, region.address, size, region.settings.clone()))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let has_multiple_regions = regions.len() > 1;
|
||||||
|
for (index, address, size, settings) in regions {
|
||||||
|
let name = if has_multiple_regions {
|
||||||
|
format!("{}_REGION_{}", bank_name, index + 1)
|
||||||
|
} else {
|
||||||
|
bank_name.to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
memory_regions.push(stm32_data_serde::chip::Memory {
|
||||||
|
name,
|
||||||
|
kind: stm32_data_serde::chip::memory::Kind::Flash,
|
||||||
|
address,
|
||||||
|
size,
|
||||||
|
settings: Some(settings.clone()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
memory_regions.push(stm32_data_serde::chip::Memory {
|
memory_regions.push(stm32_data_serde::chip::Memory {
|
||||||
name: key.to_string(),
|
name: key.to_string(),
|
||||||
kind: stm32_data_serde::chip::memory::Kind::Flash,
|
kind: stm32_data_serde::chip::memory::Kind::Flash,
|
||||||
address: u32::try_from(*address).unwrap(),
|
address: u32::try_from(*address).unwrap(),
|
||||||
size,
|
size: 0,
|
||||||
settings: Some(memories.determine_flash_settings(chip_name)),
|
settings: None,
|
||||||
});
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut found = HashSet::new();
|
let mut found = HashSet::new();
|
||||||
@ -1063,8 +1118,16 @@ fn process_chip(
|
|||||||
found.insert(key);
|
found.insert(key);
|
||||||
|
|
||||||
let size = if key == "SRAM" {
|
let size = if key == "SRAM" {
|
||||||
let size = memories.determine_ram_size(chip_name);
|
// if memory.ram.bytes != ram_total {
|
||||||
std::cmp::min(size, ram_total)
|
// println!(
|
||||||
|
// "SRAM mismatch for chip {} with die {}: Expected {} was {}",
|
||||||
|
// chip_name,
|
||||||
|
// group.die.as_ref().unwrap(),
|
||||||
|
// ram_total,
|
||||||
|
// memory.ram.bytes,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
std::cmp::min(memory.ram.bytes, ram_total)
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
@ -1079,13 +1142,12 @@ fn process_chip(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let docs = docs.documents_for(chip_name);
|
let docs = docs.documents_for(chip_name);
|
||||||
let device_id = memories.determine_device_id(chip_name);
|
|
||||||
let chip = stm32_data_serde::Chip {
|
let chip = stm32_data_serde::Chip {
|
||||||
name: chip_name.to_string(),
|
name: chip_name.to_string(),
|
||||||
family: group.family.clone().unwrap(),
|
family: group.family.clone().unwrap(),
|
||||||
line: group.line.clone().unwrap(),
|
line: group.line.clone().unwrap(),
|
||||||
die: group.die.clone().unwrap(),
|
die: group.die.clone().unwrap(),
|
||||||
device_id,
|
device_id: memory.device_id,
|
||||||
packages: chip.packages.clone(),
|
packages: chip.packages.clone(),
|
||||||
memory: memory_regions,
|
memory: memory_regions,
|
||||||
docs,
|
docs,
|
||||||
|
@ -1,68 +1,32 @@
|
|||||||
use std::fs;
|
use std::{cmp::Ordering, collections::HashMap, fs};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
struct Memory {
|
pub struct Memory {
|
||||||
pub device_id: u16,
|
pub device_id: u16,
|
||||||
pub names: Vec<String>,
|
|
||||||
pub ram: Ram,
|
pub ram: Ram,
|
||||||
pub flash: Option<Flash>,
|
pub flash_size: u32,
|
||||||
|
pub flash_regions: Vec<FlashRegion>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
struct Ram {
|
pub struct Ram {
|
||||||
pub address: u32,
|
pub address: u32,
|
||||||
pub bytes: u32,
|
pub bytes: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
struct Flash {
|
pub struct FlashRegion {
|
||||||
|
pub bank: FlashBank,
|
||||||
pub address: u32,
|
pub address: u32,
|
||||||
pub bytes: u32,
|
pub bytes: u32,
|
||||||
pub settings: stm32_data_serde::chip::memory::Settings,
|
pub settings: stm32_data_serde::chip::memory::Settings,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn splat_names(base: &str, parts: Vec<&str>) -> Vec<String> {
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
let mut names = Vec::new();
|
pub enum FlashBank {
|
||||||
for part in parts {
|
Bank1,
|
||||||
if part.starts_with("STM32") {
|
Bank2,
|
||||||
names.push(base.to_string());
|
Otp,
|
||||||
} else if part.starts_with(&base[5..6]) {
|
|
||||||
names.push("STM32".to_string() + part);
|
|
||||||
} else {
|
|
||||||
let diff = base.len() - part.len();
|
|
||||||
names.push((base[..diff]).to_string() + part);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
names
|
|
||||||
}
|
|
||||||
|
|
||||||
fn split_names(str: &str) -> Vec<String> {
|
|
||||||
let mut cleaned = Vec::new();
|
|
||||||
let mut current_base = None;
|
|
||||||
for name in str.split('/') {
|
|
||||||
let name = name.split(' ').next().unwrap().trim();
|
|
||||||
if name.contains('-') {
|
|
||||||
let parts: Vec<_> = name.split('-').collect();
|
|
||||||
current_base = parts.first().map(ToString::to_string);
|
|
||||||
let splatted = splat_names(¤t_base.unwrap(), parts);
|
|
||||||
current_base = splatted.first().map(Clone::clone);
|
|
||||||
cleaned.extend(splatted);
|
|
||||||
} else if name.starts_with("STM32") {
|
|
||||||
current_base = Some(name.to_string());
|
|
||||||
cleaned.push(name.to_string())
|
|
||||||
} else if name.starts_with(¤t_base.clone().unwrap()[5..6]) {
|
|
||||||
// names.append('STM32' + name)
|
|
||||||
cleaned.push("STM32".to_string() + name);
|
|
||||||
} else {
|
|
||||||
cleaned.push(
|
|
||||||
(current_base.clone().unwrap()[0..(current_base.clone().unwrap().len() - name.len())]).to_string()
|
|
||||||
+ name,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cleaned
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mod xml {
|
mod xml {
|
||||||
@ -148,6 +112,8 @@ mod xml {
|
|||||||
pub struct Configuration {
|
pub struct Configuration {
|
||||||
#[serde(rename = "Parameters", default)]
|
#[serde(rename = "Parameters", default)]
|
||||||
pub parameters: Option<configuration::Parameters>,
|
pub parameters: Option<configuration::Parameters>,
|
||||||
|
#[serde(rename = "Organization", default)]
|
||||||
|
pub organization: Option<String>,
|
||||||
#[serde(rename = "Allignement", deserialize_with = "opt_from_hex", default)]
|
#[serde(rename = "Allignement", deserialize_with = "opt_from_hex", default)]
|
||||||
pub allignement: Option<u32>,
|
pub allignement: Option<u32>,
|
||||||
#[serde(rename = "Bank")]
|
#[serde(rename = "Bank")]
|
||||||
@ -157,7 +123,7 @@ mod xml {
|
|||||||
mod configuration {
|
mod configuration {
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use super::super::super::super::super::from_hex;
|
use super::super::super::super::super::{from_hex, opt_from_hex};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq)]
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
pub struct Parameters {
|
pub struct Parameters {
|
||||||
@ -165,10 +131,14 @@ mod xml {
|
|||||||
pub address: u32,
|
pub address: u32,
|
||||||
#[serde(deserialize_with = "from_hex")]
|
#[serde(deserialize_with = "from_hex")]
|
||||||
pub size: u32,
|
pub size: u32,
|
||||||
|
#[serde(deserialize_with = "opt_from_hex", default)]
|
||||||
|
pub occurence: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, PartialEq)]
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
pub struct Bank {
|
pub struct Bank {
|
||||||
|
#[serde(default)]
|
||||||
|
pub name: Option<String>,
|
||||||
#[serde(rename = "Field", default)]
|
#[serde(rename = "Field", default)]
|
||||||
pub field: Vec<bank::Field>,
|
pub field: Vec<bank::Field>,
|
||||||
}
|
}
|
||||||
@ -188,7 +158,7 @@ mod xml {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub struct Memories(Vec<Memory>);
|
pub struct Memories(HashMap<u16, Memory>);
|
||||||
|
|
||||||
impl Memories {
|
impl Memories {
|
||||||
pub fn parse() -> anyhow::Result<Self> {
|
pub fn parse() -> anyhow::Result<Self> {
|
||||||
@ -198,7 +168,7 @@ impl Memories {
|
|||||||
.collect();
|
.collect();
|
||||||
paths.sort();
|
paths.sort();
|
||||||
|
|
||||||
let mut memories = Vec::new();
|
let mut memories = HashMap::new();
|
||||||
|
|
||||||
for f in paths {
|
for f in paths {
|
||||||
// println!("Parsing {f:?}");
|
// println!("Parsing {f:?}");
|
||||||
@ -207,12 +177,12 @@ impl Memories {
|
|||||||
// dbg!(&parsed);
|
// dbg!(&parsed);
|
||||||
|
|
||||||
let device_id = parsed.device.device_id;
|
let device_id = parsed.device.device_id;
|
||||||
let names = split_names(&parsed.device.name);
|
|
||||||
|
|
||||||
let mut ram = None;
|
let mut ram = None;
|
||||||
let mut flash = None;
|
let mut flash_size = None;
|
||||||
|
let mut flash_regions = vec![];
|
||||||
|
|
||||||
for peripheral in parsed.device.peripherals.peripharal {
|
for mut peripheral in parsed.device.peripherals.peripharal {
|
||||||
if peripheral.name == "Embedded SRAM" && ram.is_none() {
|
if peripheral.name == "Embedded SRAM" && ram.is_none() {
|
||||||
let config = peripheral.configuration.first().unwrap();
|
let config = peripheral.configuration.first().unwrap();
|
||||||
let parameters = config.parameters.as_ref().unwrap();
|
let parameters = config.parameters.as_ref().unwrap();
|
||||||
@ -222,127 +192,95 @@ impl Memories {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if peripheral.name == "Embedded Flash" && flash.is_none() {
|
enum BlockKind {
|
||||||
|
Main,
|
||||||
|
Otp,
|
||||||
|
}
|
||||||
|
let kind = match peripheral.name.as_str() {
|
||||||
|
"Embedded Flash" => Some(BlockKind::Main),
|
||||||
|
"OTP" => Some(BlockKind::Otp),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(kind) = kind {
|
||||||
|
peripheral.configuration.sort_by(|a, b| {
|
||||||
|
// Prefer largest size
|
||||||
|
let ordering = b
|
||||||
|
.parameters
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.size
|
||||||
|
.partial_cmp(&a.parameters.as_ref().unwrap().size)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// ... then prefer single ordering over dual
|
||||||
|
if ordering == Ordering::Equal {
|
||||||
|
// Possible values are Single and Dual
|
||||||
|
b.organization.partial_cmp(&a.organization).unwrap()
|
||||||
|
} else {
|
||||||
|
ordering
|
||||||
|
}
|
||||||
|
});
|
||||||
let config = peripheral.configuration.first().unwrap();
|
let config = peripheral.configuration.first().unwrap();
|
||||||
|
|
||||||
|
if flash_size.is_none() {
|
||||||
let parameters = config.parameters.as_ref().unwrap();
|
let parameters = config.parameters.as_ref().unwrap();
|
||||||
let bank = config.bank.first().unwrap();
|
|
||||||
let erase_size = bank.field.iter().map(|field| field.parameters.size).max().unwrap();
|
|
||||||
|
|
||||||
flash = Some(Flash {
|
flash_size = Some(parameters.size);
|
||||||
address: parameters.address,
|
}
|
||||||
bytes: parameters.size,
|
|
||||||
settings: stm32_data_serde::chip::memory::Settings {
|
for bank in config.bank.iter() {
|
||||||
erase_value: peripheral.erased_value.unwrap(),
|
let flash_bank = match kind {
|
||||||
write_size: config.allignement.unwrap(),
|
BlockKind::Main => match bank.name.as_ref().map(|x| x.as_str()) {
|
||||||
erase_size,
|
Some("Bank 1") => Some(FlashBank::Bank1),
|
||||||
|
Some("Bank 2") => Some(FlashBank::Bank2),
|
||||||
|
Some("EEPROM1") => None,
|
||||||
|
Some("EEPROM2") => None,
|
||||||
|
None => {
|
||||||
|
assert_eq!(1, config.bank.len());
|
||||||
|
Some(FlashBank::Bank1)
|
||||||
|
}
|
||||||
|
Some(other) => unimplemented!("Unsupported flash bank {}", other),
|
||||||
},
|
},
|
||||||
});
|
BlockKind::Otp => Some(FlashBank::Otp),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(flash_bank) = flash_bank {
|
||||||
|
let erase_value = peripheral.erased_value.unwrap();
|
||||||
|
let write_size = config.allignement.unwrap();
|
||||||
|
flash_regions.extend(bank.field.iter().map(|field| FlashRegion {
|
||||||
|
bank: flash_bank,
|
||||||
|
address: field.parameters.address,
|
||||||
|
bytes: field.parameters.occurence.unwrap() * field.parameters.size,
|
||||||
|
settings: stm32_data_serde::chip::memory::Settings {
|
||||||
|
erase_value,
|
||||||
|
write_size,
|
||||||
|
erase_size: field.parameters.size,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memories.push(Memory {
|
memories.insert(
|
||||||
|
device_id,
|
||||||
|
Memory {
|
||||||
device_id,
|
device_id,
|
||||||
names,
|
|
||||||
ram: ram.unwrap(),
|
ram: ram.unwrap(),
|
||||||
flash,
|
flash_size: flash_size.unwrap_or_default(),
|
||||||
});
|
flash_regions,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The chips below are missing from cubeprogdb
|
|
||||||
memories.push(Memory {
|
|
||||||
device_id: 0,
|
|
||||||
names: vec!["STM32F302xD".to_string()],
|
|
||||||
ram: Ram {
|
|
||||||
address: 0x20000000,
|
|
||||||
bytes: 64 * 1024,
|
|
||||||
},
|
|
||||||
flash: Some(Flash {
|
|
||||||
address: 0x08000000,
|
|
||||||
bytes: 384 * 1024,
|
|
||||||
settings: stm32_data_serde::chip::memory::Settings {
|
|
||||||
erase_value: 0xFF,
|
|
||||||
write_size: 8,
|
|
||||||
erase_size: 2048,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
memories.push(Memory {
|
|
||||||
device_id: 0,
|
|
||||||
names: vec!["STM32F303xD".to_string()],
|
|
||||||
ram: Ram {
|
|
||||||
address: 0x20000000,
|
|
||||||
bytes: 80 * 1024,
|
|
||||||
},
|
|
||||||
flash: Some(Flash {
|
|
||||||
address: 0x08000000,
|
|
||||||
bytes: 384 * 1024,
|
|
||||||
settings: stm32_data_serde::chip::memory::Settings {
|
|
||||||
erase_value: 0xFF,
|
|
||||||
write_size: 8,
|
|
||||||
erase_size: 2048,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
memories.push(Memory {
|
|
||||||
device_id: 0,
|
|
||||||
names: vec!["STM32L100x6".to_string()],
|
|
||||||
ram: Ram {
|
|
||||||
address: 0x20000000,
|
|
||||||
bytes: 32 * 1024,
|
|
||||||
},
|
|
||||||
flash: Some(Flash {
|
|
||||||
address: 0x08000000,
|
|
||||||
bytes: 4 * 1024,
|
|
||||||
settings: stm32_data_serde::chip::memory::Settings {
|
|
||||||
erase_value: 0xFF,
|
|
||||||
write_size: 4,
|
|
||||||
erase_size: 256,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(Self(memories))
|
Ok(Self(memories))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_chip(&self, chip_name: &str) -> &Memory {
|
pub fn get(&self, die: &str) -> &Memory {
|
||||||
for each in &self.0 {
|
assert!(die.starts_with("DIE"));
|
||||||
for name in &each.names {
|
let device_id = u16::from_str_radix(&die[3..], 16).unwrap();
|
||||||
if is_chip_name_match(name, chip_name) {
|
|
||||||
return each;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
panic!("could not find memory information for {chip_name}");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn determine_ram_size(&self, chip_name: &str) -> u32 {
|
self.0.get(&device_id).unwrap()
|
||||||
self.lookup_chip(chip_name).ram.bytes
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn determine_flash_size(&self, chip_name: &str) -> u32 {
|
|
||||||
self.lookup_chip(chip_name).flash.as_ref().unwrap().bytes
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn determine_flash_settings(&self, chip_name: &str) -> stm32_data_serde::chip::memory::Settings {
|
|
||||||
self.lookup_chip(chip_name).flash.as_ref().unwrap().settings.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn determine_device_id(&self, chip_name: &str) -> u16 {
|
|
||||||
self.lookup_chip(chip_name).device_id
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_chip_name_match(pattern: &str, chip_name: &str) -> bool {
|
|
||||||
let mut chip_name = chip_name.replace("STM32F479", "STM32F469"); // F479 is missing, it's the same as F469.
|
|
||||||
chip_name = chip_name.replace("STM32G050", "STM32G051"); // same...
|
|
||||||
chip_name = chip_name.replace("STM32G060", "STM32G061"); // same...
|
|
||||||
chip_name = chip_name.replace("STM32G070", "STM32G071"); // same...
|
|
||||||
chip_name = chip_name.replace("STM32G0B0", "STM32G0B1"); // same...
|
|
||||||
chip_name = chip_name.replace("STM32G4A", "STM32G49"); // same...
|
|
||||||
chip_name = chip_name.replace("STM32L422", "STM32L412"); // same...
|
|
||||||
chip_name = chip_name.replace("STM32WB30", "STM32WB35"); // same...
|
|
||||||
let pattern = pattern.replace('x', ".");
|
|
||||||
regex::Regex::new(&pattern).unwrap().is_match(&chip_name)
|
|
||||||
}
|
|
||||||
|
@ -117,13 +117,32 @@ impl Gen {
|
|||||||
}
|
}
|
||||||
writeln!(&mut extra, "pub const CORE_INDEX: usize = {};", core_index).unwrap();
|
writeln!(&mut extra, "pub const CORE_INDEX: usize = {};", core_index).unwrap();
|
||||||
|
|
||||||
let flash = chip.memory.iter().find(|r| r.name == "BANK_1").unwrap();
|
let flash_regions: Vec<&MemoryRegion> = chip
|
||||||
let settings = flash.settings.as_ref().unwrap();
|
.memory
|
||||||
writeln!(&mut extra, "pub const FLASH_BASE: usize = {};", flash.address).unwrap();
|
.iter()
|
||||||
writeln!(&mut extra, "pub const FLASH_SIZE: usize = {};", flash.size).unwrap();
|
.filter(|x| x.kind == MemoryRegionKind::Flash && x.name.starts_with("BANK_"))
|
||||||
writeln!(&mut extra, "pub const ERASE_SIZE: usize = {};", settings.erase_size).unwrap();
|
.collect();
|
||||||
writeln!(&mut extra, "pub const WRITE_SIZE: usize = {};", settings.write_size).unwrap();
|
let first_flash = flash_regions.first().unwrap();
|
||||||
writeln!(&mut extra, "pub const ERASE_VALUE: u8 = {};", settings.erase_value).unwrap();
|
let total_flash_size = flash_regions
|
||||||
|
.iter()
|
||||||
|
.map(|x| x.size)
|
||||||
|
.reduce(|acc, item| acc + item)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
writeln!(&mut extra, "pub const FLASH_BASE: usize = {};", first_flash.address).unwrap();
|
||||||
|
writeln!(&mut extra, "pub const FLASH_SIZE: usize = {};", total_flash_size).unwrap();
|
||||||
|
|
||||||
|
let write_sizes: HashSet<_> = flash_regions
|
||||||
|
.iter()
|
||||||
|
.map(|r| r.settings.as_ref().unwrap().write_size)
|
||||||
|
.collect();
|
||||||
|
assert_eq!(1, write_sizes.len());
|
||||||
|
writeln!(
|
||||||
|
&mut extra,
|
||||||
|
"pub const WRITE_SIZE: usize = {};",
|
||||||
|
write_sizes.iter().next().unwrap()
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Cleanups!
|
// Cleanups!
|
||||||
transform::sort::Sort {}.run(&mut ir).unwrap();
|
transform::sort::Sort {}.run(&mut ir).unwrap();
|
||||||
@ -348,22 +367,45 @@ fn gen_opts() -> generate::Options {
|
|||||||
fn gen_memory_x(out_dir: &Path, chip: &Chip) {
|
fn gen_memory_x(out_dir: &Path, chip: &Chip) {
|
||||||
let mut memory_x = String::new();
|
let mut memory_x = String::new();
|
||||||
|
|
||||||
let flash = chip.memory.iter().find(|r| r.name == "BANK_1").unwrap();
|
let flash = chip
|
||||||
let ram = chip.memory.iter().find(|r| r.name == "SRAM").unwrap();
|
.memory
|
||||||
|
.iter()
|
||||||
|
.filter(|r| r.kind == MemoryRegionKind::Flash && r.name.starts_with("BANK_"));
|
||||||
|
let (flash_address, flash_size) = flash
|
||||||
|
.clone()
|
||||||
|
.map(|r| (r.address, r.size))
|
||||||
|
.reduce(|acc, el| (u32::min(acc.0, el.0), acc.1 + el.1))
|
||||||
|
.unwrap();
|
||||||
|
let ram = chip.memory.iter().find(|r| r.kind == MemoryRegionKind::Ram).unwrap();
|
||||||
|
let otp = chip
|
||||||
|
.memory
|
||||||
|
.iter()
|
||||||
|
.find(|r| r.kind == MemoryRegionKind::Flash && r.name == "OTP");
|
||||||
|
|
||||||
write!(memory_x, "MEMORY\n{{\n").unwrap();
|
write!(memory_x, "MEMORY\n{{\n").unwrap();
|
||||||
writeln!(
|
writeln!(
|
||||||
memory_x,
|
memory_x,
|
||||||
" FLASH : ORIGIN = 0x{:x}, LENGTH = {}",
|
" FLASH : ORIGIN = 0x{:08x}, LENGTH = {:>4}K /* {} */",
|
||||||
flash.address, flash.size,
|
flash_address,
|
||||||
|
flash_size / 1024,
|
||||||
|
flash.map(|x| x.name.as_ref()).collect::<Vec<&str>>().join(" + ")
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
writeln!(
|
writeln!(
|
||||||
memory_x,
|
memory_x,
|
||||||
" RAM : ORIGIN = 0x{:x}, LENGTH = {}",
|
" RAM : ORIGIN = 0x{:08x}, LENGTH = {:>4}K",
|
||||||
ram.address, ram.size,
|
ram.address,
|
||||||
|
ram.size / 1024,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
if let Some(otp) = otp {
|
||||||
|
writeln!(
|
||||||
|
memory_x,
|
||||||
|
" OTP : ORIGIN = 0x{:08x}, LENGTH = {:>4}",
|
||||||
|
otp.address, otp.size,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
write!(memory_x, "}}").unwrap();
|
write!(memory_x, "}}").unwrap();
|
||||||
|
|
||||||
fs::create_dir_all(out_dir.join("memory_x")).unwrap();
|
fs::create_dir_all(out_dir.join("memory_x")).unwrap();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user