stm32/build.rs: switch to using stm32-metapac metadata and quote.
This commit is contained in:
parent
4d73d87b40
commit
940412c034
@ -35,7 +35,9 @@ seq-macro = "0.2.2"
|
|||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[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]
|
[features]
|
||||||
sdmmc-rs = ["embedded-sdmmc"]
|
sdmmc-rs = ["embedded-sdmmc"]
|
||||||
|
@ -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::env;
|
||||||
use std::fmt::Write;
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use stm32_metapac::metadata::METADATA;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let chip_name = match env::vars()
|
let chip_name = match env::vars()
|
||||||
@ -18,67 +20,50 @@ fn main() {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.to_ascii_lowercase();
|
.to_ascii_lowercase();
|
||||||
|
|
||||||
struct Peripheral {
|
for p in METADATA.peripherals {
|
||||||
kind: String,
|
if let Some(r) = &p.registers {
|
||||||
name: String,
|
println!("cargo:rustc-cfg={}", r.kind);
|
||||||
version: String,
|
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
|
// Generate singletons
|
||||||
|
|
||||||
let mut singletons: Vec<String> = Vec::new();
|
let mut singletons: Vec<String> = Vec::new();
|
||||||
for p in peripherals {
|
for p in METADATA.peripherals {
|
||||||
match p.kind.as_str() {
|
if let Some(r) = &p.registers {
|
||||||
// Generate singletons per pin, not per port
|
match r.kind {
|
||||||
"gpio" => {
|
// Generate singletons per pin, not per port
|
||||||
println!("{}", p.name);
|
"gpio" => {
|
||||||
let port_letter = p.name.strip_prefix("GPIO").unwrap();
|
println!("{}", p.name);
|
||||||
for pin_num in 0..16 {
|
let port_letter = p.name.strip_prefix("GPIO").unwrap();
|
||||||
singletons.push(format!("P{}{}", port_letter, pin_num));
|
for pin_num in 0..16 {
|
||||||
|
singletons.push(format!("P{}{}", port_letter, pin_num));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// No singleton for these, the HAL handles them specially.
|
// No singleton for these, the HAL handles them specially.
|
||||||
"exti" => {}
|
"exti" => {}
|
||||||
|
|
||||||
// We *shouldn't* have singletons for these, but the HAL currently requires
|
// We *shouldn't* have singletons for these, but the HAL currently requires
|
||||||
// singletons, for using with RccPeripheral to enable/disable clocks to them.
|
// singletons, for using with RccPeripheral to enable/disable clocks to them.
|
||||||
"rcc" => {
|
"rcc" => {
|
||||||
if p.version == "h7" {
|
if r.version == "h7" {
|
||||||
singletons.push("MCO1".to_string());
|
singletons.push("MCO1".to_string());
|
||||||
singletons.push("MCO2".to_string());
|
singletons.push("MCO2".to_string());
|
||||||
|
}
|
||||||
|
singletons.push(p.name.to_string());
|
||||||
}
|
}
|
||||||
singletons.push(p.name.clone());
|
//"dbgmcu" => {}
|
||||||
}
|
//"syscfg" => {}
|
||||||
//"dbgmcu" => {}
|
//"dma" => {}
|
||||||
//"syscfg" => {}
|
//"bdma" => {}
|
||||||
//"dma" => {}
|
//"dmamux" => {}
|
||||||
//"bdma" => {}
|
|
||||||
//"dmamux" => {}
|
|
||||||
|
|
||||||
// For other peripherals, one singleton per peri
|
// For other peripherals, one singleton per peri
|
||||||
_ => singletons.push(p.name.clone()),
|
_ => singletons.push(p.name.to_string()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,68 +73,67 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// One singleton per DMA channel
|
// One singleton per DMA channel
|
||||||
stm32_metapac::dma_channels! {
|
for c in METADATA.dma_channels {
|
||||||
($channel_peri:ident, $dma_peri:ident, $version:ident, $channel_num:expr, $ignore:tt) => {
|
singletons.push(c.name.to_string());
|
||||||
singletons.push(stringify!($channel_peri).to_string());
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut generated = String::new();
|
let mut g = TokenStream::new();
|
||||||
write!(
|
|
||||||
&mut generated,
|
let singleton_tokens: Vec<_> = singletons.iter().map(|s| format_ident!("{}", s)).collect();
|
||||||
"embassy_hal_common::peripherals!({});\n",
|
g.extend(quote! {
|
||||||
singletons.join(",")
|
embassy_hal_common::peripherals!(#(#singleton_tokens),*);
|
||||||
)
|
});
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// ========
|
// ========
|
||||||
// Generate DMA IRQs.
|
// 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: HashSet<&str> = HashSet::new();
|
||||||
let mut dma_irqs: Vec<String> = Vec::new();
|
let mut bdma_irqs: HashSet<&str> = HashSet::new();
|
||||||
#[allow(unused_mut)]
|
|
||||||
let mut bdma_irqs: Vec<String> = Vec::new();
|
|
||||||
|
|
||||||
stm32_metapac::interrupts! {
|
for p in METADATA.peripherals {
|
||||||
($peri:ident, dma, $block:ident, $signal_name:ident, $irq:ident) => {
|
if let Some(r) = &p.registers {
|
||||||
dma_irqs.push(stringify!($irq).to_string());
|
match r.kind {
|
||||||
};
|
"dma" => {
|
||||||
($peri:ident, bdma, $block:ident, $signal_name:ident, $irq:ident) => {
|
for irq in p.interrupts {
|
||||||
bdma_irqs.push(stringify!($irq).to_string());
|
dma_irqs.insert(irq.interrupt);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
"bdma" => {
|
||||||
|
for irq in p.interrupts {
|
||||||
|
bdma_irqs.insert(irq.interrupt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dma_irqs.sort();
|
let tokens: Vec<_> = dma_irqs.iter().map(|s| format_ident!("{}", s)).collect();
|
||||||
dma_irqs.dedup();
|
g.extend(quote! {
|
||||||
bdma_irqs.sort();
|
#(
|
||||||
bdma_irqs.dedup();
|
#[crate::interrupt]
|
||||||
|
unsafe fn #tokens () {
|
||||||
|
crate::dma::dma::on_irq();
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
});
|
||||||
|
|
||||||
for irq in dma_irqs {
|
let tokens: Vec<_> = bdma_irqs.iter().map(|s| format_ident!("{}", s)).collect();
|
||||||
write!(
|
g.extend(quote! {
|
||||||
&mut generated,
|
#(
|
||||||
"#[crate::interrupt] unsafe fn {} () {{ crate::dma::dma::on_irq(); }}\n",
|
#[crate::interrupt]
|
||||||
irq
|
unsafe fn #tokens () {
|
||||||
)
|
crate::dma::bdma::on_irq();
|
||||||
.unwrap();
|
}
|
||||||
}
|
)*
|
||||||
|
});
|
||||||
for irq in bdma_irqs {
|
|
||||||
write!(
|
|
||||||
&mut generated,
|
|
||||||
"#[crate::interrupt] unsafe fn {} () {{ crate::dma::bdma::on_irq(); }}\n",
|
|
||||||
irq
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========
|
// ========
|
||||||
// Write generated.rs
|
// Write generated.rs
|
||||||
|
|
||||||
let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||||
let out_file = out_dir.join("generated.rs").to_string_lossy().to_string();
|
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
|
// Multicore
|
||||||
|
Loading…
Reference in New Issue
Block a user