diff --git a/CHANGELOG.md b/CHANGELOG.md index 64475b5a..2dc293e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/). ## [Unreleased] +- Use `ConstDefault::DEFAULT` instead of `Default::default()` to force const + ## [v0.34.0] - 2024-11-05 - Revert #711 diff --git a/ci/script.sh b/ci/script.sh index 3d71b080..a2278c44 100755 --- a/ci/script.sh +++ b/ci/script.sh @@ -43,6 +43,7 @@ main() { echo 'cortex-m = "0.7.7"' >> $td/Cargo.toml echo 'cortex-m-rt = "0.7.3"' >> $td/Cargo.toml echo 'vcell = "0.1.3"' >> $td/Cargo.toml + echo 'const-default = { version = "1.0", default-features = false }' >> $td/Cargo.toml if [[ "$options" == *"--atomics"* ]]; then echo 'portable-atomic = { version = "1.4", default-features = false }' >> $td/Cargo.toml fi diff --git a/ci/svd2rust-regress/src/svd_test.rs b/ci/svd2rust-regress/src/svd_test.rs index 30033dbd..0f61304d 100644 --- a/ci/svd2rust-regress/src/svd_test.rs +++ b/ci/svd2rust-regress/src/svd_test.rs @@ -11,7 +11,11 @@ use std::{ path::Path, }; -const CRATES_ALL: &[&str] = &["critical-section = \"1.0\"", "vcell = \"0.1.2\""]; +const CRATES_ALL: &[&str] = &[ + "critical-section = \"1.0\"", + "vcell = \"0.1.2\"", + "const-default = { version = \"1.0\", default-features = false }", +]; const CRATES_MSP430: &[&str] = &["msp430 = \"0.4.0\"", "msp430-rt = \"0.4.0\""]; const CRATES_ATOMICS: &[&str] = &["portable-atomic = { version = \"0.3.16\", default-features = false }"]; diff --git a/src/generate/generic.rs b/src/generate/generic.rs index 706b7e12..3dcc4b1a 100644 --- a/src/generate/generic.rs +++ b/src/generate/generic.rs @@ -1,9 +1,10 @@ use core::marker; +use const_default::ConstDefault; /// Raw register type (`u8`, `u16`, `u32`, ...) pub trait RawReg: Copy - + Default + + ConstDefault + From + core::ops::BitOr + core::ops::BitAnd @@ -74,10 +75,10 @@ pub trait Writable: RegisterSpec { type Safety; /// Specifies the register bits that are not changed if you pass `1` and are changed if you pass `0` - const ZERO_TO_MODIFY_FIELDS_BITMAP: Self::Ux; + const ZERO_TO_MODIFY_FIELDS_BITMAP: Self::Ux = Self::Ux::DEFAULT; /// Specifies the register bits that are not changed if you pass `0` and are changed if you pass `1` - const ONE_TO_MODIFY_FIELDS_BITMAP: Self::Ux; + const ONE_TO_MODIFY_FIELDS_BITMAP: Self::Ux = Self::Ux::DEFAULT; } /// Reset value of the register. @@ -86,7 +87,7 @@ pub trait Writable: RegisterSpec { /// register by using the `reset` method. pub trait Resettable: RegisterSpec { /// Reset value of the register. - const RESET_VALUE: Self::Ux; + const RESET_VALUE: Self::Ux = Self::Ux::DEFAULT; /// Reset value of the register. #[inline(always)] diff --git a/src/generate/generic_atomic.rs b/src/generate/generic_atomic.rs index 54c491c3..d40d686c 100644 --- a/src/generate/generic_atomic.rs +++ b/src/generate/generic_atomic.rs @@ -39,7 +39,7 @@ mod atomic { impl Reg where - REG::Ux: AtomicOperations + REG::Ux: AtomicOperations, { /// Set high every bit in the register that was set in the write proxy. Leave other bits /// untouched. The write is done in a single atomic instruction. @@ -53,7 +53,7 @@ mod atomic { F: FnOnce(&mut W) -> &mut W, { let bits = f(&mut W { - bits: Default::default(), + bits: REG::Ux::DEFAULT, _reg: marker::PhantomData, }) .bits; @@ -72,7 +72,7 @@ mod atomic { F: FnOnce(&mut W) -> &mut W, { let bits = f(&mut W { - bits: !REG::Ux::default(), + bits: !REG::Ux::DEFAULT, _reg: marker::PhantomData, }) .bits; @@ -91,7 +91,7 @@ mod atomic { F: FnOnce(&mut W) -> &mut W, { let bits = f(&mut W { - bits: Default::default(), + bits: REG::Ux::DEFAULT, _reg: marker::PhantomData, }) .bits; diff --git a/src/generate/generic_reg_vcell.rs b/src/generate/generic_reg_vcell.rs index b0ca0d5e..1cfbd64e 100644 --- a/src/generate/generic_reg_vcell.rs +++ b/src/generate/generic_reg_vcell.rs @@ -148,7 +148,7 @@ impl Reg { F: FnOnce(&mut W) -> &mut W, { let value = f(&mut W { - bits: REG::Ux::default(), + bits: REG::Ux::DEFAULT, _reg: marker::PhantomData, }) .bits; @@ -169,7 +169,7 @@ impl Reg { F: FnOnce(&mut W) -> T, { let mut writer = W { - bits: REG::Ux::default(), + bits: REG::Ux::DEFAULT, _reg: marker::PhantomData, }; diff --git a/src/generate/register.rs b/src/generate/register.rs index 8ab2eeb3..303c57c0 100644 --- a/src/generate/register.rs +++ b/src/generate/register.rs @@ -413,24 +413,31 @@ pub fn render_register_mod( let doc = format!("`write(|w| ..)` method takes [`{mod_ty}::W`](W) writer structure",); - let zero_to_modify_fields_bitmap = util::hex(zero_to_modify_fields_bitmap); - let one_to_modify_fields_bitmap = util::hex(one_to_modify_fields_bitmap); + let zero_to_modify_fields_bitmap = util::hex_nonzero(zero_to_modify_fields_bitmap) + .map(|bm| quote!(const ZERO_TO_MODIFY_FIELDS_BITMAP: #rty = #bm;)); + let one_to_modify_fields_bitmap = util::hex_nonzero(one_to_modify_fields_bitmap) + .map(|bm| quote!(const ONE_TO_MODIFY_FIELDS_BITMAP: #rty = #bm;)); mod_items.extend(quote! { #[doc = #doc] impl crate::Writable for #regspec_ty { type Safety = crate::#safe_ty; - const ZERO_TO_MODIFY_FIELDS_BITMAP: #rty = #zero_to_modify_fields_bitmap; - const ONE_TO_MODIFY_FIELDS_BITMAP: #rty = #one_to_modify_fields_bitmap; + #zero_to_modify_fields_bitmap + #one_to_modify_fields_bitmap } }); } - if let Some(rv) = properties.reset_value.map(util::hex) { - let doc = format!("`reset()` method sets {} to value {rv}", register.name); + if let Some(rv) = properties.reset_value.map(util::hex_nonzero) { + let doc = if let Some(rv) = &rv { + format!("`reset()` method sets {} to value {rv}", register.name) + } else { + format!("`reset()` method sets {} to value 0", register.name) + }; + let rv = rv.map(|rv| quote!(const RESET_VALUE: #rty = #rv;)); mod_items.extend(quote! { #[doc = #doc] impl crate::Resettable for #regspec_ty { - const RESET_VALUE: #rty = #rv; + #rv } }); } diff --git a/src/lib.rs b/src/lib.rs index edec886e..6b1c5dc8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,6 +62,7 @@ //! - [`cortex-m`](https://crates.io/crates/cortex-m) >=v0.7.6 //! - [`cortex-m-rt`](https://crates.io/crates/cortex-m-rt) >=v0.6.13 //! - [`vcell`](https://crates.io/crates/vcell) >=v0.1.2 +//! - [`const-default`](https://crates.io/crates/const-default) >=v1.0 //! //! Furthermore, the "device" feature of `cortex-m-rt` must be enabled when the `rt` feature //! is enabled. The `Cargo.toml` of the device crate will look like this: @@ -126,6 +127,7 @@ //! - [`msp430`](https://crates.io/crates/msp430) v0.4.x //! - [`msp430-rt`](https://crates.io/crates/msp430-rt) v0.4.x //! - [`vcell`](https://crates.io/crates/vcell) v0.1.x +//! - [`const-default`](https://crates.io/crates/const-default) v1.x.x //! //! The "device" feature of `msp430-rt` must be enabled when the `rt` feature is //! enabled. The `Cargo.toml` of the device crate will look like this: @@ -136,6 +138,7 @@ //! msp430 = "0.4.0" //! msp430-rt = { version = "0.4.0", optional = true } //! vcell = "0.1.0" +//! const-default = { version = "1.0", default-features = false } //! //! [features] //! rt = ["msp430-rt/device"] @@ -153,6 +156,7 @@ //! - [`riscv-peripheral`](https://crates.io/crates/riscv-peripheral) v0.2.x (if target is RISC-V and has standard peripherals) //! - [`riscv-rt`](https://crates.io/crates/riscv-rt) v0.13.x (if target is RISC-V) //! - [`vcell`](https://crates.io/crates/vcell) v0.1.x +//! - [`const-default`](https://crates.io/crates/const-default) v1.x.x //! //! The `*-rt` dependencies must be optional only enabled when the `rt` feature is enabled. //! If target is RISC-V and supports vectored mode, you must include a feature `v-trap` to activate `riscv-rt/v-trap`. @@ -165,6 +169,7 @@ //! riscv-peripheral = "0.2.0" //! riscv-rt = { version = "0.13.0", optional = true } //! vcell = "0.1.0" +//! const-default = { version = "1.0", default-features = false } //! //! [features] //! rt = ["riscv-rt"] diff --git a/src/util.rs b/src/util.rs index 3520bcf3..b0b9f09b 100644 --- a/src/util.rs +++ b/src/util.rs @@ -255,6 +255,11 @@ pub fn hex(n: u64) -> LitInt { ) } +/// Turns non-zero `n` into an unsuffixed separated hex token +pub fn hex_nonzero(n: u64) -> Option { + (n != 0).then(|| hex(n)) +} + /// Turns `n` into an unsuffixed token pub fn unsuffixed(n: impl Into) -> LitInt { LitInt::new(&n.into().to_string(), Span::call_site())