@@ -10,7 +10,7 @@ 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};
|
||||
use alloc::{format, string::String, vec, vec::Vec};
|
||||
use core::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use core::str::FromStr;
|
||||
use core::sync::atomic::Ordering;
|
||||
@@ -21,6 +21,11 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use embassy_sync::mutex::{Mutex, MutexGuard};
|
||||
use embassy_sync::once_lock::OnceLock;
|
||||
use embassy_time::{Duration, Timer, WithTimeout};
|
||||
use embedded_storage::nor_flash::{check_erase, NorFlash, ReadNorFlash};
|
||||
use esp_bootloader_esp_idf::ota::OtaImageState::Valid;
|
||||
use esp_bootloader_esp_idf::ota::{Ota, OtaImageState};
|
||||
use esp_bootloader_esp_idf::partitions::{AppPartitionSubType, FlashRegion};
|
||||
use esp_hal::Blocking;
|
||||
use esp_hal::gpio::{Input, RtcPinWithResistors};
|
||||
use esp_hal::rng::Rng;
|
||||
use esp_hal::rtc_cntl::{
|
||||
@@ -29,8 +34,6 @@ use esp_hal::rtc_cntl::{
|
||||
};
|
||||
use esp_hal::system::software_reset;
|
||||
use esp_hal::uart::Uart;
|
||||
use esp_hal::Blocking;
|
||||
use esp_hal_ota::Ota;
|
||||
use esp_println::println;
|
||||
use esp_radio::wifi::{
|
||||
AccessPointConfig, AccessPointInfo, AuthMethod, ClientConfig, ModeConfig, ScanConfig,
|
||||
@@ -126,7 +129,12 @@ 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 uart0: Uart<'a, Blocking>,
|
||||
pub ota: &'static mut Ota<&'static mut MutexFlashStorage>,
|
||||
|
||||
pub ota: Ota<'static, MutexFlashStorage>,
|
||||
pub ota_target: &'static mut FlashRegion<'static, MutexFlashStorage>,
|
||||
pub current: AppPartitionSubType,
|
||||
pub slot0_state: OtaImageState,
|
||||
pub slot1_state: OtaImageState,
|
||||
}
|
||||
|
||||
// SAFETY: On this target we never move Esp across OS threads; the firmware runs single-core
|
||||
@@ -147,6 +155,7 @@ macro_rules! mk_static {
|
||||
}
|
||||
|
||||
impl Esp<'_> {
|
||||
|
||||
pub(crate) async fn read_serial_line(&mut self) -> FatResult<Option<alloc::string::String>> {
|
||||
let mut buf = [0u8; 1];
|
||||
let mut line = String::new();
|
||||
@@ -162,7 +171,7 @@ impl Esp<'_> {
|
||||
}
|
||||
line.push(c);
|
||||
}
|
||||
Err(error) => {
|
||||
Err(error ) => {
|
||||
if line.is_empty() {
|
||||
return Ok(None);
|
||||
} else {
|
||||
@@ -241,6 +250,50 @@ impl Esp<'_> {
|
||||
Ok((buf, read))
|
||||
}
|
||||
|
||||
pub(crate) async fn write_ota(&mut self, offset: u32, buf: &[u8]) -> Result<(), FatError> {
|
||||
let _ = check_erase(self.ota_target, offset, offset + 4096);
|
||||
self.ota_target.erase(offset, offset + 4096)?;
|
||||
|
||||
let mut temp = vec![0; buf.len()];
|
||||
let read_back = temp.as_mut_slice();
|
||||
//change to nor flash, align writes!
|
||||
self.ota_target.write(offset, buf)?;
|
||||
self.ota_target.read(offset, read_back)?;
|
||||
if buf != read_back {
|
||||
info!("Expected {buf:?} but got {read_back:?}");
|
||||
bail!(
|
||||
"Flash error, read back does not match write buffer at offset {:x}",
|
||||
offset
|
||||
)
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn finalize_ota(&mut self) -> Result<(), FatError> {
|
||||
let current = self.ota.current_app_partition()?;
|
||||
if self.ota.current_ota_state()? != Valid {
|
||||
info!("Validating current slot {current:?} as it was able to ota");
|
||||
self.ota.set_current_ota_state(Valid)?;
|
||||
}
|
||||
let next = match current {
|
||||
AppPartitionSubType::Ota0 => AppPartitionSubType::Ota1,
|
||||
AppPartitionSubType::Ota1 => AppPartitionSubType::Ota0,
|
||||
_ => {
|
||||
bail!("Invalid current slot {current:?} for ota");
|
||||
}
|
||||
};
|
||||
self.ota.set_current_app_partition(next)?;
|
||||
info!("switched slot");
|
||||
self.ota.set_current_ota_state(OtaImageState::New)?;
|
||||
info!("switched state for new partition");
|
||||
let state_new = self.ota.current_ota_state()?;
|
||||
info!("state on new partition now {state_new:?}");
|
||||
//determine nextslot crc
|
||||
|
||||
self.set_restart_to_conf(true);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn mode_override_pressed(&mut self) -> bool {
|
||||
self.boot_button.is_low()
|
||||
}
|
||||
@@ -541,7 +594,14 @@ impl Esp<'_> {
|
||||
duration_in_ms: u64,
|
||||
mut rtc: MutexGuard<CriticalSectionRawMutex, Rtc>,
|
||||
) -> ! {
|
||||
//TODO HERE Mark the current OTA image as valid if we reached here while in pending verify.
|
||||
// Mark the current OTA image as valid if we reached here while in pending verify.
|
||||
if let Ok(cur) = self.ota.current_ota_state() {
|
||||
if cur == OtaImageState::PendingVerify {
|
||||
self.ota
|
||||
.set_current_ota_state(Valid)
|
||||
.expect("Could not set image to valid");
|
||||
}
|
||||
}
|
||||
|
||||
if duration_in_ms == 0 {
|
||||
software_reset();
|
||||
|
||||
Reference in New Issue
Block a user