diff options
| author | Dario Nieuwenhuis <[email protected]> | 2022-02-09 00:28:05 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2022-02-09 00:28:05 +0100 |
| commit | 4d73d87b40ae9530681c8d0461810aae85430669 (patch) | |
| tree | a4e89d12a8420a0d0cb47d009b7b14dc8dca7439 | |
| parent | 2cf79f6569a7d65d70599a62642c7bc353abd692 (diff) | |
stm32-metapac: add option to generate chip metadata as a rust const.
| -rw-r--r-- | stm32-metapac-gen/src/assets/metadata.rs | 97 | ||||
| -rw-r--r-- | stm32-metapac-gen/src/lib.rs | 74 | ||||
| -rw-r--r-- | stm32-metapac/Cargo.toml | 8 |
3 files changed, 170 insertions, 9 deletions
diff --git a/stm32-metapac-gen/src/assets/metadata.rs b/stm32-metapac-gen/src/assets/metadata.rs new file mode 100644 index 000000000..7fe49ceba --- /dev/null +++ b/stm32-metapac-gen/src/assets/metadata.rs | |||
| @@ -0,0 +1,97 @@ | |||
| 1 | #[derive(Debug, Eq, PartialEq, Clone)] | ||
| 2 | pub struct Metadata { | ||
| 3 | pub name: &'static str, | ||
| 4 | pub family: &'static str, | ||
| 5 | pub line: &'static str, | ||
| 6 | pub memory: &'static [MemoryRegion], | ||
| 7 | pub peripherals: &'static [Peripheral], | ||
| 8 | pub interrupts: &'static [Interrupt], | ||
| 9 | pub dma_channels: &'static [DmaChannel], | ||
| 10 | } | ||
| 11 | |||
| 12 | #[derive(Debug, Eq, PartialEq, Clone)] | ||
| 13 | pub struct MemoryRegion { | ||
| 14 | pub name: &'static str, | ||
| 15 | pub kind: MemoryRegionKind, | ||
| 16 | pub address: u32, | ||
| 17 | pub size: u32, | ||
| 18 | } | ||
| 19 | |||
| 20 | #[derive(Debug, Eq, PartialEq, Clone)] | ||
| 21 | pub enum MemoryRegionKind { | ||
| 22 | Flash, | ||
| 23 | Ram, | ||
| 24 | } | ||
| 25 | |||
| 26 | #[derive(Debug, Eq, PartialEq, Clone)] | ||
| 27 | pub struct Interrupt { | ||
| 28 | pub name: &'static str, | ||
| 29 | pub number: u32, | ||
| 30 | } | ||
| 31 | |||
| 32 | #[derive(Debug, Eq, PartialEq, Clone)] | ||
| 33 | pub struct Package { | ||
| 34 | pub name: &'static str, | ||
| 35 | pub package: &'static str, | ||
| 36 | } | ||
| 37 | |||
| 38 | #[derive(Debug, Eq, PartialEq, Clone)] | ||
| 39 | pub struct Peripheral { | ||
| 40 | pub name: &'static str, | ||
| 41 | pub address: u64, | ||
| 42 | pub registers: Option<PeripheralRegisters>, | ||
| 43 | pub rcc: Option<PeripheralRcc>, | ||
| 44 | pub pins: &'static [PeripheralPin], | ||
| 45 | pub dma_channels: &'static [PeripheralDmaChannel], | ||
| 46 | pub interrupts: &'static [PeripheralInterrupt], | ||
| 47 | } | ||
| 48 | |||
| 49 | #[derive(Debug, Eq, PartialEq, Clone)] | ||
| 50 | pub struct PeripheralRegisters { | ||
| 51 | pub kind: &'static str, | ||
| 52 | pub version: &'static str, | ||
| 53 | pub block: &'static str, | ||
| 54 | } | ||
| 55 | |||
| 56 | #[derive(Debug, Eq, PartialEq, Clone)] | ||
| 57 | pub struct PeripheralInterrupt { | ||
| 58 | pub signal: &'static str, | ||
| 59 | pub interrupt: &'static str, | ||
| 60 | } | ||
| 61 | |||
| 62 | #[derive(Debug, Eq, PartialEq, Clone)] | ||
| 63 | pub struct PeripheralRcc { | ||
| 64 | pub clock: &'static str, | ||
| 65 | pub enable: Option<PeripheralRccRegister>, | ||
| 66 | pub reset: Option<PeripheralRccRegister>, | ||
| 67 | } | ||
| 68 | |||
| 69 | #[derive(Debug, Eq, PartialEq, Clone)] | ||
| 70 | pub struct PeripheralRccRegister { | ||
| 71 | pub register: &'static str, | ||
| 72 | pub field: &'static str, | ||
| 73 | } | ||
| 74 | |||
| 75 | #[derive(Debug, Eq, PartialEq, Clone)] | ||
| 76 | pub struct PeripheralPin { | ||
| 77 | pub pin: &'static str, | ||
| 78 | pub signal: &'static str, | ||
| 79 | pub af: Option<&'static str>, | ||
| 80 | } | ||
| 81 | |||
| 82 | #[derive(Debug, Eq, PartialEq, Clone)] | ||
| 83 | pub struct DmaChannel { | ||
| 84 | pub name: &'static str, | ||
| 85 | pub dma: &'static str, | ||
| 86 | pub channel: u32, | ||
| 87 | pub dmamux: Option<&'static str>, | ||
| 88 | pub dmamux_channel: Option<u32>, | ||
| 89 | } | ||
| 90 | |||
| 91 | #[derive(Debug, Eq, PartialEq, Clone)] | ||
| 92 | pub struct PeripheralDmaChannel { | ||
| 93 | pub signal: &'static str, | ||
| 94 | pub channel: Option<&'static str>, | ||
| 95 | pub dmamux: Option<&'static str>, | ||
| 96 | pub request: Option<u32>, | ||
| 97 | } | ||
diff --git a/stm32-metapac-gen/src/lib.rs b/stm32-metapac-gen/src/lib.rs index fd8da8a6f..ccf737eff 100644 --- a/stm32-metapac-gen/src/lib.rs +++ b/stm32-metapac-gen/src/lib.rs | |||
| @@ -16,6 +16,17 @@ use chiptool::{generate, ir, transform}; | |||
| 16 | mod data; | 16 | mod data; |
| 17 | use data::*; | 17 | use data::*; |
| 18 | 18 | ||
| 19 | #[derive(Debug, Eq, PartialEq, Clone)] | ||
| 20 | struct Metadata<'a> { | ||
| 21 | name: &'a str, | ||
| 22 | family: &'a str, | ||
| 23 | line: &'a str, | ||
| 24 | memory: &'a [MemoryRegion], | ||
| 25 | peripherals: &'a [Peripheral], | ||
| 26 | interrupts: &'a [Interrupt], | ||
| 27 | dma_channels: &'a [DmaChannel], | ||
| 28 | } | ||
| 29 | |||
| 19 | fn make_peripheral_counts(out: &mut String, data: &BTreeMap<String, u8>) { | 30 | fn make_peripheral_counts(out: &mut String, data: &BTreeMap<String, u8>) { |
| 20 | write!( | 31 | write!( |
| 21 | out, | 32 | out, |
| @@ -384,12 +395,7 @@ pub fn gen_chip( | |||
| 384 | let mut device_x = String::new(); | 395 | let mut device_x = String::new(); |
| 385 | 396 | ||
| 386 | for irq in &core.interrupts { | 397 | for irq in &core.interrupts { |
| 387 | write!( | 398 | write!(&mut device_x, "PROVIDE({} = DefaultHandler);\n", irq.name).unwrap(); |
| 388 | &mut device_x, | ||
| 389 | "PROVIDE({} = DefaultHandler);\n", | ||
| 390 | irq.name.to_ascii_uppercase() | ||
| 391 | ) | ||
| 392 | .unwrap(); | ||
| 393 | } | 399 | } |
| 394 | 400 | ||
| 395 | // ============================== | 401 | // ============================== |
| @@ -397,6 +403,7 @@ pub fn gen_chip( | |||
| 397 | 403 | ||
| 398 | let mut data = String::new(); | 404 | let mut data = String::new(); |
| 399 | 405 | ||
| 406 | write!(&mut data, "#[cfg(feature=\"metadata\")] pub mod metadata;").unwrap(); | ||
| 400 | write!(&mut data, "#[cfg(feature=\"pac\")] mod pac;").unwrap(); | 407 | write!(&mut data, "#[cfg(feature=\"pac\")] mod pac;").unwrap(); |
| 401 | write!(&mut data, "#[cfg(feature=\"pac\")] pub use pac::*; ").unwrap(); | 408 | write!(&mut data, "#[cfg(feature=\"pac\")] pub use pac::*; ").unwrap(); |
| 402 | 409 | ||
| @@ -425,6 +432,38 @@ pub fn gen_chip( | |||
| 425 | file.write_all(data.as_bytes()).unwrap(); | 432 | file.write_all(data.as_bytes()).unwrap(); |
| 426 | 433 | ||
| 427 | // ============================== | 434 | // ============================== |
| 435 | // generate metadata.rs | ||
| 436 | |||
| 437 | let metadata = Metadata { | ||
| 438 | name: &chip.name, | ||
| 439 | family: &chip.family, | ||
| 440 | line: &chip.line, | ||
| 441 | memory: &chip.memory, | ||
| 442 | peripherals: &core.peripherals, | ||
| 443 | interrupts: &core.interrupts, | ||
| 444 | dma_channels: &core.dma_channels, | ||
| 445 | }; | ||
| 446 | let metadata = format!("{:#?}", metadata); | ||
| 447 | let metadata = metadata.replace("[\n", "&[\n"); | ||
| 448 | let metadata = metadata.replace("[],\n", "&[],\n"); | ||
| 449 | |||
| 450 | let mut data = String::new(); | ||
| 451 | |||
| 452 | write!( | ||
| 453 | &mut data, | ||
| 454 | " | ||
| 455 | include!(\"../../metadata.rs\"); | ||
| 456 | use MemoryRegionKind::*; | ||
| 457 | pub const METADATA: Metadata = {}; | ||
| 458 | ", | ||
| 459 | metadata | ||
| 460 | ) | ||
| 461 | .unwrap(); | ||
| 462 | |||
| 463 | let mut file = File::create(chip_dir.join("metadata.rs")).unwrap(); | ||
| 464 | file.write_all(data.as_bytes()).unwrap(); | ||
| 465 | |||
| 466 | // ============================== | ||
| 428 | // generate device.x | 467 | // generate device.x |
| 429 | 468 | ||
| 430 | File::create(chip_dir.join("device.x")) | 469 | File::create(chip_dir.join("device.x")) |
| @@ -462,7 +501,21 @@ pub fn gen(options: Options) { | |||
| 462 | for chip_name in &options.chips { | 501 | for chip_name in &options.chips { |
| 463 | println!("Generating {}...", chip_name); | 502 | println!("Generating {}...", chip_name); |
| 464 | 503 | ||
| 465 | let chip = load_chip(&options, chip_name); | 504 | let mut chip = load_chip(&options, chip_name); |
| 505 | |||
| 506 | // Cleanup | ||
| 507 | for core in &mut chip.cores { | ||
| 508 | for irq in &mut core.interrupts { | ||
| 509 | irq.name = irq.name.to_ascii_uppercase(); | ||
| 510 | } | ||
| 511 | for p in &mut core.peripherals { | ||
| 512 | for irq in &mut p.interrupts { | ||
| 513 | irq.interrupt = irq.interrupt.to_ascii_uppercase(); | ||
| 514 | } | ||
| 515 | } | ||
| 516 | } | ||
| 517 | |||
| 518 | // Generate | ||
| 466 | for (core_index, core) in chip.cores.iter().enumerate() { | 519 | for (core_index, core) in chip.cores.iter().enumerate() { |
| 467 | let chip_core_name = match chip.cores.len() { | 520 | let chip_core_name = match chip.cores.len() { |
| 468 | 1 => chip_name.clone(), | 521 | 1 => chip_name.clone(), |
| @@ -557,6 +610,13 @@ pub fn gen(options: Options) { | |||
| 557 | ) | 610 | ) |
| 558 | .unwrap(); | 611 | .unwrap(); |
| 559 | 612 | ||
| 613 | // Generate src/metadata.rs | ||
| 614 | fs::write( | ||
| 615 | options.out_dir.join("src").join("metadata.rs"), | ||
| 616 | include_bytes!("assets/metadata.rs"), | ||
| 617 | ) | ||
| 618 | .unwrap(); | ||
| 619 | |||
| 560 | // Generate Cargo.toml | 620 | // Generate Cargo.toml |
| 561 | const BUILDDEP_BEGIN: &[u8] = b"# BEGIN BUILD DEPENDENCIES"; | 621 | const BUILDDEP_BEGIN: &[u8] = b"# BEGIN BUILD DEPENDENCIES"; |
| 562 | const BUILDDEP_END: &[u8] = b"# END BUILD DEPENDENCIES"; | 622 | const BUILDDEP_END: &[u8] = b"# END BUILD DEPENDENCIES"; |
diff --git a/stm32-metapac/Cargo.toml b/stm32-metapac/Cargo.toml index 4115da349..5642af46e 100644 --- a/stm32-metapac/Cargo.toml +++ b/stm32-metapac/Cargo.toml | |||
| @@ -19,10 +19,14 @@ regex = "1.5.4" | |||
| 19 | default = ["pac"] | 19 | default = ["pac"] |
| 20 | 20 | ||
| 21 | # Build the actual PAC. Set by default. | 21 | # Build the actual PAC. Set by default. |
| 22 | # If not set, only the macrotables will be generated. You may want to not set it | 22 | # If you just want the metadata, unset it with `default-features = false`. |
| 23 | # if you're using stm32-metapac from a build.rs script to use the macros. | ||
| 24 | pac = [] | 23 | pac = [] |
| 25 | 24 | ||
| 25 | # Build the chip metadata. | ||
| 26 | # If set, a const `stm32_metapac::METADATA` will be exported, containing all the | ||
| 27 | # metadata for the currently selected chip. | ||
| 28 | metadata = [] | ||
| 29 | |||
| 26 | rt = ["cortex-m-rt/device"] | 30 | rt = ["cortex-m-rt/device"] |
| 27 | memory-x = [] | 31 | memory-x = [] |
| 28 | 32 | ||
