diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ca2152d..02b0dd76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/). ## [Unreleased] - Fix `enumeratedValues` with `isDefault` only +- Generate unique identifier instead of `DEVICE_PERIPHERALS` to solve + the link time issue when multiple devices used ## [v0.33.4] - 2024-06-16 diff --git a/src/generate/device.rs b/src/generate/device.rs index dd601ada..8786d374 100644 --- a/src/generate/device.rs +++ b/src/generate/device.rs @@ -1,6 +1,8 @@ use crate::svd::{array::names, Device, Peripheral}; use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens}; +use regex::Regex; +use syn::Ident; use log::debug; use std::fs::File; @@ -270,12 +272,22 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke } } + // Generate unique identifier to prevent linkage errors when using multiple devices. + let mut id = String::from("TAKEN_"); + let re = Regex::new(r"[^A-Za-z0-9_]").unwrap(); + let result = re.replace_all(&d.name, "_"); + for ch in result.chars() { + id.extend(ch.to_uppercase()); + } + + let taken: Ident = syn::parse_str(&id)?; + out.extend(quote! { // NOTE `no_mangle` is used here to prevent linking different minor versions of the device // crate as that would let you `take` the device peripherals more than once (one per minor // version) #[no_mangle] - static mut DEVICE_PERIPHERALS: bool = false; + static mut #taken: bool = false; /// All the peripherals. #[allow(non_snake_case)] @@ -290,12 +302,12 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke pub fn take() -> Option<Self> { critical_section::with(|_| { // SAFETY: We are in a critical section, so we have exclusive access - // to `DEVICE_PERIPHERALS`. - if unsafe { DEVICE_PERIPHERALS } { + // to `#taken`. + if unsafe { #taken } { return None } - // SAFETY: `DEVICE_PERIPHERALS` is set to `true` by `Peripherals::steal`, + // SAFETY: `#taken` is set to `true` by `Peripherals::steal`, // ensuring the peripherals can only be returned once. Some(unsafe { Peripherals::steal() }) }) @@ -308,7 +320,7 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result<Toke /// Each of the returned peripherals must be used at most once. #[inline] pub unsafe fn steal() -> Self { - DEVICE_PERIPHERALS = true; + #taken = true; Peripherals { #exprs