diff --git a/src/generate/generic.rs b/src/generate/generic.rs index a04a6e0d..c539badd 100644 --- a/src/generate/generic.rs +++ b/src/generate/generic.rs @@ -9,14 +9,20 @@ pub trait RegisterSpec { /// Trait implemented by readable registers to enable the `read` method. /// /// Registers marked with `Writable` can be also `modify`'ed. -pub trait Readable: RegisterSpec {} +pub trait Readable: RegisterSpec { + /// Result from a call to `read` and argument to `modify`. + type Reader: core::convert::From> + core::ops::Deref>; +} /// Trait implemented by writeable registers. /// /// This enables the `write`, `write_with_zero` and `reset` methods. /// /// Registers marked with `Readable` can be also `modify`'ed. -pub trait Writable: RegisterSpec {} +pub trait Writable: RegisterSpec { + /// Writer type argument to `write`, et al. + type Writer: core::convert::From> + core::ops::Deref>; +} /// Reset value of the register. /// @@ -61,11 +67,11 @@ impl Reg { /// let flag = reader.field2().bit_is_set(); /// ``` #[inline(always)] - pub fn read(&self) -> R { - R { + pub fn read(&self) -> REG::Reader { + REG::Reader::from(R { bits: self.register.get(), _reg: marker::PhantomData, - } + }) } } @@ -96,13 +102,13 @@ impl Reg { #[inline(always)] pub fn write(&self, f: F) where - F: FnOnce(&mut W) -> &mut W, + F: FnOnce(&mut REG::Writer) -> &mut REG::Writer, { self.register.set( - f(&mut W { + f(&mut REG::Writer::from(W { bits: REG::reset_value(), _reg: marker::PhantomData, - }) + })) .bits, ); } @@ -118,13 +124,13 @@ where #[inline(always)] pub fn write_with_zero(&self, f: F) where - F: FnOnce(&mut W) -> &mut W, + F: FnOnce(&mut REG::Writer) -> &mut REG::Writer, { self.register.set( - f(&mut W { + (*f(&mut REG::Writer::from(W { bits: REG::Ux::default(), _reg: marker::PhantomData, - }) + }))) .bits, ); } @@ -151,19 +157,19 @@ impl Reg { #[inline(always)] pub fn modify(&self, f: F) where - for<'w> F: FnOnce(&R, &'w mut W) -> &'w mut W, + for<'w> F: FnOnce(®::Reader, &'w mut REG::Writer) -> &'w mut REG::Writer, { let bits = self.register.get(); self.register.set( f( - &R { + ®::Reader::from(R { bits, _reg: marker::PhantomData, - }, - &mut W { + }), + &mut REG::Writer::from(W { bits, _reg: marker::PhantomData, - }, + }), ) .bits, ); @@ -174,7 +180,7 @@ impl Reg { /// /// Result of the `read` methods of registers. Also used as a closure argument in the `modify` /// method. -pub struct R { +pub struct R { pub(crate) bits: REG::Ux, _reg: marker::PhantomData, } @@ -201,7 +207,7 @@ where /// Register writer. /// /// Used as an argument to the closures in the `write` and `modify` methods of the register. -pub struct W { +pub struct W { ///Writable bits pub(crate) bits: REG::Ux, _reg: marker::PhantomData, @@ -210,9 +216,8 @@ pub struct W { impl W { /// Writes raw bits to the register. #[inline(always)] - pub unsafe fn bits(&mut self, bits: REG::Ux) -> &mut Self { + pub unsafe fn bits(&mut self, bits: REG::Ux) { self.bits = bits; - self } } diff --git a/src/generate/register.rs b/src/generate/register.rs index 535680ea..0c7ac27b 100644 --- a/src/generate/register.rs +++ b/src/generate/register.rs @@ -57,7 +57,22 @@ pub fn render( let desc = format!("Reader of register {}", register.name); mod_items.extend(quote! { #[doc = #desc] - pub type R = crate::R<#name_uc_spec>; + pub struct R(crate::R<#name_uc_spec>); + + impl core::ops::Deref for R { + type Target = crate::R<#name_uc_spec>; + + #[inline(always)] + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl core::convert::From> for R { + fn from(reader: crate::R<#name_uc_spec>) -> Self { + R(reader) + } + } }); methods.push("read"); } @@ -66,7 +81,29 @@ pub fn render( let desc = format!("Writer for register {}", register.name); mod_items.extend(quote! { #[doc = #desc] - pub type W = crate::W<#name_uc_spec>; + pub struct W(crate::W<#name_uc_spec>); + + impl core::ops::Deref for W { + type Target = crate::W<#name_uc_spec>; + + #[inline(always)] + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl core::ops::DerefMut for W { + #[inline(always)] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + + impl core::convert::From> for W { + fn from(writer: crate::W<#name_uc_spec>) -> Self { + W(writer) + } + } }); methods.push("write_with_zero"); if can_reset { @@ -125,6 +162,14 @@ pub fn render( mod_items.extend(w_impl_items); + mod_items.extend(quote! { + #[doc = "Writes raw bits to the register."] + pub unsafe fn bits(&mut self, bits: #rty) -> &mut Self { + self.0.bits(bits); + self + } + }); + close.to_tokens(&mut mod_items); } @@ -167,7 +212,9 @@ pub fn render( ); mod_items.extend(quote! { #[doc = #doc] - impl crate::Readable for #name_uc_spec {} + impl crate::Readable for #name_uc_spec { + type Reader = R; + } }); } if can_write { @@ -177,7 +224,9 @@ pub fn render( ); mod_items.extend(quote! { #[doc = #doc] - impl crate::Writable for #name_uc_spec {} + impl crate::Writable for #name_uc_spec { + type Writer = W; + } }); } if let Some(rv) = res_val.map(util::hex) { @@ -388,7 +437,22 @@ pub fn fields( mod_items.extend(quote! { #[doc = #readerdoc] - pub type #name_pc_r = crate::FieldReader<#fty, #name_pc_a>; + pub struct #name_pc_r(crate::FieldReader<#fty, #name_pc_a>); + + impl #name_pc_r { + pub(crate) fn new(bits: #fty) -> Self { + #name_pc_r(crate::FieldReader::new(bits)) + } + } + + impl core::ops::Deref for #name_pc_r { + type Target = crate::FieldReader<#fty, #name_pc_a>; + + #[inline(always)] + fn deref(&self) -> &Self::Target { + &self.0 + } + } }); } else { let has_reserved_variant = evs.values.len() != (1 << width); @@ -463,23 +527,51 @@ pub fn fields( #[doc = #doc] #inline pub fn #is_variant(&self) -> bool { - *self == #name_pc_a::#pc + **self == #name_pc_a::#pc } }); } mod_items.extend(quote! { #[doc = #readerdoc] - pub type #name_pc_r = crate::FieldReader<#fty, #name_pc_a>; + pub struct #name_pc_r(crate::FieldReader<#fty, #name_pc_a>); + impl #name_pc_r { + pub(crate) fn new(bits: #fty) -> Self { + #name_pc_r(crate::FieldReader::new(bits)) + } #enum_items } + + impl core::ops::Deref for #name_pc_r { + type Target = crate::FieldReader<#fty, #name_pc_a>; + + #[inline(always)] + fn deref(&self) -> &Self::Target { + &self.0 + } + } }); } } else { mod_items.extend(quote! { #[doc = #readerdoc] - pub type #name_pc_r = crate::FieldReader<#fty, #fty>; + pub struct #name_pc_r(crate::FieldReader<#fty, #fty>); + + impl #name_pc_r { + pub(crate) fn new(bits: #fty) -> Self { + #name_pc_r(crate::FieldReader::new(bits)) + } + } + + impl core::ops::Deref for #name_pc_r { + type Target = crate::FieldReader<#fty, #fty>; + + #[inline(always)] + fn deref(&self) -> &Self::Target { + &self.0 + } + } }) } }