Repository: mspm0-rs/mspm0-data
Pull request #5: Add perimap from stm32-data
Author: login: Iooon
Created: 2025-05-16T07:44:11Z | Merged: 2025-05-25T23:29:45Z

This PR adds a perimap to support different versions of peripheral registers.
This implements a regex perimap similar to stm32-data, however there are some differences:
- STM32 also uses IP versions from ST in the perimap key
- There is no guide on how to identify versions, stm32 has a google spreadsheet for that


Diff:
diff --git a/README.md b/README.md
index 905fe4f..af8b2df 100644
--- a/README.md
+++ b/README.md
@@ -42,3 +42,62 @@ These are the data sources currently used.
 1. Update the data sources to include the new chip. You will need to get the SVD and sysconfig metadata.
 2. Add the new chip family and part numbers to [`parts.yaml`](./data/parts.yaml)
 3. If needed, add any chip specific register blocks like `sysctl`.
+4. Check the peripheral mapping in [`perimap.rs`](./mspm0-data-gen/src/perimap.rs) to use the correct peripherals.
+
+# Adding support for a new peripheral
+
+This will help you add support for a new peripheral to all MSPM0 families. (Please take the time to add it for all families, even if you personally
+are only interested in one. It's easier than it looks, and doing all families at once is significantly less work than adding one now then having to revisit everything later when adding more. It also helps massively in catching mistakes and inconsistencies in the source SVDs.)
+
+- Install chiptool with `./d install-chiptool`
+- Run `./d extract-all CANFD0`. This'll output a bunch of yamls in `tmp/CANFD0`. NOTE sometimes peripherals have a number sometimes not (`CANFD0` vs `CANFD`). You might want to try both and merge the outputted YAMLs into a single directory.
+- Diff them between themselves, to identify differences. The differences can either be:
+  - 1: Legitimate differences between families, because there are different CANFD versions. For example, added registers/fields.
+  - 2: SVD inconsistencies, like different register names for the same register
+  - 3: SVD mistakes (yes, there are some)
+  - 4: Missing stuff in SVDs, usually enums or doc descriptions.
+- Identify how many actually-different (incompatible) versions of the peripheral exist, as we must _not_ merge them. Name them v1, v2.. (if possible, by order of chip release date
+- For each version, pick the "best" YAML (the one that has less enums/docs missing), place them in `data/registers/canfd_vX.yaml`
+- Cleanup the register yamls (see below).
+- Minimize the diff between each pair of versions. For example between `canfd_v1.yaml` and `canfd_v2.yaml`. If one is missing enums or descriptions, copy it from another.
+- Add entries to [`perimap`](./mspm0-data-gen/src/perimap.rs), see below.
+- Rebuild (`./d gen && ./d build-metapac`), then:
+  - Check `mspm0-metapac/src/chips/<chip>/pac.rs` has the right `#[path = "../../peripherals/canfd_v1.rs"]` paths.
+  - Ensure a successful build of the affected pac. e.g.
+
+    ```
+    cd build/mspm0-metapac
+    cargo build --features mspm0g3507pm
+    ```
+
+Please separate manual changes and changes resulting from regen in separate commits. It helps tremendously with review and rebasing/merging.
+
+## Register cleanup
+
+SVDs have some widespread annoyances that should be fixed when adding register YAMLs to this repo. Check out `chiptool` transforms, they can help in speeding up the cleanups.
+
+- Remove "useless prefixes". For example if all regs in the `RNG` peripheral are named `RNG_FOO`, `RNG_BAR`, the `RNG_` peripheral is not conveying any useful information at all, and must go.
+- Remove "useless enums". Useless enums is one of the biggest cause of slow compilation times in STM32 PACs.
+  - 0=disabled, 1=enabled. Common in `xxEN` and `xxIE` fields. If a field says "enable foo" and is one bit, it's obvious "true" means enabled and "false" means disabled.
+  - "Write 0/1 to clear" enums, common in `xxIF` fields.
+  - Check out the `DeleteEnums` chiptool transforms.
+- Convert repeated registers or fields (like `FOO0 FOO1, FOO2, FOO3`) to arrays `FOO[n]`.
+  - Check out the `MakeRegisterArray`, `MakeFieldArray` chiptool transforms.
+- Use `chiptool fmt` on each of the register yamls.
+
+## Peripheral mapping (perimap)
+
+The `mspm0-metapac-gen` binary has a map to match peripherals to the right version in all chips, the [perimap](./mspm0-data-gen/src/perimap.rs).
+
+When parsing a chip, for each peripheral a "key" string is constructed using this format: `FAMILY:PERIPHERAL_NAME`, where:
+
+- `FAMILY`: chip family in lowercase, for example `mspm0g350x`
+- `PERIPHERAL_NAME`: peripheral name, for example `spi`.
+
+`perimap` entries are regexes matching on the above "key" string. First regex that matches wins. For example:
+
+```
+(".*:tim", ("tim", "v1")),
+("mspm0c110x:sysctl", ("sysctl", "c110x")),
+("mspm0g..0x:sysctl", ("sysctl", "g350x_g310x_g150x_g110x")),
+```
diff --git a/data/registers/beeper.yaml b/data/registers/beeper_v1.yaml
similarity index 100%
rename from data/registers/beeper.yaml
rename to data/registers/beeper_v1.yaml
diff --git a/data/registers/cpuss.yaml b/data/registers/cpuss_v1.yaml
similarity index 100%
rename from data/registers/cpuss.yaml
rename to data/registers/cpuss_v1.yaml
diff --git a/data/registers/dma.yaml b/data/registers/dma_v1.yaml
similarity index 100%
rename from data/registers/dma.yaml
rename to data/registers/dma_v1.yaml
diff --git a/data/registers/gpio.yaml b/data/registers/gpio_v1.yaml
similarity index 100%
rename from data/registers/gpio.yaml
rename to data/registers/gpio_v1.yaml
diff --git a/data/registers/i2c.yaml b/data/registers/i2c_v1.yaml
similarity index 100%
rename from data/registers/i2c.yaml
rename to data/registers/i2c_v1.yaml
diff --git a/data/registers/iomux.yaml b/data/registers/iomux_v1.yaml
similarity index 100%
rename from data/registers/iomux.yaml
rename to data/registers/iomux_v1.yaml
diff --git a/data/registers/tim.yaml b/data/registers/tim_v1.yaml
similarity index 100%
rename from data/registers/tim.yaml
rename to data/registers/tim_v1.yaml
diff --git a/data/registers/uart.yaml b/data/registers/uart_v1.yaml
similarity index 100%
rename from data/registers/uart.yaml
rename to data/registers/uart_v1.yaml
diff --git a/mspm0-data-gen/src/generate.rs b/mspm0-data-gen/src/generate.rs
index 2aff6e2..afa5d23 100644
--- a/mspm0-data-gen/src/generate.rs
+++ b/mspm0-data-gen/src/generate.rs
@@ -11,6 +11,7 @@ use crate::{
     header::{Header, Headers},
     int_group::Groups,
     parts::{PartFamily, PartMemory, PartsFile},
+    perimap::PERIMAP,
     sysconfig::{self, PartPeripheralWrapper, Sysconfig, SysconfigFile},
     verify,
 };
@@ -441,12 +442,15 @@ fn generate_missing(
     static GPIO_PIN: LazyLock<Regex> =
         LazyLock::new(|| Regex::new(r"(?m)^P(?<bank>[A-Z])\d+").unwrap());
 
+    let version = PERIMAP
+        .get(&format!("{}:{}", chip_name, PeripheralType::Dma))
+        .map(|s| s.to_string());
     peripherals.insert(
         "DMA".to_string(),
         Peripheral {
             name: "DMA".to_string(),
             ty: PeripheralType::Dma,
-            version: None,
+            version,
             address: Some(0x4042A000),
             // DMA always lives in PD1
             power_domain: PowerDomain::Pd1,
@@ -465,12 +469,15 @@ fn generate_missing(
             let address = get_peripheral_addresses(chip_name, &bank, header, sysconfig)?
                 .context(format!("{bank} must have address"))?;
 
+            let version = PERIMAP
+                .get(&format!("{}:{}", chip_name, PeripheralType::Gpio))
+                .map(|s| s.to_string());
             let gpio = peripherals
                 .entry(bank)
                 .or_insert_with_key(|name| Peripheral {
                     name: name.clone(),
                     ty: PeripheralType::Gpio,
-                    version: None,
+                    version,
                     address: Some(address),
                     // GPIO always lives in PD0
                     power_domain: PowerDomain::Pd0,
@@ -506,7 +513,10 @@ fn maybe_rename(name: &str) -> String {
 
 fn get_peripheral_type_version(chip_name: &str, name: &str) -> (PeripheralType, Option<String>) {
     if name.starts_with("SYSCTL") {
-        return (PeripheralType::Sysctl, Some(get_sysctl_version(chip_name)));
+        let version = PERIMAP
+            .get(&format!("{}:{}", chip_name, PeripheralType::Sysctl))
+            .map(|s| s.to_string());
+        return (PeripheralType::Sysctl, version);
     }
 
     let ty = if name.starts_with("ADC") {
@@ -572,8 +582,11 @@ fn get_peripheral_type_version(chip_name: &str, name: &str) -> (PeripheralType,
     } else {
         PeripheralType::Unknown
     };
+    let version = PERIMAP
+        .get(&format!("{}:{}", chip_name, ty))
+        .map(|s| s.to_string());
 
-    (ty, None)
+    (ty, version)
 }
 
 fn get_peripheral_addresses(
@@ -605,21 +618,6 @@ fn get_peripheral_addresses(
     Ok(Some(address))
 }
 
-fn get_sysctl_version(chip_name: &str) -> String {
-    let s = match chip_name {
-        "msps003fx" | "mspm0c110x" => "c110x",
-        "mspm0l110x" | "mspm0l130x" | "mspm0l134x" => "l110x_l130x_l134x",
-        "mspm0l122x" | "mspm0l222x" => "l122x_l222x",
-        "mspm0g110x" | "mspm0g150x" | "mspm0g310x" | "mspm0g350x" => "g350x_g310x_g150x_g110x",
-        "mspm0g151x" | "mspm0g351x" => "g351x_g151x",
-        "mspm0h321x" => "h321x",
-
-        _ => unreachable!("Missing mapping from {chip_name} to sysctl version"),
-    };
-
-    String::from(s)
-}
-
 fn generate_irqs(
     chip_name: &str,
     header: &Header,
diff --git a/mspm0-data-gen/src/main.rs b/mspm0-data-gen/src/main.rs
index 5d9a543..fde8a01 100644
--- a/mspm0-data-gen/src/main.rs
+++ b/mspm0-data-gen/src/main.rs
@@ -3,7 +3,9 @@ mod generate;
 mod header;
 mod int_group;
 mod parts;
+mod perimap;
 mod sysconfig;
+mod util;
 mod verify;
 
 use std::{path::PathBuf, time::Instant};
diff --git a/mspm0-data-gen/src/perimap.rs b/mspm0-data-gen/src/perimap.rs
new file mode 100644
index 0000000..b1d1fdc
--- /dev/null
+++ b/mspm0-data-gen/src/perimap.rs
@@ -0,0 +1,19 @@
+use crate::util::RegexMap;
+
+pub static PERIMAP: RegexMap<&str> = RegexMap::new(&[
+    (".*:uart", "v1"),
+    (".*:gpio", "v1"),
+    (".*:dma", "v1"),
+    (".*:i2c", "v1"),
+    (".*:beeper", "v1"),
+    (".*:cpuss", "v1"),
+    (".*:iomux", "v1"),
+    (".*:tim", "v1"),
+    ("mspm0c110x:sysctl", "c110x"),
+    ("msps003fx:sysctl", "c110x"),
+    ("mspm0g..0x:sysctl", "g350x_g310x_g150x_g110x"),
+    ("mspm0g..1x:sysctl", "g351x_g151x"),
+    ("mspm0l..0x:sysctl", "l110x_l130x_l134x"),
+    ("mspm0l134x:sysctl", "l110x_l130x_l134x"),
+    ("mspm0l..2x:sysctl", "l122x_l222x"),
+]);
diff --git a/mspm0-data-gen/src/sysconfig.rs b/mspm0-data-gen/src/sysconfig.rs
index 0d4bb22..0d87c70 100644
--- a/mspm0-data-gen/src/sysconfig.rs
+++ b/mspm0-data-gen/src/sysconfig.rs
@@ -132,6 +132,7 @@ pub struct PeripheralPin {
 pub struct Peripheral {
     pub id: String,
     pub name: String,
+    pub version: Option<String>,
     pub description: String,
     /// Attributes are dynamic and depend on the peripheral type.
     pub attributes: serde_json::Value,
diff --git a/mspm0-data-gen/src/util.rs b/mspm0-data-gen/src/util.rs
new file mode 100644
index 0000000..105a1b5
--- /dev/null
+++ b/mspm0-data-gen/src/util.rs
@@ -0,0 +1,56 @@
+use std::collections::HashMap;
+use std::sync::{Mutex, OnceLock};
+
+use regex::Regex;
+
+pub struct RegexMap<'a, T> {
+    map: &'a [(&'a str, T)],
+    regexes: OnceLock<Vec<Regex>>,
+    cache: Mutex<Option<HashMap<String, Option<usize>>>>,
+}
+
+impl<'a, T> RegexMap<'a, T> {
+    pub const fn new(map: &'a [(&'a str, T)]) -> Self {
+        Self {
+            map,
+            regexes: OnceLock::new(),
+            cache: Mutex::new(None),
+        }
+    }
+
+    pub fn get(&self, key: &str) -> Option<&'a T> {
+        if let Some(&val) = self
+            .cache
+            .lock()
+            .unwrap()
+            .get_or_insert_with(Default::default)
+            .get(key)
+        {
+            return val.map(|i| &self.map[i].1);
+        }
+        let val = self.get_uncached(key);
+        self.cache
+            .lock()
+            .unwrap()
+            .as_mut()
+            .unwrap()
+            .insert(key.to_string(), val);
+        val.map(|i| &self.map[i].1)
+    }
+
+    fn get_uncached(&self, key: &str) -> Option<usize> {
+        let regexes = self.regexes.get_or_init(|| {
+            self.map
+                .iter()
+                .map(|(k, _)| Regex::new(&format!("^{k}$")).unwrap())
+                .collect()
+        });
+
+        for (i, k) in regexes.iter().enumerate() {
+            if k.is_match(key) {
+                return Some(i);
+            }
+        }
+        None
+    }
+}
diff --git a/mspm0-metapac-gen/res/lib.rs b/mspm0-metapac-gen/res/lib.rs
index 75dd100..c2c0a57 100644
--- a/mspm0-metapac-gen/res/lib.rs
+++ b/mspm0-metapac-gen/res/lib.rs
@@ -14,4 +14,5 @@ pub mod metadata {
     include!("metadata.rs");
     include!(env!("MSPM0_METAPAC_METADATA_PATH"));
     include!("all_chips.rs");
+    include!("all_peripheral_versions.rs");
 }
diff --git a/mspm0-metapac-gen/src/main.rs b/mspm0-metapac-gen/src/main.rs
index 059d4e7..10a6b60 100644
--- a/mspm0-metapac-gen/src/main.rs
+++ b/mspm0-metapac-gen/src/main.rs
@@ -1,5 +1,5 @@
 use std::{
-    collections::BTreeMap,
+    collections::{BTreeMap, BTreeSet},
     fmt::Write as _,
     fs::{self, File},
     io::Write as _,
@@ -53,12 +53,13 @@ fn main() -> anyhow::Result<()> {
     registers::generate(&out_dir)?;
 
     let mut metadata_dedup = BTreeMap::new();
+    let mut all_peripheral_versions = BTreeMap::new();
 
     for (name, chip) in &mut chips {
         for package in chip.packages.iter() {
             let name = format!("{name}{}", package.package.to_lowercase());
 
-            generate_chip_pac(&name, chip, &out_dir);
+            generate_chip_pac(&name, chip, &out_dir, &mut all_peripheral_versions);
             generate_chip_metadata(&name, chip, package, &out_dir, &mut metadata_dedup);
 
             linker::generate_device_x(&name, chip, &out_dir)?;
@@ -67,13 +68,19 @@ fn main() -> anyhow::Result<()> {
     }
 
     generate_all_chips(&out_dir, chips.values())?;
+    generate_all_peripheral_versions(&out_dir, &all_peripheral_versions)?;
 
     krate::generate(&out_dir, &chips)?;
 
     Ok(())
 }
 
-fn generate_chip_pac(name: &str, chip: &Chip, out_dir: &Path) {
+fn generate_chip_pac(
+    name: &str,
+    chip: &Chip,
+    out_dir: &Path,
+    all_peripheral_versions: &mut BTreeMap<String, BTreeSet<String>>,
+) {
     let chips = out_dir.join("src/chips");
     fs::create_dir_all(&chips).unwrap();
 
@@ -85,7 +92,12 @@ fn generate_chip_pac(name: &str, chip: &Chip, out_dir: &Path) {
 
     writeln!(&mut file, "{AUTOGENERATED_TEXT}").unwrap();
     writeln!(&mut file, "{}", interrupt::generate(chip)).unwrap();
-    writeln!(&mut file, "{}", peripheral::generate(chip)).unwrap();
+    writeln!(
+        &mut file,
+        "{}",
+        peripheral::generate(chip, all_peripheral_versions)
+    )
+    .unwrap();
 
     drop(file);
 
@@ -186,6 +198,30 @@ fn generate_all_chips<'a>(
     Ok(())
 }
 
+fn generate_all_peripheral_versions(
+    out_dir: &Path,
+    all_versions: &BTreeMap<String, BTreeSet<String>>,
+) -> anyhow::Result<()> {
+    let mut contents = String::new();
+    writeln!(
+        &mut contents,
+        "pub static ALL_PERIPHERAL_VERSIONS: &[(&str, &[&str])] = &["
+    )?;
+    for (kind, versions) in all_versions.iter() {
+        write!(&mut contents, "    ({:?}, &[", kind)?;
+        for version in versions.iter() {
+            write!(&mut contents, "{:?}, ", version)?;
+        }
+        writeln!(&mut contents, "]),")?;
+    }
+    writeln!(&mut contents, "];")?;
+    let all_peripheral_versions = out_dir.join("src/all_peripheral_versions.rs");
+    fs::write(&all_peripheral_versions, contents)?;
+    rustfmt(all_peripheral_versions);
+
+    Ok(())
+}
+
 fn rustfmt<P: AsRef<Path>>(path: P) {
     Command::new("rustfmt")
         .arg(path.as_ref())
diff --git a/mspm0-metapac-gen/src/metadata.rs b/mspm0-metapac-gen/src/metadata.rs
index e2ef43b..359b541 100644
--- a/mspm0-metapac-gen/src/metadata.rs
+++ b/mspm0-metapac-gen/src/metadata.rs
@@ -157,6 +157,10 @@ fn generate_peripheral(
 
     let name = &peripheral.name;
     let kind = &peripheral.ty.to_string();
+    let version = match &peripheral.version {
+        Some(v) => quote! { Some(#v) },
+        None => quote! { None },
+    };
 
     let mut pins = Vec::<TokenStream>::new();
 
@@ -183,6 +187,7 @@ fn generate_peripheral(
         Peripheral {
             name: #name,
             kind: #kind,
+            version: #version,
             pins: &[#(#pins),*],
         }
     })
diff --git a/mspm0-metapac-gen/src/peripheral.rs b/mspm0-metapac-gen/src/peripheral.rs
index 4bd157e..28382b8 100644
--- a/mspm0-metapac-gen/src/peripheral.rs
+++ b/mspm0-metapac-gen/src/peripheral.rs
@@ -1,3 +1,5 @@
+use std::collections::{BTreeMap, BTreeSet};
+
 use heck::ToPascalCase;
 use mspm0_data_types::{Chip, Peripheral, PeripheralType};
 use proc_macro2::{Ident, Literal, Span, TokenStream};
@@ -17,8 +19,8 @@ const GENERATE_PERIPHERALS: &[PeripheralType] = &[
     PeripheralType::Uart,
 ];
 
-pub fn generate(chip: &Chip) -> TokenStream {
-    let peripheral_imports = generate_peripheral_imports(chip);
+pub fn generate(chip: &Chip, all_versions: &mut BTreeMap<String, BTreeSet<String>>) -> TokenStream {
+    let peripheral_imports = generate_peripheral_imports(chip, all_versions);
     let peripheral_consts = generate_peripheral_consts(chip);
 
     quote! {
@@ -27,7 +29,10 @@ pub fn generate(chip: &Chip) -> TokenStream {
     }
 }
 
-fn generate_peripheral_imports(chip: &Chip) -> TokenStream {
+fn generate_peripheral_imports(
+    chip: &Chip,
+    all_versions: &mut BTreeMap<String, BTreeSet<String>>,
+) -> TokenStream {
     // Sort the peripherals by type for generation.
     let mut peripheral_types = chip.peripherals.iter().collect::<Vec<_>>();
     peripheral_types.sort_by(|(a, _), (b, _)| a.cmp(b));
@@ -35,11 +40,15 @@ fn generate_peripheral_imports(chip: &Chip) -> TokenStream {
 
     peripheral_types
         .iter()
-        .map(|(name, peripheral)| generate_import(name, peripheral))
+        .map(|(name, peripheral)| generate_import(name, peripheral, all_versions))
         .collect()
 }
 
-fn generate_import(_name: &str, peripheral: &Peripheral) -> TokenStream {
+fn generate_import(
+    _name: &str,
+    peripheral: &Peripheral,
+    all_versions: &mut BTreeMap<String, BTreeSet<String>>,
+) -> TokenStream {
     if !GENERATE_PERIPHERALS
         .iter()
         .any(|ty_generate| &peripheral.ty == ty_generate)
@@ -52,15 +61,18 @@ fn generate_import(_name: &str, peripheral: &Peripheral) -> TokenStream {
         Span::call_site(),
     );
 
-    let path = if let Some(ref version) = peripheral.version {
-        format!("../../peripherals/{}_{}.rs", peripheral.ty, version)
+    if let Some(version) = peripheral.version.clone() {
+        all_versions
+            .entry(name.to_string())
+            .or_default()
+            .insert(version.clone());
+        let path = format!("../../peripherals/{}_{}.rs", name, version);
+        quote! {
+            #[path = #path]
+            pub mod #name;
+        }
     } else {
-        format!("../../peripherals/{}.rs", peripheral.ty)
-    };
-
-    quote! {
-        #[path = #path]
-        pub mod #name;
+        TokenStream::default()
     }
 }
 


Reviews:
user: login: i509VCB
body: Looks good so far.

One other note is that we should probably put some of this data into metapac, putting the version on each peripheral. And then a file like `all_peripheral_versions`. This is so that we can do something like the following in embassy-mspm0:

```rust
#[cfg(sysctl_c110x)]
foo();

#[cfg(sysctl_l122x_l222x)]
foo_but_lx22x();
```

This will be needed especially for the clock setup in the `Config` for the crate (which I have not done yet).
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-16T16:21:10Z
user: login: Iooon
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-21T19:14:04Z
user: login: i509VCB
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-24T00:27:28Z

Review comments:
diff_hunk: @@ -0,0 +1,18 @@
+use crate::util::RegexMap;
+
+pub static PERIMAP: RegexMap<(&str, &str)> = RegexMap::new(&[
+    (".*:uart", ("uart", "v1")),
+    (".*:gpio", ("gpio", "v1")),
+    (".*:dma", ("dma", "v1")),
+    (".*:i2c", ("i2c", "v1")),
+    (".*:beeper", ("beeper", "v1")),
+    (".*:cpuss", ("cpuss", "v1")),
+    (".*:iomux", ("iomux", "v1")),
+    (".*:tim", ("tim", "v1")),
+    ("mspm0c110x:sysctl", ("sysctl", "c110x")),
path: mspm0-metapac-gen/src/perimap.rs
user: login: i509VCB
body: Is this going to match `msps003fx`?
created_at: 2025-05-16T16:18:15Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,18 @@
+use crate::util::RegexMap;
+
+pub static PERIMAP: RegexMap<(&str, &str)> = RegexMap::new(&[
+    (".*:uart", ("uart", "v1")),
+    (".*:gpio", ("gpio", "v1")),
+    (".*:dma", ("dma", "v1")),
+    (".*:i2c", ("i2c", "v1")),
+    (".*:beeper", ("beeper", "v1")),
+    (".*:cpuss", ("cpuss", "v1")),
+    (".*:iomux", ("iomux", "v1")),
+    (".*:tim", ("tim", "v1")),
+    ("mspm0c110x:sysctl", ("sysctl", "c110x")),
path: mspm0-metapac-gen/src/perimap.rs
user: login: Iooon
body: Oh yeah, I forgot the msps0
created_at: 2025-05-21T19:14:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -186,6 +198,27 @@ fn generate_all_chips<'a>(
     Ok(())
 }
 
+fn generate_all_peripheral_versions(
+    out_dir: &Path,
+    all_versions: &BTreeMap<String, BTreeSet<String>>,
+) {
+    let mut contents = String::new();
+    writeln!(
+        &mut contents,
+        "pub static ALL_PERIPHERAL_VERSIONS: &[(&str, &[&str])] = &["
+    )
+    .unwrap();
+    for (kind, versions) in all_versions.iter() {
+        write!(&mut contents, "    ({:?}, &[", kind).unwrap();
+        for version in versions.iter() {
+            write!(&mut contents, "{:?}, ", version).unwrap();
+        }
+        writeln!(&mut contents, "]),").unwrap();
+    }
+    writeln!(&mut contents, "];").unwrap();
+    fs::write(out_dir.join("src/all_peripheral_versions.rs"), contents).unwrap();
path: mspm0-metapac-gen/src/main.rs
user: login: i509VCB
body: rustfmt the output? (just to minimize the diff on the generated code)
created_at: 2025-05-24T00:27:13Z
author_association: MEMBER

PR comments:
user: login: Iooon
created_at: 2025-05-21T19:17:59Z
body: > Looks good so far.
> 
> One other note is that we should probably put some of this data into metapac, putting the version on each peripheral. And then a file like `all_peripheral_versions`. This is so that we can do something like the following in embassy-mspm0:
> 
> ```rust
> #[cfg(sysctl_c110x)]
> foo();
> 
> #[cfg(sysctl_l122x_l222x)]
> foo_but_lx22x();
> ```
> 
> This will be needed especially for the clock setup in the `Config` for the crate (which I have not done yet).

@i509VCB How should the `all_peripheral_versions` file be structured?"
author_association: CONTRIBUTOR
user: login: i509VCB
created_at: 2025-05-21T20:40:10Z
body: > How should the `all_peripheral_versions` file be structured?"

Copy whatever stm32-data does (I think it does something like `<peripheral>_<version>` for the string.

And then it's just a big list of the type: `&'static [&'static str]`.
author_association: MEMBER