diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c56f42d..0aa32833 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,6 @@ on: push: - branches: master + branches: [master] pull_request: merge_group: diff --git a/CHANGELOG.md b/CHANGELOG.md index 110b0c25..e921e919 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/). ## [Unreleased] - Generic `Periph` +- use `ConstZero::ZERO` instead of `Default::default()` to force const - Add `mtvec_align` field to `riscv_config` to configure the byte alignment of interrupt vector table. - Fix reexport path when "%s" inside "derivedFrom" - Force using rust edition 2021 in CI diff --git a/src/generate/generic.rs b/src/generate/generic.rs index 9d124093..e527a4a8 100644 --- a/src/generate/generic.rs +++ b/src/generate/generic.rs @@ -49,7 +49,6 @@ impl core::ops::Deref for Periph { /// Raw register type (`u8`, `u16`, `u32`, ...) pub trait RawReg: Copy - + Default + From + core::ops::BitOr + core::ops::BitAnd @@ -60,8 +59,10 @@ pub trait RawReg: { /// Mask for bits of width `WI` fn mask() -> Self; - /// Mask for bits of width 1 - fn one() -> Self; + /// `0` + const ZERO: Self; + /// `1` + const ONE: Self; } macro_rules! raw_reg { @@ -71,10 +72,8 @@ macro_rules! raw_reg { fn mask() -> Self { $mask::() } - #[inline(always)] - fn one() -> Self { - 1 - } + const ZERO: Self = 0; + const ONE: Self = 1; } const fn $mask() -> $U { <$U>::MAX >> ($size - WI) @@ -120,10 +119,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::ZERO; /// 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::ZERO; } /// Reset value of the register. @@ -132,7 +131,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::ZERO; /// Reset value of the register. #[inline(always)] @@ -539,8 +538,8 @@ macro_rules! bit_proxy { /// Writes bit to the field #[inline(always)] pub fn bit(self, value: bool) -> &'a mut W { - self.w.bits &= !(REG::Ux::one() << self.o); - self.w.bits |= (REG::Ux::from(value) & REG::Ux::one()) << self.o; + self.w.bits &= !(REG::Ux::ONE << self.o); + self.w.bits |= (REG::Ux::from(value) & REG::Ux::ONE) << self.o; self.w } /// Writes `variant` to the field @@ -568,13 +567,13 @@ where /// Sets the field bit #[inline(always)] pub fn set_bit(self) -> &'a mut W { - self.w.bits |= REG::Ux::one() << self.o; + self.w.bits |= REG::Ux::ONE << self.o; self.w } /// Clears the field bit #[inline(always)] pub fn clear_bit(self) -> &'a mut W { - self.w.bits &= !(REG::Ux::one() << self.o); + self.w.bits &= !(REG::Ux::ONE << self.o); self.w } } @@ -587,7 +586,7 @@ where /// Sets the field bit #[inline(always)] pub fn set_bit(self) -> &'a mut W { - self.w.bits |= REG::Ux::one() << self.o; + self.w.bits |= REG::Ux::ONE << self.o; self.w } } @@ -600,7 +599,7 @@ where /// Clears the field bit #[inline(always)] pub fn clear_bit(self) -> &'a mut W { - self.w.bits &= !(REG::Ux::one() << self.o); + self.w.bits &= !(REG::Ux::ONE << self.o); self.w } } @@ -613,7 +612,7 @@ where ///Clears the field bit by passing one #[inline(always)] pub fn clear_bit_by_one(self) -> &'a mut W { - self.w.bits |= REG::Ux::one() << self.o; + self.w.bits |= REG::Ux::ONE << self.o; self.w } } @@ -626,7 +625,7 @@ where ///Sets the field bit by passing zero #[inline(always)] pub fn set_bit_by_zero(self) -> &'a mut W { - self.w.bits &= !(REG::Ux::one() << self.o); + self.w.bits &= !(REG::Ux::ONE << self.o); self.w } } @@ -639,7 +638,7 @@ where ///Toggle the field bit by passing one #[inline(always)] pub fn toggle_bit(self) -> &'a mut W { - self.w.bits |= REG::Ux::one() << self.o; + self.w.bits |= REG::Ux::ONE << self.o; self.w } } @@ -652,7 +651,7 @@ where ///Toggle the field bit by passing zero #[inline(always)] pub fn toggle_bit(self) -> &'a mut W { - self.w.bits &= !(REG::Ux::one() << self.o); + self.w.bits &= !(REG::Ux::ONE << self.o); self.w } } diff --git a/src/generate/generic_atomic.rs b/src/generate/generic_atomic.rs index 54c491c3..55250961 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::ZERO, _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::ZERO, _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::ZERO, _reg: marker::PhantomData, }) .bits; diff --git a/src/generate/generic_reg_vcell.rs b/src/generate/generic_reg_vcell.rs index b0ca0d5e..9e436334 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::ZERO, _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::ZERO, _reg: marker::PhantomData, }; diff --git a/src/generate/register.rs b/src/generate/register.rs index 7ff3c265..c1cdc876 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/util.rs b/src/util.rs index dbf0dde5..40a1e526 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())