From c67d7056b4f7ba6c3f324773fe6f6bfaa76ade68 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Thu, 6 Jul 2023 21:23:54 +0300 Subject: [PATCH] make register reader/writer copiable, return writer --- CHANGELOG.md | 1 + src/generate/generic.rs | 177 +++++++++++++++++++++------------------ src/generate/register.rs | 26 +++--- 3 files changed, 110 insertions(+), 94 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30b43980..dc2459a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/). ## [Unreleased] +- make register reader/writer copiable, return writer from write & modify - removed register writer & reader wrappers, generic `REG` in field writers (#731) - Updated syn to version 2 (#732) - Let readable field fetch doc from svd description (#734) diff --git a/src/generate/generic.rs b/src/generate/generic.rs index c589b149..489b64ea 100644 --- a/src/generate/generic.rs +++ b/src/generate/generic.rs @@ -125,10 +125,7 @@ impl Reg { /// ``` #[inline(always)] pub fn read(&self) -> R { - R { - bits: self.register.get(), - _reg: marker::PhantomData, - } + R::new(self.register.get()) } } @@ -137,8 +134,9 @@ impl Reg { /// /// Resets the register to its initial state. #[inline(always)] - pub fn reset(&self) { - self.register.set(REG::RESET_VALUE) + pub fn reset(&self) -> W { + self.register.set(REG::RESET_VALUE); + W::new(REG::RESET_VALUE) } /// Writes bits to a `Writable` register. @@ -165,18 +163,16 @@ impl Reg { /// ``` /// In the latter case, other fields will be set to their reset value. #[inline(always)] - pub fn write(&self, f: F) + pub fn write(&self, f: F) -> W where - F: FnOnce(&mut W) -> &mut W, + F: FnOnce(W) -> W, { - self.register.set( - f(&mut W { - bits: REG::RESET_VALUE & !REG::ONE_TO_MODIFY_FIELDS_BITMAP - | REG::ZERO_TO_MODIFY_FIELDS_BITMAP, - _reg: marker::PhantomData, - }) - .bits, - ); + let w = f(W::new( + REG::RESET_VALUE & !REG::ONE_TO_MODIFY_FIELDS_BITMAP + | REG::ZERO_TO_MODIFY_FIELDS_BITMAP, + )); + self.register.set(w.bits); + w } } @@ -191,15 +187,9 @@ impl Reg { #[inline(always)] pub unsafe fn write_with_zero(&self, f: F) where - F: FnOnce(&mut W) -> &mut W, + F: FnOnce(W) -> W, { - self.register.set( - f(&mut W { - bits: REG::Ux::default(), - _reg: marker::PhantomData, - }) - .bits, - ); + self.register.set(f(W::new(REG::Ux::default())).bits); } } @@ -230,25 +220,17 @@ impl Reg { /// ``` /// Other fields will have the value they had before the call to `modify`. #[inline(always)] - pub fn modify(&self, f: F) + pub fn modify(&self, f: F) -> W where - for<'w> F: FnOnce(&R, &'w mut W) -> &'w mut W, + F: FnOnce(R, W) -> W, { let bits = self.register.get(); - self.register.set( - f( - &R { - bits, - _reg: marker::PhantomData, - }, - &mut W { - bits: bits & !REG::ONE_TO_MODIFY_FIELDS_BITMAP - | REG::ZERO_TO_MODIFY_FIELDS_BITMAP, - _reg: marker::PhantomData, - }, - ) - .bits, + let w = f( + R::new(bits), + W::new(bits & !REG::ONE_TO_MODIFY_FIELDS_BITMAP | REG::ZERO_TO_MODIFY_FIELDS_BITMAP), ); + self.register.set(w.bits); + w } } @@ -259,11 +241,28 @@ impl Reg { pub type R = RRaw; #[doc(hidden)] +#[derive(Copy)] pub struct RRaw { pub(crate) bits: REG::Ux, _reg: marker::PhantomData, } +impl Clone for RRaw { + fn clone(&self) -> Self { + Self::new(self.bits) + } +} + +impl RRaw { + #[inline(always)] + const fn new(bits: REG::Ux) -> Self { + Self { + bits, + _reg: marker::PhantomData, + } + } +} + impl R { /// Reads raw bits from register. #[inline(always)] @@ -290,16 +289,33 @@ where pub type W = WRaw; #[doc(hidden)] +#[derive(Copy)] pub struct WRaw { ///Writable bits pub(crate) bits: REG::Ux, _reg: marker::PhantomData, } +impl Clone for WRaw { + fn clone(&self) -> Self { + Self::new(self.bits) + } +} + +impl WRaw { + #[inline(always)] + const fn new(bits: REG::Ux) -> Self { + Self { + bits, + _reg: marker::PhantomData, + } + } +} + #[doc(hidden)] pub struct FieldReaderRaw where - FI: FieldSpec + FI: FieldSpec, { pub(crate) bits: FI::Ux, _reg: marker::PhantomData, @@ -396,17 +412,16 @@ pub struct Safe; pub struct Unsafe; #[doc(hidden)] -pub struct FieldWriterRaw<'a, REG, const WI: u8, const O: u8, FI = u8, Safety = Unsafe> +pub struct FieldWriterRaw where REG: Writable + RegisterSpec, FI: FieldSpec, { - pub(crate) w: &'a mut W, + pub(crate) w: W, _field: marker::PhantomData<(FI, Safety)>, } -impl<'a, REG, const WI: u8, const O: u8, FI, Safety> - FieldWriterRaw<'a, REG, WI, O, FI, Safety> +impl FieldWriterRaw where REG: Writable + RegisterSpec, FI: FieldSpec, @@ -414,7 +429,7 @@ where /// Creates a new instance of the writer #[allow(unused)] #[inline(always)] - pub(crate) fn new(w: &'a mut W) -> Self { + pub(crate) fn new(w: W) -> Self { Self { w, _field: marker::PhantomData, @@ -423,16 +438,16 @@ where } #[doc(hidden)] -pub struct BitWriterRaw<'a, REG, const O: u8, FI = bool, M = BitM> +pub struct BitWriterRaw where REG: Writable + RegisterSpec, bool: From, { - pub(crate) w: &'a mut W, + pub(crate) w: W, _field: marker::PhantomData<(FI, M)>, } -impl<'a, REG, const O: u8, FI, M> BitWriterRaw<'a, REG, O, FI, M> +impl BitWriterRaw where REG: Writable + RegisterSpec, bool: From, @@ -440,7 +455,7 @@ where /// Creates a new instance of the writer #[allow(unused)] #[inline(always)] - pub(crate) fn new(w: &'a mut W) -> Self { + pub(crate) fn new(w: W) -> Self { Self { w, _field: marker::PhantomData, @@ -449,13 +464,13 @@ where } /// Write field Proxy with unsafe `bits` -pub type FieldWriter<'a, REG, const WI: u8, const O: u8, FI = u8> = - FieldWriterRaw<'a, REG, WI, O, FI, Unsafe>; +pub type FieldWriter = + FieldWriterRaw; /// Write field Proxy with safe `bits` -pub type FieldWriterSafe<'a, REG, const WI: u8, const O: u8, FI = u8> = - FieldWriterRaw<'a, REG, WI, O, FI, Safe>; +pub type FieldWriterSafe = + FieldWriterRaw; -impl<'a, REG, const WI: u8, const OF: u8, FI> FieldWriter<'a, REG, WI, OF, FI> +impl FieldWriter where REG: Writable + RegisterSpec, FI: FieldSpec, @@ -464,7 +479,7 @@ where pub const WIDTH: u8 = WI; } -impl<'a, REG, const WI: u8, const OF: u8, FI> FieldWriterSafe<'a, REG, WI, OF, FI> +impl FieldWriterSafe where REG: Writable + RegisterSpec, FI: FieldSpec, @@ -479,9 +494,9 @@ macro_rules! bit_proxy { pub struct $mwv; /// Bit-wise write field proxy - pub type $writer<'a, REG, const O: u8, FI = bool> = BitWriterRaw<'a, REG, O, FI, $mwv>; + pub type $writer = BitWriterRaw; - impl<'a, REG, const OF: u8, FI> $writer<'a, REG, OF, FI> + impl $writer where REG: Writable + RegisterSpec, bool: From, @@ -494,21 +509,21 @@ macro_rules! bit_proxy { macro_rules! impl_bit_proxy { ($writer:ident) => { - impl<'a, REG, const OF: u8, FI> $writer<'a, REG, OF, FI> + impl $writer where REG: Writable + RegisterSpec, bool: From, { /// Writes bit to the field #[inline(always)] - pub fn bit(self, value: bool) -> &'a mut W { + pub fn bit(mut self, value: bool) -> W { self.w.bits &= !(REG::Ux::one() << OF); self.w.bits |= (REG::Ux::from(value) & REG::Ux::one()) << OF; self.w } /// Writes `variant` to the field #[inline(always)] - pub fn variant(self, variant: FI) -> &'a mut W { + pub fn variant(self, variant: FI) -> W { self.bit(bool::from(variant)) } } @@ -523,7 +538,7 @@ bit_proxy!(BitWriter0S, Bit0S); bit_proxy!(BitWriter1T, Bit1T); bit_proxy!(BitWriter0T, Bit0T); -impl<'a, REG, const WI: u8, const OF: u8, FI> FieldWriter<'a, REG, WI, OF, FI> +impl FieldWriter where REG: Writable + RegisterSpec, FI: FieldSpec, @@ -535,18 +550,18 @@ where /// /// Passing incorrect value can cause undefined behaviour. See reference manual #[inline(always)] - pub unsafe fn bits(self, value: FI::Ux) -> &'a mut W { + pub unsafe fn bits(mut self, value: FI::Ux) -> W { self.w.bits &= !(REG::Ux::mask::() << OF); self.w.bits |= (REG::Ux::from(value) & REG::Ux::mask::()) << OF; self.w } /// Writes `variant` to the field #[inline(always)] - pub fn variant(self, variant: FI) -> &'a mut W { + pub fn variant(self, variant: FI) -> W { unsafe { self.bits(FI::Ux::from(variant)) } } } -impl<'a, REG, const WI: u8, const OF: u8, FI> FieldWriterSafe<'a, REG, WI, OF, FI> +impl FieldWriterSafe where REG: Writable + RegisterSpec, FI: FieldSpec, @@ -554,14 +569,14 @@ where { /// Writes raw bits to the field #[inline(always)] - pub fn bits(self, value: FI::Ux) -> &'a mut W { + pub fn bits(mut self, value: FI::Ux) -> W { self.w.bits &= !(REG::Ux::mask::() << OF); self.w.bits |= (REG::Ux::from(value) & REG::Ux::mask::()) << OF; self.w } /// Writes `variant` to the field #[inline(always)] - pub fn variant(self, variant: FI) -> &'a mut W { + pub fn variant(self, variant: FI) -> W { self.bits(FI::Ux::from(variant)) } } @@ -574,98 +589,98 @@ impl_bit_proxy!(BitWriter0S); impl_bit_proxy!(BitWriter1T); impl_bit_proxy!(BitWriter0T); -impl<'a, REG, const OF: u8, FI> BitWriter<'a, REG, OF, FI> +impl BitWriter where REG: Writable + RegisterSpec, bool: From, { /// Sets the field bit #[inline(always)] - pub fn set_bit(self) -> &'a mut W { + pub fn set_bit(mut self) -> W { self.w.bits |= REG::Ux::one() << OF; self.w } /// Clears the field bit #[inline(always)] - pub fn clear_bit(self) -> &'a mut W { + pub fn clear_bit(mut self) -> W { self.w.bits &= !(REG::Ux::one() << OF); self.w } } -impl<'a, REG, const OF: u8, FI> BitWriter1S<'a, REG, OF, FI> +impl BitWriter1S where REG: Writable + RegisterSpec, bool: From, { /// Sets the field bit #[inline(always)] - pub fn set_bit(self) -> &'a mut W { + pub fn set_bit(mut self) -> W { self.w.bits |= REG::Ux::one() << OF; self.w } } -impl<'a, REG, const OF: u8, FI> BitWriter0C<'a, REG, OF, FI> +impl BitWriter0C where REG: Writable + RegisterSpec, bool: From, { /// Clears the field bit #[inline(always)] - pub fn clear_bit(self) -> &'a mut W { + pub fn clear_bit(mut self) -> W { self.w.bits &= !(REG::Ux::one() << OF); self.w } } -impl<'a, REG, const OF: u8, FI> BitWriter1C<'a, REG, OF, FI> +impl BitWriter1C where REG: Writable + RegisterSpec, bool: From, { ///Clears the field bit by passing one #[inline(always)] - pub fn clear_bit_by_one(self) -> &'a mut W { + pub fn clear_bit_by_one(mut self) -> W { self.w.bits |= REG::Ux::one() << OF; self.w } } -impl<'a, REG, const OF: u8, FI> BitWriter0S<'a, REG, OF, FI> +impl BitWriter0S where REG: Writable + RegisterSpec, bool: From, { ///Sets the field bit by passing zero #[inline(always)] - pub fn set_bit_by_zero(self) -> &'a mut W { + pub fn set_bit_by_zero(mut self) -> W { self.w.bits &= !(REG::Ux::one() << OF); self.w } } -impl<'a, REG, const OF: u8, FI> BitWriter1T<'a, REG, OF, FI> +impl BitWriter1T where REG: Writable + RegisterSpec, bool: From, { ///Toggle the field bit by passing one #[inline(always)] - pub fn toggle_bit(self) -> &'a mut W { + pub fn toggle_bit(mut self) -> W { self.w.bits |= REG::Ux::one() << OF; self.w } } -impl<'a, REG, const OF: u8, FI> BitWriter0T<'a, REG, OF, FI> +impl BitWriter0T where REG: Writable + RegisterSpec, bool: From, { ///Toggle the field bit by passing zero #[inline(always)] - pub fn toggle_bit(self) -> &'a mut W { + pub fn toggle_bit(mut self) -> W { self.w.bits &= !(REG::Ux::one() << OF); self.w } diff --git a/src/generate/register.rs b/src/generate/register.rs index fc56fb25..f15a37a5 100644 --- a/src/generate/register.rs +++ b/src/generate/register.rs @@ -291,7 +291,7 @@ pub fn render_register_mod( mod_items.extend(quote! { #[doc = "Writes raw bits to the register."] #[inline(always)] - pub fn bits(&mut self, bits: #rty) -> &mut Self { + pub fn bits(mut self, bits: #rty) -> Self { self.bits = bits; self } @@ -300,7 +300,7 @@ pub fn render_register_mod( mod_items.extend(quote! { #[doc = "Writes raw bits to the register."] #[inline(always)] - pub unsafe fn bits(&mut self, bits: #rty) -> &mut Self { + pub unsafe fn bits(mut self, bits: #rty) -> Self { self.bits = bits; self } @@ -921,7 +921,7 @@ pub fn fields( proxy_items.extend(quote! { #[doc = #doc] #inline - pub fn #sc(self) -> &'a mut crate::W { + pub fn #sc(self) -> crate::W { self.variant(#value_write_ty::#pc) } }); @@ -952,9 +952,9 @@ pub fn fields( span, ); if value_write_ty == "bool" { - quote! { crate::#wproxy<'a, REG, O> } + quote! { crate::#wproxy } } else { - quote! { crate::#wproxy<'a, REG, O, #value_write_ty> } + quote! { crate::#wproxy } } } else { let wproxy = Ident::new( @@ -967,14 +967,14 @@ pub fn fields( ); let width = &util::unsuffixed(width as _); if value_write_ty == "u8" { - quote! { crate::#wproxy<'a, REG, #width, O> } + quote! { crate::#wproxy } } else { - quote! { crate::#wproxy<'a, REG, #width, O, #value_write_ty> } + quote! { crate::#wproxy } } }; mod_items.extend(quote! { #[doc = #field_writer_brief] - pub type #writer_ty<'a, REG, const O: u8> = #proxy; + pub type #writer_ty = #proxy; }); } @@ -982,7 +982,7 @@ pub fn fields( if !proxy_items.is_empty() { mod_items.extend(if width == 1 { quote! { - impl<'a, REG, const O: u8> #writer_ty<'a, REG, O> + impl #writer_ty where REG: crate::Writable + crate::RegisterSpec, { @@ -991,7 +991,7 @@ pub fn fields( } } else { quote! { - impl<'a, REG, const O: u8> #writer_ty<'a, REG, O> + impl #writer_ty where REG: crate::Writable + crate::RegisterSpec, REG::Ux: From<#fty> @@ -1043,7 +1043,7 @@ pub fn fields( #[doc = #doc] #inline #[must_use] - pub unsafe fn #name_snake_case(&mut self) -> #writer_ty<#regspec_ident, O> { + pub unsafe fn #name_snake_case(self) -> #writer_ty<#regspec_ident, O> { #writer_ty::new(self) } }); @@ -1062,7 +1062,7 @@ pub fn fields( #[doc = #doc] #inline #[must_use] - pub fn #name_snake_case_n(&mut self) -> #writer_ty<#regspec_ident, #sub_offset> { + pub fn #name_snake_case_n(self) -> #writer_ty<#regspec_ident, #sub_offset> { #writer_ty::new(self) } }); @@ -1074,7 +1074,7 @@ pub fn fields( #[doc = #doc] #inline #[must_use] - pub fn #name_snake_case(&mut self) -> #writer_ty<#regspec_ident, #offset> { + pub fn #name_snake_case(self) -> #writer_ty<#regspec_ident, #offset> { #writer_ty::new(self) } });