diff --git a/src/config.rs b/src/config.rs index 57c11798..97f46dc8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -36,7 +36,6 @@ pub struct Config { pub field_names_for_enums: bool, pub base_address_shift: u64, pub raw_access: bool, - pub raw_read_write: bool, } #[allow(clippy::upper_case_acronyms)] diff --git a/src/generate/device.rs b/src/generate/device.rs index 0f36bbf4..86c40abd 100644 --- a/src/generate/device.rs +++ b/src/generate/device.rs @@ -63,8 +63,12 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result Result Result { for p_name in names(p, dim_element) { @@ -271,7 +273,7 @@ pub fn render(d: &Device, config: &Config, device_x: &mut String) -> Result { + ptr: *mut u8, _marker: marker::PhantomData, } unsafe impl Send for Reg where REG::Ux: Send {} impl Reg { + #[inline(always)] + pub const fn new(ptr: *mut u8) -> Self { + Self { + ptr, + _marker: marker::PhantomData, + } + } /// Returns the underlying memory address of register. /// /// ```ignore /// let reg_ptr = periph.reg.as_ptr(); /// ``` #[inline(always)] - pub fn as_ptr(&self) -> *mut REG::Ux { - (self as *const Self).cast_mut().cast() + pub const fn as_ptr(&self) -> *mut REG::Ux { + self.ptr.cast() } } @@ -161,7 +169,7 @@ impl Reg { impl core::fmt::Debug for crate::generic::Reg where - R: core::fmt::Debug + R: core::fmt::Debug, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { unsafe { core::fmt::Debug::fmt(&self.read(), f) } diff --git a/src/generate/peripheral.rs b/src/generate/peripheral.rs index 60da97f6..2a244c9c 100644 --- a/src/generate/peripheral.rs +++ b/src/generate/peripheral.rs @@ -61,7 +61,7 @@ pub fn render(p_original: &Peripheral, index: &Index, config: &Config) -> Result feature_attribute.extend(quote! { #[cfg(feature = #feature_name)] }); }; - let steal_fn = quote! { + let steal_docs = quote! { /// Steal an instance of this peripheral /// /// # Safety @@ -75,9 +75,6 @@ pub fn render(p_original: &Peripheral, index: &Index, config: &Config) -> Result /// Additionally, other software such as HALs may rely on only one /// peripheral instance existing to ensure memory safety; ensure /// no stolen instances are passed to such software. - pub unsafe fn steal() -> Self { - Self { _marker: PhantomData } - } }; match &p { @@ -97,39 +94,74 @@ pub fn render(p_original: &Peripheral, index: &Index, config: &Config) -> Result feature_attribute_n.extend(quote! { #[cfg(feature = #p_feature)] }) }; // Insert the peripherals structure - out.extend(quote! { - #[doc = #description] - #doc_alias - #feature_attribute_n - pub struct #p_ty { _marker: PhantomData<*const ()> } + out.extend(if config.raw_access { + quote! { + #[doc = #description] + #doc_alias + #feature_attribute_n + pub struct #p_ty { rb: #base::RegisterBlock } + + #feature_attribute_n + unsafe impl Send for #p_ty {} + + #feature_attribute_n + impl #p_ty { + #steal_docs + pub unsafe fn steal() -> Self { + Self { rb: #base::RegisterBlock::new(#address as *mut u8) } + } + } - #feature_attribute_n - unsafe impl Send for #p_ty {} + #feature_attribute_n + impl Deref for #p_ty { + type Target = #base::RegisterBlock; - #feature_attribute_n - impl #p_ty { - ///Pointer to the register block - pub const PTR: *const #base::RegisterBlock = #address as *const _; - - ///Return the pointer to the register block - #[inline(always)] - pub const fn ptr() -> *const #base::RegisterBlock { - Self::PTR + #[inline(always)] + fn deref(&self) -> &Self::Target { + &self.rb + } } - - #steal_fn } + } else { + quote! { + #[doc = #description] + #doc_alias + #feature_attribute_n + pub struct #p_ty { _marker: PhantomData<*const ()> } + + #feature_attribute_n + unsafe impl Send for #p_ty {} + + #feature_attribute_n + impl #p_ty { + ///Pointer to the register block + pub const PTR: *const #base::RegisterBlock = #address as *const _; + + ///Return the pointer to the register block + #[inline(always)] + pub const fn ptr() -> *const #base::RegisterBlock { + Self::PTR + } - #feature_attribute_n - impl Deref for #p_ty { - type Target = #base::RegisterBlock; + #steal_docs + pub unsafe fn steal() -> Self { + Self { _marker: PhantomData } + } + } - #[inline(always)] - fn deref(&self) -> &Self::Target { - unsafe { &*Self::PTR } + #feature_attribute_n + impl Deref for #p_ty { + type Target = #base::RegisterBlock; + + #[inline(always)] + fn deref(&self) -> &Self::Target { + unsafe { &*Self::PTR } + } } } + }); + out.extend(quote! { #feature_attribute_n impl core::fmt::Debug for #p_ty { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { @@ -159,38 +191,72 @@ pub fn render(p_original: &Peripheral, index: &Index, config: &Config) -> Result feature_attribute.extend(quote! { #[cfg(feature = #p_feature)] }) }; // Insert the peripheral structure - out.extend(quote! { - #[doc = #description] - #feature_attribute - pub struct #p_ty { _marker: PhantomData<*const ()> } + out.extend(if config.raw_access { + quote! { + #[doc = #description] + #feature_attribute + #[repr(transparent)] + pub struct #p_ty { rb: #base::RegisterBlock } - #feature_attribute - unsafe impl Send for #p_ty {} + #feature_attribute + unsafe impl Send for #p_ty {} - #feature_attribute - impl #p_ty { - ///Pointer to the register block - pub const PTR: *const #base::RegisterBlock = #address as *const _; - - ///Return the pointer to the register block - #[inline(always)] - pub const fn ptr() -> *const #base::RegisterBlock { - Self::PTR + #feature_attribute + impl #p_ty { + #steal_docs + pub unsafe fn steal() -> Self { + Self { rb: #base::RegisterBlock::new(#address as *mut u8) } + } } - #steal_fn + #feature_attribute + impl Deref for #p_ty { + type Target = #base::RegisterBlock; + + #[inline(always)] + fn deref(&self) -> &Self::Target { + &self.rb + } + } } + } else { + quote! { + #[doc = #description] + #feature_attribute + pub struct #p_ty { _marker: PhantomData<*const ()> } - #feature_attribute - impl Deref for #p_ty { - type Target = #base::RegisterBlock; + #feature_attribute + unsafe impl Send for #p_ty {} + + #feature_attribute + impl #p_ty { + ///Pointer to the register block + pub const PTR: *const #base::RegisterBlock = #address as *const _; + + ///Return the pointer to the register block + #[inline(always)] + pub const fn ptr() -> *const #base::RegisterBlock { + Self::PTR + } - #[inline(always)] - fn deref(&self) -> &Self::Target { - unsafe { &*Self::PTR } + #steal_docs + pub unsafe fn steal() -> Self { + Self { _marker: PhantomData } + } } - } + #feature_attribute + impl Deref for #p_ty { + type Target = #base::RegisterBlock; + + #[inline(always)] + fn deref(&self) -> &Self::Target { + unsafe { &*Self::PTR } + } + } + } + }); + out.extend(quote! { #feature_attribute impl core::fmt::Debug for #p_ty { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { @@ -649,6 +715,18 @@ fn register_or_cluster_block( Ident::new("RegisterBlock", span) }; + if config.raw_access { + accessors.extend(quote! { + pub(crate) const fn new(ptr: *mut u8) -> Self { + Self { ptr } + } + #[inline(always)] + pub const fn ptr(&self) -> *mut u8 { + self.ptr + } + }) + } + let accessors = (!accessors.is_empty()).then(|| { quote! { impl #block_ty { @@ -657,16 +735,31 @@ fn register_or_cluster_block( } }); - Ok(quote! { - #[repr(C)] - #derive_debug - #[doc = #doc] - #doc_alias - pub struct #block_ty { - #rbfs + Ok(if config.raw_access { + quote! { + #[doc = #doc] + #[repr(C)] + #derive_debug + #doc_alias + #[non_exhaustive] + pub struct #block_ty { + ptr: *mut u8, + } + + #accessors } + } else { + quote! { + #[doc = #doc] + #[repr(C)] + #derive_debug + #doc_alias + pub struct #block_ty { + #rbfs + } - #accessors + #accessors + } }) } @@ -1009,7 +1102,7 @@ fn expand_cluster(cluster: &Cluster, config: &Config) -> Result Result Result Result AccessType { - if flag { + pub fn ptr_or_rawref_if(self, ptr_flag: bool, raw_flag: bool) -> AccessType { + if ptr_flag { + AccessType::Ptr(self) + } else if raw_flag { AccessType::RawRef(self) } else { AccessType::Ref(self) @@ -27,7 +30,7 @@ impl Accessor { impl AccessType { pub fn raw(self) -> Self { match self { - Self::RawRef(_) => self, + Self::RawRef(_) | Self::Ptr(_) => self, Self::Ref(a) => Self::RawRef(a), } } @@ -59,6 +62,20 @@ impl ToTokens for AccessType { } } } + Self::Ptr(Accessor::Reg(RegAccessor { + doc, + name, + ty, + offset, + })) => { + quote! { + #[doc = #doc] + #[inline(always)] + pub const fn #name(&self) -> #ty { + #ty::new(unsafe { self.ptr().add(#offset) }) + } + } + } Self::Ref(Accessor::Array(ArrayAccessor { doc, name, ty, .. })) => { let name_iter = Ident::new(&format!("{name}_iter"), Span::call_site()); quote! { @@ -101,6 +118,32 @@ impl ToTokens for AccessType { } } } + Self::Ptr(Accessor::Array(ArrayAccessor { + doc, + name, + ty, + offset, + dim, + increment, + })) => { + let name_iter = Ident::new(&format!("{name}_iter"), Span::call_site()); + let cast = quote! { #ty::new(unsafe { self.ptr().add(#offset).add(#increment * n) }) }; + quote! { + #[doc = #doc] + #[inline(always)] + pub const fn #name(&self, n: usize) -> #ty { + #[allow(clippy::no_effect)] + [(); #dim][n]; + #cast + } + #[doc = "Iterator for array of:"] + #[doc = #doc] + #[inline(always)] + pub fn #name_iter(&self) -> impl Iterator + '_ { + (0..#dim).map(move |n| #cast) + } + } + } Self::RawRef(Accessor::ArrayElem(elem)) | Self::Ref(Accessor::ArrayElem(elem)) => { let ArrayElemAccessor { doc, @@ -117,6 +160,21 @@ impl ToTokens for AccessType { } } } + Self::Ptr(Accessor::ArrayElem(ArrayElemAccessor { + doc, + name, + ty, + basename, + i, + })) => { + quote! { + #[doc = #doc] + #[inline(always)] + pub const fn #name(&self) -> #ty { + self.#basename(#i) + } + } + } } .to_tokens(tokens); } diff --git a/src/main.rs b/src/main.rs index 46d90dc0..1fc7de18 100755 --- a/src/main.rs +++ b/src/main.rs @@ -248,12 +248,6 @@ Allowed cases are `unchanged` (''), `pascal` ('p'), `constant` ('c') and `snake` .alias("raw_access") .help("Always access to registers by address"), ) - .arg( - Arg::new("raw_read_write") - .long("raw-read-write") - .alias("raw_read_write") - .help("Read/Write/Modify registers without vcell"), - ) .arg( Arg::new("reexport_core_peripherals") .long("reexport-core-peripherals")