diff --git a/CHANGELOG.md b/CHANGELOG.md index cc5aa8e9..93686001 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +- Use modifiedWriteValues for 1-bitwise fields if present - Use generic `FieldWriter`, `FieldReader`, `BitWriter`, `BitReader` - Disable two clippy warnings in `array_proxy.rs` - Add comments in docs about `readAction` diff --git a/src/generate/generic.rs b/src/generate/generic.rs index dd367f7e..2417efe8 100644 --- a/src/generate/generic.rs +++ b/src/generate/generic.rs @@ -352,16 +352,16 @@ where } #[doc(hidden)] -pub struct BitWriterRaw<'a, U, REG, FI, const O: u8> +pub struct BitWriterRaw<'a, U, REG, FI, M, const O: u8> where REG: Writable + RegisterSpec, FI: Into, { pub(crate) w: &'a mut REG::Writer, - _field: marker::PhantomData, + _field: marker::PhantomData<(FI, M)>, } -impl<'a, U, REG, FI, const O: u8> BitWriterRaw<'a, U, REG, FI, O> +impl<'a, U, REG, FI, M, const O: u8> BitWriterRaw<'a, U, REG, FI, M, O> where REG: Writable + RegisterSpec, FI: Into, @@ -382,9 +382,6 @@ pub type FieldWriter<'a, U, REG, N, FI, const WI: u8, const O: u8> = FieldWriter /// Write field Proxy with safe `bits` pub type FieldWriterSafe<'a, U, REG, N, FI, const WI: u8, const O: u8> = FieldWriterRaw<'a, U, REG, N, FI, Safe, WI, O>; -/// Bit-wise write field proxy -pub type BitWriter<'a, U, REG, FI, const O: u8> = BitWriterRaw<'a, U, REG, FI, O>; - impl<'a, U, REG, N, FI, const WI: u8, const OF: u8> FieldWriter<'a, U, REG, N, FI, WI, OF> where @@ -408,17 +405,57 @@ where pub const OFFSET: u8 = OF; } -impl<'a, U, REG, FI, const OF: u8> BitWriter<'a, U, REG, FI, OF> -where - REG: Writable + RegisterSpec, - FI: Into, -{ - /// Field width - pub const WIDTH: u8 = 1; - /// Field offset - pub const OFFSET: u8 = OF; +macro_rules! bit_proxy { + ($writer:ident, $mwv:ident) => { + #[doc(hidden)] + pub struct $mwv; + + /// Bit-wise write field proxy + pub type $writer<'a, U, REG, FI, const O: u8> = BitWriterRaw<'a, U, REG, FI, $mwv, O>; + + impl<'a, U, REG, FI, const OF: u8> $writer<'a, U, REG, FI, OF> + where + REG: Writable + RegisterSpec, + FI: Into, + { + /// Field width + pub const WIDTH: u8 = 1; + /// Field offset + pub const OFFSET: u8 = OF; + } + } } +macro_rules! impl_bit_proxy { + ($writer:ident, $U:ty) => { + impl<'a, REG, FI, const OF: u8> $writer<'a, $U, REG, FI, OF> + where + REG: Writable + RegisterSpec, + FI: Into, + { + /// Writes bit to the field + #[inline(always)] + pub fn bit(self, value: bool) -> &'a mut REG::Writer { + self.w.bits = (self.w.bits & !(1 << { OF })) | ((<$U>::from(value) & 1) << { OF }); + self.w + } + /// Writes `variant` to the field + #[inline(always)] + pub fn variant(self, variant: FI) -> &'a mut REG::Writer { + self.bit(variant.into()) + } + } + } +} + +bit_proxy!(BitWriter, BitM); +bit_proxy!(BitWriter1S, Bit1S); +bit_proxy!(BitWriter0C, Bit0C); +bit_proxy!(BitWriter1C, Bit1C); +bit_proxy!(BitWriter0S, Bit0S); +bit_proxy!(BitWriter1T, Bit1T); +bit_proxy!(BitWriter0T, Bit0T); + macro_rules! impl_proxy { ($U:ty) => { impl<'a, REG, N, FI, const WI: u8, const OF: u8> FieldWriter<'a, $U, REG, N, FI, WI, OF> @@ -465,32 +502,94 @@ macro_rules! impl_proxy { self.bits(variant.into()) } } + impl_bit_proxy!(BitWriter, $U); + impl_bit_proxy!(BitWriter1S, $U); + impl_bit_proxy!(BitWriter0C, $U); + impl_bit_proxy!(BitWriter1C, $U); + impl_bit_proxy!(BitWriter0S, $U); + impl_bit_proxy!(BitWriter1T, $U); + impl_bit_proxy!(BitWriter0T, $U); impl<'a, REG, FI, const OF: u8> BitWriter<'a, $U, REG, FI, OF> where REG: Writable + RegisterSpec, FI: Into, { - /// Writes bit to the field + /// Sets the field bit #[inline(always)] - pub fn bit(self, value: bool) -> &'a mut REG::Writer { - self.w.bits = (self.w.bits & !(1 << { OF })) | ((<$U>::from(value) & 1) << { OF }); - self.w + pub fn set_bit(self) -> &'a mut REG::Writer { + self.bit(true) } - /// Writes `variant` to the field + /// Clears the field bit #[inline(always)] - pub fn variant(self, variant: FI) -> &'a mut REG::Writer { - self.bit(variant.into()) + pub fn clear_bit(self) -> &'a mut REG::Writer { + self.bit(false) } + } + impl<'a, REG, FI, const OF: u8> BitWriter1S<'a, $U, REG, FI, OF> + where + REG: Writable + RegisterSpec, + FI: Into, + { /// Sets the field bit #[inline(always)] pub fn set_bit(self) -> &'a mut REG::Writer { self.bit(true) } + } + impl<'a, REG, FI, const OF: u8> BitWriter0C<'a, $U, REG, FI, OF> + where + REG: Writable + RegisterSpec, + FI: Into, + { /// Clears the field bit #[inline(always)] pub fn clear_bit(self) -> &'a mut REG::Writer { self.bit(false) } } + impl<'a, REG, FI, const OF: u8> BitWriter1C<'a, $U, REG, FI, OF> + where + REG: Writable + RegisterSpec, + FI: Into, + { + ///Clears the field bit by passing one + #[inline(always)] + pub fn clear_bit_by_one(self) -> &'a mut REG::Writer { + self.bit(true) + } + } + impl<'a, REG, FI, const OF: u8> BitWriter0S<'a, $U, REG, FI, OF> + where + REG: Writable + RegisterSpec, + FI: Into, + { + ///Sets the field bit by passing zero + #[inline(always)] + pub fn set_bit_by_zero(self) -> &'a mut REG::Writer { + self.bit(false) + } + } + impl<'a, REG, FI, const OF: u8> BitWriter1T<'a, $U, REG, FI, OF> + where + REG: Writable + RegisterSpec, + FI: Into, + { + ///Toggle the field bit by passing one + #[inline(always)] + pub fn toggle_bit(self) -> &'a mut REG::Writer { + self.bit(true) + } + } + impl<'a, REG, FI, const OF: u8> BitWriter0T<'a, $U, REG, FI, OF> + where + REG: Writable + RegisterSpec, + FI: Into, + { + ///Toggle the field bit by passing zero + #[inline(always)] + pub fn toggle_bit(self) -> &'a mut REG::Writer { + self.bit(false) + } + } } } diff --git a/src/generate/register.rs b/src/generate/register.rs index 55caf3a1..6b810da5 100644 --- a/src/generate/register.rs +++ b/src/generate/register.rs @@ -1,6 +1,6 @@ use crate::svd::{ - Access, BitRange, DeriveFrom, EnumeratedValues, Field, Peripheral, ReadAction, Register, - RegisterProperties, Usage, WriteConstraint, + Access, BitRange, DeriveFrom, EnumeratedValues, Field, ModifiedWriteValues, Peripheral, + ReadAction, Register, RegisterProperties, Usage, WriteConstraint, }; use cast::u64; use core::u64; @@ -604,6 +604,10 @@ pub fn fields( } if can_write { + let mwv = f + .modified_write_values + .or(register.modified_write_values) + .unwrap_or_default(); let writerdoc = if let Some((_, _, _, _, suffixes_str)) = &field_dim { format!( "Fields `{}` writer - {}", @@ -673,20 +677,38 @@ pub fn fields( } if !derived { - let wproxy = if unsafety { - Ident::new("FieldWriter", span) - } else { - Ident::new("FieldWriterSafe", span) - }; - let (offset, gen_offset) = if field_dim.is_some() { (quote! { O }, quote! {, const O: u8 }) } else { (util::unsuffixed(offset as u64), quote! {}) }; let proxy = if width == 1 { - quote! { crate::BitWriter<'a, #rty, #name_uc_spec, #name_pc_aw, #offset> } + let wproxy = Ident::new( + match mwv { + ModifiedWriteValues::Modify => "BitWriter", + ModifiedWriteValues::OneToSet | ModifiedWriteValues::Set => { + "BitWriter1S" + } + ModifiedWriteValues::ZeroToClear | ModifiedWriteValues::Clear => { + "BitWriter0C" + } + ModifiedWriteValues::OneToClear => "BitWriter1C", + ModifiedWriteValues::ZeroToSet => "BitWriter0C", + ModifiedWriteValues::OneToToggle => "BitWriter1T", + ModifiedWriteValues::ZeroToToggle => "BitWriter0T", + }, + span, + ); + quote! { crate::#wproxy<'a, #rty, #name_uc_spec, #name_pc_aw, #offset> } } else { + let wproxy = Ident::new( + if unsafety { + "FieldWriter" + } else { + "FieldWriterSafe" + }, + span, + ); let width = &util::unsuffixed(width as _); quote! { crate::#wproxy<'a, #rty, #name_uc_spec, #fty, #name_pc_aw, #width, #offset> } };