1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use core::marker::PhantomData;
use core::ptr::NonNull;

use crate::access::{self, Access};
use crate::integers::Integer;

#[cfg(doc)]
use crate::access::{ReadOnly, ReadWrite, WriteOnly};
#[cfg(doc)]
use crate::RegMap;

/// A pointer to a register with volatile reads and writes.
///
/// # Access permissions
/// The read/write permission for the register is set by the generic parameter `A`:
/// - when `A` is [`ReadOnly`] or [`ReadWrite`], the register can be read from with [`Reg::read`],
/// - when `A` is [`WriteOnly`] or [`ReadWrite`], the register can be written to with
///   [`Reg::write`].
///
/// Access permissions are defined by the derive macro [`RegMap`] using the `#[reg()]` attribute,
/// see [Access permissions](crate#access-permissions) in the crate documentation.
pub struct Reg<'a, T, A> {
    ptr: NonNull<T>,
    _ref: PhantomData<&'a T>,
    _acs: PhantomData<A>,
}
impl<'a, T: Integer, A: Access> Reg<'a, T, A> {
    /// Creates a new `Reg`.
    ///
    /// ⚠️ This function is called by the field-access methods defined by the derive macro
    /// [`RegMap`]. Do *not* call this function directly. Changes to this function are not
    /// considered semver breaking.
    ///
    /// # Safety
    /// - `ptr` must be [valid for reads](core::ptr::read_volatile#safety) if `A: Readable`,
    /// - `ptr` must be [valid for writes](core::ptr::write_volatile#safety) if `A: Writable`,
    /// - `ptr` must be properly aligned;
    /// - `ptr` must be valid for the whole lifetime `'a`.
    #[doc(hidden)]
    #[allow(non_snake_case)]
    #[inline]
    pub const unsafe fn __MACRO_ONLY__from_ptr(ptr: *mut T) -> Self {
        Self::from_nonnull(NonNull::new_unchecked(ptr))
    }
    #[inline]
    pub(crate) const unsafe fn from_nonnull(ptr: NonNull<T>) -> Self {
        Self {
            ptr,
            _ref: PhantomData,
            _acs: PhantomData,
        }
    }
    /// Returns a raw pointer to the underlying register.
    #[inline]
    pub const fn as_ptr(&self) -> *mut T {
        self.ptr.as_ptr()
    }
    /// Perform a volatile read.
    #[inline]
    pub fn read(&self) -> T
    where
        A: access::Readable,
    {
        unsafe { self.ptr.read_volatile() }
    }
    /// Perform a volatile write.
    #[inline]
    pub fn write(&self, val: T)
    where
        A: access::Writable,
    {
        unsafe { self.ptr.write_volatile(val) }
    }
}

/// Pointers to custom register maps derived by [`RegMap`].
///
/// ⚠️ This trait is implemented by the derive macro [`RegMap`]. Do *not* implement this trait
/// directly. Adding new required items to this trait is not considered semver breaking.
///
/// # Safety
/// This trait should only be implemented through the derive macro [`RegMap`].
pub unsafe trait RegMapPtr<'a>: Sized + 'a {
    type RegMap;

    /// Creates a new pointer to `Self::RegMap`.
    ///
    /// # Safety
    /// - `ptr` must point to a valid instance of `Self::RegMap`;
    /// - `ptr` must be valid for the whole lifetime `'a`;
    /// - all fields of `Self::RegMap` must allow volatile reads/writes.
    unsafe fn from_nonnull(ptr: NonNull<Self::RegMap>) -> Self;

    /// Creates a new pointer to `Self::RegMap`.
    ///
    /// # Safety
    /// - `ptr` must not be null;
    /// - `ptr` must point to a valid instance of `Self::RegMap`;
    /// - `ptr` must be valid for the whole lifetime `'a`;
    /// - all fields of `Self::RegMap` must allow volatile reads/writes.
    unsafe fn from_ptr(ptr: *mut Self::RegMap) -> Self;

    /// Return a pointer to `Self::RegMap` from a mutable (exclusive) reference.
    fn from_mut(reg: &'a mut Self::RegMap) -> Self;

    /// Returns a raw pointer to the underlying register map.
    fn as_ptr(&self) -> *mut Self::RegMap;
}