shared flash test
This commit is contained in:
@@ -7,6 +7,7 @@ use serde::Serialize;
|
||||
|
||||
use crate::fat_error::{ContextExt, FatError, FatResult};
|
||||
use crate::hal::little_fs2storage_adapter::LittleFs2Filesystem;
|
||||
use crate::hal::shared_flash::MutexFlashStorage;
|
||||
use alloc::string::ToString;
|
||||
use alloc::sync::Arc;
|
||||
use alloc::{format, string::String, vec, vec::Vec};
|
||||
@@ -36,7 +37,6 @@ use esp_radio::wifi::{
|
||||
AccessPointConfig, AccessPointInfo, AuthMethod, ClientConfig, ModeConfig, ScanConfig,
|
||||
ScanTypeConfig, WifiController, WifiDevice, WifiStaState,
|
||||
};
|
||||
use esp_storage::FlashStorage;
|
||||
use littlefs2::fs::Filesystem;
|
||||
use littlefs2_core::{FileType, PathBuf, SeekFrom};
|
||||
use log::{info, warn};
|
||||
@@ -127,8 +127,8 @@ pub struct Esp<'a> {
|
||||
// RTC-capable GPIO used as external wake source (store the raw peripheral)
|
||||
pub wake_gpio1: esp_hal::peripherals::GPIO1<'static>,
|
||||
|
||||
pub ota: Ota<'static, FlashStorage<'static>>,
|
||||
pub ota_target: &'static mut FlashRegion<'static, FlashStorage<'static>>,
|
||||
pub ota: Ota<'static, MutexFlashStorage>,
|
||||
pub ota_target: &'static mut FlashRegion<'static, MutexFlashStorage>,
|
||||
pub current: AppPartitionSubType,
|
||||
pub slot0_state: OtaImageState,
|
||||
pub slot1_state: OtaImageState,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::hal::shared_flash::MutexFlashStorage;
|
||||
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;
|
||||
@@ -9,7 +9,7 @@ use littlefs2::io::Result as lfs2Result;
|
||||
use log::error;
|
||||
|
||||
pub struct LittleFs2Filesystem {
|
||||
pub(crate) storage: &'static mut FlashRegion<'static, FlashStorage<'static>>,
|
||||
pub(crate) storage: &'static mut FlashRegion<'static, MutexFlashStorage>,
|
||||
}
|
||||
|
||||
impl lfs2Storage for LittleFs2Filesystem {
|
||||
|
||||
@@ -4,11 +4,13 @@ pub mod esp;
|
||||
mod initial_hal;
|
||||
mod little_fs2storage_adapter;
|
||||
pub(crate) mod rtc;
|
||||
mod shared_flash;
|
||||
mod v3_hal;
|
||||
mod v3_shift_register;
|
||||
mod v4_hal;
|
||||
pub(crate) mod v4_sensor;
|
||||
mod water;
|
||||
|
||||
use crate::alloc::string::ToString;
|
||||
use crate::hal::rtc::{DS3231Module, RTCModuleInteraction};
|
||||
use esp_hal::peripherals::Peripherals;
|
||||
@@ -79,7 +81,7 @@ use crate::hal::water::TankSensor;
|
||||
use crate::log::LOG_ACCESS;
|
||||
use embassy_sync::mutex::Mutex;
|
||||
use embassy_sync::once_lock::OnceLock;
|
||||
use embedded_storage::nor_flash::ReadNorFlash;
|
||||
use embedded_storage::ReadStorage;
|
||||
use esp_alloc as _;
|
||||
use esp_backtrace as _;
|
||||
use esp_bootloader_esp_idf::ota::{Ota, OtaImageState};
|
||||
@@ -101,6 +103,7 @@ use littlefs2::object_safe::DynStorage;
|
||||
use log::{error, info, warn};
|
||||
use portable_atomic::AtomicBool;
|
||||
use serde::Serialize;
|
||||
use shared_flash::MutexFlashStorage;
|
||||
|
||||
pub static TIME_ACCESS: OnceLock<Mutex<CriticalSectionRawMutex, Rtc>> = OnceLock::new();
|
||||
|
||||
@@ -306,7 +309,15 @@ impl PlantHal {
|
||||
[u8; esp_bootloader_esp_idf::partitions::PARTITION_TABLE_MAX_LEN],
|
||||
[0u8; esp_bootloader_esp_idf::partitions::PARTITION_TABLE_MAX_LEN]
|
||||
);
|
||||
let flash_storage = mk_static!(FlashStorage, FlashStorage::new(peripherals.FLASH));
|
||||
|
||||
let bullshit = MutexFlashStorage {
|
||||
inner: Arc::new(CriticalSectionMutex::new(RefCell::new(FlashStorage::new(
|
||||
peripherals.FLASH,
|
||||
)))),
|
||||
};
|
||||
let flash_storage = mk_static!(MutexFlashStorage, bullshit.clone());
|
||||
let flash_storage_2 = mk_static!(MutexFlashStorage, bullshit.clone());
|
||||
let flash_storage_3 = mk_static!(MutexFlashStorage, bullshit.clone());
|
||||
|
||||
let pt =
|
||||
esp_bootloader_esp_idf::partitions::read_partition_table(flash_storage, tablebuffer)?;
|
||||
@@ -320,8 +331,8 @@ impl PlantHal {
|
||||
);
|
||||
|
||||
let ota_data = mk_static!(
|
||||
FlashRegion<FlashStorage>,
|
||||
ota_data.as_embedded_storage(flash_storage)
|
||||
FlashRegion<MutexFlashStorage>,
|
||||
ota_data.as_embedded_storage(flash_storage_2)
|
||||
);
|
||||
|
||||
let state_0 = ota_state(AppPartitionSubType::Ota0, ota_data);
|
||||
@@ -353,7 +364,7 @@ impl PlantHal {
|
||||
|
||||
let ota_target = mk_static!(PartitionEntry, ota_target);
|
||||
let ota_target = mk_static!(
|
||||
FlashRegion<FlashStorage>,
|
||||
FlashRegion<MutexFlashStorage>,
|
||||
ota_target.as_embedded_storage(flash_storage)
|
||||
);
|
||||
|
||||
@@ -365,8 +376,8 @@ impl PlantHal {
|
||||
let data_partition = mk_static!(PartitionEntry, data_partition);
|
||||
|
||||
let data = mk_static!(
|
||||
FlashRegion<FlashStorage>,
|
||||
data_partition.as_embedded_storage(flash_storage)
|
||||
FlashRegion<MutexFlashStorage>,
|
||||
data_partition.as_embedded_storage(flash_storage_3)
|
||||
);
|
||||
let lfs2filesystem = mk_static!(LittleFs2Filesystem, LittleFs2Filesystem { storage: data });
|
||||
let alloc = mk_static!(Allocation<LittleFs2Filesystem>, lfs2Filesystem::allocate());
|
||||
@@ -584,15 +595,18 @@ impl PlantHal {
|
||||
}
|
||||
}
|
||||
|
||||
fn ota_state(slot: AppPartitionSubType, ota_data: &mut FlashRegion<FlashStorage>) -> OtaImageState {
|
||||
fn ota_state(
|
||||
slot: AppPartitionSubType,
|
||||
ota_data: &mut FlashRegion<MutexFlashStorage>,
|
||||
) -> OtaImageState {
|
||||
// Read and log OTA states for both slots before constructing Ota
|
||||
// Each OTA select entry is 32 bytes: [seq:4][label:20][state:4][crc:4]
|
||||
// Offsets within the OTA data partition: slot0 @ 0x0000, slot1 @ 0x1000
|
||||
let mut slot_buf = [0u8; 32];
|
||||
if slot == AppPartitionSubType::Ota0 {
|
||||
let _ = ota_data.read(0x0000, &mut slot_buf);
|
||||
let _ = ReadStorage::read(ota_data, 0x0000, &mut slot_buf);
|
||||
} else {
|
||||
let _ = ota_data.read(0x1000, &mut slot_buf);
|
||||
let _ = ReadStorage::read(ota_data, 0x1000, &mut slot_buf);
|
||||
}
|
||||
let raw_state = u32::from_le_bytes(slot_buf[24..28].try_into().unwrap_or([0xff; 4]));
|
||||
|
||||
@@ -600,7 +614,7 @@ fn ota_state(slot: AppPartitionSubType, ota_data: &mut FlashRegion<FlashStorage>
|
||||
}
|
||||
|
||||
fn get_current_slot_and_fix_ota_data(
|
||||
ota: &mut Ota<FlashStorage>,
|
||||
ota: &mut Ota<MutexFlashStorage>,
|
||||
state0: OtaImageState,
|
||||
state1: OtaImageState,
|
||||
) -> Result<AppPartitionSubType, FatError> {
|
||||
|
||||
63
Software/MainBoard/rust/src/hal/shared_flash.rs
Normal file
63
Software/MainBoard/rust/src/hal/shared_flash.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
use alloc::sync::Arc;
|
||||
use core::cell::RefCell;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use embassy_sync::blocking_mutex::CriticalSectionMutex;
|
||||
use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash};
|
||||
use embedded_storage::ReadStorage;
|
||||
use esp_storage::{FlashStorage, FlashStorageError};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MutexFlashStorage {
|
||||
pub(crate) inner: Arc<CriticalSectionMutex<RefCell<FlashStorage<'static>>>>,
|
||||
}
|
||||
|
||||
impl ReadStorage for MutexFlashStorage {
|
||||
type Error = FlashStorageError;
|
||||
|
||||
fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), FlashStorageError> {
|
||||
self.inner
|
||||
.lock(|f| ReadStorage::read(f.borrow_mut().deref_mut(), offset, bytes))
|
||||
}
|
||||
|
||||
fn capacity(&self) -> usize {
|
||||
self.inner
|
||||
.lock(|f| ReadStorage::capacity(f.borrow().deref()))
|
||||
}
|
||||
}
|
||||
|
||||
impl embedded_storage::Storage for MutexFlashStorage {
|
||||
fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
|
||||
NorFlash::write(self, offset, bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl ErrorType for MutexFlashStorage {
|
||||
type Error = FlashStorageError;
|
||||
}
|
||||
|
||||
impl ReadNorFlash for MutexFlashStorage {
|
||||
const READ_SIZE: usize = 0;
|
||||
|
||||
fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
|
||||
ReadStorage::read(self, offset, bytes)
|
||||
}
|
||||
|
||||
fn capacity(&self) -> usize {
|
||||
ReadStorage::capacity(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl NorFlash for MutexFlashStorage {
|
||||
const WRITE_SIZE: usize = 0;
|
||||
const ERASE_SIZE: usize = 0;
|
||||
|
||||
fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
|
||||
self.inner
|
||||
.lock(|f| NorFlash::erase(f.borrow_mut().deref_mut(), from, to))
|
||||
}
|
||||
|
||||
fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
|
||||
self.inner
|
||||
.lock(|f| NorFlash::write(f.borrow_mut().deref_mut(), offset, bytes))
|
||||
}
|
||||
}
|
||||
@@ -101,8 +101,9 @@ impl SensorInteraction for SensorImpl {
|
||||
Timer::after_millis(10).await;
|
||||
|
||||
let mut moistures = Moistures::default();
|
||||
let _ = Self::wait_for_can_measurements(&mut twai, &mut moistures).with_timeout(Duration::from_millis(5000)).await;
|
||||
|
||||
let _ = Self::wait_for_can_measurements(&mut twai, &mut moistures)
|
||||
.with_timeout(Duration::from_millis(5000))
|
||||
.await;
|
||||
|
||||
can_power.set_low();
|
||||
|
||||
@@ -170,7 +171,7 @@ impl SensorImpl {
|
||||
can_power.set_low();
|
||||
twai_config.replace(config);
|
||||
|
||||
let result= moistures.into();
|
||||
let result = moistures.into();
|
||||
|
||||
info!("Autodetection result: {result:?}");
|
||||
Ok(result)
|
||||
@@ -182,7 +183,6 @@ impl SensorImpl {
|
||||
as_async: &mut Twai<'_, Async>,
|
||||
moistures: &mut Moistures,
|
||||
) -> FatResult<()> {
|
||||
|
||||
loop {
|
||||
match as_async.receive_async().await {
|
||||
Ok(can_frame) => match can_frame.id() {
|
||||
|
||||
@@ -120,8 +120,12 @@ impl PlantState {
|
||||
let raw = moistures.sensor_a_hz[plant_id];
|
||||
match map_range_moisture(
|
||||
raw,
|
||||
board.board_hal.get_config().plants[plant_id].moisture_sensor_min_frequency.map(|a| a as f32),
|
||||
board.board_hal.get_config().plants[plant_id].moisture_sensor_max_frequency.map(|b| b as f32),
|
||||
board.board_hal.get_config().plants[plant_id]
|
||||
.moisture_sensor_min_frequency
|
||||
.map(|a| a as f32),
|
||||
board.board_hal.get_config().plants[plant_id]
|
||||
.moisture_sensor_max_frequency
|
||||
.map(|b| b as f32),
|
||||
) {
|
||||
Ok(moisture_percent) => MoistureSensorState::MoistureValue {
|
||||
raw_hz: raw,
|
||||
@@ -137,8 +141,12 @@ impl PlantState {
|
||||
let raw = moistures.sensor_b_hz[plant_id];
|
||||
match map_range_moisture(
|
||||
raw,
|
||||
board.board_hal.get_config().plants[plant_id].moisture_sensor_min_frequency.map(|a| a as f32),
|
||||
board.board_hal.get_config().plants[plant_id].moisture_sensor_max_frequency.map(|b| b as f32)
|
||||
board.board_hal.get_config().plants[plant_id]
|
||||
.moisture_sensor_min_frequency
|
||||
.map(|a| a as f32),
|
||||
board.board_hal.get_config().plants[plant_id]
|
||||
.moisture_sensor_max_frequency
|
||||
.map(|b| b as f32),
|
||||
) {
|
||||
Ok(moisture_percent) => MoistureSensorState::MoistureValue {
|
||||
raw_hz: raw,
|
||||
@@ -196,8 +204,12 @@ impl PlantState {
|
||||
(Some(moisture_a), Some(moisture_b)) => {
|
||||
(Some(((moisture_a + moisture_b) / 2.) as u8), (None, None))
|
||||
}
|
||||
(Some(moisture_percent), _) => (Some(moisture_percent as u8), (None, self.sensor_b.is_err())),
|
||||
(_, Some(moisture_percent)) => (Some(moisture_percent as u8), (self.sensor_a.is_err(), None)),
|
||||
(Some(moisture_percent), _) => {
|
||||
(Some(moisture_percent as u8), (None, self.sensor_b.is_err()))
|
||||
}
|
||||
(_, Some(moisture_percent)) => {
|
||||
(Some(moisture_percent as u8), (self.sensor_a.is_err(), None))
|
||||
}
|
||||
_ => (None, (self.sensor_a.is_err(), self.sensor_b.is_err())),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user