i2c working, rtc working, eeprom working
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
use crate::hal::Box;
|
||||
use crate::FatError::{FatError, FatResult};
|
||||
use alloc::string::String;
|
||||
use async_trait::async_trait;
|
||||
|
||||
@@ -5,7 +5,7 @@ use alloc::vec::Vec;
|
||||
use crate::alloc::boxed::Box;
|
||||
use crate::hal::water::TankSensor;
|
||||
use crate::hal::{BoardInteraction, FreePeripherals, Sensor};
|
||||
use crate::FatError::FatError;
|
||||
use crate::FatError::{FatError, FatResult};
|
||||
use crate::{
|
||||
bail,
|
||||
config::PlantControllerConfig,
|
||||
@@ -32,11 +32,15 @@ impl RTCModuleInteraction for NoRTC {
|
||||
bail!("Please configure board revision")
|
||||
}
|
||||
|
||||
async fn get_backup_config(&mut self) -> Result<Vec<u8>, FatError> {
|
||||
async fn get_backup_config(&mut self, chunk: usize) -> FatResult<([u8; 32], usize, u16)> {
|
||||
bail!("Please configure board revision")
|
||||
}
|
||||
|
||||
async fn backup_config(&mut self, _bytes: &[u8]) -> Result<(), FatError> {
|
||||
async fn backup_config(&mut self, offset: usize, bytes: &[u8]) -> FatResult<()> {
|
||||
bail!("Please configure board revision")
|
||||
}
|
||||
|
||||
async fn backup_config_finalize(&mut self, crc: u16, length: usize) -> FatResult<()> {
|
||||
bail!("Please configure board revision")
|
||||
}
|
||||
|
||||
|
||||
@@ -2,13 +2,13 @@ pub(crate) mod battery;
|
||||
pub mod esp;
|
||||
mod initial_hal;
|
||||
mod little_fs2storage_adapter;
|
||||
mod rtc;
|
||||
pub(crate) mod rtc;
|
||||
mod v4_hal;
|
||||
mod water;
|
||||
//mod water;
|
||||
|
||||
use crate::alloc::string::ToString;
|
||||
use crate::hal::rtc::RTCModuleInteraction;
|
||||
use crate::hal::rtc::{DS3231Module, RTCModuleInteraction};
|
||||
use esp_hal::peripherals::Peripherals;
|
||||
use esp_hal::peripherals::GPIO0;
|
||||
use esp_hal::peripherals::GPIO1;
|
||||
@@ -54,10 +54,20 @@ use alloc::format;
|
||||
use alloc::sync::Arc;
|
||||
use async_trait::async_trait;
|
||||
use chrono::{DateTime, FixedOffset, Utc};
|
||||
use core::cell::RefCell;
|
||||
use ds323x::ic::DS3231;
|
||||
use ds323x::interface::I2cInterface;
|
||||
use ds323x::{DateTimeAccess, Ds323x};
|
||||
use eeprom24x::addr_size::TwoBytes;
|
||||
use eeprom24x::page_size::B32;
|
||||
use eeprom24x::unique_serial::No;
|
||||
use eeprom24x::{Eeprom24x, SlaveAddr, Storage};
|
||||
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_sync::blocking_mutex::{CriticalSectionMutex, NoopMutex};
|
||||
//use battery::BQ34Z100G1;
|
||||
//use bq34z100::Bq34z100g1Driver;
|
||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
|
||||
use esp_bootloader_esp_idf::partitions::{
|
||||
AppPartitionSubType, DataPartitionSubType, FlashRegion, PartitionEntry,
|
||||
};
|
||||
@@ -74,10 +84,14 @@ use embassy_sync::once_lock::OnceLock;
|
||||
use esp_alloc as _;
|
||||
use esp_backtrace as _;
|
||||
use esp_bootloader_esp_idf::ota::Slot;
|
||||
use esp_hal::delay::Delay;
|
||||
use esp_hal::i2c::master::{BusTimeout, Config, I2c};
|
||||
use esp_hal::rng::Rng;
|
||||
use esp_hal::rtc_cntl::{Rtc, SocResetReason};
|
||||
use esp_hal::system::reset_reason;
|
||||
use esp_hal::time::Rate;
|
||||
use esp_hal::timer::timg::TimerGroup;
|
||||
use esp_hal::Blocking;
|
||||
use esp_storage::FlashStorage;
|
||||
use esp_wifi::{init, EspWifiController};
|
||||
use littlefs2::fs::{Allocation, Filesystem as lfs2Filesystem};
|
||||
@@ -90,8 +104,9 @@ pub static TIME_ACCESS: OnceLock<Rtc> = OnceLock::new();
|
||||
pub const PLANT_COUNT: usize = 8;
|
||||
|
||||
const TANK_MULTI_SAMPLE: usize = 11;
|
||||
|
||||
//pub static I2C_DRIVER: LazyLock<Mutex<CriticalSectionRawMutex,I2cDriver<'static>>> = LazyLock::new(PlantHal::create_i2c);
|
||||
static I2C_DRIVER: OnceLock<
|
||||
embassy_sync::blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<I2c<Blocking>>>,
|
||||
> = OnceLock::new();
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Sensor {
|
||||
@@ -127,22 +142,16 @@ pub trait BoardInteraction<'a> {
|
||||
fn set_config(&mut self, config: PlantControllerConfig);
|
||||
async fn get_mptt_voltage(&mut self) -> Result<Voltage, FatError>;
|
||||
async fn get_mptt_current(&mut self) -> Result<Current, FatError>;
|
||||
}
|
||||
|
||||
impl dyn BoardInteraction<'_> {
|
||||
//the counter is just some arbitrary number that increases whenever some progress was made, try to keep the updates < 10 per second for ux reasons
|
||||
async fn _progress(&mut self, counter: u32) {
|
||||
async fn progress(&mut self, counter: u32) {
|
||||
let even = counter % 2 == 0;
|
||||
let current = counter / (PLANT_COUNT as u32);
|
||||
for led in 0..PLANT_COUNT {
|
||||
match self.fault(led, current == led as u32).await {
|
||||
Result::Ok(_) => {}
|
||||
Err(err) => {
|
||||
warn!("Fault on plant {}: {:?}", led, err);
|
||||
}
|
||||
if let Err(err) = self.fault(led, current == led as u32).await {
|
||||
warn!("Fault on plant {}: {:?}", led, err);
|
||||
}
|
||||
}
|
||||
let _ = self.general_fault(even.into());
|
||||
let _ = self.general_fault(even.into()).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +205,7 @@ macro_rules! mk_static {
|
||||
const GW_IP_ADDR_ENV: Option<&'static str> = option_env!("GATEWAY_IP");
|
||||
|
||||
impl PlantHal {
|
||||
// fn create_i2c() -> Mutex<CriticalSectionRawMutex, I2cDriver<'static>> {
|
||||
//fn create_i2c() -> Mutex<CriticalSectionRawMutex, ()> {
|
||||
// let peripherals = unsafe { Peripherals::new() };
|
||||
//
|
||||
// let config = I2cConfig::new()
|
||||
@@ -210,7 +219,7 @@ impl PlantHal {
|
||||
// let sda = peripherals.pins.gpio20.downgrade();
|
||||
//
|
||||
// Mutex::new(I2cDriver::new(i2c, sda, scl, &config).unwrap())
|
||||
// }
|
||||
//}
|
||||
|
||||
pub async fn create(
|
||||
spawner: Spawner,
|
||||
@@ -427,28 +436,55 @@ impl PlantHal {
|
||||
let config = esp.load_config().await;
|
||||
|
||||
log::info!("Init rtc driver");
|
||||
// let mut rtc = Ds323x::new_ds3231(MutexDevice::new(&I2C_DRIVER));
|
||||
//
|
||||
// log::info!("Init rtc eeprom driver");
|
||||
// let eeprom = {
|
||||
// Eeprom24x::new_24x32(
|
||||
// MutexDevice::new(&I2C_DRIVER),
|
||||
// SlaveAddr::Alternative(true, true, true),
|
||||
// )
|
||||
// };
|
||||
// let rtc_time = rtc.datetime();
|
||||
// match rtc_time {
|
||||
// OkStd(tt) => {
|
||||
// log::info!("Rtc Module reports time at UTC {}", tt);
|
||||
// }
|
||||
// Err(err) => {
|
||||
// log::info!("Rtc Module could not be read {:?}", err);
|
||||
// }
|
||||
// }
|
||||
|
||||
// let storage = Storage::new(eeprom, Delay::new(1000));
|
||||
let rtc_module: Box<dyn RTCModuleInteraction + Send> = Box::new(initial_hal::NoRTC {});
|
||||
// Box::new(DS3231Module { rtc, storage }) as Box<dyn RTCModuleInteraction + Send>;
|
||||
let sda = peripherals.GPIO20;
|
||||
let scl = peripherals.GPIO19;
|
||||
|
||||
let i2c = I2c::new(
|
||||
peripherals.I2C0,
|
||||
Config::default()
|
||||
.with_frequency(Rate::from_hz(100))
|
||||
.with_timeout(BusTimeout::Maximum),
|
||||
)?
|
||||
.with_scl(scl)
|
||||
.with_sda(sda);
|
||||
let i2c_bus: embassy_sync::blocking_mutex::Mutex<
|
||||
CriticalSectionRawMutex,
|
||||
RefCell<I2c<Blocking>>,
|
||||
> = CriticalSectionMutex::new(RefCell::new(i2c));
|
||||
|
||||
I2C_DRIVER.init(i2c_bus).expect("Could not init i2c driver");
|
||||
|
||||
let i2c_bus = I2C_DRIVER.get().await;
|
||||
let rtc_device = I2cDevice::new(&i2c_bus);
|
||||
let eeprom_device = I2cDevice::new(&i2c_bus);
|
||||
|
||||
let mut rtc: Ds323x<
|
||||
I2cInterface<I2cDevice<CriticalSectionRawMutex, I2c<Blocking>>>,
|
||||
DS3231,
|
||||
> = Ds323x::new_ds3231(rtc_device);
|
||||
|
||||
info!("Init rtc eeprom driver");
|
||||
let eeprom = Eeprom24x::new_24x32(eeprom_device, SlaveAddr::Alternative(true, true, true));
|
||||
let rtc_time = rtc.datetime();
|
||||
match rtc_time {
|
||||
Ok(tt) => {
|
||||
log::info!("Rtc Module reports time at UTC {}", tt);
|
||||
}
|
||||
Err(err) => {
|
||||
log::info!("Rtc Module could not be read {:?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
let storage: Storage<
|
||||
I2cDevice<'static, CriticalSectionRawMutex, I2c<Blocking>>,
|
||||
B32,
|
||||
TwoBytes,
|
||||
No,
|
||||
Delay,
|
||||
> = Storage::new(eeprom, Delay::new());
|
||||
let rtc_module: Box<dyn RTCModuleInteraction + Send> =
|
||||
Box::new(DS3231Module { rtc, storage }) as Box<dyn RTCModuleInteraction + Send>;
|
||||
|
||||
let hal = match config {
|
||||
Result::Ok(config) => {
|
||||
|
||||
@@ -1,139 +1,138 @@
|
||||
use crate::bail;
|
||||
use crate::hal::Box;
|
||||
use crate::FatError::FatResult;
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
use async_trait::async_trait;
|
||||
use bincode::config::Configuration;
|
||||
use bincode::{config, Decode, Encode};
|
||||
use chrono::{DateTime, Utc};
|
||||
use crc::Digest;
|
||||
use ds323x::ic::DS3231;
|
||||
use ds323x::interface::I2cInterface;
|
||||
use ds323x::{DateTimeAccess, Ds323x};
|
||||
use eeprom24x::addr_size::TwoBytes;
|
||||
use eeprom24x::page_size::B32;
|
||||
use eeprom24x::unique_serial::No;
|
||||
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
|
||||
use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
|
||||
use embedded_storage::{ReadStorage, Storage};
|
||||
use esp_hal::delay::Delay;
|
||||
use esp_hal::i2c::master::I2c;
|
||||
use esp_hal::Blocking;
|
||||
use littlefs2_core::{PathBuf, SeekFrom};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
// use crate::hal::Box;
|
||||
// use alloc::vec::Vec;
|
||||
// use anyhow::{anyhow, bail};
|
||||
// use async_trait::async_trait;
|
||||
// use bincode::config::Configuration;
|
||||
// use bincode::{config, Decode, Encode};
|
||||
// use chrono::{DateTime, Utc};
|
||||
// use ds323x::{DateTimeAccess, Ds323x};
|
||||
// use eeprom24x::addr_size::TwoBytes;
|
||||
// use eeprom24x::page_size::B32;
|
||||
// use eeprom24x::unique_serial::No;
|
||||
// use eeprom24x::Storage;
|
||||
// use embedded_storage::ReadStorage as embedded_storage_ReadStorage;
|
||||
// use embedded_storage::Storage as embedded_storage_Storage;
|
||||
// use serde::{Deserialize, Serialize};
|
||||
//
|
||||
// const X25: crc::Crc<u16> = crc::Crc::<u16>::new(&crc::CRC_16_IBM_SDLC);
|
||||
// const CONFIG: Configuration = config::standard();
|
||||
pub const X25: crc::Crc<u16> = crc::Crc::<u16>::new(&crc::CRC_16_IBM_SDLC);
|
||||
const CONFIG: Configuration = config::standard();
|
||||
//
|
||||
#[async_trait]
|
||||
pub trait RTCModuleInteraction {
|
||||
async fn get_backup_info(&mut self) -> FatResult<BackupHeader>;
|
||||
async fn get_backup_config(&mut self) -> FatResult<Vec<u8>>;
|
||||
async fn backup_config(&mut self, bytes: &[u8]) -> FatResult<()>;
|
||||
async fn get_backup_config(&mut self, chunk: usize) -> FatResult<([u8; 32], usize, u16)>;
|
||||
async fn backup_config(&mut self, offset: usize, bytes: &[u8]) -> FatResult<()>;
|
||||
async fn backup_config_finalize(&mut self, crc: u16, length: usize) -> FatResult<()>;
|
||||
async fn get_rtc_time(&mut self) -> FatResult<DateTime<Utc>>;
|
||||
async fn set_rtc_time(&mut self, time: &DateTime<Utc>) -> FatResult<()>;
|
||||
}
|
||||
//
|
||||
// const BACKUP_HEADER_MAX_SIZE: usize = 64;
|
||||
// #[derive(Serialize, Deserialize, PartialEq, Debug, Default, Encode, Decode)]
|
||||
const BACKUP_HEADER_MAX_SIZE: usize = 64;
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Encode, Decode)]
|
||||
pub struct BackupHeader {
|
||||
pub timestamp: i64,
|
||||
crc16: u16,
|
||||
pub size: u16,
|
||||
}
|
||||
//
|
||||
// pub struct DS3231Module<'a> {
|
||||
// pub(crate) rtc:
|
||||
// Ds323x<ds323x::interface::I2cInterface<MutexDevice<'a, I2cDriver<'a>>>, ds323x::ic::DS3231>,
|
||||
//
|
||||
// pub(crate) storage: Storage<MutexDevice<'a, I2cDriver<'a>>, B32, TwoBytes, No, Delay>,
|
||||
// }
|
||||
//
|
||||
// impl RTCModuleInteraction for DS3231Module<'_> {
|
||||
// fn get_backup_info(&mut self) -> anyhow::Result<BackupHeader> {
|
||||
// let mut header_page_buffer = [0_u8; BACKUP_HEADER_MAX_SIZE];
|
||||
//
|
||||
// self.storage
|
||||
// .read(0, &mut header_page_buffer)
|
||||
// .map_err(|err| anyhow!("Error reading eeprom header {:?}", err))?;
|
||||
//
|
||||
// let (header, len): (BackupHeader, usize) =
|
||||
// bincode::decode_from_slice(&header_page_buffer[..], CONFIG)?;
|
||||
//
|
||||
// log::info!("Raw header is {:?} with size {}", header_page_buffer, len);
|
||||
// anyhow::Ok(header)
|
||||
// }
|
||||
//
|
||||
// fn get_backup_config(&mut self) -> anyhow::Result<Vec<u8>> {
|
||||
// let mut header_page_buffer = [0_u8; BACKUP_HEADER_MAX_SIZE];
|
||||
//
|
||||
// self.storage
|
||||
// .read(0, &mut header_page_buffer)
|
||||
// .map_err(|err| anyhow!("Error reading eeprom header {:?}", err))?;
|
||||
// let (header, _header_size): (BackupHeader, usize) =
|
||||
// bincode::decode_from_slice(&header_page_buffer[..], CONFIG)?;
|
||||
//
|
||||
// let mut data_buffer = vec![0_u8; header.size as usize];
|
||||
// //read the specified number of bytes after the header
|
||||
// self.storage
|
||||
// .read(BACKUP_HEADER_MAX_SIZE as u32, &mut data_buffer)
|
||||
// .map_err(|err| anyhow!("Error reading eeprom data {:?}", err))?;
|
||||
//
|
||||
// let checksum = X25.checksum(&data_buffer);
|
||||
// if checksum != header.crc16 {
|
||||
// bail!(
|
||||
// "Invalid checksum, got {} but expected {}",
|
||||
// checksum,
|
||||
// header.crc16
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// anyhow::Ok(data_buffer)
|
||||
// }
|
||||
// fn backup_config(&mut self, bytes: &[u8]) -> anyhow::Result<()> {
|
||||
// let mut header_page_buffer = [0_u8; BACKUP_HEADER_MAX_SIZE];
|
||||
//
|
||||
// let time = self.get_rtc_time()?.timestamp_millis();
|
||||
// let checksum = X25.checksum(bytes);
|
||||
//
|
||||
// let header = BackupHeader {
|
||||
// crc16: checksum,
|
||||
// timestamp: time,
|
||||
// size: bytes.len() as u16,
|
||||
// };
|
||||
// let config = config::standard();
|
||||
// let encoded = bincode::encode_into_slice(&header, &mut header_page_buffer, config)?;
|
||||
// log::info!(
|
||||
// "Raw header is {:?} with size {}",
|
||||
// header_page_buffer,
|
||||
// encoded
|
||||
// );
|
||||
// self.storage
|
||||
// .write(0, &header_page_buffer)
|
||||
// .map_err(|err| anyhow!("Error writing header {:?}", err))?;
|
||||
//
|
||||
// //write rest after the header
|
||||
// self.storage
|
||||
// .write(BACKUP_HEADER_MAX_SIZE as u32, &bytes)
|
||||
// .map_err(|err| anyhow!("Error writing body {:?}", err))?;
|
||||
//
|
||||
// anyhow::Ok(())
|
||||
// }
|
||||
//
|
||||
// fn get_rtc_time(&mut self) -> anyhow::Result<DateTime<Utc>> {
|
||||
// match self.rtc.datetime() {
|
||||
// OkStd(rtc_time) => anyhow::Ok(rtc_time.and_utc()),
|
||||
// Err(err) => {
|
||||
// bail!("Error getting rtc time {:?}", err)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fn set_rtc_time(&mut self, time: &DateTime<Utc>) -> anyhow::Result<()> {
|
||||
// let naive_time = time.naive_utc();
|
||||
// match self.rtc.set_datetime(&naive_time) {
|
||||
// OkStd(_) => anyhow::Ok(()),
|
||||
// Err(err) => {
|
||||
// bail!("Error getting rtc time {:?}", err)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
pub struct DS3231Module {
|
||||
pub(crate) rtc: Ds323x<
|
||||
I2cInterface<I2cDevice<'static, CriticalSectionRawMutex, I2c<'static, Blocking>>>,
|
||||
DS3231,
|
||||
>,
|
||||
|
||||
pub(crate) storage: eeprom24x::Storage<
|
||||
I2cDevice<'static, CriticalSectionRawMutex, I2c<'static, Blocking>>,
|
||||
B32,
|
||||
TwoBytes,
|
||||
No,
|
||||
Delay,
|
||||
>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl RTCModuleInteraction for DS3231Module {
|
||||
async fn get_backup_info(&mut self) -> FatResult<BackupHeader> {
|
||||
let mut header_page_buffer = [0_u8; BACKUP_HEADER_MAX_SIZE];
|
||||
|
||||
self.storage.read(0, &mut header_page_buffer)?;
|
||||
|
||||
let (header, len): (BackupHeader, usize) =
|
||||
bincode::decode_from_slice(&header_page_buffer[..], CONFIG)?;
|
||||
|
||||
log::info!("Raw header is {:?} with size {}", header_page_buffer, len);
|
||||
Ok(header)
|
||||
}
|
||||
|
||||
async fn get_backup_config(&mut self, chunk: usize) -> FatResult<([u8; 32], usize, u16)> {
|
||||
let mut header_page_buffer = [0_u8; BACKUP_HEADER_MAX_SIZE];
|
||||
|
||||
self.storage.read(0, &mut header_page_buffer)?;
|
||||
let (header, _header_size): (BackupHeader, usize) =
|
||||
bincode::decode_from_slice(&header_page_buffer[..], CONFIG)?;
|
||||
|
||||
let mut buf = [0_u8; 32];
|
||||
let offset = chunk * buf.len() + BACKUP_HEADER_MAX_SIZE;
|
||||
|
||||
let end: usize = header.size as usize + BACKUP_HEADER_MAX_SIZE;
|
||||
let current_end = offset + buf.len();
|
||||
let chunk_size = if current_end > end {
|
||||
end - offset
|
||||
} else {
|
||||
buf.len()
|
||||
};
|
||||
if chunk_size == 0 {
|
||||
Ok((buf, 0, header.crc16))
|
||||
} else {
|
||||
self.storage.read(offset as u32, &mut buf)?;
|
||||
let data = &buf[..chunk_size];
|
||||
Ok((buf, chunk_size, header.crc16))
|
||||
}
|
||||
}
|
||||
async fn backup_config(&mut self, offset: usize, bytes: &[u8]) -> FatResult<()> {
|
||||
//skip header and write after
|
||||
self.storage
|
||||
.write((BACKUP_HEADER_MAX_SIZE + offset) as u32, &bytes)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn backup_config_finalize(&mut self, crc: u16, length: usize) -> FatResult<()> {
|
||||
let mut header_page_buffer = [0_u8; BACKUP_HEADER_MAX_SIZE];
|
||||
|
||||
let time = self.get_rtc_time().await?.timestamp_millis();
|
||||
let header = BackupHeader {
|
||||
crc16: crc,
|
||||
timestamp: time,
|
||||
size: length as u16,
|
||||
};
|
||||
let config = config::standard();
|
||||
let encoded = bincode::encode_into_slice(&header, &mut header_page_buffer, config)?;
|
||||
log::info!(
|
||||
"Raw header is {:?} with size {}",
|
||||
header_page_buffer,
|
||||
encoded
|
||||
);
|
||||
self.storage.write(0, &header_page_buffer)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_rtc_time(&mut self) -> FatResult<DateTime<Utc>> {
|
||||
Ok(self.rtc.datetime()?.and_utc())
|
||||
}
|
||||
|
||||
async fn set_rtc_time(&mut self, time: &DateTime<Utc>) -> FatResult<()> {
|
||||
let naive_time = time.naive_utc();
|
||||
Ok(self.rtc.set_datetime(&naive_time)?)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user