Skip to main content

esp_nvs/
platform.rs

1use embedded_storage::nor_flash::NorFlash;
2
3/// See README.md for an example implementation.
4pub trait Platform: Crc + NorFlash {}
5
6impl<T: Crc + NorFlash> Platform for T {}
7
8pub type FnCrc32 = fn(init: u32, data: &[u8]) -> u32;
9
10pub trait Crc {
11    fn crc32(init: u32, data: &[u8]) -> u32;
12}
13
14impl<T: Crc> Crc for &mut T {
15    fn crc32(init: u32, data: &[u8]) -> u32 {
16        T::crc32(init, data)
17    }
18}
19
20/// Software CRC32 using the IEEE 802.3 polynomial (0xEDB88320).
21///
22/// This follows the zlib convention: the internal state is obtained by XOR-ing
23/// `init` with `0xFFFFFFFF` before processing, and the returned value is the
24/// internal state XOR-ed with `0xFFFFFFFF` after processing.
25///
26/// For a standard one-shot CRC32, pass `init = 0`.
27///
28/// For incremental/streaming use, pass the previous return value as `init`.
29///
30/// This function is compatible with `libz_sys::crc32` and the ESP-IDF ROM
31/// `crc32_le` function, and can be used to implement the [`Crc`] trait on
32/// host platforms without a C library dependency.
33pub fn software_crc32(init: u32, data: &[u8]) -> u32 {
34    let mut crc = init ^ 0xFFFFFFFF;
35
36    for &byte in data {
37        crc ^= byte as u32;
38        for _ in 0..8 {
39            if crc & 1 != 0 {
40                crc = (crc >> 1) ^ 0xEDB88320;
41            } else {
42                crc >>= 1;
43            }
44        }
45    }
46
47    crc ^ 0xFFFFFFFF
48}
49
50pub trait AlignedOps: Platform {
51    fn align_read(size: usize) -> usize {
52        align_ceil(size, Self::READ_SIZE)
53    }
54
55    fn align_write_ceil(size: usize) -> usize {
56        align_ceil(size, Self::WRITE_SIZE)
57    }
58
59    fn align_write_floor(size: usize) -> usize {
60        align_floor(size, Self::WRITE_SIZE)
61    }
62}
63
64#[inline(always)]
65const fn align_ceil(size: usize, alignment: usize) -> usize {
66    if size.is_power_of_two() {
67        size.saturating_add(alignment - 1) & !(alignment - 1)
68    } else {
69        size.saturating_add(alignment - 1) / alignment * alignment
70    }
71}
72
73#[inline(always)]
74const fn align_floor(size: usize, alignment: usize) -> usize {
75    if size.is_power_of_two() {
76        size & !(alignment - 1)
77    } else {
78        size / alignment * alignment
79    }
80}
81
82impl<T: Platform> AlignedOps for T {}
83
84#[cfg(any(
85    feature = "esp32",
86    feature = "esp32s2",
87    feature = "esp32s3",
88    feature = "esp32c2",
89    feature = "esp32c3",
90    feature = "esp32c6",
91    feature = "esp32h2",
92))]
93mod chip {
94    use esp_storage::FlashStorage;
95
96    use crate::platform::Crc;
97
98    impl Crc for FlashStorage<'_> {
99        fn crc32(init: u32, data: &[u8]) -> u32 {
100            esp_hal::rom::crc::crc32_le(init, data)
101        }
102    }
103}