use embassy_rp_plus::embassy_rp::flash;
use embassy_rp_plus::embassy_rp::flash::{Instance, Mode};
use crate::flash::err::FlashResult;
use crate::flash::flash_lock::FlashLock;
pub struct FlashUtil<'a, T: Instance, M: Mode, const FLASH_SIZE: usize> {
pub flash: &'a FlashLock<'a, T, M, FLASH_SIZE>,
pub offset: u32,
erase_size: u32,
}
impl<'a, T: Instance, M: Mode, const FLASH_SIZE: usize> FlashUtil<'a, T, M, FLASH_SIZE> {
#[inline]
pub fn new(flash: &'a FlashLock<'a, T, M, FLASH_SIZE>, offset: u32, erase_size: u32) -> Self {
Self { flash, offset, erase_size }
}
#[inline]
pub fn new_default(flash: &'a FlashLock<'a, T, M, FLASH_SIZE>) -> Self {
Self::new(flash, 0x100000, 4096)
}
#[inline]
pub async fn try_read(&self, buf: &mut [u8]) -> Result<(), flash::Error> {
self.flash.blocking_read(self.offset, buf).await
}
pub async fn try_erase(&self, num: u32) -> Result<(), flash::Error> {
if num == 0 { return Ok(()); }
self.flash.blocking_erase(self.offset, self.offset + self.erase_size * num).await
}
pub async fn try_erase_write(&self, buf: &[u8]) -> FlashResult<()> {
if buf.is_empty() { return Ok(()); }
let len = u32::try_from(buf.len())?;
let sub_to = if len % self.offset == 0 { 0 } else { 1 };
let to = self.erase_size * (len / self.offset + sub_to) + self.offset;
self.flash.try_erase_write(self.offset, to, buf).await?;
Ok(())
}
#[inline]
pub async fn erase_write(&self, buf: &[u8]) {
self.try_erase_write(buf).await.ok();
}
}