can: fix missing interrupts

This commit is contained in:
xoviat 2023-06-17 19:13:00 -05:00
parent d52fe499e2
commit e388dcebe7
3 changed files with 56 additions and 53 deletions

2
.vscode/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
launch.json
tasks.json

View File

@ -935,13 +935,40 @@ fn process_core(
} }
if let Some(peri_irqs) = chip_irqs.get(&pname) { if let Some(peri_irqs) = chip_irqs.get(&pname) {
use stm32_data_serde::chip::core::peripheral::Interrupt;
//filter by available, because some are conditioned on <Die> //filter by available, because some are conditioned on <Die>
let mut irqs: Vec<_> = peri_irqs
.iter() let mut irqs: Vec<_> =
.filter(|i| header_irqs.contains_key(&i.interrupt)) if pname == "CAN" && (chip_name.starts_with("STM32F358") || chip_name.starts_with("STM32F398")) {
.cloned() /*
.collect(); This section is needed because the interrupt definition file does not apply uniformly to
all chips that it covers in this specific case. This cannot be done in interrupt.rs
because there, it's only possible to modify the interrupt definition file in a uniform manner.
*/
peri_irqs
.iter()
.map(|i| Interrupt {
interrupt: i
.interrupt
.trim_start_matches("USB_LP_")
.trim_start_matches("USB_HP_")
.to_owned(),
signal: i.signal.clone(),
})
.filter(|i| header_irqs.contains_key(&i.interrupt))
.collect()
} else {
peri_irqs
.iter()
.filter(|i| header_irqs.contains_key(&i.interrupt))
.cloned()
.collect()
};
irqs.sort_by_key(|x| (x.signal.clone(), x.interrupt.clone())); irqs.sort_by_key(|x| (x.signal.clone(), x.interrupt.clone()));
irqs.dedup_by_key(|x| (x.signal.clone(), x.interrupt.clone()));
p.interrupts = Some(irqs); p.interrupts = Some(irqs);
} }
peripherals.push(p); peripherals.push(p);

View File

