reg_map/
reg.rs

1use core::marker::PhantomData;
2use core::ptr::NonNull;
3
4use crate::access::{self, Access};
5use crate::integers::Integer;
6
7#[cfg(doc)]
8use crate::access::{ReadOnly, ReadWrite, WriteOnly};
9#[cfg(doc)]
10use crate::RegMap;
11
12/// A pointer to a register with volatile reads and writes.
13///
14/// # Access permissions
15/// The read/write permission for the register is set by the generic parameter `A`:
16/// - when `A` is [`ReadOnly`] or [`ReadWrite`], the register can be read from with [`Reg::read`],
17/// - when `A` is [`WriteOnly`] or [`ReadWrite`], the register can be written to with
18///   [`Reg::write`].
19///
20/// Access permissions are defined by the derive macro [`RegMap`] using the `#[reg()]` attribute,
21/// see [Access permissions](crate#access-permissions) in the crate documentation.
22pub struct Reg<'a, T, A> {
23    ptr: NonNull<T>,
24    _ref: PhantomData<&'a T>,
25    _acs: PhantomData<A>,
26}
27impl<'a, T: Integer, A: Access> Reg<'a, T, A> {
28    /// Creates a new `Reg`.
29    ///
30    /// ⚠️ This function is called by the field-access methods defined by the derive macro
31    /// [`RegMap`]. Do *not* call this function directly. Changes to this function are not
32    /// considered semver breaking.
33    ///
34    /// # Safety
35    /// - `ptr` must be [valid for reads](core::ptr::read_volatile#safety) if `A: Readable`,
36    /// - `ptr` must be [valid for writes](core::ptr::write_volatile#safety) if `A: Writable`,
37    /// - `ptr` must be properly aligned;
38    /// - `ptr` must be valid for the whole lifetime `'a`.
39    #[doc(hidden)]
40    #[allow(non_snake_case)]
41    #[inline]
42    pub const unsafe fn __MACRO_ONLY__from_ptr(ptr: *mut T) -> Self {
43        Self::from_nonnull(NonNull::new_unchecked(ptr))
44    }
45    #[inline]
46    pub(crate) const unsafe fn from_nonnull(ptr: NonNull<T>) -> Self {
47        Self {
48            ptr,
49            _ref: PhantomData,
50            _acs: PhantomData,
51        }
52    }
53    /// Returns a raw pointer to the underlying register.
54    #[inline]
55    pub const fn as_ptr(&self) -> *mut T {
56        self.ptr.as_ptr()
57    }
58    /// Perform a volatile read.
59    #[inline]
60    pub fn read(&self) -> T
61    where
62        A: access::Readable,
63    {
64        unsafe { self.ptr.read_volatile() }
65    }
66    /// Perform a volatile write.
67    #[inline]
68    pub fn write(&self, val: T)
69    where
70        A: access::Writable,
71    {
72        unsafe { self.ptr.write_volatile(val) }
73    }
74}
75
76/// Pointers to custom register maps derived by [`RegMap`].
77///
78/// ⚠️ This trait is implemented by the derive macro [`RegMap`]. Do *not* implement this trait
79/// directly. Adding new required items to this trait is not considered semver breaking.
80///
81/// # Safety
82/// This trait should only be implemented through the derive macro [`RegMap`].
83pub unsafe trait RegMapPtr<'a>: Sized + 'a {
84    type RegMap;
85
86    /// Creates a new pointer to `Self::RegMap`.
87    ///
88    /// # Safety
89    /// - `ptr` must point to a valid instance of `Self::RegMap`;
90    /// - `ptr` must be valid for the whole lifetime `'a`;
91    /// - all fields of `Self::RegMap` must allow volatile reads/writes.
92    unsafe fn from_nonnull(ptr: NonNull<Self::RegMap>) -> Self;
93
94    /// Creates a new pointer to `Self::RegMap`.
95    ///
96    /// # Safety
97    /// - `ptr` must not be null;
98    /// - `ptr` must point to a valid instance of `Self::RegMap`;
99    /// - `ptr` must be valid for the whole lifetime `'a`;
100    /// - all fields of `Self::RegMap` must allow volatile reads/writes.
101    unsafe fn from_ptr(ptr: *mut Self::RegMap) -> Self;
102
103    /// Return a pointer to `Self::RegMap` from a mutable (exclusive) reference.
104    fn from_mut(reg: &'a mut Self::RegMap) -> Self;
105
106    /// Returns a raw pointer to the underlying register map.
107    fn as_ptr(&self) -> *mut Self::RegMap;
108}