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
14pub trait AlignedOps: Platform {
15    fn align_read(size: usize) -> usize {
16        align_ceil(size, Self::READ_SIZE)
17    }
18
19    fn align_write_ceil(size: usize) -> usize {
20        align_ceil(size, Self::WRITE_SIZE)
21    }
22
23    fn align_write_floor(size: usize) -> usize {
24        align_floor(size, Self::WRITE_SIZE)
25    }
26}
27
28#[inline(always)]
29const fn align_ceil(size: usize, alignment: usize) -> usize {
30    if size.is_power_of_two() {
31        size.saturating_add(alignment - 1) & !(alignment - 1)
32    } else {
33        size.saturating_add(alignment - 1) / alignment * alignment
34    }
35}
36
37#[inline(always)]
38const fn align_floor(size: usize, alignment: usize) -> usize {
39    if size.is_power_of_two() {
40        size & !(alignment - 1)
41    } else {
42        size / alignment * alignment
43    }
44}
45
46impl<T: Platform> AlignedOps for T {}
47
48#[cfg(any(
49    feature = "esp32",
50    feature = "esp32s2",
51    feature = "esp32s3",
52    feature = "esp32c2",
53    feature = "esp32c3",
54    feature = "esp32c6",
55    feature = "esp32h2",
56))]
57mod chip {
58    use crate::platform::Crc;
59    use embedded_storage::nor_flash::{ErrorType, NorFlash};
60    use esp_storage::{FlashStorage, FlashStorageError};
61
62    pub struct EspFlash<'d> {
63        inner: FlashStorage<'d>,
64    }
65
66    impl<'d> EspFlash<'d> {
67        pub fn new(inner: FlashStorage<'d>) -> Self {
68            Self { inner }
69        }
70    }
71
72    impl ErrorType for EspFlash<'_> {
73        type Error = FlashStorageError;
74    }
75
76    impl NorFlash for EspFlash<'_> {
77        const WRITE_SIZE: usize = FlashStorage::WRITE_SIZE;
78        const ERASE_SIZE: usize = FlashStorage::ERASE_SIZE;
79
80        fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
81            // info!("erase: from {:x}: to {:x}", from, to);
82            self.inner.erase(from, to)
83        }
84
85        fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
86            // info!("write: offset {:x}: bytes {}", offset, bytes.len());
87            self.inner.write(offset, bytes)
88        }
89    }
90
91    impl embedded_storage::nor_flash::ReadNorFlash for EspFlash<'_> {
92        const READ_SIZE: usize = FlashStorage::READ_SIZE;
93
94        fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
95            // info!("read: offset {:x}: bytes {}", offset, bytes.len());
96            self.inner.read(offset, bytes)
97        }
98
99        fn capacity(&self) -> usize {
100            self.inner.capacity()
101        }
102    }
103
104    impl Crc for EspFlash<'_> {
105        fn crc32(init: u32, data: &[u8]) -> u32 {
106            esp_hal::rom::crc::crc32_le(init, data)
107        }
108    }
109    impl Crc for &mut EspFlash<'_> {
110        fn crc32(init: u32, data: &[u8]) -> u32 {
111            esp_hal::rom::crc::crc32_le(init, data)
112        }
113    }
114}
115
116#[cfg(any(
117    feature = "esp32",
118    feature = "esp32s2",
119    feature = "esp32s3",
120    feature = "esp32c2",
121    feature = "esp32c3",
122    feature = "esp32c6",
123    feature = "esp32h2",
124))]
125pub use chip::*;