@ -36,6 +36,7 @@ mod xml {
#[derive(Debug)] #[derive(Debug)]
pub struct ChipInterrupts( pub struct ChipInterrupts(
// (chip name, chip version), (signal name, [interrupt])
pub HashMap<(String, String), HashMap<String, Vec<stm32_data_serde::chip::core::peripheral::Interrupt>>>, pub HashMap<(String, String), HashMap<String, Vec<stm32_data_serde::chip::core::peripheral::Interrupt>>>,
); );
@ -51,9 +52,10 @@ impl ChipInterrupts {
for f in files { for f in files {
trace!("parsing {f:?}"); trace!("parsing {f:?}");
let mut irqs = HashMap::<String, _>::new(); let file = std::fs::read_to_string(&f)?;
let file = std::fs::read_to_string(f)?;
let parsed: xml::Ip = quick_xml::de::from_str(&file)?; let parsed: xml::Ip = quick_xml::de::from_str(&file)?;
let mut chip_signals = HashMap::<_, Vec<_>>::new();
for irq in parsed for irq in parsed
.ref_parameters .ref_parameters
.into_iter() .into_iter()
@ -79,11 +81,6 @@ impl ChipInterrupts {
// More typos // More typos
let name = name.replace("USAR11", "USART11"); let name = name.replace("USAR11", "USART11");
let entry = match irqs.entry(name.to_string()) {
std::collections::hash_map::Entry::Occupied(_) => continue,
std::collections::hash_map::Entry::Vacant(entry) => entry,
};
// Flags. // Flags.
// Y // Y
// unknown, it's in all of them // unknown, it's in all of them
@ -113,7 +110,7 @@ impl ChipInterrupts {
continue; continue;
} }
let mut signals = HashSet::<(String, String)>::new(); let mut interrupt_signals = HashSet::<(String, String)>::new();
if [ if [
"NonMaskableInt", "NonMaskableInt",
"HardFault", "HardFault",
@ -147,27 +144,27 @@ impl ChipInterrupts {
ch_from..=ch_to ch_from..=ch_to
}; };
for ch in range { for ch in range {
signals.insert((dma.to_string(), format!("CH{ch}"))); interrupt_signals.insert((dma.to_string(), format!("CH{ch}")));
} }
} }
assert!(dmas_iter.next().is_none()); assert!(dmas_iter.next().is_none());
assert!(chans_iter.next().is_none()); assert!(chans_iter.next().is_none());
} else if name == "DMAMUX1" || name == "DMAMUX1_S" || name == "DMAMUX_OVR" || name == "DMAMUX1_OVR" { } else if name == "DMAMUX1" || name == "DMAMUX1_S" || name == "DMAMUX_OVR" || name == "DMAMUX1_OVR" {
signals.insert(("DMAMUX1".to_string(), "OVR".to_string())); interrupt_signals.insert(("DMAMUX1".to_string(), "OVR".to_string()));
} else if name == "DMAMUX2_OVR" { } else if name == "DMAMUX2_OVR" {
signals.insert(("DMAMUX2".to_string(), "OVR".to_string())); interrupt_signals.insert(("DMAMUX2".to_string(), "OVR".to_string()));
} else if flags.contains(&"DMAMUX") { } else if flags.contains(&"DMAMUX") {
panic!("should've been handled above"); panic!("should've been handled above");
} else if flags.contains(&"EXTI") { } else if flags.contains(&"EXTI") {
for signal in parts[2].split(',') { for signal in parts[2].split(',') {
signals.insert(("EXTI".to_string(), signal.to_string())); interrupt_signals.insert(("EXTI".to_string(), signal.to_string()));
} }
} else if name == "FLASH" { } else if name == "FLASH" {
signals.insert(("FLASH".to_string(), "GLOBAL".to_string())); interrupt_signals.insert(("FLASH".to_string(), "GLOBAL".to_string()));
} else if name == "CRS" { } else if name == "CRS" {
signals.insert(("RCC".to_string(), "CRS".to_string())); interrupt_signals.insert(("RCC".to_string(), "CRS".to_string()));
} else if name == "RCC" { } else if name == "RCC" {
signals.insert(("RCC".to_string(), "GLOBAL".to_string())); interrupt_signals.insert(("RCC".to_string(), "GLOBAL".to_string()));
} else { } else {
if parts[2].is_empty() { if parts[2].is_empty() {
continue; continue;
@ -193,7 +190,7 @@ impl ChipInterrupts {
curr_peris = peri_names.clone(); curr_peris = peri_names.clone();
} }
// Parse IRQ signals from the IRQ name. // Parse IRQ interrupt_signals from the IRQ name.
for part in tokenize_name(name2) { for part in tokenize_name(name2) {
let part = { let part = {
if part == "TAMPER" { if part == "TAMPER" {
@ -204,13 +201,13 @@ impl ChipInterrupts {
}; };
if part == "LSECSS" { if part == "LSECSS" {
signals.insert(("RCC".to_string(), "LSECSS".to_string())); interrupt_signals.insert(("RCC".to_string(), "LSECSS".to_string()));
} else if part == "CSS" { } else if part == "CSS" {
signals.insert(("RCC".to_string(), "CSS".to_string())); interrupt_signals.insert(("RCC".to_string(), "CSS".to_string()));
} else if part == "LSE" { } else if part == "LSE" {
signals.insert(("RCC".to_string(), "LSE".to_string())); interrupt_signals.insert(("RCC".to_string(), "LSE".to_string()));
} else if part == "CRS" { } else if part == "CRS" {
signals.insert(("RCC".to_string(), "CRS".to_string())); interrupt_signals.insert(("RCC".to_string(), "CRS".to_string()));
} else { } else {
let pp = match_peris(&peri_names, &part); let pp = match_peris(&peri_names, &part);
trace!(" part={part}, pp={pp:?}"); trace!(" part={part}, pp={pp:?}");
@ -228,7 +225,7 @@ impl ChipInterrupts {
for (p, mut ss) in peri_signals.into_iter() { for (p, mut ss) in peri_signals.into_iter() {
let known = valid_signals(&p); let known = valid_signals(&p);
// If we have no signals for the peri, assume it's "global" so assign it all known ones // If we have no interrupt_signals for the peri, assume it's "global" so assign it all known ones
if ss.is_empty() { if ss.is_empty() {
if p.starts_with("COMP") { if p.starts_with("COMP") {
ss = vec!["WKUP".to_string()]; ss = vec!["WKUP".to_string()];
@ -241,22 +238,14 @@ impl ChipInterrupts {
if !known.contains(&s.clone()) { if !known.contains(&s.clone()) {
panic!("Unknown signal {s} for peri {p}, known={known:?}, parts={parts:?}"); panic!("Unknown signal {s} for peri {p}, known={known:?}, parts={parts:?}");
} }
signals.insert((p.clone(), s)); interrupt_signals.insert((p.clone(), s));
} }
} }
} }
// for (peri, signal) in &signals { for (p, s) in interrupt_signals {
// println!(" {peri}:{signal}");
// }
entry.insert(signals);
}
let mut irqs2 = HashMap::<_, Vec<_>>::new();
for (name, signals) in irqs {
for (p, s) in signals {
let key = if p == "USB_DRD_FS" { "USB".to_string() } else { p }; let key = if p == "USB_DRD_FS" { "USB".to_string() } else { p };
irqs2 chip_signals
.entry(key) .entry(key)
.or_default() .or_default()
.push(stm32_data_serde::chip::core::peripheral::Interrupt { .push(stm32_data_serde::chip::core::peripheral::Interrupt {
@ -266,22 +255,7 @@ impl ChipInterrupts {
} }
} }
for pirqs in irqs2.values_mut() { chip_interrupts.insert((parsed.name, parsed.version), chip_signals);
let mut psirqs = HashMap::<_, Vec<_>>::new();
for irq in pirqs {
psirqs
.entry(irq.signal.clone())
.or_default()
.push(irq.interrupt.clone());
}
// for (s, irqs) in psirqs {
// if irqs.len() != 1 {
// println!("DUPE: {p} {s} {irqs:?}");
// }
// }
}
chip_interrupts.insert((parsed.name, parsed.version), irqs2);
} }
Ok(Self(chip_interrupts)) Ok(Self(chip_interrupts))