Skip to main content

rubidium/volatile/
read_only_vol_addr.rs

1use super::*;
2
3/// Represents an MMIO address that can be safely read, but not written.
4///
5/// Unlike with raw pointers, this type favors unsafe construction and then
6/// assumes that all usage is safe once the value has been constructed.
7///
8/// The convention is that reading the address will have no side effects.
9/// However, the register can be changed by non-CPU parts of the hardware, and
10/// so each time you perform a read the value might have changed.
11///
12/// For addresses where reads have a side effect, other types are used.
13#[repr(transparent)]
14#[derive(Debug, Clone, Copy)]
15pub struct ReadOnlyVolAddr<T> {
16  addr: NonZeroUsize,
17  _marker: PhantomData<T>,
18}
19
20impl_vol_eq!(ReadOnlyVolAddr<T>);
21
22impl<T> ReadOnlyVolAddr<T> {
23  /// Constructs a new address.
24  ///
25  /// ## Safety
26  /// The input must
27  /// * Not be 0 (or _instant_ UB).
28  /// * Be an actual MMIO location for the data type specified (or
29  ///   [`read`](RwVolAddr::read) will UB).
30  #[must_use]
31  #[inline(always)]
32  pub(crate) const unsafe fn new(addr: usize) -> Self {
33    Self { addr: NonZeroUsize::new_unchecked(addr), _marker: PhantomData }
34  }
35
36  /// Reads the current value at the address.
37  #[must_use]
38  #[inline(always)]
39  pub fn read(&self) -> T
40  where
41    T: Copy,
42  {
43    unsafe { read_volatile(self.addr.get() as *const T) }
44  }
45}