eeprom support
This commit is contained in:
parent
d335e30901
commit
7be84f137c
@ -11,6 +11,9 @@ use crate::Peri;
|
|||||||
use crate::_generated::FLASH_BASE;
|
use crate::_generated::FLASH_BASE;
|
||||||
use crate::peripherals::FLASH;
|
use crate::peripherals::FLASH;
|
||||||
|
|
||||||
|
#[cfg(eeprom)]
|
||||||
|
use crate::_generated::{EEPROM_BASE, EEPROM_SIZE};
|
||||||
|
|
||||||
/// Internal flash memory driver.
|
/// Internal flash memory driver.
|
||||||
pub struct Flash<'d, MODE = Async> {
|
pub struct Flash<'d, MODE = Async> {
|
||||||
pub(crate) inner: Peri<'d, FLASH>,
|
pub(crate) inner: Peri<'d, FLASH>,
|
||||||
@ -72,6 +75,100 @@ impl<'d, MODE> Flash<'d, MODE> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(eeprom)]
|
||||||
|
impl<'d> Flash<'d, Blocking> {
|
||||||
|
fn eeprom_base(&self) -> u32 {
|
||||||
|
EEPROM_BASE as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eeprom_size(&self) -> u32 {
|
||||||
|
EEPROM_SIZE as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_eeprom_offset(&self, offset: u32, size: u32) -> Result<(), Error> {
|
||||||
|
if offset + size > self.eeprom_size() {
|
||||||
|
Err(Error::Size)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read a byte (u8) from EEPROM at the given offset.
|
||||||
|
pub fn eeprom_read_u8(&self, offset: u32) -> Result<u8, Error> {
|
||||||
|
self.check_eeprom_offset(offset, 1)?;
|
||||||
|
let addr = self.eeprom_base() + offset;
|
||||||
|
Ok(unsafe { core::ptr::read_volatile(addr as *const u8) })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read a half-word (u16) from EEPROM at the given offset.
|
||||||
|
pub fn eeprom_read_u16(&self, offset: u32) -> Result<u16, Error> {
|
||||||
|
if offset % 2 != 0 {
|
||||||
|
return Err(Error::Unaligned);
|
||||||
|
}
|
||||||
|
self.check_eeprom_offset(offset, 2)?;
|
||||||
|
let addr = self.eeprom_base() + offset;
|
||||||
|
Ok(unsafe { core::ptr::read_volatile(addr as *const u16) })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read a word (u32) from EEPROM at the given offset.
|
||||||
|
pub fn eeprom_read_u32(&self, offset: u32) -> Result<u32, Error> {
|
||||||
|
if offset % 4 != 0 {
|
||||||
|
return Err(Error::Unaligned);
|
||||||
|
}
|
||||||
|
self.check_eeprom_offset(offset, 4)?;
|
||||||
|
let addr = self.eeprom_base() + offset;
|
||||||
|
Ok(unsafe { core::ptr::read_volatile(addr as *const u32) })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write a byte (u8) to EEPROM at the given offset.
|
||||||
|
pub fn eeprom_write_u8(&mut self, offset: u32, value: u8) -> Result<(), Error> {
|
||||||
|
self.check_eeprom_offset(offset, 1)?;
|
||||||
|
let addr = self.eeprom_base() + offset;
|
||||||
|
unsafe {
|
||||||
|
family::unlock();
|
||||||
|
core::ptr::write_volatile(addr as *mut u8, value);
|
||||||
|
family::wait_ready_blocking()?;
|
||||||
|
family::clear_all_err();
|
||||||
|
family::lock();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write a half-word (u16) to EEPROM at the given offset.
|
||||||
|
pub fn eeprom_write_u16(&mut self, offset: u32, value: u16) -> Result<(), Error> {
|
||||||
|
if offset % 2 != 0 {
|
||||||
|
return Err(Error::Unaligned);
|
||||||
|
}
|
||||||
|
self.check_eeprom_offset(offset, 2)?;
|
||||||
|
let addr = self.eeprom_base() + offset;
|
||||||
|
unsafe {
|
||||||
|
family::unlock();
|
||||||
|
core::ptr::write_volatile(addr as *mut u16, value);
|
||||||
|
family::wait_ready_blocking()?;
|
||||||
|
family::clear_all_err();
|
||||||
|
family::lock();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write a word (u32) to EEPROM at the given offset.
|
||||||
|
pub fn eeprom_write_u32(&mut self, offset: u32, value: u32) -> Result<(), Error> {
|
||||||
|
if offset % 4 != 0 {
|
||||||
|
return Err(Error::Unaligned);
|
||||||
|
}
|
||||||
|
self.check_eeprom_offset(offset, 4)?;
|
||||||
|
let addr = self.eeprom_base() + offset;
|
||||||
|
unsafe {
|
||||||
|
family::unlock();
|
||||||
|
core::ptr::write_volatile(addr as *mut u32, value);
|
||||||
|
family::wait_ready_blocking()?;
|
||||||
|
family::clear_all_err();
|
||||||
|
family::lock();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
|
pub(super) fn blocking_read(base: u32, size: u32, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
|
||||||
if offset + bytes.len() as u32 > size {
|
if offset + bytes.len() as u32 > size {
|
||||||
return Err(Error::Size);
|
return Err(Error::Size);
|
||||||
|
|||||||
@ -162,7 +162,7 @@ pub(crate) unsafe fn clear_all_err() {
|
|||||||
pac::FLASH.nssr().modify(|_| {});
|
pac::FLASH.nssr().modify(|_| {});
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn wait_ready_blocking() -> Result<(), Error> {
|
pub(crate) unsafe fn wait_ready_blocking() -> Result<(), Error> {
|
||||||
loop {
|
loop {
|
||||||
#[cfg(not(flash_l5))]
|
#[cfg(not(flash_l5))]
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user