littlefs2 impl stuff
This commit is contained in:
parent
8b938e7687
commit
4c54edbcea
@ -159,6 +159,8 @@ edge-nal-embassy = "0.6.0"
|
|||||||
static_cell = "2.1.1"
|
static_cell = "2.1.1"
|
||||||
cfg-if = "1.0.3"
|
cfg-if = "1.0.3"
|
||||||
edge-http = { version = "0.6.1", features = ["log"] }
|
edge-http = { version = "0.6.1", features = ["log"] }
|
||||||
|
littlefs2 = { version = "0.6.1", features = ["c-stubs"] }
|
||||||
|
littlefs2-core = "0.1.1"
|
||||||
|
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
|
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 chrono::{DateTime, Utc};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use crate::hal::LittleFS2StorageAdapter::LittleFs2Filesystem;
|
||||||
use alloc::string::ToString;
|
use alloc::string::ToString;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use alloc::{format, string::String, vec::Vec};
|
use alloc::{format, string::String, vec::Vec};
|
||||||
@ -32,6 +33,8 @@ use esp_wifi::wifi::{
|
|||||||
AccessPointConfiguration, AccessPointInfo, Configuration, Interfaces, ScanConfig,
|
AccessPointConfiguration, AccessPointInfo, Configuration, Interfaces, ScanConfig,
|
||||||
ScanTypeConfig, WifiController, WifiDevice, WifiEvent, WifiState,
|
ScanTypeConfig, WifiController, WifiDevice, WifiEvent, WifiState,
|
||||||
};
|
};
|
||||||
|
use littlefs2::fs::Filesystem;
|
||||||
|
use littlefs2_core::{FileType, PathBuf};
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
|
|
||||||
#[link_section = ".rtc.data"]
|
#[link_section = ".rtc.data"]
|
||||||
@ -54,8 +57,6 @@ pub struct FileList {
|
|||||||
total: usize,
|
total: usize,
|
||||||
used: usize,
|
used: usize,
|
||||||
files: Vec<FileInfo>,
|
files: Vec<FileInfo>,
|
||||||
file_system_corrupt: Option<String>,
|
|
||||||
iter_error: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FileSystemSizeInfo {
|
pub struct FileSystemSizeInfo {
|
||||||
@ -70,6 +71,7 @@ pub struct MqttClient<'a> {
|
|||||||
base_topic: heapless::String<64>,
|
base_topic: heapless::String<64>,
|
||||||
}
|
}
|
||||||
pub struct Esp<'a> {
|
pub struct Esp<'a> {
|
||||||
|
pub fs: Arc<Mutex<CriticalSectionRawMutex, Filesystem<'static, LittleFs2Filesystem>>>,
|
||||||
pub rng: Rng,
|
pub rng: Rng,
|
||||||
//first starter (ap or sta will take these)
|
//first starter (ap or sta will take these)
|
||||||
pub interfaces: Option<Interfaces<'static>>,
|
pub interfaces: Option<Interfaces<'static>>,
|
||||||
@ -432,60 +434,32 @@ impl Esp<'_> {
|
|||||||
// })
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn list_files(&self) -> FileList {
|
pub(crate) async fn list_files(&self) -> anyhow::Result<FileList> {
|
||||||
return FileList {
|
let path = PathBuf::new();
|
||||||
|
|
||||||
|
let mut result = FileList {
|
||||||
total: 0,
|
total: 0,
|
||||||
used: 0,
|
used: 0,
|
||||||
file_system_corrupt: None,
|
|
||||||
files: Vec::new(),
|
files: Vec::new(),
|
||||||
iter_error: None,
|
|
||||||
};
|
};
|
||||||
//
|
|
||||||
// let storage = CString::new(Self::SPIFFS_PARTITION_NAME).unwrap();
|
match self.fs.lock().await.read_dir_and_then(&path, |dir| {
|
||||||
//
|
for entry in dir {
|
||||||
// let mut file_system_corrupt = None;
|
let e = entry?;
|
||||||
//
|
|
||||||
// let mut iter_error = None;
|
result.files.push(FileInfo {
|
||||||
// let mut result = Vec::new();
|
filename: e.path().to_string(),
|
||||||
//
|
size: e.metadata().len(),
|
||||||
// let filepath = Path::new(Self::BASE_PATH);
|
});
|
||||||
// let read_dir = fs::read_dir(filepath);
|
}
|
||||||
// match read_dir {
|
Result::Ok(())
|
||||||
// OkStd(read_dir) => {
|
}) {
|
||||||
// for item in read_dir {
|
Ok(_) => {}
|
||||||
// match item {
|
Err(err) => {
|
||||||
// OkStd(file) => {
|
bail!(format!("{err:?}"))
|
||||||
// let f = FileInfo {
|
}
|
||||||
// filename: file.file_name().into_string().unwrap(),
|
}
|
||||||
// size: file.metadata().map(|it| it.len()).unwrap_or_default()
|
Ok(result)
|
||||||
// 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,
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
pub(crate) async fn delete_file(&self, _filename: &str) -> anyhow::Result<()> {
|
pub(crate) async fn delete_file(&self, _filename: &str) -> anyhow::Result<()> {
|
||||||
bail!("todo");
|
bail!("todo");
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
mod LittleFS2StorageAdapter;
|
||||||
pub(crate) mod battery;
|
pub(crate) mod battery;
|
||||||
pub mod esp;
|
pub mod esp;
|
||||||
mod initial_hal;
|
mod initial_hal;
|
||||||
@ -22,7 +23,7 @@ use crate::{
|
|||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::format;
|
use alloc::format;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use anyhow::{Ok, Result};
|
use anyhow::{bail, Ok, Result};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
//use battery::BQ34Z100G1;
|
//use battery::BQ34Z100G1;
|
||||||
@ -32,11 +33,13 @@ use esp_bootloader_esp_idf::partitions::{
|
|||||||
AppPartitionSubType, DataPartitionSubType, FlashRegion, PartitionEntry,
|
AppPartitionSubType, DataPartitionSubType, FlashRegion, PartitionEntry,
|
||||||
};
|
};
|
||||||
use esp_hal::clock::CpuClock;
|
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 esp_println::println;
|
||||||
use measurements::{Current, Voltage};
|
use measurements::{Current, Voltage};
|
||||||
|
|
||||||
|
use crate::hal::LittleFS2StorageAdapter::LittleFs2Filesystem;
|
||||||
use embassy_sync::mutex::Mutex;
|
use embassy_sync::mutex::Mutex;
|
||||||
|
use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
|
||||||
use esp_alloc as _;
|
use esp_alloc as _;
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
use esp_bootloader_esp_idf::ota::Slot;
|
use esp_bootloader_esp_idf::ota::Slot;
|
||||||
@ -44,7 +47,8 @@ use esp_hal::rng::Rng;
|
|||||||
use esp_hal::timer::timg::TimerGroup;
|
use esp_hal::timer::timg::TimerGroup;
|
||||||
use esp_storage::FlashStorage;
|
use esp_storage::FlashStorage;
|
||||||
use esp_wifi::{init, EspWifiController};
|
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!
|
//Only support for 8 right now!
|
||||||
pub const PLANT_COUNT: usize = 8;
|
pub const PLANT_COUNT: usize = 8;
|
||||||
@ -275,6 +279,7 @@ impl PlantHal {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let ota_next = mk_static!(PartitionEntry, ota_partition);
|
let ota_next = mk_static!(PartitionEntry, ota_partition);
|
||||||
|
let storage_ota = mk_static!(FlashStorage, FlashStorage::new());
|
||||||
let ota_next = mk_static!(
|
let ota_next = mk_static!(
|
||||||
FlashRegion<FlashStorage>,
|
FlashRegion<FlashStorage>,
|
||||||
ota_next.as_embedded_storage(storage_ota)
|
ota_next.as_embedded_storage(storage_ota)
|
||||||
@ -285,12 +290,34 @@ impl PlantHal {
|
|||||||
DataPartitionSubType::LittleFs,
|
DataPartitionSubType::LittleFs,
|
||||||
))?
|
))?
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
let data_partition = mk_static!(PartitionEntry, data_partition);
|
||||||
|
|
||||||
let mut data = data_partition.as_embedded_storage(storage_ota);
|
let storage_data = mk_static!(FlashStorage, FlashStorage::new());
|
||||||
let mut alloc = Filesystem::allocate();
|
let mut data = mk_static!(
|
||||||
let mut fs = Filesystem::mount(&mut alloc, &mut data).unwrap();
|
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 {
|
let mut esp = Esp {
|
||||||
|
fs,
|
||||||
rng,
|
rng,
|
||||||
controller: Arc::new(Mutex::new(controller)),
|
controller: Arc::new(Mutex::new(controller)),
|
||||||
interfaces: Some(interfaces),
|
interfaces: Some(interfaces),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user