Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use ConstZero instead of Default #838

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
on:
push:
branches: master
branches: [master]
pull_request:
merge_group:

Expand Down Expand Up @@ -83,7 +83,11 @@ jobs:
- { rust: stable, vendor: Spansion, options: "--atomics" }
- { rust: stable, vendor: STMicro, options: "" }
- { rust: stable, vendor: STMicro, options: "--atomics" }
- { rust: stable, vendor: STM32-patched, options: "--strict -f enum_value::p: --max-cluster-size --atomics --atomics-feature atomics --impl-debug --impl-defmt defmt" }
- {
rust: stable,
vendor: STM32-patched,
options: "--strict -f enum_value::p: --max-cluster-size --atomics --atomics-feature atomics --impl-debug --impl-defmt defmt",
}
- { rust: stable, vendor: Toshiba, options: all }
- { rust: stable, vendor: Toshiba, options: "" }
# Test MSRV
Expand All @@ -92,8 +96,16 @@ jobs:
- { rust: nightly, vendor: MSP430, options: "--atomics" }
- { rust: nightly, vendor: MSP430, options: "" }
# Workaround for _1token0
- { rust: nightly-2024-09-25, vendor: Espressif, options: "--atomics --ident-formats-theme legacy" }
- { rust: nightly-2024-09-25, vendor: Espressif, options: "--ident-format register:::Reg" }
- {
rust: nightly-2024-09-25,
vendor: Espressif,
options: "--atomics --ident-formats-theme legacy",
}
- {
rust: nightly-2024-09-25,
vendor: Espressif,
options: "--ident-format register:::Reg",
}

steps:
- uses: actions/checkout@v4
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased]

- Use `ConstZero::ZERO` instead of `Default::default()` to force const
- Force using rust edition 2021 in CI

## [v0.35.0] - 2024-11-12
Expand Down
1 change: 1 addition & 0 deletions ci/script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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 'num-traits = { version = "0.2.19", default-features = false }' >> $td/Cargo.toml
if [[ "$options" == *"--atomics"* ]]; then
echo 'portable-atomic = { version = "1.4", default-features = false }' >> $td/Cargo.toml
fi
Expand Down
6 changes: 5 additions & 1 deletion ci/svd2rust-regress/src/svd_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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\"",
"num-traits = { version = \"0.2.19\", 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 }"];
Expand Down
49 changes: 25 additions & 24 deletions src/generate/generic.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use core::marker;
use num_traits::{ConstOne, ConstZero};

/// Raw register type (`u8`, `u16`, `u32`, ...)
pub trait RawReg:
Copy
+ Default
+ ConstOne
+ ConstZero
+ From<bool>
+ core::ops::BitOr<Output = Self>
+ core::ops::BitAnd<Output = Self>
Expand All @@ -14,8 +16,6 @@ pub trait RawReg:
{
/// Mask for bits of width `WI`
fn mask<const WI: u8>() -> Self;
/// Mask for bits of width 1
fn one() -> Self;
}

