1use embedded_storage::Region;
2use embedded_storage::iter::IterableByOverlaps;
3pub use embedded_storage::nor_flash::{ErrorType, NorFlashError, NorFlashErrorKind};
4
5use crate::{ReadStorage, Storage};
6
7pub trait ReadNorFlash: ErrorType {
9 const READ_SIZE: usize;
11
12 async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error>;
20
21 fn capacity(&self) -> usize;
23}
24
25pub trait NorFlash: ReadNorFlash {
27 const WRITE_SIZE: usize;
29
30 const ERASE_SIZE: usize;
32
33 async fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error>;
46
47 async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error>;
56}
57
58impl<T: ReadNorFlash> ReadNorFlash for &mut T {
59 const READ_SIZE: usize = T::READ_SIZE;
60
61 async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
62 T::read(self, offset, bytes).await
63 }
64
65 fn capacity(&self) -> usize {
66 T::capacity(self)
67 }
68}
69
70impl<T: NorFlash> NorFlash for &mut T {
71 const WRITE_SIZE: usize = T::WRITE_SIZE;
72 const ERASE_SIZE: usize = T::ERASE_SIZE;
73
74 async fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
75 T::erase(self, from, to).await
76 }
77
78 async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
79 T::write(self, offset, bytes).await
80 }
81}
82
83pub trait MultiwriteNorFlash: NorFlash {}
94impl<T: MultiwriteNorFlash> MultiwriteNorFlash for &mut T {}
95
96struct Page {
97 pub start: u32,
98 pub size: usize,
99}
100
101impl Page {
102 fn new(index: u32, size: usize) -> Self {
103 Self {
104 start: index * size as u32,
105 size,
106 }
107 }
108
109 const fn end(&self) -> u32 {
111 self.start + self.size as u32
112 }
113}
114
115impl Region for Page {
116 fn contains(&self, address: u32) -> bool {
118 (self.start <= address) && (self.end() > address)
119 }
120}
121
122#[derive(Debug)]
124pub struct RmwNorFlashStorage<'a, S> {
125 storage: S,
126 merge_buffer: &'a mut [u8],
127}
128
129impl<'a, S> RmwNorFlashStorage<'a, S>
130where
131 S: NorFlash,
132{
133 pub fn new(nor_flash: S, merge_buffer: &'a mut [u8]) -> Self {
138 if merge_buffer.len() < S::ERASE_SIZE {
139 panic!("Merge buffer is too small");
140 }
141
142 Self {
143 storage: nor_flash,
144 merge_buffer,
145 }
146 }
147
148 pub fn into_inner(self) -> S {
150 self.storage
151 }
152}
153
154impl<'a, S> ReadStorage for RmwNorFlashStorage<'a, S>
155where
156 S: ReadNorFlash,
157{
158 type Error = S::Error;
159
160 async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
161 self.storage.read(offset, bytes).await
163 }
164
165 fn capacity(&self) -> usize {
166 self.storage.capacity()
167 }
168}
169
170impl<'a, S> Storage for RmwNorFlashStorage<'a, S>
171where
172 S: NorFlash,
173{
174 async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
175 let last_page = self.storage.capacity() / S::ERASE_SIZE;
177
178 for (data, page, addr) in (0..last_page as u32)
181 .map(move |i| Page::new(i, S::ERASE_SIZE))
182 .overlaps(bytes, offset)
183 {
184 let offset_into_page = addr.saturating_sub(page.start) as usize;
185
186 self.storage
187 .read(page.start, &mut self.merge_buffer[..S::ERASE_SIZE])
188 .await?;
189
190 self.storage.erase(page.start, page.end()).await?;
192 self.merge_buffer[..S::ERASE_SIZE]
193 .iter_mut()
194 .skip(offset_into_page)
195 .zip(data)
196 .for_each(|(byte, input)| *byte = *input);
197 self.storage
198 .write(page.start, &self.merge_buffer[..S::ERASE_SIZE])
199 .await?;
200 }
201 Ok(())
202 }
203}
204
205pub struct RmwMultiwriteNorFlashStorage<'a, S> {
207 storage: S,
208 merge_buffer: &'a mut [u8],
209}
210
211impl<'a, S> RmwMultiwriteNorFlashStorage<'a, S>
212where
213 S: MultiwriteNorFlash,
214{
215 pub fn new(nor_flash: S, merge_buffer: &'a mut [u8]) -> Self {
220 if merge_buffer.len() < S::ERASE_SIZE {
221 panic!("Merge buffer is too small");
222 }
223
224 Self {
225 storage: nor_flash,
226 merge_buffer,
227 }
228 }
229
230 pub fn into_inner(self) -> S {
232 self.storage
233 }
234}
235
236impl<'a, S> ReadStorage for RmwMultiwriteNorFlashStorage<'a, S>
237where
238 S: ReadNorFlash,
239{
240 type Error = S::Error;
241
242 async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
243 self.storage.read(offset, bytes).await
245 }
246
247 fn capacity(&self) -> usize {
248 self.storage.capacity()
249 }
250}
251
252impl<'a, S> Storage for RmwMultiwriteNorFlashStorage<'a, S>
253where
254 S: MultiwriteNorFlash,
255{
256 async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
257 let last_page = self.storage.capacity() / S::ERASE_SIZE;
259
260 for (data, page, addr) in (0..last_page as u32)
263 .map(move |i| Page::new(i, S::ERASE_SIZE))
264 .overlaps(bytes, offset)
265 {
266 let offset_into_page = addr.saturating_sub(page.start) as usize;
267
268 self.storage
269 .read(page.start, &mut self.merge_buffer[..S::ERASE_SIZE])
270 .await?;
271
272 let rhs = &self.merge_buffer[offset_into_page..S::ERASE_SIZE];
273 let is_subset = data.iter().zip(rhs.iter()).all(|(a, b)| *a & *b == *a);
274
275 if is_subset {
278 let offset = addr as usize % S::WRITE_SIZE;
280 let aligned_end = data.len() % S::WRITE_SIZE + offset + data.len();
281 self.merge_buffer[..aligned_end].fill(0xff);
282 self.merge_buffer[offset..offset + data.len()].copy_from_slice(data);
283 self.storage
284 .write(addr - offset as u32, &self.merge_buffer[..aligned_end])
285 .await?;
286 } else {
287 self.storage.erase(page.start, page.end()).await?;
288 self.merge_buffer[..S::ERASE_SIZE]
289 .iter_mut()
290 .skip(offset_into_page)
291 .zip(data)
292 .for_each(|(byte, input)| *byte = *input);
293 self.storage
294 .write(page.start, &self.merge_buffer[..S::ERASE_SIZE])
295 .await?;
296 }
297 }
298 Ok(())
299 }
300}