new API
This commit is contained in:
parent
21004fce0d
commit
1accd56005
@ -9,8 +9,6 @@ use super::{
|
|||||||
};
|
};
|
||||||
use crate::Peri;
|
use crate::Peri;
|
||||||
use crate::_generated::FLASH_BASE;
|
use crate::_generated::FLASH_BASE;
|
||||||
#[cfg(eeprom)]
|
|
||||||
use crate::_generated::{EEPROM_BASE, EEPROM_SIZE};
|
|
||||||
use crate::peripherals::FLASH;
|
use crate::peripherals::FLASH;
|
||||||
|
|
||||||
/// Internal flash memory driver.
|
/// Internal flash memory driver.
|
||||||
@ -74,100 +72,6 @@ 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);
|
||||||
|
|||||||
224
embassy-stm32/src/flash/eeprom.rs
Normal file
224
embassy-stm32/src/flash/eeprom.rs
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
use super::{family, Blocking, Error, Flash, EEPROM_BASE, EEPROM_SIZE};
|
||||||
|
|
||||||
|
#[cfg(eeprom)]
|
||||||
|
impl<'d> Flash<'d, Blocking> {
|
||||||
|
// --- Internal helpers ---
|
||||||
|
|
||||||
|
fn check_eeprom_offset(&self, offset: u32, size: u32) -> Result<(), Error> {
|
||||||
|
if offset
|
||||||
|
.checked_add(size)
|
||||||
|
.filter(|&end| end <= EEPROM_SIZE as u32)
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(Error::Size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Unlocked (unsafe, internal) functions ---
|
||||||
|
|
||||||
|
unsafe fn eeprom_write_u8_slice_unlocked(&self, offset: u32, data: &[u8]) -> Result<(), Error> {
|
||||||
|
for (i, &byte) in data.iter().enumerate() {
|
||||||
|
let addr = EEPROM_BASE as u32 + offset + i as u32;
|
||||||
|
core::ptr::write_volatile(addr as *mut u8, byte);
|
||||||
|
family::wait_ready_blocking()?;
|
||||||
|
family::clear_all_err();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn eeprom_write_u16_slice_unlocked(&self, offset: u32, data: &[u16]) -> Result<(), Error> {
|
||||||
|
for (i, &value) in data.iter().enumerate() {
|
||||||
|
let addr = EEPROM_BASE as u32 + offset + i as u32 * 2;
|
||||||
|
core::ptr::write_volatile(addr as *mut u16, value);
|
||||||
|
family::wait_ready_blocking()?;
|
||||||
|
family::clear_all_err();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn eeprom_write_u32_slice_unlocked(&self, offset: u32, data: &[u32]) -> Result<(), Error> {
|
||||||
|
for (i, &value) in data.iter().enumerate() {
|
||||||
|
let addr = EEPROM_BASE as u32 + offset + i as u32 * 4;
|
||||||
|
core::ptr::write_volatile(addr as *mut u32, value);
|
||||||
|
family::wait_ready_blocking()?;
|
||||||
|
family::clear_all_err();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Public, safe API ---
|
||||||
|
|
||||||
|
pub fn eeprom_write_u8(&mut self, offset: u32, value: u8) -> Result<(), Error> {
|
||||||
|
self.check_eeprom_offset(offset, 1)?;
|
||||||
|
unsafe {
|
||||||
|
family::unlock();
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
self.eeprom_write_u8_slice_unlocked(offset, core::slice::from_ref(&value))?;
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
family::lock();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
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)?;
|
||||||
|
unsafe {
|
||||||
|
family::unlock();
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
self.eeprom_write_u16_slice_unlocked(offset, core::slice::from_ref(&value))?;
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
family::lock();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
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)?;
|
||||||
|
unsafe {
|
||||||
|
family::unlock();
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
self.eeprom_write_u32_slice_unlocked(offset, core::slice::from_ref(&value))?;
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
family::lock();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn eeprom_write_u8_slice(&mut self, offset: u32, data: &[u8]) -> Result<(), Error> {
|
||||||
|
self.check_eeprom_offset(offset, data.len() as u32)?;
|
||||||
|
unsafe {
|
||||||
|
family::unlock();
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
self.eeprom_write_u8_slice_unlocked(offset, data)?;
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
family::lock();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn eeprom_write_u16_slice(&mut self, offset: u32, data: &[u16]) -> Result<(), Error> {
|
||||||
|
if offset % 2 != 0 {
|
||||||
|
return Err(Error::Unaligned);
|
||||||
|
}
|
||||||
|
self.check_eeprom_offset(offset, data.len() as u32 * 2)?;
|
||||||
|
unsafe {
|
||||||
|
family::unlock();
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
self.eeprom_write_u16_slice_unlocked(offset, data)?;
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
family::lock();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn eeprom_write_u32_slice(&mut self, offset: u32, data: &[u32]) -> Result<(), Error> {
|
||||||
|
if offset % 4 != 0 {
|
||||||
|
return Err(Error::Unaligned);
|
||||||
|
}
|
||||||
|
self.check_eeprom_offset(offset, data.len() as u32 * 4)?;
|
||||||
|
unsafe {
|
||||||
|
family::unlock();
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
self.eeprom_write_u32_slice_unlocked(offset, data)?;
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
family::lock();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn eeprom_write(&mut self, offset: u32, data: &[u8]) -> Result<(), Error> {
|
||||||
|
let start = offset;
|
||||||
|
let end = offset.checked_add(data.len() as u32).ok_or(Error::Size)?;
|
||||||
|
if end > EEPROM_SIZE as u32 {
|
||||||
|
return Err(Error::Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
let misalign = (start % 4) as usize;
|
||||||
|
let prefix_len = if misalign == 0 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
(4 - misalign).min(data.len())
|
||||||
|
};
|
||||||
|
let (prefix, rest) = data.split_at(prefix_len);
|
||||||
|
let aligned_len = (rest.len() / 4) * 4;
|
||||||
|
let (aligned, suffix) = rest.split_at(aligned_len);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
family::unlock();
|
||||||
|
}
|
||||||
|
if !prefix.is_empty() {
|
||||||
|
unsafe {
|
||||||
|
self.eeprom_write_u8_slice_unlocked(start, prefix)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !aligned.is_empty() {
|
||||||
|
let aligned_offset = start + prefix_len as u32;
|
||||||
|
let u32_data = unsafe { core::slice::from_raw_parts(aligned.as_ptr() as *const u32, aligned.len() / 4) };
|
||||||
|
unsafe {
|
||||||
|
self.eeprom_write_u32_slice_unlocked(aligned_offset, u32_data)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !suffix.is_empty() {
|
||||||
|
let suffix_offset = start + (prefix_len + aligned_len) as u32;
|
||||||
|
unsafe {
|
||||||
|
self.eeprom_write_u8_slice_unlocked(suffix_offset, suffix)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
family::lock();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn eeprom_read_u8(&self, offset: u32) -> Result<u8, Error> {
|
||||||
|
self.check_eeprom_offset(offset, 1)?;
|
||||||
|
let addr = EEPROM_BASE as u32 + offset;
|
||||||
|
Ok(unsafe { core::ptr::read_volatile(addr as *const u8) })
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = EEPROM_BASE as u32 + offset;
|
||||||
|
Ok(unsafe { core::ptr::read_volatile(addr as *const u16) })
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = EEPROM_BASE as u32 + offset;
|
||||||
|
Ok(unsafe { core::ptr::read_volatile(addr as *const u32) })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn eeprom_read_slice(&self, offset: u32, buf: &mut [u8]) -> Result<(), Error> {
|
||||||
|
self.check_eeprom_offset(offset, buf.len() as u32)?;
|
||||||
|
let addr = EEPROM_BASE as u32 + offset;
|
||||||
|
let src = unsafe { core::slice::from_raw_parts(addr as *const u8, buf.len()) };
|
||||||
|
buf.copy_from_slice(src);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,11 +5,16 @@ use embedded_storage::nor_flash::{NorFlashError, NorFlashErrorKind};
|
|||||||
mod asynch;
|
mod asynch;
|
||||||
#[cfg(flash)]
|
#[cfg(flash)]
|
||||||
mod common;
|
mod common;
|
||||||
|
#[cfg(eeprom)]
|
||||||
|
mod eeprom;
|
||||||
|
|
||||||
#[cfg(flash_f4)]
|
#[cfg(flash_f4)]
|
||||||
pub use asynch::InterruptHandler;
|
pub use asynch::InterruptHandler;
|
||||||
#[cfg(flash)]
|
#[cfg(flash)]
|
||||||
pub use common::*;
|
pub use common::*;
|
||||||
|
#[cfg(eeprom)]
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
pub use eeprom::*;
|
||||||
|
|
||||||
pub use crate::_generated::flash_regions::*;
|
pub use crate::_generated::flash_regions::*;
|
||||||
#[cfg(eeprom)]
|
#[cfg(eeprom)]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user