Merge pull request #254 from JuliDi/dont-remove-analogswitch-pins

Handle "_C" pins
This commit is contained in:
xoviat 2023-09-30 15:28:30 +00:00 committed by GitHub
commit 8ee2862086
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 62 additions and 78 deletions

2
Cargo.lock generated
View File

@ -620,6 +620,8 @@ version = "0.1.0"
dependencies = [ dependencies = [
"itertools", "itertools",
"rayon", "rayon",
"ref_thread_local",
"regex",
"serde", "serde",
"serde_json", "serde_json",
] ]

View File

@ -68,7 +68,7 @@ pub struct ChipGroup {
chip_names: Vec<String>, chip_names: Vec<String>,
xml: xml::Mcu, xml: xml::Mcu,
ips: HashMap<String, xml::Ip>, ips: HashMap<String, xml::Ip>,
pins: HashMap<stm32_data_serde::chip::core::peripheral::pin::Pin, xml::Pin>, pins: HashMap<String, xml::Pin>,
family: Option<String>, family: Option<String>,
line: Option<String>, line: Option<String>,
die: Option<String>, die: Option<String>,
@ -503,18 +503,20 @@ fn merge_periph_pins_info(
} }
// covert to hashmap // covert to hashmap
let af_pins: HashMap<(stm32_data_serde::chip::core::peripheral::pin::Pin, &str), Option<u8>> = let af_pins: HashMap<(&str, &str), Option<u8>> = af_pins
af_pins.iter().map(|v| ((v.pin, v.signal.as_str()), v.af)).collect(); .iter()
.map(|v| ((v.pin.as_str(), v.signal.as_str()), v.af))
.collect();
for pin in core_pins { for pin in core_pins {
let af = af_pins.get(&(pin.pin, &pin.signal)).copied().flatten(); let af = af_pins.get(&(&pin.pin, &pin.signal)).copied().flatten();
// try to look for a signal with another name // try to look for a signal with another name
let af = af.or_else(|| { let af = af.or_else(|| {
if pin.signal == "CTS" { if pin.signal == "CTS" {
// for some godforsaken reason UART4's and UART5's CTS are called CTS_NSS in the GPIO xml // for some godforsaken reason UART4's and UART5's CTS are called CTS_NSS in the GPIO xml
// so try to match with these // so try to match with these
af_pins.get(&(pin.pin, "CTS_NSS")).copied().flatten() af_pins.get(&(pin.pin.as_str(), "CTS_NSS")).copied().flatten()
} else if periph_name == "I2C1" { } else if periph_name == "I2C1" {
// it appears that for __some__ STM32 MCUs there is no AFIO specified in GPIO file // it appears that for __some__ STM32 MCUs there is no AFIO specified in GPIO file
// (notably - STM32F030C6 with it's I2C1 on PF6 and PF7) // (notably - STM32F030C6 with it's I2C1 on PF6 and PF7)
@ -910,7 +912,7 @@ fn process_core(
if let Some(signal) = signal.strip_prefix(&format!("{periph}_")) { if let Some(signal) = signal.strip_prefix(&format!("{periph}_")) {
periph_pins.entry(periph.to_string()).or_default().push( periph_pins.entry(periph.to_string()).or_default().push(
stm32_data_serde::chip::core::peripheral::Pin { stm32_data_serde::chip::core::peripheral::Pin {
pin: *pin_name, pin: pin_name.clone(),
signal: signal.to_string(), signal: signal.to_string(),
af: None, af: None,
}, },
@ -1002,7 +1004,7 @@ fn process_core(
} }
p.pins.extend(i2s_pins.iter().map(|p| Pin { p.pins.extend(i2s_pins.iter().map(|p| Pin {
pin: p.pin, pin: p.pin.clone(),
signal: "I2S_".to_owned() + &p.signal, signal: "I2S_".to_owned() + &p.signal,
af: p.af, af: p.af,
})); }));

View File

@ -38,16 +38,9 @@ mod xml {
} }
} }
pub fn clean_pin(pin_name: &str) -> Option<stm32_data_serde::chip::core::peripheral::pin::Pin> { pub fn clean_pin(pin_name: &str) -> Option<String> {
// some H7s have analog-only pins like PC2_C, PC3_C. Ignore these for now since the // Some H7 chips have additonal "_C" pins.
// data model can't deal with pins that are not part of a GPIO port yet. Some(regex!(r"^P[A-Z]\d+(?:_C)?").find(pin_name)?.as_str().into())
if regex!(r"^P[A-Z]\d+_C$").is_match(pin_name) {
return None;
}
let pin_name = regex!(r"^P[A-Z]\d+").find(pin_name)?.as_str();
stm32_data_serde::chip::core::peripheral::pin::Pin::parse(pin_name)
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
@ -87,7 +80,7 @@ impl Af {
}; };
peris.entry(peri_name.to_string()).or_default().push( peris.entry(peri_name.to_string()).or_default().push(
stm32_data_serde::chip::core::peripheral::Pin { stm32_data_serde::chip::core::peripheral::Pin {
pin: pin_name, pin: pin_name.clone(),
signal: signal_name.to_string(), signal: signal_name.to_string(),
af: afn, af: afn,
}, },

View File

@ -7,6 +7,8 @@ edition = "2021"
[dependencies] [dependencies]
serde = { version = "1.0.157", features = ["derive"] } serde = { version = "1.0.157", features = ["derive"] }
regex = "1.7.1"
ref_thread_local = "0.1.1"
[dev-dependencies] [dev-dependencies]
itertools = "0.10.5" itertools = "0.10.5"

View File

@ -1,5 +1,15 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[macro_export]
macro_rules! regex {
($re:literal) => {{
::ref_thread_local::ref_thread_local! {
static managed REGEX: ::regex::Regex = ::regex::Regex::new($re).unwrap();
}
<REGEX as ::ref_thread_local::RefThreadLocal<::regex::Regex>>::borrow(&REGEX)
}};
}
#[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Chip { pub struct Chip {
pub name: String, pub name: String,
@ -121,76 +131,51 @@ pub mod chip {
} }
} }
#[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub struct Pin { pub struct Pin {
pub pin: pin::Pin, pub pin: String,
pub signal: String, pub signal: String,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub af: Option<u8>, pub af: Option<u8>,
} }
pub mod pin { fn extract_port_and_pin(pin: &str) -> (char, u8) {
use serde::{Deserialize, Serialize}; let captures = regex!(r"^P([A-Z])(\d+)(?:_C)?")
.captures(pin)
.expect("Could not match regex on pin");
let port = captures
.get(1)
.expect("Could not extract port")
.as_str()
.chars()
.next()
.expect("Empty port");
let pin_number = captures
.get(2)
.expect("Could not extract pin number")
.as_str()
.parse::<u8>()
.expect("Could not parse pin number to u8");
(port, pin_number)
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)] impl Ord for Pin {
pub struct Pin { fn cmp(&self, other: &Self) -> std::cmp::Ordering {
pub port: char, let (port_a, pin_number_a) = extract_port_and_pin(&self.pin);
pub num: u8, let (port_b, pin_number_b) = extract_port_and_pin(&other.pin);
}
impl Pin { if port_a != port_b {
pub fn parse(pin: &str) -> Option<Self> { port_a.cmp(&port_b)
let mut chars = pin.chars(); } else if pin_number_a != pin_number_b {
let p = chars.next()?; pin_number_a.cmp(&pin_number_b)
if p != 'P' { } else {
return None; self.signal.cmp(&other.signal)
}
let port = chars.next()?;
let num = chars.as_str().parse().ok()?;
Some(Self { port, num })
} }
} }
}
impl std::fmt::Display for Pin { impl PartialOrd for Pin {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
write!(f, "P{}{}", self.port, self.num) Some(self.cmp(other))
}
}
impl Serialize for Pin {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&format!("{self}"))
}
}
struct PinVisitor;
impl<'de> serde::de::Visitor<'de> for PinVisitor {
type Value = Pin;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("pin")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Pin::parse(v).unwrap())
}
}
impl<'de> Deserialize<'de> for Pin {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_str(PinVisitor)
}
} }
} }