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}