1use crate::{iter::IterableByOverlaps, ReadStorage, Region, Storage};
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#[non_exhaustive]
30pub enum NorFlashErrorKind {
31 NotAligned,
33
34 OutOfBounds,
36
37 Other,
39}
40
41impl NorFlashError for NorFlashErrorKind {
42 fn kind(&self) -> NorFlashErrorKind {
43 *self
44 }
45}
46
47impl core::fmt::Display for NorFlashErrorKind {
48 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
49 match self {
50 Self::NotAligned => write!(f, "Arguments are not properly aligned"),
51 Self::OutOfBounds => write!(f, "Arguments are out of bounds"),
52 Self::Other => write!(f, "An implementation specific error occurred"),
53 }
54 }
55}
56
57pub trait ReadNorFlash: ErrorType {
59 const READ_SIZE: usize;
61
62 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error>;
70
71 fn capacity(&self) -> usize;
73}
74
75pub fn check_read<T: ReadNorFlash>(
77 flash: &T,
78 offset: u32,
79 length: usize,
80) -> Result<(), NorFlashErrorKind> {
81 check_slice(flash, T::READ_SIZE, offset, length)
82}
83
84pub trait NorFlash: ReadNorFlash {
86 const WRITE_SIZE: usize;
88
89 const ERASE_SIZE: usize;
91
92 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error>;
103
104 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error>;
113}
114
115pub fn check_erase<T: NorFlash>(flash: &T, from: u32, to: u32) -> Result<(), NorFlashErrorKind> {
117 let (from, to) = (from as usize, to as usize);
118 if from > to || to > flash.capacity() {
119 return Err(NorFlashErrorKind::OutOfBounds);
120 }
121 if from % T::ERASE_SIZE != 0 || to % T::ERASE_SIZE != 0 {
122 return Err(NorFlashErrorKind::NotAligned);
123 }
124 Ok(())
125}
126
127pub fn check_write<T: NorFlash>(
129 flash: &T,
130 offset: u32,
131 length: usize,
132) -> Result<(), NorFlashErrorKind> {
133 check_slice(flash, T::WRITE_SIZE, offset, length)
134}
135
136fn check_slice<T: ReadNorFlash>(
137 flash: &T,
138 align: usize,
139 offset: u32,
140 length: usize,
141) -> Result<(), NorFlashErrorKind> {
142 let offset = offset as usize;
143 if length > flash.capacity() || offset > flash.capacity() - length {
144 return Err(NorFlashErrorKind::OutOfBounds);
145 }
146 if offset % align != 0 || length % align != 0 {
147 return Err(NorFlashErrorKind::NotAligned);
148 }
149 Ok(())
150}
151
152impl<T: ErrorType> ErrorType for &mut T {
153 type Error = T::Error;
154}
155
156impl<T: ReadNorFlash> ReadNorFlash for &mut T {
157 const READ_SIZE: usize = T::READ_SIZE;
158
159 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
160 T::read(self, offset, bytes)
161 }
162
163 fn capacity(&self) -> usize {
164 T::capacity(self)
165 }
166}
167
168impl<T: NorFlash> NorFlash for &mut T {
169 const WRITE_SIZE: usize = T::WRITE_SIZE;
170 const ERASE_SIZE: usize = T::ERASE_SIZE;
171
172 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
173 T::erase(self, from, to)
174 }
175
176 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
177 T::write(self, offset, bytes)
178 }
179}
180
181pub trait MultiwriteNorFlash: NorFlash {}
192
193struct Page {
194 pub start: u32,
195 pub size: usize,
196}
197
198impl Page {
199 fn new(index: u32, size: usize) -> Self {
200 Self {
201 start: index * size as u32,
202 size,
203 }
204 }
205
206 const fn end(&self) -> u32 {
208 self.start + self.size as u32
209 }
210}
211
212impl Region for Page {
213 fn contains(&self, address: u32) -> bool {
215 (self.start <= address) && (self.end() > address)
216 }
217}
218
219pub struct RmwNorFlashStorage<'a, S> {
221 storage: S,
222 merge_buffer: &'a mut [u8],
223}
224
225impl<'a, S> RmwNorFlashStorage<'a, S>
226where
227 S: NorFlash,
228{
229 pub fn new(nor_flash: S, merge_buffer: &'a mut [u8]) -> Self {
234 if merge_buffer.len() < S::ERASE_SIZE {
235 panic!("Merge buffer is too small");
236 }
237
238 Self {
239 storage: nor_flash,
240 merge_buffer,
241 }
242 }
243}
244
245impl<'a, S> ReadStorage for RmwNorFlashStorage<'a, S>
246where
247 S: ReadNorFlash,
248{
249 type Error = S::Error;
250
251 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
252 self.storage.read(offset, bytes)
254 }
255
256 fn capacity(&self) -> usize {
257 self.storage.capacity()
258 }
259}
260
261impl<'a, S> Storage for RmwNorFlashStorage<'a, S>
262where
263 S: NorFlash,
264{
265 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
266 let last_page = self.storage.capacity() / S::ERASE_SIZE;
268
269 for (data, page, addr) in (0..last_page as u32)
272 .map(move |i| Page::new(i, S::ERASE_SIZE))
273 .overlaps(bytes, offset)
274 {
275 let offset_into_page = addr.saturating_sub(page.start) as usize;
276
277 self.storage
278 .read(page.start, &mut self.merge_buffer[..S::ERASE_SIZE])?;
279
280 self.storage.erase(page.start, page.end())?;
282 self.merge_buffer[..S::ERASE_SIZE]
283 .iter_mut()
284 .skip(offset_into_page)
285 .zip(data)
286 .for_each(|(byte, input)| *byte = *input);
287 self.storage
288 .write(page.start, &self.merge_buffer[..S::ERASE_SIZE])?;
289 }
290 Ok(())
291 }
292}
293
294pub struct RmwMultiwriteNorFlashStorage<'a, S> {
296 storage: S,
297 merge_buffer: &'a mut [u8],
298}
299
300impl<'a, S> RmwMultiwriteNorFlashStorage<'a, S>
301where
302 S: MultiwriteNorFlash,
303{
304 pub fn new(nor_flash: S, merge_buffer: &'a mut [u8]) -> Self {
309 if merge_buffer.len() < S::ERASE_SIZE {
310 panic!("Merge buffer is too small");
311 }
312
313 Self {
314 storage: nor_flash,
315 merge_buffer,
316 }
317 }
318}
319
320impl<'a, S> ReadStorage for RmwMultiwriteNorFlashStorage<'a, S>
321where
322 S: ReadNorFlash,
323{
324 type Error = S::Error;
325
326 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
327 self.storage.read(offset, bytes)
329 }
330
331 fn capacity(&self) -> usize {
332 self.storage.capacity()
333 }
334}
335
336impl<'a, S> Storage for RmwMultiwriteNorFlashStorage<'a, S>
337where
338 S: MultiwriteNorFlash,
339{
340 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
341 let last_page = self.storage.capacity() / S::ERASE_SIZE;
343
344 for (data, page, addr) in (0..last_page as u32)
347 .map(move |i| Page::new(i, S::ERASE_SIZE))
348 .overlaps(bytes, offset)
349 {
350 let offset_into_page = addr.saturating_sub(page.start) as usize;
351
352 self.storage
353 .read(page.start, &mut self.merge_buffer[..S::ERASE_SIZE])?;
354
355 let rhs = &self.merge_buffer[offset_into_page..S::ERASE_SIZE];
356 let is_subset = data.iter().zip(rhs.iter()).all(|(a, b)| *a & *b == *a);
357
358 if is_subset {
361 let offset = addr as usize % S::WRITE_SIZE;
363 let aligned_end = data.len() % S::WRITE_SIZE + offset + data.len();
364 self.merge_buffer[..aligned_end].fill(0xff);
365 self.merge_buffer[offset..offset + data.len()].copy_from_slice(data);
366 self.storage
367 .write(addr - offset as u32, &self.merge_buffer[..aligned_end])?;
368 } else {
369 self.storage.erase(page.start, page.end())?;
370 self.merge_buffer[..S::ERASE_SIZE]
371 .iter_mut()
372 .skip(offset_into_page)
373 .zip(data)
374 .for_each(|(byte, input)| *byte = *input);
375 self.storage
376 .write(page.start, &self.merge_buffer[..S::ERASE_SIZE])?;
377 }
378 }
379 Ok(())
380 }
381}