1use crate::{ReadStorage, Region, Storage, iter::IterableByOverlaps};
2
3pub trait NorFlashError: core::fmt::Debug {
8 fn kind(&self) -> NorFlashErrorKind;
10}
11
12impl NorFlashError for core::convert::Infallible {
13 fn kind(&self) -> NorFlashErrorKind {
14 match *self {}
15 }
16}
17
18pub trait ErrorType {
20 type Error: NorFlashError;
22}
23
24#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
29#[cfg_attr(feature = "defmt", derive(defmt::Format))]
30#[non_exhaustive]
31pub enum NorFlashErrorKind {
32 NotAligned,
34
35 OutOfBounds,
37
38 Other,
40}
41
42impl NorFlashError for NorFlashErrorKind {
43 fn kind(&self) -> NorFlashErrorKind {
44 *self
45 }
46}
47
48impl core::fmt::Display for NorFlashErrorKind {
49 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
50 match self {
51 Self::NotAligned => write!(f, "Arguments are not properly aligned"),
52 Self::OutOfBounds => write!(f, "Arguments are out of bounds"),
53 Self::Other => write!(f, "An implementation specific error occurred"),
54 }
55 }
56}
57
58pub trait ReadNorFlash: ErrorType {
60 const READ_SIZE: usize;
62
63 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error>;
71
72 fn capacity(&self) -> usize;
74}
75
76pub fn check_read<T: ReadNorFlash>(
78 flash: &T,
79 offset: u32,
80 length: usize,
81) -> Result<(), NorFlashErrorKind> {
82 check_slice(flash, T::READ_SIZE, offset, length)
83}
84
85pub trait NorFlash: ReadNorFlash {
87 const WRITE_SIZE: usize;
89
90 const ERASE_SIZE: usize;
92
93 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error>;
106
107 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error>;
116}
117
118pub fn check_erase<T: NorFlash>(flash: &T, from: u32, to: u32) -> Result<(), NorFlashErrorKind> {
120 let (from, to) = (from as usize, to as usize);
121 if from > to || to > flash.capacity() {
122 return Err(NorFlashErrorKind::OutOfBounds);
123 }
124 if from % T::ERASE_SIZE != 0 || to % T::ERASE_SIZE != 0 {
125 return Err(NorFlashErrorKind::NotAligned);
126 }
127 Ok(())
128}
129
130pub fn check_write<T: NorFlash>(
132 flash: &T,
133 offset: u32,
134 length: usize,
135) -> Result<(), NorFlashErrorKind> {
136 check_slice(flash, T::WRITE_SIZE, offset, length)
137}
138
139fn check_slice<T: ReadNorFlash>(
140 flash: &T,
141 align: usize,
142 offset: u32,
143 length: usize,
144) -> Result<(), NorFlashErrorKind> {
145 let offset = offset as usize;
146 if length > flash.capacity() || offset > flash.capacity() - length {
147 return Err(NorFlashErrorKind::OutOfBounds);
148 }
149 if !offset.is_multiple_of(align) || !length.is_multiple_of(align) {
150 return Err(NorFlashErrorKind::NotAligned);
151 }
152 Ok(())
153}
154
155impl<T: ErrorType> ErrorType for &mut T {
156 type Error = T::Error;
157}
158
159impl<T: ReadNorFlash> ReadNorFlash for &mut T {
160 const READ_SIZE: usize = T::READ_SIZE;
161
162 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
163 T::read(self, offset, bytes)
164 }
165
166 fn capacity(&self) -> usize {
167 T::capacity(self)
168 }
169}
170
171impl<T: NorFlash> NorFlash for &mut T {
172 const WRITE_SIZE: usize = T::WRITE_SIZE;
173 const ERASE_SIZE: usize = T::ERASE_SIZE;
174
175 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
176 T::erase(self, from, to)
177 }
178
179 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
180 T::write(self, offset, bytes)
181 }
182}
183
184pub trait MultiwriteNorFlash: NorFlash {}
195impl<T: MultiwriteNorFlash> MultiwriteNorFlash for &mut T {}
196
197struct Page {
198 pub start: u32,
199 pub size: usize,
200}
201
202impl Page {
203 fn new(index: u32, size: usize) -> Self {
204 Self {
205 start: index * size as u32,
206 size,
207 }
208 }
209
210 const fn end(&self) -> u32 {
212 self.start + self.size as u32
213 }
214}
215
216impl Region for Page {
217 fn contains(&self, address: u32) -> bool {
219 (self.start <= address) && (self.end() > address)
220 }
221}
222
223pub struct RmwNorFlashStorage<'a, S> {
225 storage: S,
226 merge_buffer: &'a mut [u8],
227}
228
229impl<'a, S> RmwNorFlashStorage<'a, S>
230where
231 S: NorFlash,
232{
233 pub fn new(nor_flash: S, merge_buffer: &'a mut [u8]) -> Self {
238 if merge_buffer.len() < S::ERASE_SIZE {
239 panic!("Merge buffer is too small");
240 }
241
242 Self {
243 storage: nor_flash,
244 merge_buffer,
245 }
246 }
247
248 pub fn into_inner(self) -> S {
250 self.storage
251 }
252}
253
254impl<'a, S> ReadStorage for RmwNorFlashStorage<'a, S>
255where
256 S: ReadNorFlash,
257{
258 type Error = S::Error;
259
260 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
261 self.storage.read(offset, bytes)
263 }
264
265 fn capacity(&self) -> usize {
266 self.storage.capacity()
267 }
268}
269
270impl<'a, S> Storage for RmwNorFlashStorage<'a, S>
271where
272 S: NorFlash,
273{
274 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
275 let last_page = self.storage.capacity() / S::ERASE_SIZE;
277
278 for (data, page, addr) in (0..last_page as u32)
281 .map(move |i| Page::new(i, S::ERASE_SIZE))
282 .overlaps(bytes, offset)
283 {
284 let offset_into_page = addr.saturating_sub(page.start) as usize;
285
286 self.storage
287 .read(page.start, &mut self.merge_buffer[..S::ERASE_SIZE])?;
288
289 self.storage.erase(page.start, page.end())?;
291 self.merge_buffer[..S::ERASE_SIZE]
292 .iter_mut()
293 .skip(offset_into_page)
294 .zip(data)
295 .for_each(|(byte, input)| *byte = *input);
296 self.storage
297 .write(page.start, &self.merge_buffer[..S::ERASE_SIZE])?;
298 }
299 Ok(())
300 }
301}
302
303pub struct RmwMultiwriteNorFlashStorage<'a, S> {
305 storage: S,
306 merge_buffer: &'a mut [u8],
307}
308
309impl<'a, S> RmwMultiwriteNorFlashStorage<'a, S>
310where
311 S: MultiwriteNorFlash,
312{
313 pub fn new(nor_flash: S, merge_buffer: &'a mut [u8]) -> Self {
318 if merge_buffer.len() < S::ERASE_SIZE {
319 panic!("Merge buffer is too small");
320 }
321
322 Self {
323 storage: nor_flash,
324 merge_buffer,
325 }
326 }
327
328 pub fn into_inner(self) -> S {
330 self.storage
331 }
332}
333
334impl<'a, S> ReadStorage for RmwMultiwriteNorFlashStorage<'a, S>
335where
336 S: ReadNorFlash,
337{
338 type Error = S::Error;
339
340 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
341 self.storage.read(offset, bytes)
343 }
344
345 fn capacity(&self) -> usize {
346 self.storage.capacity()
347 }
348}
349
350impl<'a, S> Storage for RmwMultiwriteNorFlashStorage<'a, S>
351where
352 S: MultiwriteNorFlash,
353{
354 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
355 let last_page = self.storage.capacity() / S::ERASE_SIZE;
357
358 for (data, page, addr) in (0..last_page as u32)
361 .map(move |i| Page::new(i, S::ERASE_SIZE))
362 .overlaps(bytes, offset)
363 {
364 let offset_into_page = addr.saturating_sub(page.start) as usize;
365
366 self.storage
367 .read(page.start, &mut self.merge_buffer[..S::ERASE_SIZE])?;
368
369 let rhs = &self.merge_buffer[offset_into_page..S::ERASE_SIZE];
370 let is_subset = data.iter().zip(rhs.iter()).all(|(a, b)| *a & *b == *a);
371
372 if is_subset {
375 let offset = addr as usize % S::WRITE_SIZE;
377 let aligned_end = data.len() % S::WRITE_SIZE + offset + data.len();
378 self.merge_buffer[..aligned_end].fill(0xff);
379 self.merge_buffer[offset..offset + data.len()].copy_from_slice(data);
380 self.storage
381 .write(addr - offset as u32, &self.merge_buffer[..aligned_end])?;
382 } else {
383 self.storage.erase(page.start, page.end())?;
384 self.merge_buffer[..S::ERASE_SIZE]
385 .iter_mut()
386 .skip(offset_into_page)
387 .zip(data)
388 .for_each(|(byte, input)| *byte = *input);
389 self.storage
390 .write(page.start, &self.merge_buffer[..S::ERASE_SIZE])?;
391 }
392 }
393 Ok(())
394 }
395}