[−][src]Struct voladdress::VolAddress
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 timeconst
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]
T: Copy,
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> Clone for VolAddress<T>
[src]
fn clone(&self) -> Self
[src]
fn clone_from(&mut self, source: &Self)
1.0.0[src]
Performs copy-assignment from source
. Read more
impl<T> Debug for VolAddress<T>
[src]
impl<T> PartialEq<VolAddress<T>> for VolAddress<T>
[src]
fn eq(&self, other: &Self) -> bool
[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 cmp(&self, other: &Self) -> Ordering
[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]
fn partial_cmp(&self, other: &Self) -> Option<Ordering>
[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]
Auto Trait Implementations
impl<T> !Send for VolAddress<T>
impl<T> !Sync for VolAddress<T>
Blanket Implementations
impl<T, U> TryFrom for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T> From for T
[src]
impl<T, U> TryInto for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
The type returned in the event of a conversion error.
fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>
[src]
impl<T, U> Into for T where
U: From<T>,
[src]
U: From<T>,
impl<T> Borrow for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Same for T
[src]
type Output = T
Should always be Self