Fix memory various region generation bugs

This commit is contained in:
Rasmus Melchior Jacobsen 2023-03-25 12:31:16 +01:00
parent b9d1c2a2ab
commit 9e0a4b153e
3 changed files with 159 additions and 117 deletions

View File

@ -983,7 +983,9 @@ 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 mut flash_remaining = flash_size;
let flash_regions = memories.determine_flash_regions(chip_name, flash_size);
let ram_total = chip.ram * 1024; let ram_total = chip.ram * 1024;
let mut memory_regions = Vec::new(); let mut memory_regions = Vec::new();
let mut found = HashSet::<&str>::new(); let mut found = HashSet::<&str>::new();
@ -996,11 +998,15 @@ fn process_chip(
"D1_AXIICP", "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" => "BANK1", "FLASH" => (
"FLASH_BANK1" => "BANK1", "BANK_1",
"FLASH_BANK2" => "BANK2", 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) {
@ -1008,49 +1014,62 @@ fn process_chip(
} }
found.insert(key); found.insert(key);
if key == "FLASH_OTP" { if let Some(banks) = banks {
if let Some(region) = memories for bank in banks {
.determine_flash_regions(chip_name) let bank_name = match bank {
memory::FlashBank::Bank1 => "BANK_1",
memory::FlashBank::Bank2 => "BANK_2",
memory::FlashBank::Otp => "OTP",
};
let regions: Vec<_> = flash_regions
.iter() .iter()
.find(|x| x.bank == memory::FlashBank::Otp) .filter(|region| region.bank == *bank)
{ .enumerate()
memory_regions.push(stm32_data_serde::chip::Memory { .map_while(|(index, region)| {
name: region.name.clone(), let size = if *bank == memory::FlashBank::Bank1 || *bank == memory::FlashBank::Bank2 {
kind: stm32_data_serde::chip::memory::Kind::Otp, // Truncate region to the total amount of remaining chip flash
address: u32::try_from(*address).unwrap(), let size = std::cmp::min(region.bytes, flash_remaining);
size: region.bytes, flash_remaining -= size;
settings: Some(region.settings.clone()), if size == 0 {
// No more regions are present on this chip
return None;
}
size
} else {
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 { } else {
let bank = if key == "BANK2" {
memory::FlashBank::Bank2
} else {
memory::FlashBank::Bank1
};
for region in memories
.determine_flash_regions(chip_name)
.iter()
.filter(|x| x.bank == bank)
{
let size = if key == "BANK1" || key == "BANK2" {
std::cmp::min(region.bytes, flash_total)
} else {
0
};
memory_regions.push(stm32_data_serde::chip::Memory { memory_regions.push(stm32_data_serde::chip::Memory {
name: format!("{}_{}", key, region.name), 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(region.settings.clone()), settings: None,
}) })
} }
} }
} }
}
let mut found = HashSet::new(); let mut found = HashSet::new();
for each in [ for each in [
"SRAM", "SRAM",
@ -1077,7 +1096,7 @@ 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); let size = memories.determine_ram_size(chip_name, flash_size);
std::cmp::min(size, ram_total) std::cmp::min(size, ram_total)
} else { } else {
0 0
@ -1093,7 +1112,7 @@ 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 device_id = memories.determine_device_id(chip_name, flash_size);
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(),

View File

@ -1,11 +1,12 @@
use std::fs; use std::{cmp::Ordering, fs};
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
struct Memory { struct Memory {
pub device_id: u16, pub device_id: u16,
pub names: Vec<String>, pub names: Vec<String>,
pub ram: Ram, pub ram: Ram,
pub flash: Vec<FlashRegion>, pub flash_size: u32,
pub flash_regions: Vec<FlashRegion>,
} }
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
@ -17,7 +18,6 @@ struct Ram {
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct FlashRegion { pub struct FlashRegion {
pub bank: FlashBank, pub bank: FlashBank,
pub name: String,
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,
@ -214,7 +214,6 @@ impl Memories {
paths.sort(); paths.sort();
let mut memories = Vec::new(); let mut memories = Vec::new();
let alphabet: Vec<char> = (b'A'..=b'Z').map(|c| c as char).collect();
for f in paths { for f in paths {
// println!("Parsing {f:?}"); // println!("Parsing {f:?}");
@ -226,9 +225,10 @@ impl Memories {
let names = split_names(&parsed.device.name); let names = split_names(&parsed.device.name);
let mut ram = None; let mut ram = None;
let mut flash = vec![]; 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();
@ -249,57 +249,72 @@ impl Memories {
}; };
if let Some(kind) = kind { if let Some(kind) = kind {
// Use single bank alignment if both single and dual is available peripheral.configuration.sort_by(|a, b| {
let config = peripheral // Prefer largest size
.configuration let ordering = b
.iter() .parameters
.find(|c| c.organization.as_ref().map(|x| x.as_str()).unwrap_or_default() == "Single") .as_ref()
.unwrap_or_else(|| peripheral.configuration.first().unwrap()); .unwrap()
let parameters = config.parameters.as_ref().unwrap(); .size
let bank = config.bank.first().unwrap(); .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();
if flash_size.is_none() {
let parameters = config.parameters.as_ref().unwrap();
flash_size = Some(parameters.size);
}
for bank in config.bank.iter() {
let flash_bank = match kind { let flash_bank = match kind {
BlockKind::Main => match bank.name.as_ref().map(|x| x.as_str()) { BlockKind::Main => match bank.name.as_ref().map(|x| x.as_str()) {
Some("Bank 1") => FlashBank::Bank1, Some("Bank 1") => Some(FlashBank::Bank1),
Some("Bank 2") => FlashBank::Bank2, Some("Bank 2") => Some(FlashBank::Bank2),
None => FlashBank::Bank1, Some("EEPROM1") => None,
_ => unimplemented!(), Some("EEPROM2") => None,
None => {
assert_eq!(1, config.bank.len());
Some(FlashBank::Bank1)
}
Some(other) => unimplemented!("Unsupported flash bank {}", other),
}, },
BlockKind::Otp => FlashBank::Otp, BlockKind::Otp => Some(FlashBank::Otp),
}; };
if let Some(flash_bank) = flash_bank {
let erase_value = peripheral.erased_value.unwrap(); let erase_value = peripheral.erased_value.unwrap();
let write_size = config.allignement.unwrap(); let write_size = config.allignement.unwrap();
flash.extend(bank.field.iter().enumerate().map(|(index, field)| { flash_regions.extend(bank.field.iter().map(|field| FlashRegion {
let name = match kind {
BlockKind::Main => format!("MAIN{}", alphabet[index]).to_string(),
BlockKind::Otp => "OTP".to_string(),
};
let bytes = if let Some(occurence) = field.parameters.occurence {
occurence * field.parameters.size
} else {
parameters.size
};
FlashRegion {
bank: flash_bank, bank: flash_bank,
name,
address: field.parameters.address, address: field.parameters.address,
bytes, bytes: field.parameters.occurence.unwrap() * field.parameters.size,
settings: stm32_data_serde::chip::memory::Settings { settings: stm32_data_serde::chip::memory::Settings {
erase_value, erase_value,
write_size, write_size,
erase_size: field.parameters.size, erase_size: field.parameters.size,
}, },
}
})); }));
} }
} }
}
}
memories.push(Memory { memories.push(Memory {
device_id, device_id,
names, names,
ram: ram.unwrap(), ram: ram.unwrap(),
flash, flash_size: flash_size.unwrap_or_default(),
flash_regions,
}); });
} }
@ -311,9 +326,9 @@ impl Memories {
address: 0x20000000, address: 0x20000000,
bytes: 64 * 1024, bytes: 64 * 1024,
}, },
flash: vec![FlashRegion { flash_size: 384 * 1024,
flash_regions: vec![FlashRegion {
bank: FlashBank::Bank1, bank: FlashBank::Bank1,
name: "MAINA".to_string(),
address: 0x08000000, address: 0x08000000,
bytes: 384 * 1024, bytes: 384 * 1024,
settings: stm32_data_serde::chip::memory::Settings { settings: stm32_data_serde::chip::memory::Settings {
@ -331,9 +346,9 @@ impl Memories {
address: 0x20000000, address: 0x20000000,
bytes: 80 * 1024, bytes: 80 * 1024,
}, },
flash: vec![FlashRegion { flash_size: 384 * 1024,
flash_regions: vec![FlashRegion {
bank: FlashBank::Bank1, bank: FlashBank::Bank1,
name: "MAINA".to_string(),
address: 0x08000000, address: 0x08000000,
bytes: 384 * 1024, bytes: 384 * 1024,
settings: stm32_data_serde::chip::memory::Settings { settings: stm32_data_serde::chip::memory::Settings {
@ -349,45 +364,54 @@ impl Memories {
names: vec!["STM32L100x6".to_string()], names: vec!["STM32L100x6".to_string()],
ram: Ram { ram: Ram {
address: 0x20000000, address: 0x20000000,
bytes: 32 * 1024,
},
flash: vec![FlashRegion {
bank: FlashBank::Bank1,
name: "MAINA".to_string(),
address: 0x08000000,
bytes: 4 * 1024, bytes: 4 * 1024,
},
flash_size: 32 * 1024,
flash_regions: vec![FlashRegion {
bank: FlashBank::Bank1,
address: 0x08000000,
bytes: 32 * 1024,
settings: stm32_data_serde::chip::memory::Settings { settings: stm32_data_serde::chip::memory::Settings {
erase_value: 0xFF,
write_size: 4,
erase_size: 256, erase_size: 256,
write_size: 4,
erase_value: 0xFF,
}, },
}], }],
}); });
// Sort memories by flash size in descending order so that when we look
// a chip up later by name, the it will find the one with the largest flash size.
memories.sort_by(|a, b| b.flash_size.cmp(&a.flash_size));
Ok(Self(memories)) Ok(Self(memories))
} }
fn lookup_chip(&self, chip_name: &str) -> &Memory { fn lookup_chip(&self, chip_name: &str, flash_size: u32) -> &Memory {
// We use here that the memories are sorted in descending order by flash size.
// We emit the memory for which which the regions include at least the flash size of the requested chip.
for each in &self.0 { for each in &self.0 {
if each.flash_size >= flash_size {
for name in &each.names { for name in &each.names {
if is_chip_name_match(name, chip_name) { if is_chip_name_match(name, chip_name) {
return each; return each;
} }
} }
} }
panic!("could not find memory information for {chip_name}");
} }
pub fn determine_ram_size(&self, chip_name: &str) -> u32 { panic!("could not find memory information for {chip_name} with flash size {flash_size}");
self.lookup_chip(chip_name).ram.bytes
} }
pub fn determine_flash_regions(&self, chip_name: &str) -> &[FlashRegion] { pub fn determine_ram_size(&self, chip_name: &str, flash_size: u32) -> u32 {
self.lookup_chip(chip_name).flash.as_slice() self.lookup_chip(chip_name, flash_size).ram.bytes
} }
pub fn determine_device_id(&self, chip_name: &str) -> u16 { pub fn determine_flash_regions(&self, chip_name: &str, flash_size: u32) -> &[FlashRegion] {
self.lookup_chip(chip_name).device_id self.lookup_chip(chip_name, flash_size).flash_regions.as_slice()
}
pub fn determine_device_id(&self, chip_name: &str, flash_size: u32) -> u16 {
self.lookup_chip(chip_name, flash_size).device_id
} }
} }

View File

@ -40,7 +40,6 @@ pub mod chip {
pub enum Kind { pub enum Kind {
Flash, Flash,
Ram, Ram,
Otp,
} }
#[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Deserialize)]