fix some ota stuff

This commit is contained in:
2025-10-04 03:05:11 +02:00
parent 0ddf6a6886
commit 894be7c373
6 changed files with 66 additions and 91 deletions

View File

@@ -1,4 +1,4 @@
use crate::{bail};
use crate::bail;
use crate::config::{NetworkConfig, PlantControllerConfig};
use crate::hal::{get_next_slot, PLANT_COUNT, TIME_ACCESS};
use crate::log::{LogMessage, LOG_ACCESS};
@@ -9,7 +9,7 @@ use crate::fat_error::{ContextExt, FatError, FatResult};
use crate::hal::little_fs2storage_adapter::LittleFs2Filesystem;
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,8 +21,8 @@ use embassy_sync::mutex::{Mutex, MutexGuard};
use embassy_sync::once_lock::OnceLock;
use embassy_time::{Duration, Timer};
use embedded_storage::nor_flash::{check_erase, NorFlash, ReadNorFlash};
use esp_bootloader_esp_idf::ota::{Ota, OtaImageState};
use esp_bootloader_esp_idf::ota::OtaImageState::Valid;
use esp_bootloader_esp_idf::ota::{Ota, OtaImageState};
use esp_bootloader_esp_idf::partitions::FlashRegion;
use esp_hal::gpio::{Input, RtcPinWithResistors};
use esp_hal::rng::Rng;
@@ -128,7 +128,7 @@ pub struct Esp<'a> {
pub wake_gpio1: esp_hal::peripherals::GPIO1<'static>,
pub ota: Ota<'static, FlashStorage>,
pub ota_next: &'static mut FlashRegion<'static, FlashStorage>
pub ota_next: &'static mut FlashRegion<'static, FlashStorage>,
}
// SAFETY: On this target we never move Esp across OS threads; the firmware runs single-core
@@ -235,53 +235,32 @@ impl Esp<'_> {
}
}
pub(crate) async fn write_ota(
&mut self,
offset: u32,
buf: &[u8],
) -> Result<(), FatError> {
pub(crate) async fn write_ota(&mut self, offset: u32, buf: &[u8]) -> Result<(), FatError> {
if self.ota.current_ota_state() == Ok(OtaImageState::Invalid) {
bail!("Invalid OTA state, refusing ota write")
}
if self.ota.current_ota_state() == Ok(OtaImageState::Undefined) {
bail!("Invalid OTA state, refusing ota write")
}
let _ = check_erase(self.ota_next, offset, offset + 4096);
self.ota_next.erase(offset, offset + 4096)?;
let mut read_back = [0_u8; 1024];
let useful = &mut read_back[..buf.len()];
let mut temp = vec![0; buf.len()];
let read_back = temp.as_mut_slice();
//change to nor flash, align writes!
self.ota_next.write(offset, buf)?;
self.ota_next.read(offset, useful)?;
if buf != useful {
info!("Expected {:?} but got {:?}", buf, useful);
bail!("Flash error, read back does not match write buffer at offset {:x}", offset)
self.ota_next.read(offset, read_back)?;
if buf != read_back {
info!("Expected {:?} but got {:?}", buf, read_back);
bail!(
"Flash error, read back does not match write buffer at offset {:x}",
offset
)
}
Ok(())
}
pub(crate) async fn ota_erase(&mut self, block_start: u32) -> FatResult<()> {
// Ensure 4K block size and alignment
if self.ota_next.capacity() % 4096 != 0 {
bail!("Partition size is not a multiple of 4096")
}
if block_start % 4096 != 0 {
bail!("ota_erase called with unaligned block_start: {:x}", block_start)
}
let capacity = self.ota_next.capacity() as u32;
if block_start >= capacity {
bail!("ota_erase block_start out of range: {:x}", block_start)
}
let end = core::cmp::min(block_start + 4096, capacity);
// Check current erase state (will error if not erased); we ignore the result and erase anyway
let _ = check_erase(self.ota_next, block_start, end);
info!("erasing block {:x}-{:x}", block_start, end);
self.ota_next.erase(block_start, end)?;
Ok(())
}
pub(crate) async fn finalize_ota(
&mut self,
) -> Result<(), FatError> {
pub(crate) async fn finalize_ota(&mut self) -> Result<(), FatError> {
if self.ota.current_ota_state() == Ok(OtaImageState::Invalid) {
bail!("Invalid OTA state, refusing ota write")
}
@@ -289,20 +268,19 @@ impl Esp<'_> {
bail!("Invalid OTA state, refusing ota write")
}
let current_state = self.ota.current_ota_state()?;
info!("current state {:?}", current_state);
info!("current state {:?}", current_state);
let next_slot = get_next_slot(&mut self.ota)?;
info!("current slot {:?}", next_slot.next());
info!("current slot {:?}", next_slot.next());
if current_state == OtaImageState::PendingVerify {
info!("verifying ota image from pending");
self.ota.set_current_ota_state(Valid)?;
}
self.ota.set_current_slot(next_slot)?;
info!("switched slot");
info!("switched slot");
self.ota.set_current_ota_state(OtaImageState::New)?;
info!("switched state for new partition");
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
@@ -344,6 +322,7 @@ impl Esp<'_> {
if ntp_addrs.is_empty() {
bail!("Failed to resolve DNS");
}
info!("NTP server: {:?}", ntp_addrs);
let mut counter = 0;
loop {
@@ -368,7 +347,6 @@ impl Esp<'_> {
}
}
pub(crate) async fn wifi_scan(&mut self) -> FatResult<Vec<AccessPointInfo>> {
info!("start wifi scan");
let mut lock = self.controller.try_lock()?;