macro_rules! raw_reg {
Expand All @@ -25,10 +25,6 @@ macro_rules! raw_reg {
fn mask<const WI: u8>() -> Self {
$mask::<WI>()
}
#[inline(always)]
fn one() -> Self {
1
}
}
const fn $mask<const WI: u8>() -> $U {
<$U>::MAX >> ($size - WI)
Expand Down Expand Up @@ -74,10 +70,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.
Expand All @@ -86,7 +82,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)]
Expand Down Expand Up @@ -247,7 +243,10 @@ impl<REG: Writable> W<REG> {
self
}
}
impl<REG> W<REG> where REG: Writable<Safety = Safe> {
impl<REG> W<REG>
where
REG: Writable<Safety = Safe>,
{
/// Writes raw bits to the register.
#[inline(always)]
pub fn set(&mut self, bits: REG::Ux) -> &mut Self {
Expand Down Expand Up @@ -335,7 +334,8 @@ pub struct RangeFrom<const MIN: u64>;
pub struct RangeTo<const MAX: u64>;

/// Write field Proxy
pub type FieldWriter<'a, REG, const WI: u8, FI = u8, Safety = Unsafe> = raw::FieldWriter<'a, REG, WI, FI, Safety>;
pub type FieldWriter<'a, REG, const WI: u8, FI = u8, Safety = Unsafe> =
raw::FieldWriter<'a, REG, WI, FI, Safety>;

impl<'a, REG, const WI: u8, FI, Safety> FieldWriter<'a, REG, WI, FI, Safety>
where
Expand Down Expand Up @@ -390,7 +390,8 @@ where
}
}

impl<'a, REG, const WI: u8, FI, const MIN: u64, const MAX: u64> FieldWriter<'a, REG, WI, FI, Range<MIN, MAX>>
impl<'a, REG, const WI: u8, FI, const MIN: u64, const MAX: u64>
FieldWriter<'a, REG, WI, FI, Range<MIN, MAX>>
where
REG: Writable + RegisterSpec,
FI: FieldSpec,
Expand Down Expand Up @@ -478,7 +479,7 @@ macro_rules! bit_proxy {
pub const fn width(&self) -> u8 {
Self::WIDTH
}

/// Field offset
#[inline(always)]
pub const fn offset(&self) -> u8 {
Expand All @@ -488,8 +489,8 @@ macro_rules! bit_proxy {
/// Writes bit to the field
#[inline(always)]
pub fn bit(self, value: bool) -> &'a mut W<REG> {
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
Expand Down Expand Up @@ -517,13 +518,13 @@ where
/// Sets the field bit
#[inline(always)]
pub fn set_bit(self) -> &'a mut W<REG> {
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<REG> {
self.w.bits &= !(REG::Ux::one() << self.o);
self.w.bits &= !(REG::Ux::ONE << self.o);
self.w
}
}
Expand All @@ -536,7 +537,7 @@ where
/// Sets the field bit
#[inline(always)]
pub fn set_bit(self) -> &'a mut W<REG> {
self.w.bits |= REG::Ux::one() << self.o;
self.w.bits |= REG::Ux::ONE << self.o;
self.w
}
}
Expand All @@ -549,7 +550,7 @@ where
/// Clears the field bit
#[inline(always)]
pub fn clear_bit(self) -> &'a mut W<REG> {
self.w.bits &= !(REG::Ux::one() << self.o);
self.w.bits &= !(REG::Ux::ONE << self.o);
self.w
}
}
Expand All @@ -562,7 +563,7 @@ where
///Clears the field bit by passing one
#[inline(always)]
pub fn clear_bit_by_one(self) -> &'a mut W<REG> {
self.w.bits |= REG::Ux::one() << self.o;
self.w.bits |= REG::Ux::ONE << self.o;
self.w
}
}
Expand All @@ -575,7 +576,7 @@ where
///Sets the field bit by passing zero
#[inline(always)]
pub fn set_bit_by_zero(self) -> &'a mut W<REG> {
self.w.bits &= !(REG::Ux::one() << self.o);
self.w.bits &= !(REG::Ux::ONE << self.o);
self.w
}
}
Expand All @@ -588,7 +589,7 @@ where
///Toggle the field bit by passing one
#[inline(always)]
pub fn toggle_bit(self) -> &'a mut W<REG> {
self.w.bits |= REG::Ux::one() << self.o;
self.w.bits |= REG::Ux::ONE << self.o;
self.w
}
}
Expand All @@ -601,7 +602,7 @@ where
///Toggle the field bit by passing zero
#[inline(always)]
pub fn toggle_bit(self) -> &'a mut W<REG> {
self.w.bits &= !(REG::Ux::one() << self.o);
self.w.bits &= !(REG::Ux::ONE << self.o);
self.w
}
}
8 changes: 4 additions & 4 deletions src/generate/generic_atomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ mod atomic {

impl<REG: Readable + Writable> Reg<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.
Expand All @@ -53,7 +53,7 @@ mod atomic {
F: FnOnce(&mut W<REG>) -> &mut W<REG>,
{
let bits = f(&mut W {
bits: Default::default(),
bits: REG::Ux::ZERO,
_reg: marker::PhantomData,
})
.bits;
Expand All @@ -72,7 +72,7 @@ mod atomic {
F: FnOnce(&mut W<REG>) -> &mut W<REG>,
{
let bits = f(&mut W {
bits: !REG::Ux::default(),
bits: !REG::Ux::ZERO,
_reg: marker::PhantomData,
})
.bits;
Expand All @@ -91,7 +91,7 @@ mod atomic {
F: FnOnce(&mut W<REG>) -> &mut W<REG>,
{
let bits = f(&mut W {
bits: Default::default(),
bits: REG::Ux::ZERO,
_reg: marker::PhantomData,
})
.bits;
Expand Down
4 changes: 2 additions & 2 deletions src/generate/generic_reg_vcell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ impl<REG: Writable> Reg<REG> {
F: FnOnce(&mut W<REG>) -> &mut W<REG>,
{
let value = f(&mut W {
bits: REG::Ux::default(),
bits: REG::Ux::ZERO,
_reg: marker::PhantomData,
})
.bits;
Expand All @@ -169,7 +169,7 @@ impl<REG: Writable> Reg<REG> {
F: FnOnce(&mut W<REG>) -> T,
{
let mut writer = W {
bits: REG::Ux::default(),
bits: REG::Ux::ZERO,
_reg: marker::PhantomData,
};

Expand Down
21 changes: 14 additions & 7 deletions src/generate/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
});
}
Expand Down
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
//! - [`num-traits`](https://crates.io/crates/const-default) >=v0.2.18
//!
//! 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:
Expand Down Expand Up @@ -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
//! - [`num-traits`](https://crates.io/crates/const-default) v0.2.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:
Expand All @@ -136,6 +138,7 @@
//! msp430 = "0.4.0"
//! msp430-rt = { version = "0.4.0", optional = true }
//! vcell = "0.1.0"
//! num-traits = { version = "0.2.19", default-features = false }
//!
//! [features]
//! rt = ["msp430-rt/device"]
Expand All @@ -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
//! - [`num-traits`](https://crates.io/crates/const-default) v0.2.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`.
Expand All @@ -165,6 +169,7 @@
//! riscv-peripheral = "0.2.0"
//! riscv-rt = { version = "0.13.0", optional = true }
//! vcell = "0.1.0"
//! num-traits = { version = "0.2.19", default-features = false }
//!
//! [features]
//! rt = ["riscv-rt"]
Expand Down
5 changes: 5 additions & 0 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<LitInt> {
(n != 0).then(|| hex(n))
}

/// Turns `n` into an unsuffixed token
pub fn unsuffixed(n: impl Into<u64>) -> LitInt {
LitInt::new(&n.into().to_string(), Span::call_site())
Expand Down
Loading