#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Bus {
Ahb1,
Apb1,
Apb2,
}
impl Bus {
pub fn name(self) -> &'static str {
match self {
Bus::Ahb1 => "AHB1",
Bus::Apb1 => "APB1",
Bus::Apb2 => "APB2",
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct Role {
pub key: &'static str,
pub signal: &'static str,
pub required: bool,
}
const fn req(key: &'static str, signal: &'static str) -> Role {
Role {
key,
signal,
required: true,
}
}
const fn opt(key: &'static str, signal: &'static str) -> Role {
Role {
key,
signal,
required: false,
}
}
struct Kind {
roles: &'static [Role],
}
const USART: Kind = Kind {
roles: &[
req("tx", "TX"),
req("rx", "RX"),
opt("cts", "CTS"),
opt("rts", "RTS"),
opt("ck", "CK"),
],
};
const SPI: Kind = Kind {
roles: &[
req("mosi", "MOSI"),
req("miso", "MISO"),
req("sck", "SCK"),
opt("nss", "NSS"),
],
};
const I2C: Kind = Kind {
roles: &[req("sda", "SDA"), req("scl", "SCL"), opt("smba", "SMBA")],
};
const TIM: Kind = Kind {
roles: &[
opt("channel1", "CH1"),
opt("channel2", "CH2"),
opt("channel3", "CH3"),
opt("channel4", "CH4"),
],
};
pub fn roles_for(instance: &str) -> Option<&'static [Role]> {
let kind = instance.trim_end_matches(|c: char| c.is_ascii_digit());
let kind = match kind {
"usart" | "uart" => &USART,
"spi" => &SPI,
"i2c" | "fmpi2c" => &I2C,
"tim" => &TIM,
_ => return None,
};
Some(kind.roles)
}
pub fn peripheral_name(instance: &str) -> String {
instance.to_ascii_uppercase()
}
pub fn peripheral_bus(peripheral: &str) -> Option<Bus> {
let p = peripheral;
let bus = match p {
"USART1" | "USART6" | "SPI1" | "SPI4" | "SDIO" | "ADC1" | "ADC2" | "ADC3" | "SAI1"
| "SAI2" | "TIM1" | "TIM8" | "TIM9" | "TIM10" | "TIM11" => Bus::Apb2,
"USART2" | "USART3" | "UART4" | "UART5" | "SPI2" | "SPI3" | "I2C1" | "I2C2" | "I2C3"
| "FMPI2C1" | "CAN1" | "CAN2" | "SPDIFRX" | "CEC" | "TIM2" | "TIM3" | "TIM4" | "TIM5"
| "TIM6" | "TIM7" | "TIM12" | "TIM13" | "TIM14" => Bus::Apb1,
"DCMI" | "QUADSPI" | "FMC" => Bus::Ahb1,
_ => return None,
};
Some(bus)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn role_tables_resolve_by_prefix() {
assert!(roles_for("usart2").is_some());
assert!(roles_for("spi1").is_some());
assert!(roles_for("i2c3").is_some());
assert!(roles_for("tim2").is_some());
assert!(roles_for("wibble9").is_none());
}
#[test]
fn spi_required_and_optional() {
let roles = roles_for("spi1").unwrap();
let nss = roles.iter().find(|r| r.key == "nss").unwrap();
let sck = roles.iter().find(|r| r.key == "sck").unwrap();
assert!(!nss.required);
assert!(sck.required);
}
#[test]
fn buses_match_f446() {
assert_eq!(peripheral_bus("SPI1"), Some(Bus::Apb2));
assert_eq!(peripheral_bus("USART2"), Some(Bus::Apb1));
assert_eq!(peripheral_bus("I2C1"), Some(Bus::Apb1));
assert_eq!(peripheral_bus("MADEUP"), None);
}
}