Implement read from EEPROM into generic type

main
finga 9 months ago
parent 28d6707c30
commit 0177da7268
  1. 2
      Cargo.toml
  2. 61
      src/lib.rs

@ -20,3 +20,5 @@ lto = true
opt-level = "s"
[dependencies]
avr-device = { version = "0.3", features = ["atmega328p"] }
nb = "1.0"

@ -1,15 +1,66 @@
#![no_std]
use avr_device::atmega328p::EEPROM;
use core::{
convert::Infallible,
mem::{size_of, MaybeUninit},
};
use nb::{self, Error::WouldBlock};
pub struct Eeprom(EEPROM);
impl Eeprom {
pub fn new(eeprom: EEPROM) -> Self {
Eeprom(eeprom)
}
pub fn read_byte(&self, p_addr: *const u8) -> nb::Result<u8, Infallible> {
// Wait for completion of previous write
if self.0.eecr.read().eepe().bit_is_set() {
return Err(WouldBlock);
}
// Write address into eeprom address register
self.0.eear.write(|w| unsafe { w.bits(p_addr as u16) });
// Start to read from eeprom by setting EERE
self.0.eecr.write(|w| w.eere().set_bit());
// Return data from eeprom data register
Ok(self.0.eedr.read().bits())
}
pub fn read_value<T>(&self, data: &EepromData<T>) -> T
where
T: Sized + Copy,
{
let mut buffer = MaybeUninit::<T>::uninit();
let res: *mut T = buffer.as_mut_ptr();
let p_addr = data.ptr() as *const u8;
let out_bytes = res as *mut u8;
let size_type = size_of::<T>();
let size_bytes = size_type as usize;
let size_bytes = size_bytes as u8;
for i in 0..size_bytes {
let i: isize = i.into();
let value = nb::block!(self.read_byte(unsafe { p_addr.offset(i) })).unwrap();
unsafe { out_bytes.offset(i).write(value) };
}
unsafe { buffer.assume_init() }
}
}
#[repr(transparent)]
pub struct Eeprom<T>(T);
pub struct EepromData<T>(T);
impl<T> Eeprom<T> {
impl<T> EepromData<T> {
pub const fn new(t: T) -> Self {
Eeprom(t)
EepromData(t)
}
}
impl<T: Copy> Eeprom<T> {
impl<T: Copy> EepromData<T> {
pub fn ptr(&self) -> *const T {
&self.0 as *const T
}
@ -29,7 +80,7 @@ macro_rules! eeprom_internal {
// User attributes
$(#[$attr])*
// The actual static definition
$($vis)* static $name : $crate::Eeprom<$ty> = $crate::Eeprom::new($value);
$($vis)* static $name : $crate::EepromData<$ty> = $crate::EepromData::new($value);
};
}

Loading…
Cancel
Save