eculocate

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit a932717f67c60a89ff669f98b7fe2756b39c44eb
parent 0f715179169652f3b8f73668af34f93129baeeec
Author: filipton <filipton12@gmail.com>
Date:   Fri,  5 Jul 2024 13:36:52 +0200

feat: ota verify flash (reading and crc'ing)

Diffstat:
MREADME.md | 12++++++++++--
Mexamples/src/main.rs | 10+++++++++-
Msimple-ota-server/firmware.bin | 0
Msrc/lib.rs | 37+++++++++++++++++++++++++++++++++++--
4 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md @@ -4,6 +4,12 @@ OTA for esp-hal (no-std). ## Limitations For now only works on esp32s3 (esp32c3 in the near future). +## Features +- Obviously OTA updates +- Dynamic partitions reading (so no macros, no reading from partitions.csv) - fully automatic +- Checking currently booted partition (using some pointer magic from ESP-IDF) +- CRC32 verification + ## Example This example uses embassy-net for TcpSocket, as you can see ota doesn't use async so you can easily use it with smoltcp. @@ -43,8 +49,10 @@ loop { } if res == Ok(true) { - _ = ota.ota_flush(); - // Here just reboot or sth! + if ota.ota_flush(true).is_ok() { + // Here just reboot or sth! + } + break; } } diff --git a/examples/src/main.rs b/examples/src/main.rs @@ -126,7 +126,15 @@ async fn main(spawner: Spawner) { } if res == Ok(true) { - _ = ota.ota_flush(); + let res = ota.ota_flush(false); + if let Err(e) = res { + log::error!("Ota flush error: {e:?}"); + break; + } + + log::info!("Ota OK! Rebooting in 1s!"); + Timer::after_millis(1000).await; + esp_hal::reset::software_reset(); break; } } diff --git a/simple-ota-server/firmware.bin b/simple-ota-server/firmware.bin Binary files differ. diff --git a/src/lib.rs b/src/lib.rs @@ -9,6 +9,7 @@ pub mod paddr; const PART_OFFSET: u32 = 0x8000; const PART_SIZE: u32 = 0xc00; const FIRST_OTA_PART_SUBTYPE: u8 = 0x10; +const OTA_VERIFY_READ_SIZE: usize = 256; #[derive(Clone)] pub struct FlashProgress { @@ -121,8 +122,15 @@ where Ok(progress.remaining == 0) } - // TODO: crc checks or sth - pub fn ota_flush(&mut self) -> Result<(), ()> { + /// verify - should it read flash and check crc + pub fn ota_flush(&mut self, verify: bool) -> Result<(), ()> { + if verify { + if !self.ota_verify()? { + log::error!("[OTA] Verify failed! Not flushing..."); + return Err(()); // verify error + } + } + let progress = self.progress.clone().ok_or_else(|| ())?; // add error like OtaNotStarted if progress.target_crc != progress.last_crc { log::warn!("[OTA] Calculated crc: {:?}", progress.last_crc); @@ -136,6 +144,31 @@ where Ok(()) } + /// It reads written flash and checks crc + pub fn ota_verify(&mut self) -> Result<bool, ()> { + let progress = self.progress.clone().ok_or_else(|| ())?; // add error like OtaNotStarted + let mut calc_crc = 0; + let mut bytes = [0; OTA_VERIFY_READ_SIZE]; + + let mut partition_offset = self.pinfo.ota_partitions[progress.target_partition].0; + let mut remaining = progress.flash_size; + + loop { + let n = remaining.min(OTA_VERIFY_READ_SIZE as u32); + if n == 0 { + break; + } + + _ = self.flash.read(partition_offset, &mut bytes[..n as usize]); + partition_offset += n; + remaining -= n; + + calc_crc = crc32::calc_crc32(&bytes[..n as usize], calc_crc); + } + + Ok(calc_crc == progress.target_crc) + } + /// Sets ota boot target partition pub fn set_target_ota_boot_partition(&mut self, target: usize) { let (seq1, seq2) = self.get_ota_boot_sequences();