shared flash test
This commit is contained in:
@@ -7,6 +7,7 @@ use serde::Serialize;
|
|||||||
|
|
||||||
use crate::fat_error::{ContextExt, FatError, FatResult};
|
use crate::fat_error::{ContextExt, FatError, FatResult};
|
||||||
use crate::hal::little_fs2storage_adapter::LittleFs2Filesystem;
|
use crate::hal::little_fs2storage_adapter::LittleFs2Filesystem;
|
||||||
|
use crate::hal::shared_flash::MutexFlashStorage;
|
||||||
use alloc::string::ToString;
|
use alloc::string::ToString;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use alloc::{format, string::String, vec, vec::Vec};
|
use alloc::{format, string::String, vec, vec::Vec};
|
||||||
@@ -36,7 +37,6 @@ use esp_radio::wifi::{
|
|||||||
AccessPointConfig, AccessPointInfo, AuthMethod, ClientConfig, ModeConfig, ScanConfig,
|
AccessPointConfig, AccessPointInfo, AuthMethod, ClientConfig, ModeConfig, ScanConfig,
|
||||||
ScanTypeConfig, WifiController, WifiDevice, WifiStaState,
|
ScanTypeConfig, WifiController, WifiDevice, WifiStaState,
|
||||||
};
|
};
|
||||||
use esp_storage::FlashStorage;
|
|
||||||
use littlefs2::fs::Filesystem;
|
use littlefs2::fs::Filesystem;
|
||||||
use littlefs2_core::{FileType, PathBuf, SeekFrom};
|
use littlefs2_core::{FileType, PathBuf, SeekFrom};
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
@@ -127,8 +127,8 @@ pub struct Esp<'a> {
|
|||||||
// RTC-capable GPIO used as external wake source (store the raw peripheral)
|
// RTC-capable GPIO used as external wake source (store the raw peripheral)
|
||||||
pub wake_gpio1: esp_hal::peripherals::GPIO1<'static>,
|
pub wake_gpio1: esp_hal::peripherals::GPIO1<'static>,
|
||||||
|
|
||||||
pub ota: Ota<'static, FlashStorage<'static>>,
|
pub ota: Ota<'static, MutexFlashStorage>,
|
||||||
pub ota_target: &'static mut FlashRegion<'static, FlashStorage<'static>>,
|
pub ota_target: &'static mut FlashRegion<'static, MutexFlashStorage>,
|
||||||
pub current: AppPartitionSubType,
|
pub current: AppPartitionSubType,
|
||||||
pub slot0_state: OtaImageState,
|
pub slot0_state: OtaImageState,
|
||||||
pub slot1_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 embedded_storage::nor_flash::{check_erase, NorFlash, ReadNorFlash};
|
||||||
use esp_bootloader_esp_idf::partitions::FlashRegion;
|
use esp_bootloader_esp_idf::partitions::FlashRegion;
|
||||||
use esp_storage::FlashStorage;
|
|
||||||
use littlefs2::consts::U4096 as lfsCache;
|
use littlefs2::consts::U4096 as lfsCache;
|
||||||
use littlefs2::consts::U512 as lfsLookahead;
|
use littlefs2::consts::U512 as lfsLookahead;
|
||||||
use littlefs2::driver::Storage as lfs2Storage;
|
use littlefs2::driver::Storage as lfs2Storage;
|
||||||
@@ -9,7 +9,7 @@ use littlefs2::io::Result as lfs2Result;
|
|||||||
use log::error;
|
use log::error;
|
||||||
|
|
||||||
pub struct LittleFs2Filesystem {
|
pub struct LittleFs2Filesystem {
|
||||||
pub(crate) storage: &'static mut FlashRegion<'static, FlashStorage<'static>>,
|
pub(crate) storage: &'static mut FlashRegion<'static, MutexFlashStorage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl lfs2Storage for LittleFs2Filesystem {
|
impl lfs2Storage for LittleFs2Filesystem {
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ pub mod esp;
|
|||||||
mod initial_hal;
|
mod initial_hal;
|
||||||
mod little_fs2storage_adapter;
|
mod little_fs2storage_adapter;
|
||||||
pub(crate) mod rtc;
|
pub(crate) mod rtc;
|
||||||
|
mod shared_flash;
|
||||||
mod v3_hal;
|
mod v3_hal;
|
||||||
mod v3_shift_register;
|
mod v3_shift_register;
|
||||||
mod v4_hal;
|
mod v4_hal;
|
||||||
pub(crate) mod v4_sensor;
|
pub(crate) mod v4_sensor;
|
||||||
mod water;
|
mod water;
|
||||||
|
|
||||||
use crate::alloc::string::ToString;
|
use crate::alloc::string::ToString;
|
||||||
use crate::hal::rtc::{DS3231Module, RTCModuleInteraction};
|
use crate::hal::rtc::{DS3231Module, RTCModuleInteraction};
|
||||||
use esp_hal::peripherals::Peripherals;
|
use esp_hal::peripherals::Peripherals;
|
||||||
@@ -79,7 +81,7 @@ use crate::hal::water::TankSensor;
|
|||||||
use crate::log::LOG_ACCESS;
|
use crate::log::LOG_ACCESS;
|
||||||
use embassy_sync::mutex::Mutex;
|
use embassy_sync::mutex::Mutex;
|
||||||
use embassy_sync::once_lock::OnceLock;
|
use embassy_sync::once_lock::OnceLock;
|
||||||
use embedded_storage::nor_flash::ReadNorFlash;
|
use embedded_storage::ReadStorage;
|
||||||
use esp_alloc as _;
|
use esp_alloc as _;
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
use esp_bootloader_esp_idf::ota::{Ota, OtaImageState};
|
use esp_bootloader_esp_idf::ota::{Ota, OtaImageState};
|
||||||
@@ -101,6 +103,7 @@ use littlefs2::object_safe::DynStorage;
|
|||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use portable_atomic::AtomicBool;
|
use portable_atomic::AtomicBool;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use shared_flash::MutexFlashStorage;
|
||||||
|
|
||||||
pub static TIME_ACCESS: OnceLock<Mutex<CriticalSectionRawMutex, Rtc>> = OnceLock::new();
|
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],
|
[u8; esp_bootloader_esp_idf::partitions::PARTITION_TABLE_MAX_LEN],
|
||||||
[0u8; 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 =
|
let pt =
|
||||||
esp_bootloader_esp_idf::partitions::read_partition_table(flash_storage, tablebuffer)?;
|
esp_bootloader_esp_idf::partitions::read_partition_table(flash_storage, tablebuffer)?;
|
||||||
@@ -320,8 +331,8 @@ impl PlantHal {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let ota_data = mk_static!(
|
let ota_data = mk_static!(
|
||||||
FlashRegion<FlashStorage>,
|
FlashRegion<MutexFlashStorage>,
|
||||||
ota_data.as_embedded_storage(flash_storage)
|
ota_data.as_embedded_storage(flash_storage_2)
|
||||||
);
|
);
|
||||||
|
|
||||||
let state_0 = ota_state(AppPartitionSubType::Ota0, ota_data);
|
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!(PartitionEntry, ota_target);
|
||||||
let ota_target = mk_static!(
|
let ota_target = mk_static!(
|
||||||
FlashRegion<FlashStorage>,
|
FlashRegion<MutexFlashStorage>,
|
||||||
ota_target.as_embedded_storage(flash_storage)
|
ota_target.as_embedded_storage(flash_storage)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -365,8 +376,8 @@ impl PlantHal {
|
|||||||
let data_partition = mk_static!(PartitionEntry, data_partition);
|
let data_partition = mk_static!(PartitionEntry, data_partition);
|
||||||
|
|
||||||
let data = mk_static!(
|
let data = mk_static!(
|
||||||
FlashRegion<FlashStorage>,
|
FlashRegion<MutexFlashStorage>,
|
||||||
data_partition.as_embedded_storage(flash_storage)
|
data_partition.as_embedded_storage(flash_storage_3)
|
||||||
);
|
);
|
||||||
let lfs2filesystem = mk_static!(LittleFs2Filesystem, LittleFs2Filesystem { storage: data });
|
let lfs2filesystem = mk_static!(LittleFs2Filesystem, LittleFs2Filesystem { storage: data });
|
||||||
let alloc = mk_static!(Allocation<LittleFs2Filesystem>, lfs2Filesystem::allocate());
|
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
|
// 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]
|
// 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
|
// Offsets within the OTA data partition: slot0 @ 0x0000, slot1 @ 0x1000
|
||||||
let mut slot_buf = [0u8; 32];
|
let mut slot_buf = [0u8; 32];
|
||||||
if slot == AppPartitionSubType::Ota0 {
|
if slot == AppPartitionSubType::Ota0 {
|
||||||
let _ = ota_data.read(0x0000, &mut slot_buf);
|
let _ = ReadStorage::read(ota_data, 0x0000, &mut slot_buf);
|
||||||
} else {
|
} 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]));
|
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(
|
fn get_current_slot_and_fix_ota_data(
|
||||||
ota: &mut Ota<FlashStorage>,
|
ota: &mut Ota<MutexFlashStorage>,
|
||||||
state0: OtaImageState,
|
state0: OtaImageState,
|
||||||
state1: OtaImageState,
|
state1: OtaImageState,
|
||||||
) -> Result<AppPartitionSubType, FatError> {
|
) -> 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;
|
Timer::after_millis(10).await;
|
||||||
|
|
||||||
let mut moistures = Moistures::default();
|
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();
|
can_power.set_low();
|
||||||
|
|
||||||
@@ -170,7 +171,7 @@ impl SensorImpl {
|
|||||||
can_power.set_low();
|
can_power.set_low();
|
||||||
twai_config.replace(config);
|
twai_config.replace(config);
|
||||||
|
|
||||||
let result= moistures.into();
|
let result = moistures.into();
|
||||||
|
|
||||||
info!("Autodetection result: {result:?}");
|
info!("Autodetection result: {result:?}");
|
||||||
Ok(result)
|
Ok(result)
|
||||||
@@ -182,7 +183,6 @@ impl SensorImpl {
|
|||||||
as_async: &mut Twai<'_, Async>,
|
as_async: &mut Twai<'_, Async>,
|
||||||
moistures: &mut Moistures,
|
moistures: &mut Moistures,
|
||||||
) -> FatResult<()> {
|
) -> FatResult<()> {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match as_async.receive_async().await {
|
match as_async.receive_async().await {
|
||||||
Ok(can_frame) => match can_frame.id() {
|
Ok(can_frame) => match can_frame.id() {
|
||||||
|
|||||||
@@ -120,8 +120,12 @@ impl PlantState {
|
|||||||
let raw = moistures.sensor_a_hz[plant_id];
|
let raw = moistures.sensor_a_hz[plant_id];
|
||||||
match map_range_moisture(
|
match map_range_moisture(
|
||||||
raw,
|
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]
|
||||||
board.board_hal.get_config().plants[plant_id].moisture_sensor_max_frequency.map(|b| b as f32),
|
.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 {
|
Ok(moisture_percent) => MoistureSensorState::MoistureValue {
|
||||||
raw_hz: raw,
|
raw_hz: raw,
|
||||||
@@ -137,8 +141,12 @@ impl PlantState {
|
|||||||
let raw = moistures.sensor_b_hz[plant_id];
|
let raw = moistures.sensor_b_hz[plant_id];
|
||||||
match map_range_moisture(
|
match map_range_moisture(
|
||||||
raw,
|
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]
|
||||||
board.board_hal.get_config().plants[plant_id].moisture_sensor_max_frequency.map(|b| b as f32)
|
.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 {
|
Ok(moisture_percent) => MoistureSensorState::MoistureValue {
|
||||||
raw_hz: raw,
|
raw_hz: raw,
|
||||||
@@ -196,8 +204,12 @@ impl PlantState {
|
|||||||
(Some(moisture_a), Some(moisture_b)) => {
|
(Some(moisture_a), Some(moisture_b)) => {
|
||||||
(Some(((moisture_a + moisture_b) / 2.) as u8), (None, None))
|
(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)) => (Some(moisture_percent as u8), (self.sensor_a.is_err(), None)),
|
(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())),
|
_ => (None, (self.sensor_a.is_err(), self.sensor_b.is_err())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user