littlefs2 impl stuff
This commit is contained in:
		
							
								
								
									
										63
									
								
								rust/src/hal/LittleFS2StorageAdapter.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								rust/src/hal/LittleFS2StorageAdapter.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
 | 
			
		||||
use esp_bootloader_esp_idf::partitions::FlashRegion;
 | 
			
		||||
use esp_storage::FlashStorage;
 | 
			
		||||
use littlefs2::consts::U1 as lfs2Array1;
 | 
			
		||||
use littlefs2::consts::U512 as lfs2Array512;
 | 
			
		||||
use littlefs2::driver::Storage as lfs2Storage;
 | 
			
		||||
use littlefs2::fs::Filesystem as lfs2Filesystem;
 | 
			
		||||
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 = 512;
 | 
			
		||||
    const WRITE_SIZE: usize = 512;
 | 
			
		||||
    const BLOCK_SIZE: usize = 32 * 1024; //usually optimal for flash access
 | 
			
		||||
    const BLOCK_COUNT: usize = 8 * 1024 * 1024 / 32 * 1024; //8mb in 32blocks
 | 
			
		||||
    const BLOCK_CYCLES: isize = 0;
 | 
			
		||||
    type CACHE_SIZE = lfs2Array512;
 | 
			
		||||
    type LOOKAHEAD_SIZE = lfs2Array1;
 | 
			
		||||
 | 
			
		||||
    fn read(&mut self, off: usize, buf: &mut [u8]) -> lfs2Result<usize> {
 | 
			
		||||
        let read_size: usize = Self::READ_SIZE;
 | 
			
		||||
        assert_eq!(off % read_size, 0);
 | 
			
		||||
        assert_eq!(buf.len() % read_size, 0);
 | 
			
		||||
        match self.storage.read(off as u32, buf) {
 | 
			
		||||
            anyhow::Result::Ok(..) => lfs2Result::Ok(buf.len()),
 | 
			
		||||
            Err(err) => {
 | 
			
		||||
                error!("Littlefs2Filesystem read error: {:?}", err);
 | 
			
		||||
                Err(lfs2Error::IO)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn write(&mut self, off: usize, data: &[u8]) -> lfs2Result<usize> {
 | 
			
		||||
        let write_size: usize = Self::WRITE_SIZE;
 | 
			
		||||
        assert_eq!(off % write_size, 0);
 | 
			
		||||
        assert_eq!(data.len() % write_size, 0);
 | 
			
		||||
        match self.storage.write(off as u32, data) {
 | 
			
		||||
            anyhow::Result::Ok(..) => lfs2Result::Ok(data.len()),
 | 
			
		||||
            Err(err) => {
 | 
			
		||||
                error!("Littlefs2Filesystem write error: {:?}", err);
 | 
			
		||||
                Err(lfs2Error::IO)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn erase(&mut self, off: usize, len: usize) -> lfs2Result<usize> {
 | 
			
		||||
        let block_size: usize = Self::BLOCK_SIZE;
 | 
			
		||||
        debug_assert!(off % block_size == 0);
 | 
			
		||||
        debug_assert!(len % block_size == 0);
 | 
			
		||||
        match self.storage.erase(off as u32, len as u32) {
 | 
			
		||||
            anyhow::Result::Ok(..) => lfs2Result::Ok(len),
 | 
			
		||||
            Err(err) => {
 | 
			
		||||
                error!("Littlefs2Filesystem erase error: {:?}", err);
 | 
			
		||||
                Err(lfs2Error::IO)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -6,6 +6,7 @@ use anyhow::{anyhow, bail, Context};
 | 
			
		||||
use chrono::{DateTime, Utc};
 | 
			
		||||
use serde::Serialize;
 | 
			
		||||
 | 
			
		||||
use crate::hal::LittleFS2StorageAdapter::LittleFs2Filesystem;
 | 
			
		||||
use alloc::string::ToString;
 | 
			
		||||
use alloc::sync::Arc;
 | 
			
		||||
use alloc::{format, string::String, vec::Vec};
 | 
			
		||||
@@ -32,6 +33,8 @@ use esp_wifi::wifi::{
 | 
			
		||||
    AccessPointConfiguration, AccessPointInfo, Configuration, Interfaces, ScanConfig,
 | 
			
		||||
    ScanTypeConfig, WifiController, WifiDevice, WifiEvent, WifiState,
 | 
			
		||||
};
 | 
			
		||||
use littlefs2::fs::Filesystem;
 | 
			
		||||
use littlefs2_core::{FileType, PathBuf};
 | 
			
		||||
use log::{info, warn};
 | 
			
		||||
 | 
			
		||||
#[link_section = ".rtc.data"]
 | 
			
		||||
@@ -54,8 +57,6 @@ pub struct FileList {
 | 
			
		||||
    total: usize,
 | 
			
		||||
    used: usize,
 | 
			
		||||
    files: Vec<FileInfo>,
 | 
			
		||||
    file_system_corrupt: Option<String>,
 | 
			
		||||
    iter_error: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct FileSystemSizeInfo {
 | 
			
		||||
@@ -70,6 +71,7 @@ pub struct MqttClient<'a> {
 | 
			
		||||
    base_topic: heapless::String<64>,
 | 
			
		||||
}
 | 
			
		||||
pub struct Esp<'a> {
 | 
			
		||||
    pub fs: Arc<Mutex<CriticalSectionRawMutex, Filesystem<'static, LittleFs2Filesystem>>>,
 | 
			
		||||
    pub rng: Rng,
 | 
			
		||||
    //first starter (ap or sta will take these)
 | 
			
		||||
    pub interfaces: Option<Interfaces<'static>>,
 | 
			
		||||
@@ -432,60 +434,32 @@ impl Esp<'_> {
 | 
			
		||||
        // })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub(crate) async fn list_files(&self) -> FileList {
 | 
			
		||||
        return FileList {
 | 
			
		||||
    pub(crate) async fn list_files(&self) -> anyhow::Result<FileList> {
 | 
			
		||||
        let path = PathBuf::new();
 | 
			
		||||
 | 
			
		||||
        let mut result = FileList {
 | 
			
		||||
            total: 0,
 | 
			
		||||
            used: 0,
 | 
			
		||||
            file_system_corrupt: None,
 | 
			
		||||
            files: Vec::new(),
 | 
			
		||||
            iter_error: None,
 | 
			
		||||
        };
 | 
			
		||||
        //
 | 
			
		||||
        // let storage = CString::new(Self::SPIFFS_PARTITION_NAME).unwrap();
 | 
			
		||||
        //
 | 
			
		||||
        // let mut file_system_corrupt = None;
 | 
			
		||||
        //
 | 
			
		||||
        // let mut iter_error = None;
 | 
			
		||||
        // let mut result = Vec::new();
 | 
			
		||||
        //
 | 
			
		||||
        // let filepath = Path::new(Self::BASE_PATH);
 | 
			
		||||
        // let read_dir = fs::read_dir(filepath);
 | 
			
		||||
        // match read_dir {
 | 
			
		||||
        //     OkStd(read_dir) => {
 | 
			
		||||
        //         for item in read_dir {
 | 
			
		||||
        //             match item {
 | 
			
		||||
        //                 OkStd(file) => {
 | 
			
		||||
        //                     let f = FileInfo {
 | 
			
		||||
        //                         filename: file.file_name().into_string().unwrap(),
 | 
			
		||||
        //                         size: file.metadata().map(|it| it.len()).unwrap_or_default()
 | 
			
		||||
        //                             as usize,
 | 
			
		||||
        //                     };
 | 
			
		||||
        //                     result.push(f);
 | 
			
		||||
        //                 }
 | 
			
		||||
        //                 Err(err) => {
 | 
			
		||||
        //                     iter_error = Some(format!("{err:?}"));
 | 
			
		||||
        //                     break;
 | 
			
		||||
        //                 }
 | 
			
		||||
        //             }
 | 
			
		||||
        //         }
 | 
			
		||||
        //     }
 | 
			
		||||
        //     Err(err) => {
 | 
			
		||||
        //         file_system_corrupt = Some(format!("{err:?}"));
 | 
			
		||||
        //     }
 | 
			
		||||
        // }
 | 
			
		||||
        // let mut total: usize = 0;
 | 
			
		||||
        // let mut used: usize = 0;
 | 
			
		||||
        // unsafe {
 | 
			
		||||
        //     esp_spiffs_info(storage.as_ptr(), &mut total, &mut used);
 | 
			
		||||
        // }
 | 
			
		||||
        //
 | 
			
		||||
        // FileList {
 | 
			
		||||
        //     total,
 | 
			
		||||
        //     used,
 | 
			
		||||
        //     file_system_corrupt,
 | 
			
		||||
        //     files: result,
 | 
			
		||||
        //     iter_error,
 | 
			
		||||
        // }
 | 
			
		||||
 | 
			
		||||
        match self.fs.lock().await.read_dir_and_then(&path, |dir| {
 | 
			
		||||
            for entry in dir {
 | 
			
		||||
                let e = entry?;
 | 
			
		||||
 | 
			
		||||
                result.files.push(FileInfo {
 | 
			
		||||
                    filename: e.path().to_string(),
 | 
			
		||||
                    size: e.metadata().len(),
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
            Result::Ok(())
 | 
			
		||||
        }) {
 | 
			
		||||
            Ok(_) => {}
 | 
			
		||||
            Err(err) => {
 | 
			
		||||
                bail!(format!("{err:?}"))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        Ok(result)
 | 
			
		||||
    }
 | 
			
		||||
    pub(crate) async fn delete_file(&self, _filename: &str) -> anyhow::Result<()> {
 | 
			
		||||
        bail!("todo");
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
mod LittleFS2StorageAdapter;
 | 
			
		||||
pub(crate) mod battery;
 | 
			
		||||
pub mod esp;
 | 
			
		||||
mod initial_hal;
 | 
			
		||||
@@ -22,7 +23,7 @@ use crate::{
 | 
			
		||||
use alloc::boxed::Box;
 | 
			
		||||
use alloc::format;
 | 
			
		||||
use alloc::sync::Arc;
 | 
			
		||||
use anyhow::{Ok, Result};
 | 
			
		||||
use anyhow::{bail, Ok, Result};
 | 
			
		||||
use async_trait::async_trait;
 | 
			
		||||
use embassy_executor::Spawner;
 | 
			
		||||
//use battery::BQ34Z100G1;
 | 
			
		||||
@@ -32,11 +33,13 @@ use esp_bootloader_esp_idf::partitions::{
 | 
			
		||||
    AppPartitionSubType, DataPartitionSubType, FlashRegion, PartitionEntry,
 | 
			
		||||
};
 | 
			
		||||
use esp_hal::clock::CpuClock;
 | 
			
		||||
use esp_hal::gpio::{Input, InputConfig, Io, Pull};
 | 
			
		||||
use esp_hal::gpio::{Input, InputConfig, Pull};
 | 
			
		||||
use esp_println::println;
 | 
			
		||||
use measurements::{Current, Voltage};
 | 
			
		||||
 | 
			
		||||
use crate::hal::LittleFS2StorageAdapter::LittleFs2Filesystem;
 | 
			
		||||
use embassy_sync::mutex::Mutex;
 | 
			
		||||
use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
 | 
			
		||||
use esp_alloc as _;
 | 
			
		||||
use esp_backtrace as _;
 | 
			
		||||
use esp_bootloader_esp_idf::ota::Slot;
 | 
			
		||||
@@ -44,7 +47,8 @@ use esp_hal::rng::Rng;
 | 
			
		||||
use esp_hal::timer::timg::TimerGroup;
 | 
			
		||||
use esp_storage::FlashStorage;
 | 
			
		||||
use esp_wifi::{init, EspWifiController};
 | 
			
		||||
use littlefs2::fs::Filesystem;
 | 
			
		||||
use littlefs2::fs::{Allocation, Filesystem as lfs2Filesystem};
 | 
			
		||||
use littlefs2::object_safe::DynStorage;
 | 
			
		||||
 | 
			
		||||
//Only support for 8 right now!
 | 
			
		||||
pub const PLANT_COUNT: usize = 8;
 | 
			
		||||
@@ -275,6 +279,7 @@ impl PlantHal {
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let ota_next = mk_static!(PartitionEntry, ota_partition);
 | 
			
		||||
        let storage_ota = mk_static!(FlashStorage, FlashStorage::new());
 | 
			
		||||
        let ota_next = mk_static!(
 | 
			
		||||
            FlashRegion<FlashStorage>,
 | 
			
		||||
            ota_next.as_embedded_storage(storage_ota)
 | 
			
		||||
@@ -285,12 +290,34 @@ impl PlantHal {
 | 
			
		||||
                DataPartitionSubType::LittleFs,
 | 
			
		||||
            ))?
 | 
			
		||||
            .unwrap();
 | 
			
		||||
        let data_partition = mk_static!(PartitionEntry, data_partition);
 | 
			
		||||
 | 
			
		||||
        let mut data = data_partition.as_embedded_storage(storage_ota);
 | 
			
		||||
        let mut alloc = Filesystem::allocate();
 | 
			
		||||
        let mut fs = Filesystem::mount(&mut alloc, &mut data).unwrap();
 | 
			
		||||
        let storage_data = mk_static!(FlashStorage, FlashStorage::new());
 | 
			
		||||
        let mut data = mk_static!(
 | 
			
		||||
            FlashRegion<FlashStorage>,
 | 
			
		||||
            data_partition.as_embedded_storage(storage_data)
 | 
			
		||||
        );
 | 
			
		||||
        let lfs2filesystem = mk_static!(LittleFs2Filesystem, LittleFs2Filesystem { storage: data });
 | 
			
		||||
        let alloc = mk_static!(Allocation<LittleFs2Filesystem>, lfs2Filesystem::allocate());
 | 
			
		||||
        if lfs2filesystem.is_mountable() {
 | 
			
		||||
            log::info!("Littlefs2 filesystem is mountable");
 | 
			
		||||
        } else {
 | 
			
		||||
            match lfs2filesystem.format() {
 | 
			
		||||
                Result::Ok(..) => {
 | 
			
		||||
                    log::info!("Littlefs2 filesystem is formatted");
 | 
			
		||||
                }
 | 
			
		||||
                Err(err) => {
 | 
			
		||||
                    bail!("Littlefs2 filesystem could not be formatted: {:?}", err);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let fs = Arc::new(Mutex::new(
 | 
			
		||||
            lfs2Filesystem::mount(alloc, lfs2filesystem).unwrap(),
 | 
			
		||||
        ));
 | 
			
		||||
 | 
			
		||||
        let mut esp = Esp {
 | 
			
		||||
            fs,
 | 
			
		||||
            rng,
 | 
			
		||||
            controller: Arc::new(Mutex::new(controller)),
 | 
			
		||||
            interfaces: Some(interfaces),
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user