[−][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.