[][src]Function avr_progmem::read_value

pub unsafe fn read_value<T>(p_addr: *const T) -> T where
    T: Sized + Copy

Read a single T from progmem and return it by value.

This function uses either a optimized assembly with loop or just a byte-wise assembly function which is looped outside depending on whether the lpm-asm-loop crate feature is set or not.

Notice that T might be also something like [T, N] so that in fact entire arrays can be loaded using this function. Alternatively if the the size of an array can not be known at compile time (i.e. a slice) there is also the read_slice function, but it requires proper initialization upfront.

If you need to read just a single byte you might use read_byte.

Example

use avr_progmem::read_value;

// This static must never be directly dereferenced/accessed!
// So a `let data: [u8;11] = P_ARRAY;` is Undefined Behavior!!!
// Also notice the `*` in front of the string, because we want to store the
// data, not just a reference!
/// Static bytes stored in progmem!
#[link_section = ".progmem"]
static P_ARRAY: [u8;11] = *b"Hello World";

// Load the bytes from progmem
// Here, it is sound, because due to the link_section it is indeed in the
// program code memory.
let data: [u8;11] = unsafe { read_value(&P_ARRAY) };
assert_eq!(b"Hello World", &data);

Also statically sized sub-arrays can be loaded using this function:

use std::convert::TryInto;
use avr_progmem::read_value;

/// Static bytes stored in progmem!
#[link_section = ".progmem"]
static P_ARRAY: [u8;11] = *b"Hello World";

// Get a sub-array reference without dereferencing it

// Make sure that we convert from &[T] directly to &[T;M] without
// constructing an actual [T;M], because we MAY NOT LOAD THE DATA!
// Also notice, that this sub-slicing does ensure that the bound are
// correct.
let slice: &[u8] = &P_ARRAY[6..];
let array: &[u8;5] = slice.try_into().unwrap();

// Load the bytes from progmem
// Here, it is sound, because due to the link_section it is indeed in the
// program code memory.
let data: [u8;5] = unsafe { read_value(array) };
assert_eq!(b"World", &data);

Panics

This function panics, if the size of the value (i.e. size_of::<T>()) is beyond 255 bytes. However, this is currently just a implementation limitation, which may be lifted in the future.

Safety

This call is analog to core::ptr::copy thus it has the same basic requirements such as the pointer must be valid for dereferencing i.e. not dangling and the pointer must be valid to read one entire value of type T, i.e. size_of::<T>() bytes.

Additionally, p_addr must be a valid pointer into the program memory domain.

While the alignment is not strictly required for AVR, the non-AVR fallback might be done actually use core::ptr::copy and therefore the pointers must be aligned.

Also notice, that the output slice must be correctly initialized, it would be UB if not. If you don't want to initialize the data upfront, the read_value might be a good alternative.