stm32-metapac: add option to generate chip metadata as a rust const.

This commit is contained in:
Dario Nieuwenhuis 2022-02-09 00:28:05 +01:00
parent 2cf79f6569
commit 4d73d87b40
3 changed files with 170 additions and 9 deletions

View File

@ -0,0 +1,97 @@
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Metadata {
pub name: &'static str,
pub family: &'static str,
pub line: &'static str,
pub memory: &'static [MemoryRegion],
pub peripherals: &'static [Peripheral],
pub interrupts: &'static [Interrupt],
pub dma_channels: &'static [DmaChannel],
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct MemoryRegion {
pub name: &'static str,
pub kind: MemoryRegionKind,
pub address: u32,
pub size: u32,
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum MemoryRegionKind {
Flash,
Ram,
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Interrupt {
pub name: &'static str,
pub number: u32,
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Package {
pub name: &'static str,
pub package: &'static str,
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Peripheral {
pub name: &'static str,
pub address: u64,
pub registers: Option<PeripheralRegisters>,
pub rcc: Option<PeripheralRcc>,
pub pins: &'static [PeripheralPin],
pub dma_channels: &'static [PeripheralDmaChannel],
pub interrupts: &'static [PeripheralInterrupt],
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct PeripheralRegisters {
pub kind: &'static str,
pub version: &'static str,
pub block: &'static str,
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct PeripheralInterrupt {
pub signal: &'static str,
pub interrupt: &'static str,
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct PeripheralRcc {
pub clock: &'static str,
pub enable: Option<PeripheralRccRegister>,
pub reset: Option<PeripheralRccRegister>,
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct PeripheralRccRegister {
pub register: &'static str,
pub field: &'static str,
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct PeripheralPin {
pub pin: &'static str,
pub signal: &'static str,
pub af: Option<&'static str>,
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct DmaChannel {
pub name: &'static str,
pub dma: &'static str,
pub channel: u32,
pub dmamux: Option<&'static str>,
pub dmamux_channel: Option<u32>,
}
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct PeripheralDmaChannel {
pub signal: &'static str,
pub channel: Option<&'static str>,
pub dmamux: Option<&'static str>,
pub request: Option<u32>,
}

View File

@ -16,6 +16,17 @@ use chiptool::{generate, ir, transform};
mod data; mod data;
use data::*; use data::*;
#[derive(Debug, Eq, PartialEq, Clone)]
struct Metadata<'a> {
name: &'a str,
family: &'a str,
line: &'a str,
memory: &'a [MemoryRegion],
peripherals: &'a [Peripheral],
interrupts: &'a [Interrupt],
dma_channels: &'a [DmaChannel],
}
fn make_peripheral_counts(out: &mut String, data: &BTreeMap<String, u8>) { fn make_peripheral_counts(out: &mut String, data: &BTreeMap<String, u8>) {
write!( write!(
out, out,
@ -384,12 +395,7 @@ pub fn gen_chip(
let mut device_x = String::new(); let mut device_x = String::new();
for irq in &core.interrupts { for irq in &core.interrupts {
write!( write!(&mut device_x, "PROVIDE({} = DefaultHandler);\n", irq.name).unwrap();
&mut device_x,
"PROVIDE({} = DefaultHandler);\n",
irq.name.to_ascii_uppercase()
)
.unwrap();
} }
// ============================== // ==============================
@ -397,6 +403,7 @@ pub fn gen_chip(
let mut data = String::new(); let mut data = String::new();
write!(&mut data, "#[cfg(feature=\"metadata\")] pub mod metadata;").unwrap();
write!(&mut data, "#[cfg(feature=\"pac\")] mod pac;").unwrap(); write!(&mut data, "#[cfg(feature=\"pac\")] mod pac;").unwrap();
write!(&mut data, "#[cfg(feature=\"pac\")] pub use pac::*; ").unwrap(); write!(&mut data, "#[cfg(feature=\"pac\")] pub use pac::*; ").unwrap();
@ -424,6 +431,38 @@ pub fn gen_chip(
let mut file = File::create(chip_dir.join("mod.rs")).unwrap(); let mut file = File::create(chip_dir.join("mod.rs")).unwrap();
file.write_all(data.as_bytes()).unwrap(); file.write_all(data.as_bytes()).unwrap();
// ==============================
// generate metadata.rs
let metadata = Metadata {
name: &chip.name,
family: &chip.family,
line: &chip.line,
memory: &chip.memory,
peripherals: &core.peripherals,
interrupts: &core.interrupts,
dma_channels: &core.dma_channels,
};
let metadata = format!("{:#?}", metadata);
let metadata = metadata.replace("[\n", "&[\n");
let metadata = metadata.replace("[],\n", "&[],\n");
let mut data = String::new();
write!(
&mut data,
"
include!(\"../../metadata.rs\");
use MemoryRegionKind::*;
pub const METADATA: Metadata = {};
",
metadata
)
.unwrap();
let mut file = File::create(chip_dir.join("metadata.rs")).unwrap();
file.write_all(data.as_bytes()).unwrap();
// ============================== // ==============================
// generate device.x // generate device.x
@ -462,7 +501,21 @@ pub fn gen(options: Options) {
for chip_name in &options.chips { for chip_name in &options.chips {
println!("Generating {}...", chip_name); println!("Generating {}...", chip_name);
let chip = load_chip(&options, chip_name); let mut chip = load_chip(&options, chip_name);
// Cleanup
for core in &mut chip.cores {
for irq in &mut core.interrupts {
irq.name = irq.name.to_ascii_uppercase();
}
for p in &mut core.peripherals {
for irq in &mut p.interrupts {
irq.interrupt = irq.interrupt.to_ascii_uppercase();
}
}
}
// Generate
for (core_index, core) in chip.cores.iter().enumerate() { for (core_index, core) in chip.cores.iter().enumerate() {
let chip_core_name = match chip.cores.len() { let chip_core_name = match chip.cores.len() {
1 => chip_name.clone(), 1 => chip_name.clone(),
@ -557,6 +610,13 @@ pub fn gen(options: Options) {
) )
.unwrap(); .unwrap();
// Generate src/metadata.rs
fs::write(
options.out_dir.join("src").join("metadata.rs"),
include_bytes!("assets/metadata.rs"),
)
.unwrap();
// Generate Cargo.toml // Generate Cargo.toml
const BUILDDEP_BEGIN: &[u8] = b"# BEGIN BUILD DEPENDENCIES"; const BUILDDEP_BEGIN: &[u8] = b"# BEGIN BUILD DEPENDENCIES";
const BUILDDEP_END: &[u8] = b"# END BUILD DEPENDENCIES"; const BUILDDEP_END: &[u8] = b"# END BUILD DEPENDENCIES";

View File

@ -19,10 +19,14 @@ regex = "1.5.4"
default = ["pac"] default = ["pac"]
# Build the actual PAC. Set by default. # Build the actual PAC. Set by default.
# If not set, only the macrotables will be generated. You may want to not set it # If you just want the metadata, unset it with `default-features = false`.
# if you're using stm32-metapac from a build.rs script to use the macros.
pac = [] pac = []
# Build the chip metadata.
# If set, a const `stm32_metapac::METADATA` will be exported, containing all the
# metadata for the currently selected chip.
metadata = []
rt = ["cortex-m-rt/device"] rt = ["cortex-m-rt/device"]
memory-x = [] memory-x = []