use embedded_storage::nor_flash::{check_erase, NorFlash, ReadNorFlash}; use esp_bootloader_esp_idf::partitions::FlashRegion; use esp_storage::FlashStorage; use littlefs2::consts::U4096 as lfsCache; use littlefs2::consts::U512 as lfsLookahead; use littlefs2::driver::Storage as lfs2Storage; use littlefs2::io::Error as lfs2Error; use littlefs2::io::Result as lfs2Result; use log::error; pub struct LittleFs2Filesystem { pub(crate) storage: &'static mut FlashRegion<'static, FlashStorage>, } impl lfs2Storage for LittleFs2Filesystem { const READ_SIZE: usize = 4096; const WRITE_SIZE: usize = 4096; const BLOCK_SIZE: usize = 4096; //usually optimal for flash access const BLOCK_COUNT: usize = 8 * 1000 * 1000 / 4096; //8Mb in 4k blocks + a little space for stupid calculation errors const BLOCK_CYCLES: isize = 100; type CACHE_SIZE = lfsCache; type LOOKAHEAD_SIZE = lfsLookahead; fn read(&mut self, off: usize, buf: &mut [u8]) -> lfs2Result { let read_size: usize = Self::READ_SIZE; if off % read_size != 0 { error!("Littlefs2Filesystem read error: offset not aligned to read size offset: {} read_size: {}", off, read_size); return Err(lfs2Error::IO); } if buf.len() % read_size != 0 { error!("Littlefs2Filesystem read error: length not aligned to read size length: {} read_size: {}", buf.len(), read_size); return Err(lfs2Error::IO); } match self.storage.read(off as u32, buf) { Ok(..) => Ok(buf.len()), Err(err) => { error!("Littlefs2Filesystem read error: {:?}", err); Err(lfs2Error::IO) } } } fn write(&mut self, off: usize, data: &[u8]) -> lfs2Result { let write_size: usize = Self::WRITE_SIZE; if off % write_size != 0 { error!("Littlefs2Filesystem write error: offset not aligned to write size offset: {} write_size: {}", off, write_size); return Err(lfs2Error::IO); } if data.len() % write_size != 0 { error!("Littlefs2Filesystem write error: length not aligned to write size length: {} write_size: {}", data.len(), write_size); return Err(lfs2Error::IO); } match self.storage.write(off as u32, data) { Ok(..) => Ok(data.len()), Err(err) => { error!("Littlefs2Filesystem write error: {:?}", err); Err(lfs2Error::IO) } } } fn erase(&mut self, off: usize, len: usize) -> lfs2Result { let block_size: usize = Self::BLOCK_SIZE; if off % block_size != 0 { error!("Littlefs2Filesystem erase error: offset not aligned to block size offset: {} block_size: {}", off, block_size); return lfs2Result::Err(lfs2Error::IO); } if len % block_size != 0 { error!("Littlefs2Filesystem erase error: length not aligned to block size length: {} block_size: {}", len, block_size); return lfs2Result::Err(lfs2Error::IO); } match check_erase(self.storage, off as u32, (off+len) as u32) { Ok(_) => {} Err(err) => { error!("Littlefs2Filesystem check erase error: {:?}", err); return lfs2Result::Err(lfs2Error::IO); } } match self.storage.erase(off as u32, (off + len) as u32) { Ok(..) => lfs2Result::Ok(len), Err(err) => { error!("Littlefs2Filesystem erase error: {:?}", err); lfs2Result::Err(lfs2Error::IO) } } } }