ota is back
This commit is contained in:
@@ -20,8 +20,9 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
|||||||
use embassy_sync::mutex::{Mutex, MutexGuard};
|
use embassy_sync::mutex::{Mutex, MutexGuard};
|
||||||
use embassy_sync::once_lock::OnceLock;
|
use embassy_sync::once_lock::OnceLock;
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use embedded_storage::nor_flash::ReadNorFlash;
|
use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
|
||||||
use esp_bootloader_esp_idf::ota::{Ota, OtaImageState};
|
use esp_bootloader_esp_idf::ota::{Ota, OtaImageState};
|
||||||
|
use esp_bootloader_esp_idf::ota::OtaImageState::Valid;
|
||||||
use esp_bootloader_esp_idf::partitions::FlashRegion;
|
use esp_bootloader_esp_idf::partitions::FlashRegion;
|
||||||
use esp_hal::gpio::{Input, RtcPinWithResistors};
|
use esp_hal::gpio::{Input, RtcPinWithResistors};
|
||||||
use esp_hal::rng::Rng;
|
use esp_hal::rng::Rng;
|
||||||
@@ -29,6 +30,7 @@ use esp_hal::rtc_cntl::{
|
|||||||
sleep::{TimerWakeupSource, WakeupLevel},
|
sleep::{TimerWakeupSource, WakeupLevel},
|
||||||
Rtc,
|
Rtc,
|
||||||
};
|
};
|
||||||
|
use esp_hal::sha::Digest;
|
||||||
use esp_hal::system::software_reset;
|
use esp_hal::system::software_reset;
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
use esp_storage::FlashStorage;
|
use esp_storage::FlashStorage;
|
||||||
@@ -127,7 +129,7 @@ pub struct Esp<'a> {
|
|||||||
pub wake_gpio1: esp_hal::peripherals::GPIO1<'static>,
|
pub wake_gpio1: esp_hal::peripherals::GPIO1<'static>,
|
||||||
|
|
||||||
pub ota: Ota<'static, FlashStorage>,
|
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
|
// SAFETY: On this target we never move Esp across OS threads; the firmware runs single-core
|
||||||
@@ -234,6 +236,28 @@ impl Esp<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn write_ota(
|
||||||
|
&mut self,
|
||||||
|
offset: u32,
|
||||||
|
buf: &[u8],
|
||||||
|
) -> Result<(), FatError> {
|
||||||
|
self.ota_next.write(offset, buf)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn finalize_ota(
|
||||||
|
&mut self,
|
||||||
|
) -> Result<(), FatError> {
|
||||||
|
let current_state = self.ota.current_ota_state()?;
|
||||||
|
let current_slot = self.ota.current_slot()?;
|
||||||
|
if current_state == OtaImageState::PendingVerify {
|
||||||
|
self.ota.set_current_ota_state(Valid)?;
|
||||||
|
}
|
||||||
|
self.ota.set_current_slot(current_slot.next())?;
|
||||||
|
self.set_restart_to_conf(true);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
// let current = ota.current_slot()?;
|
// let current = ota.current_slot()?;
|
||||||
// println!(
|
// println!(
|
||||||
// "current image state {:?} (only relevant if the bootloader was built with auto-rollback support)",
|
// "current image state {:?} (only relevant if the bootloader was built with auto-rollback support)",
|
||||||
|
@@ -70,14 +70,12 @@ use eeprom24x::{Eeprom24x, SlaveAddr, Storage};
|
|||||||
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
|
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
|
||||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||||
use embassy_sync::blocking_mutex::CriticalSectionMutex;
|
use embassy_sync::blocking_mutex::CriticalSectionMutex;
|
||||||
use esp_bootloader_esp_idf::partitions::{
|
use esp_bootloader_esp_idf::partitions::{AppPartitionSubType, DataPartitionSubType, Error, FlashRegion, PartitionEntry};
|
||||||
AppPartitionSubType, DataPartitionSubType, FlashRegion, PartitionEntry,
|
|
||||||
};
|
|
||||||
use esp_hal::clock::CpuClock;
|
use esp_hal::clock::CpuClock;
|
||||||
use esp_hal::gpio::{Input, InputConfig, Pull};
|
use esp_hal::gpio::{Input, InputConfig, Pull};
|
||||||
use measurements::{Current, Voltage};
|
use measurements::{Current, Voltage};
|
||||||
|
|
||||||
use crate::fat_error::{FatError, FatResult};
|
use crate::fat_error::{ContextExt, FatError, FatResult};
|
||||||
use crate::hal::battery::{print_battery_bq34z100, BQ34Z100G1};
|
use crate::hal::battery::{print_battery_bq34z100, BQ34Z100G1};
|
||||||
use crate::hal::little_fs2storage_adapter::LittleFs2Filesystem;
|
use crate::hal::little_fs2storage_adapter::LittleFs2Filesystem;
|
||||||
use crate::hal::water::TankSensor;
|
use crate::hal::water::TankSensor;
|
||||||
@@ -87,6 +85,7 @@ use embassy_sync::once_lock::OnceLock;
|
|||||||
use esp_alloc as _;
|
use esp_alloc as _;
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
use esp_bootloader_esp_idf::ota::Slot;
|
use esp_bootloader_esp_idf::ota::Slot;
|
||||||
|
use esp_bootloader_esp_idf::ota::Slot::{Slot0, Slot1};
|
||||||
use esp_hal::delay::Delay;
|
use esp_hal::delay::Delay;
|
||||||
use esp_hal::i2c::master::{BusTimeout, Config, I2c};
|
use esp_hal::i2c::master::{BusTimeout, Config, I2c};
|
||||||
use esp_hal::pcnt::unit::Unit;
|
use esp_hal::pcnt::unit::Unit;
|
||||||
@@ -323,23 +322,23 @@ impl PlantHal {
|
|||||||
|
|
||||||
let mut ota = esp_bootloader_esp_idf::ota::Ota::new(ota_data)?;
|
let mut ota = esp_bootloader_esp_idf::ota::Ota::new(ota_data)?;
|
||||||
|
|
||||||
let ota_partition = match ota.current_slot()? {
|
let next_slot = ota.current_slot()?.next();
|
||||||
|
let ota_next = match next_slot {
|
||||||
Slot::None => {
|
Slot::None => {
|
||||||
panic!("No OTA slot active?");
|
panic!("No OTA slot active?");
|
||||||
}
|
}
|
||||||
Slot::Slot0 => pt
|
Slot::Slot0 => pt
|
||||||
.find_partition(esp_bootloader_esp_idf::partitions::PartitionType::App(
|
.find_partition(esp_bootloader_esp_idf::partitions::PartitionType::App(
|
||||||
AppPartitionSubType::Ota0,
|
AppPartitionSubType::Ota0,
|
||||||
))?
|
))?.context("Partition table invalid no ota0")?,
|
||||||
.expect("No OTA slot0 found"),
|
|
||||||
Slot::Slot1 => pt
|
Slot::Slot1 => pt
|
||||||
.find_partition(esp_bootloader_esp_idf::partitions::PartitionType::App(
|
.find_partition(esp_bootloader_esp_idf::partitions::PartitionType::App(
|
||||||
AppPartitionSubType::Ota1,
|
AppPartitionSubType::Ota1,
|
||||||
))?
|
))?.context("Partition table invalid no ota1")?
|
||||||
.expect("No OTA slot1 found"),
|
,
|
||||||
};
|
};
|
||||||
|
|
||||||
let ota_next = mk_static!(PartitionEntry, ota_partition);
|
let ota_next = mk_static!(PartitionEntry, ota_next);
|
||||||
let storage_ota = mk_static!(FlashStorage, FlashStorage::new());
|
let storage_ota = mk_static!(FlashStorage, FlashStorage::new());
|
||||||
let ota_next = mk_static!(
|
let ota_next = mk_static!(
|
||||||
FlashRegion<FlashStorage>,
|
FlashRegion<FlashStorage>,
|
||||||
@@ -388,7 +387,7 @@ impl PlantHal {
|
|||||||
boot_button,
|
boot_button,
|
||||||
wake_gpio1,
|
wake_gpio1,
|
||||||
ota,
|
ota,
|
||||||
ota_next,
|
ota_next
|
||||||
};
|
};
|
||||||
|
|
||||||
//init,reset rtc memory depending on cause
|
//init,reset rtc memory depending on cause
|
||||||
@@ -589,4 +588,4 @@ pub async fn esp_set_time(time: DateTime<FixedOffset>) -> FatResult<()> {
|
|||||||
.get_rtc_module()
|
.get_rtc_module()
|
||||||
.set_rtc_time(&time.to_utc())
|
.set_rtc_time(&time.to_utc())
|
||||||
.await
|
.await
|
||||||
}
|
}
|
@@ -6,6 +6,7 @@ mod get_json;
|
|||||||
mod get_log;
|
mod get_log;
|
||||||
mod get_static;
|
mod get_static;
|
||||||
mod post_json;
|
mod post_json;
|
||||||
|
mod ota;
|
||||||
|
|
||||||
use crate::fat_error::{FatError, FatResult};
|
use crate::fat_error::{FatError, FatResult};
|
||||||
use crate::webserver::backup_manager::{backup_config, backup_info, get_backup_config};
|
use crate::webserver::backup_manager::{backup_config, backup_info, get_backup_config};
|
||||||
@@ -36,7 +37,7 @@ use embassy_net::Stack;
|
|||||||
use embassy_time::Instant;
|
use embassy_time::Instant;
|
||||||
use embedded_io_async::{Read, Write};
|
use embedded_io_async::{Read, Write};
|
||||||
use log::info;
|
use log::info;
|
||||||
|
use crate::webserver::ota::ota_operations;
|
||||||
// fn ota(
|
// fn ota(
|
||||||
// request: &mut Request<&mut EspHttpConnection>,
|
// request: &mut Request<&mut EspHttpConnection>,
|
||||||
// ) -> Result<Option<std::string::String>, anyhow::Error> {
|
// ) -> Result<Option<std::string::String>, anyhow::Error> {
|
||||||
@@ -107,6 +108,8 @@ impl Handler for HTTPRequestRouter {
|
|||||||
let prefix = "/file?filename=";
|
let prefix = "/file?filename=";
|
||||||
let status = if path.starts_with(prefix) {
|
let status = if path.starts_with(prefix) {
|
||||||
file_operations(conn, method, &path, &prefix).await?
|
file_operations(conn, method, &path, &prefix).await?
|
||||||
|
} else if path == "/ota" {
|
||||||
|
ota_operations(conn,method).await?
|
||||||
} else {
|
} else {
|
||||||
match method {
|
match method {
|
||||||
Method::Get => match path {
|
Method::Get => match path {
|
||||||
|
76
rust/src/webserver/ota.rs
Normal file
76
rust/src/webserver/ota.rs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
use alloc::borrow::ToOwned;
|
||||||
|
use alloc::format;
|
||||||
|
use edge_http::io::server::Connection;
|
||||||
|
use edge_http::Method;
|
||||||
|
use embedded_io_async::{Read, Write};
|
||||||
|
use log::info;
|
||||||
|
use crate::BOARD_ACCESS;
|
||||||
|
use crate::fat_error::FatError;
|
||||||
|
|
||||||
|
pub(crate) async fn ota_operations<T, const N: usize>(
|
||||||
|
conn: &mut Connection<'_, T, { N }>,
|
||||||
|
method: Method
|
||||||
|
) -> Result<Option<u32>, FatError>
|
||||||
|
where
|
||||||
|
T: Read + Write,
|
||||||
|
{
|
||||||
|
Ok(match method {
|
||||||
|
Method::Options => {
|
||||||
|
conn.initiate_response(
|
||||||
|
200,
|
||||||
|
Some("OK"),
|
||||||
|
&[
|
||||||
|
("Access-Control-Allow-Origin", "*"),
|
||||||
|
("Access-Control-Allow-Headers", "*"),
|
||||||
|
("Access-Control-Allow-Methods", "*"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Some(200)
|
||||||
|
}
|
||||||
|
Method::Post => {
|
||||||
|
let mut offset = 0_usize;
|
||||||
|
let mut chunk = 0;
|
||||||
|
loop {
|
||||||
|
let mut buf = [0_u8; 1024];
|
||||||
|
let to_write = conn.read(&mut buf).await?;
|
||||||
|
if to_write == 0 {
|
||||||
|
info!("file request for ota finished");
|
||||||
|
let mut board = BOARD_ACCESS.get().await.lock().await;
|
||||||
|
board.board_hal.get_esp().finalize_ota().await?;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
let mut board = BOARD_ACCESS.get().await.lock().await;
|
||||||
|
board.board_hal.progress(chunk as u32).await;
|
||||||
|
board
|
||||||
|
.board_hal
|
||||||
|
.get_esp()
|
||||||
|
.write_ota(offset as u32, &buf[0..to_write])
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
offset = offset + to_write;
|
||||||
|
chunk = chunk + 1;
|
||||||
|
}
|
||||||
|
BOARD_ACCESS
|
||||||
|
.get()
|
||||||
|
.await
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.board_hal
|
||||||
|
.clear_progress()
|
||||||
|
.await;
|
||||||
|
conn.initiate_response(
|
||||||
|
200,
|
||||||
|
Some("OK"),
|
||||||
|
&[
|
||||||
|
("Access-Control-Allow-Origin", "*"),
|
||||||
|
("Access-Control-Allow-Headers", "*"),
|
||||||
|
("Access-Control-Allow-Methods", "*"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Some(200)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
}
|
Reference in New Issue
Block a user