stm32/build.rs: switch to using stm32-metapac metadata and quote.

This commit is contained in:
Dario Nieuwenhuis 2022-02-09 00:31:21 +01:00
parent 4d73d87b40
commit 940412c034
2 changed files with 85 additions and 99 deletions

View file

@ -35,7 +35,9 @@ seq-macro = "0.2.2"
cfg-if = "1.0.0"
[build-dependencies]
stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", default-features = false }
proc-macro2 = "1.0.36"
quote = "1.0.15"
stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", default-features = false, features = ["metadata"]}
[features]
sdmmc-rs = ["embedded-sdmmc"]

View file

@ -1,8 +1,10 @@
use std::collections::HashMap;
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use std::collections::HashSet;
use std::env;
use std::fmt::Write;
use std::fs;
use std::path::PathBuf;
use stm32_metapac::metadata::METADATA;
fn main() {
let chip_name = match env::vars()
@ -18,67 +20,50 @@ fn main() {
.unwrap()
.to_ascii_lowercase();
struct Peripheral {
kind: String,
name: String,
version: String,
for p in METADATA.peripherals {
if let Some(r) = &p.registers {
println!("cargo:rustc-cfg={}", r.kind);
println!("cargo:rustc-cfg={}_{}", r.kind, r.version);
}
}
let mut peripheral_version_mapping = HashMap::<String, String>::new();
stm32_metapac::peripheral_versions!(
($peri:ident, $version:ident) => {
peripheral_version_mapping.insert(stringify!($peri).to_string(), stringify!($version).to_string());
println!("cargo:rustc-cfg={}", stringify!($peri));
println!("cargo:rustc-cfg={}_{}", stringify!($peri), stringify!($version));
};
);
let mut peripherals: Vec<Peripheral> = Vec::new();
stm32_metapac::peripherals!(
($kind:ident, $name:ident) => {
peripherals.push(Peripheral{
kind: stringify!($kind).to_string(),
name: stringify!($name).to_string(),
version: peripheral_version_mapping[&stringify!($kind).to_ascii_lowercase()].clone()
});
};
);
// ========
// Generate singletons
let mut singletons: Vec<String> = Vec::new();
for p in peripherals {
match p.kind.as_str() {
// Generate singletons per pin, not per port
"gpio" => {
println!("{}", p.name);
let port_letter = p.name.strip_prefix("GPIO").unwrap();
for pin_num in 0..16 {
singletons.push(format!("P{}{}", port_letter, pin_num));
for p in METADATA.peripherals {
if let Some(r) = &p.registers {
match r.kind {
// Generate singletons per pin, not per port
"gpio" => {
println!("{}", p.name);
let port_letter = p.name.strip_prefix("GPIO").unwrap();
for pin_num in 0..16 {
singletons.push(format!("P{}{}", port_letter, pin_num));
}
}
}
// No singleton for these, the HAL handles them specially.
"exti" => {}
// No singleton for these, the HAL handles them specially.
"exti" => {}
// We *shouldn't* have singletons for these, but the HAL currently requires
// singletons, for using with RccPeripheral to enable/disable clocks to them.
"rcc" => {
if p.version == "h7" {
singletons.push("MCO1".to_string());
singletons.push("MCO2".to_string());
// We *shouldn't* have singletons for these, but the HAL currently requires
// singletons, for using with RccPeripheral to enable/disable clocks to them.
"rcc" => {
if r.version == "h7" {
singletons.push("MCO1".to_string());
singletons.push("MCO2".to_string());
}
singletons.push(p.name.to_string());
}
singletons.push(p.name.clone());
}
//"dbgmcu" => {}
//"syscfg" => {}
//"dma" => {}
//"bdma" => {}
//"dmamux" => {}
//"dbgmcu" => {}
//"syscfg" => {}
//"dma" => {}
//"bdma" => {}
//"dmamux" => {}
// For other peripherals, one singleton per peri
_ => singletons.push(p.name.clone()),
// For other peripherals, one singleton per peri
_ => singletons.push(p.name.to_string()),
}
}
}
@ -88,68 +73,67 @@ fn main() {
}
// One singleton per DMA channel
stm32_metapac::dma_channels! {
($channel_peri:ident, $dma_peri:ident, $version:ident, $channel_num:expr, $ignore:tt) => {
singletons.push(stringify!($channel_peri).to_string());
};
for c in METADATA.dma_channels {
singletons.push(c.name.to_string());
}
let mut generated = String::new();
write!(
&mut generated,
"embassy_hal_common::peripherals!({});\n",
singletons.join(",")
)
.unwrap();
let mut g = TokenStream::new();
let singleton_tokens: Vec<_> = singletons.iter().map(|s| format_ident!("{}", s)).collect();
g.extend(quote! {
embassy_hal_common::peripherals!(#(#singleton_tokens),*);
});
// ========
// Generate DMA IRQs.
// This can't be done with macrotables alone because in many chips, one irq is shared between many
// channels, so we have to deduplicate them.
#[allow(unused_mut)]
let mut dma_irqs: Vec<String> = Vec::new();
#[allow(unused_mut)]
let mut bdma_irqs: Vec<String> = Vec::new();
let mut dma_irqs: HashSet<&str> = HashSet::new();
let mut bdma_irqs: HashSet<&str> = HashSet::new();
stm32_metapac::interrupts! {
($peri:ident, dma, $block:ident, $signal_name:ident, $irq:ident) => {
dma_irqs.push(stringify!($irq).to_string());
};
($peri:ident, bdma, $block:ident, $signal_name:ident, $irq:ident) => {
bdma_irqs.push(stringify!($irq).to_string());
};
for p in METADATA.peripherals {
if let Some(r) = &p.registers {
match r.kind {
"dma" => {
for irq in p.interrupts {
dma_irqs.insert(irq.interrupt);
}
}
"bdma" => {
for irq in p.interrupts {
bdma_irqs.insert(irq.interrupt);
}
}
_ => {}
}
}
}
dma_irqs.sort();
dma_irqs.dedup();
bdma_irqs.sort();
bdma_irqs.dedup();
let tokens: Vec<_> = dma_irqs.iter().map(|s| format_ident!("{}", s)).collect();
g.extend(quote! {
#(
#[crate::interrupt]
unsafe fn #tokens () {
crate::dma::dma::on_irq();
}
)*
});
for irq in dma_irqs {
write!(
&mut generated,
"#[crate::interrupt] unsafe fn {} () {{ crate::dma::dma::on_irq(); }}\n",
irq
)
.unwrap();
}
for irq in bdma_irqs {
write!(
&mut generated,
"#[crate::interrupt] unsafe fn {} () {{ crate::dma::bdma::on_irq(); }}\n",
irq
)
.unwrap();
}
let tokens: Vec<_> = bdma_irqs.iter().map(|s| format_ident!("{}", s)).collect();
g.extend(quote! {
#(
#[crate::interrupt]
unsafe fn #tokens () {
crate::dma::bdma::on_irq();
}
)*
});
// ========
// Write generated.rs
let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
let out_file = out_dir.join("generated.rs").to_string_lossy().to_string();
fs::write(out_file, &generated).unwrap();
fs::write(out_file, g.to_string()).unwrap();
// ========
// Multicore