[][src]Struct voladdress::VolAddress

#[repr(transparent)]
pub struct VolAddress<T> { /* fields omitted */ }

Abstracts the use of a volatile memory address.

If you're trying to do anything other than abstract a memory mapped hardware device then you probably want one of the many other smart pointer types in the standard library.

It's generally expected that you'll create VolAddress values by declaring const globals at various points in your code for the various memory locations of the device. This is fine, but please note that volatile access is not synchronized and you'll have to arrange for synchronization in some way if you intend to have a multi-threaded program.

An interrupt running on a core can safely communicate with the main program running on that same core if both are using volatile access to the same location. Of course, since you generally can't be sure what core you're going to be running on, this "trick" should only be used for single-core devices.

Safety

In order for values of this type to operate correctly they must follow quite a few safety limits:

  • The declared address must always be "valid" according to the rules of core::ptr.
  • To be extra clear: the declared address must be non-zero because this type uses the NonZeroUsize type internally (it makes the iterators a lot better). It's possible to have a device memory mapped to the zero address, but it is not ever valid to access the null address from within Rust. For that rare situation you'd need to use inline assembly.
  • The declared address must be aligned for the declared type of T.
  • The declared address must always read as a valid bit pattern for the type T, regardless of the state of the memory mapped hardware. If there's any doubt at all, you must instead read or write an unsigned int of the correct bit size (u16, u32, etc) and then parse the bits by hand.
  • Any VolAddress declared as a compile time const must not use a location that would ever be part of any allocator and/or stack frame.
  • Any VolAddress made at runtime from a *mut pointer is only valid as long as that *mut would be valid, this is not tracked because pointers don't have lifetimes.

If you're not sure about any of those points, please re-read the hardware specs of your target device and its memory map until you know for sure.

The exact points of UB are if the address is ever 0 (because it's stored as NonNullUsize), or if you ever actually read or write with an invalidly constructed VolAddress.

Methods

impl<T> VolAddress<T>[src]

pub const unsafe fn new(address: usize) -> Self[src]

Constructs a new address.

Safety

You must follow the standard safety rules as outlined in the type docs.

pub const unsafe fn cast<Z>(self) -> VolAddress<Z>[src]

Casts the type of T into type Z.

Safety

You must follow the standard safety rules as outlined in the type docs.

pub const unsafe fn offset(self, offset: isize) -> Self[src]

Offsets the address by offset slots (like pointer::wrapping_offset).

Safety

You must follow the standard safety rules as outlined in the type docs.

pub const fn is_aligned(self) -> bool[src]

Checks that the current target type of this address is aligned at this address value.

Technically it's a safety violation to even make a VolAddress that isn't aligned. However, I know you're gonna try doing the bad thing, and it's better to give you a chance to call is_aligned and potentially back off from the operation or throw a debug_assert! or something instead of triggering UB.

pub const fn to_usize(self) -> usize[src]

The usize value of this VolAddress.

Important traits for VolIter<T>
pub const unsafe fn iter_slots(self, slots: usize) -> VolIter<T>[src]

Makes an iterator starting here across the given number of slots.

Safety

The normal safety rules must be correct for each address iterated over.

pub fn read(self) -> T where
    T: Copy
[src]

Volatile reads a Copy value out of the address.

The Copy bound is actually supposed to be !Drop, but rust doesn't allow negative trait bounds. If your type isn't Copy you can use the read_non_copy fallback to do an unsafe read.

That said, I don't think that you legitimately have hardware that maps to a Rust type that isn't Copy. If you do please tell me, I'm interested to hear about it.

pub unsafe fn read_non_copy(self) -> T[src]

Volatile reads a value out of the address with no trait bound.

Safety

This is not a move, it forms a bit duplicate of the current value at the address. If T has a Drop trait that does anything it is up to you to ensure that repeated drops do not cause UB (such as a double free).

pub fn write(self, val: T)[src]

Volatile writes a value to the address.

Semantically, the value is moved into the VolAddress and then forgotten, so if T has a Drop impl then that will never get executed. This is "safe" under Rust's safety rules, but could cause something unintended (eg: a memory leak).

Trait Implementations

impl<T> Debug for VolAddress<T>[src]

impl<T> PartialEq<VolAddress<T>> for VolAddress<T>[src]

#[must_use]
fn ne(&self, other: &Rhs) -> bool
1.0.0
[src]

This method tests for !=.

impl<T> Eq for VolAddress<T>[src]

impl<T> Ord for VolAddress<T>[src]

fn max(self, other: Self) -> Self
1.21.0
[src]

Compares and returns the maximum of two values. Read more

fn min(self, other: Self) -> Self
1.21.0
[src]

Compares and returns the minimum of two values. Read more

impl<T> PartialOrd<VolAddress<T>> for VolAddress<T>[src]

#[must_use]
fn lt(&self, other: &Rhs) -> bool
1.0.0
[src]

This method tests less than (for self and other) and is used by the < operator. Read more

#[must_use]
fn le(&self, other: &Rhs) -> bool
1.0.0
[src]

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more

#[must_use]
fn gt(&self, other: &Rhs) -> bool
1.0.0
[src]

This method tests greater than (for self and other) and is used by the > operator. Read more

#[must_use]
fn ge(&self, other: &Rhs) -> bool
1.0.0
[src]

This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more

impl<T> Copy for VolAddress<T>[src]

impl<T> Pointer for VolAddress<T>[src]

fn fmt(&self, f: &mut Formatter) -> Result[src]

You can request pointer style to get just the inner value with pointer formatting.

impl<T> Clone for VolAddress<T>[src]

fn clone_from(&mut self, source: &Self)
1.0.0
[src]

Performs copy-assignment from source. Read more

Auto Trait Implementations

impl<T> !Send for VolAddress<T>

impl<T> !Sync for VolAddress<T>

Blanket Implementations

impl<T> From for T[src]

impl<T, U> TryFrom for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<T, U> Into for T where
    U: From<T>, 
[src]

impl<T> Borrow for T where
    T: ?Sized
[src]

impl<T> BorrowMut for T where
    T: ?Sized
[src]

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Same for T[src]

type Output = T

Should always be Self