commit 83ce1812642615252403701fdf8e6e06db487606
parent 0979e2137d25cfdb6a39d1abe884154d825dedea
Author: filipton <filipton12@gmail.com>
Date: Sat, 7 Sep 2024 17:32:22 +0200
feat: better slots (ota entries) reading
chore: structs cleanup (own file)
Diffstat:
| M | src/helpers.rs | | | 15 | +++++++++++++++ |
| M | src/lib.rs | | | 56 | +++++++++++++++----------------------------------------- |
| A | src/structs.rs | | | 61 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 91 insertions(+), 41 deletions(-)
diff --git a/src/helpers.rs b/src/helpers.rs
@@ -16,3 +16,18 @@ pub fn seq_or_default(seq: &[u8], crc: u32, default: u32) -> u32 {
default
}
+
+#[inline(always)]
+/// Helper function!
+/// Check if crc is correct for given seq
+pub fn is_crc_seq_correct(seq: u32, crc: u32) -> bool {
+ let bytes = unsafe {
+ let mut buf = [0; 4]; //u32
+ core::ptr::copy_nonoverlapping(&seq as *const u32 as *const u8, buf.as_mut_ptr(), 4);
+
+ buf
+ };
+
+ let crc_calc = crate::crc32::calc_crc32(&bytes, 0xFFFFFFFF);
+ crc == crc_calc
+}
diff --git a/src/lib.rs b/src/lib.rs
@@ -7,49 +7,18 @@
compile_error!("You need to select at least one target: \"esp32c3\", \"esp32s2\", \"esp32s3\".");
use embedded_storage::{ReadStorage, Storage};
+pub use structs::*;
pub mod crc32;
pub mod helpers;
pub mod paddr;
+pub mod structs;
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(Debug, PartialEq)]
-pub enum OtaError {
- NotEnoughPartitions,
- OtaNotStarted,
- FlashRWError,
- WrongCRC,
- WrongOTAPArtitionOrder,
- OtaVerifyError,
- NoNextOtaPartition,
-}
-
-type Result<T> = core::result::Result<T, OtaError>;
-
-#[derive(Clone)]
-pub struct FlashProgress {
- last_crc: u32,
- flash_offset: u32,
- flash_size: u32,
- remaining: u32,
-
- target_partition: usize,
- target_crc: u32,
-}
-
-#[derive(Debug)]
-pub struct PartitionInfo {
- ota_partitions: [(u32, u32); 16],
- ota_partitions_count: usize,
-
- otadata_offset: u32,
- otadata_size: u32,
-}
-
// NOTE: I need to use generics, because after adding esp-storage dependency to
// this project its not compiling LULE
pub struct Ota<S>
@@ -212,7 +181,8 @@ where
/// Sets ota boot target partition
pub fn set_target_ota_boot_partition(&mut self, target: usize) {
- let (seq1, seq2) = self.get_ota_boot_sequences();
+ let (slot1, slot2) = self.get_ota_boot_entries();
+ let (seq1, seq2) = (slot1.seq, slot2.seq);
let mut target_seq = seq1.max(seq2);
while helpers::seq_to_part(target_seq, self.pinfo.ota_partitions_count) != target
@@ -240,21 +210,25 @@ where
/// Returns current OTA boot sequences
///
/// NOTE: if crc doesn't match, it returns 0 for that seq
- pub fn get_ota_boot_sequences(&mut self) -> (u32, u32) {
+ /// NOTE: [Entry struct (link to .h file)](https://github.com/espressif/esp-idf/blob/master/components/bootloader_support/include/esp_flash_partitions.h#L66)
+ pub fn get_ota_boot_entries(&mut self) -> (EspOtaSelectEntry, EspOtaSelectEntry) {
let mut bytes = [0; 32];
-
_ = self.flash.read(self.pinfo.otadata_offset, &mut bytes);
- let crc1 = u32::from_le_bytes(bytes[(32 - 4)..32].try_into().unwrap());
- let seq1 = helpers::seq_or_default(&bytes[..4], crc1, 0);
+ let mut slot1: EspOtaSelectEntry =
+ unsafe { core::ptr::read(bytes.as_ptr() as *const EspOtaSelectEntry) };
+ slot1.check_crc();
+ log::info!("read slot1: {slot1:?}");
_ = self.flash.read(
self.pinfo.otadata_offset + (self.pinfo.otadata_size >> 1),
&mut bytes,
);
- let crc2 = u32::from_le_bytes(bytes[(32 - 4)..32].try_into().unwrap());
- let seq2 = helpers::seq_or_default(&bytes[..4], crc2, 0);
+ let mut slot2: EspOtaSelectEntry =
+ unsafe { core::ptr::read(bytes.as_ptr() as *const EspOtaSelectEntry) };
+ slot2.check_crc();
+ log::info!("read slot2: {slot2:?}");
- (seq1, seq2)
+ (slot1, slot2)
}
/// Returns currently booted partition index
diff --git a/src/structs.rs b/src/structs.rs
@@ -0,0 +1,61 @@
+pub(crate) type Result<T> = core::result::Result<T, OtaError>;
+
+#[derive(Debug, PartialEq)]
+pub enum OtaError {
+ NotEnoughPartitions,
+ OtaNotStarted,
+ FlashRWError,
+ WrongCRC,
+ WrongOTAPArtitionOrder,
+ OtaVerifyError,
+ NoNextOtaPartition,
+}
+
+#[derive(Clone)]
+pub struct FlashProgress {
+ pub last_crc: u32,
+ pub flash_offset: u32,
+ pub flash_size: u32,
+ pub remaining: u32,
+
+ pub target_partition: usize,
+ pub target_crc: u32,
+}
+
+#[derive(Debug)]
+pub struct PartitionInfo {
+ pub ota_partitions: [(u32, u32); 16],
+ pub ota_partitions_count: usize,
+
+ pub otadata_offset: u32,
+ pub otadata_size: u32,
+}
+
+#[repr(u32)]
+#[derive(Debug)]
+pub enum OtaImgState {
+ EspOtaImgNew = 0x0,
+ EspOtaImgPendingVerify = 0x1,
+ EspOtaImgValid = 0x2,
+ EspOtaImgInvalid = 0x3,
+ EspOtaImgAborted = 0x4,
+ EspOtaImgUndefined = 0xFFFFFFFF,
+}
+
+#[repr(C)]
+#[derive(Debug)]
+pub struct EspOtaSelectEntry {
+ pub seq: u32,
+ pub seq_label: [u8; 20],
+ pub ota_state: OtaImgState,
+ pub crc: u32,
+}
+
+impl EspOtaSelectEntry {
+ /// Check if crc(of seq) is correct, if not - its setting seq to 0
+ pub fn check_crc(&mut self) {
+ if !crate::helpers::is_crc_seq_correct(self.seq, self.crc) {
+ self.seq = 0; // set seq to 0 if crc not correct!
+ }
+ }
+}