1#[cfg(feature = "bytewise-read")]
2use crate::buffer::FlashWordBuffer;
3use crate::{
4 FlashStorage,
5 FlashStorageError,
6 buffer::{FlashSectorBuffer, uninit_slice, uninit_slice_mut},
7};
8
9impl FlashStorage<'_> {
10 #[cfg(not(feature = "bytewise-read"))]
11 pub const READ_SIZE: usize = Self::WORD_SIZE as _;
13
14 #[cfg(feature = "bytewise-read")]
15 pub const READ_SIZE: usize = 1;
17
18 pub const WRITE_SIZE: usize = Self::WORD_SIZE as _;
20
21 pub const ERASE_SIZE: usize = Self::SECTOR_SIZE as _;
23
24 #[inline(always)]
25 fn is_word_aligned(bytes: &[u8]) -> bool {
26 (bytes.as_ptr() as usize).is_multiple_of(Self::WORD_SIZE as usize)
28 }
29
30 pub fn read_nor(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), FlashStorageError> {
49 const RS: u32 = FlashStorage::READ_SIZE as u32;
50 self.check_alignment::<{ RS }>(offset, bytes.len())?;
51 self.check_bounds(offset, bytes.len())?;
52
53 #[cfg(feature = "bytewise-read")]
54 let (offset, bytes) = {
55 let byte_offset = (offset % Self::WORD_SIZE) as usize;
56 if byte_offset > 0 {
57 let mut word_buffer = FlashWordBuffer::uninit();
58
59 let offset = offset - byte_offset as u32;
60 let length = bytes.len().min(Self::WORD_SIZE as usize - byte_offset);
61
62 self.internal_read(offset, word_buffer.as_bytes_mut())?;
63 let word_buffer = unsafe { word_buffer.assume_init_bytes_mut() };
64 bytes[..length].copy_from_slice(&word_buffer[byte_offset..][..length]);
65
66 (offset + Self::WORD_SIZE, &mut bytes[length..])
67 } else {
68 (offset, bytes)
69 }
70 };
71
72 if Self::is_word_aligned(bytes) {
73 for (offset, chunk) in (offset..)
75 .step_by(Self::SECTOR_SIZE as _)
76 .zip(bytes.chunks_mut(Self::SECTOR_SIZE as _))
77 {
78 #[cfg(not(feature = "bytewise-read"))]
80 self.internal_read(offset, uninit_slice_mut(chunk))?;
81
82 #[cfg(feature = "bytewise-read")]
83 {
84 let length = chunk.len();
85 let byte_length = length % Self::WORD_SIZE as usize;
86 let length = length - byte_length;
87
88 self.internal_read(offset, &mut uninit_slice_mut(chunk)[..length])?;
89
90 if byte_length > 0 {
92 let mut word_buffer = FlashWordBuffer::uninit();
93
94 self.internal_read(offset + length as u32, word_buffer.as_bytes_mut())?;
95 let word_buffer = unsafe { word_buffer.assume_init_bytes_mut() };
96 chunk[length..].copy_from_slice(&word_buffer[..byte_length]);
97 }
98 }
99 }
100 } else {
101 let mut buffer = FlashSectorBuffer::uninit();
103
104 for (offset, chunk) in (offset..)
105 .step_by(Self::SECTOR_SIZE as _)
106 .zip(bytes.chunks_mut(Self::SECTOR_SIZE as _))
107 {
108 #[cfg(not(feature = "bytewise-read"))]
110 self.internal_read(offset, &mut buffer.as_bytes_mut()[..chunk.len()])?;
111
112 #[cfg(feature = "bytewise-read")]
114 {
115 let length = chunk.len();
116 let byte_length = length % Self::WORD_SIZE as usize;
117 let length = if byte_length > 0 {
118 length - byte_length + Self::WORD_SIZE as usize
119 } else {
120 length
121 };
122
123 self.internal_read(offset, &mut buffer.as_bytes_mut()[..length])?;
124 }
125 let buffer = unsafe { buffer.assume_init_bytes() };
126
127 chunk.copy_from_slice(&buffer[..chunk.len()]);
129 }
130 }
131
132 Ok(())
133 }
134
135 pub fn write_nor(&mut self, offset: u32, bytes: &[u8]) -> Result<(), FlashStorageError> {
160 const WS: u32 = FlashStorage::WORD_SIZE;
161 self.check_alignment::<{ WS }>(offset, bytes.len())?;
162 self.check_bounds(offset, bytes.len())?;
163
164 if Self::is_word_aligned(bytes) {
165 for (offset, chunk) in (offset..)
167 .step_by(Self::SECTOR_SIZE as _)
168 .zip(bytes.chunks(Self::SECTOR_SIZE as _))
169 {
170 self.internal_write(offset, chunk)?;
172 }
173 } else {
174 let mut buffer = FlashSectorBuffer::uninit();
176
177 for (offset, chunk) in (offset..)
178 .step_by(Self::SECTOR_SIZE as _)
179 .zip(bytes.chunks(Self::SECTOR_SIZE as _))
180 {
181 buffer.as_bytes_mut()[..chunk.len()].copy_from_slice(uninit_slice(chunk));
183 self.internal_write(offset, unsafe {
185 &buffer.assume_init_bytes()[..chunk.len()]
186 })?;
187 }
188 }
189
190 Ok(())
191 }
192
193 pub fn erase(&mut self, from: u32, to: u32) -> Result<(), FlashStorageError> {
207 if to < from {
208 return Err(FlashStorageError::OutOfBounds);
209 }
210
211 let len = (to - from) as _;
212 const SZ: u32 = FlashStorage::SECTOR_SIZE;
213 self.check_alignment::<{ SZ }>(from, len)?;
214 self.check_bounds(from, len)?;
215
216 let mut address = from;
218 while address < to && !address.is_multiple_of(Self::BLOCK_SIZE) {
219 self.internal_erase_sector(address / Self::SECTOR_SIZE)?;
220 address += Self::SECTOR_SIZE;
221 }
222
223 while (to - address) >= Self::BLOCK_SIZE {
225 self.internal_erase_block(address / Self::BLOCK_SIZE)?;
226 address += Self::BLOCK_SIZE;
227 }
228
229 while address < to {
231 self.internal_erase_sector(address / Self::SECTOR_SIZE)?;
232 address += Self::SECTOR_SIZE;
233 }
234
235 Ok(())
236 }
237}
238
239#[cfg(feature = "embedded-storage")]
240mod embedded_storage_traits {
241 use ::embedded_storage::nor_flash::{
242 ErrorType,
243 MultiwriteNorFlash,
244 NorFlash,
245 NorFlashError,
246 NorFlashErrorKind,
247 ReadNorFlash,
248 };
249
250 use super::*;
251
252 impl NorFlashError for FlashStorageError {
253 fn kind(&self) -> NorFlashErrorKind {
254 match self {
255 FlashStorageError::NotAligned => NorFlashErrorKind::NotAligned,
256 FlashStorageError::OutOfBounds => NorFlashErrorKind::OutOfBounds,
257 _ => NorFlashErrorKind::Other,
258 }
259 }
260 }
261
262 impl ErrorType for FlashStorage<'_> {
263 type Error = FlashStorageError;
264 }
265
266 impl ReadNorFlash for FlashStorage<'_> {
267 const READ_SIZE: usize = FlashStorage::READ_SIZE;
268
269 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
270 FlashStorage::read_nor(self, offset, bytes)
271 }
272
273 fn capacity(&self) -> usize {
274 FlashStorage::capacity(self)
275 }
276 }
277
278 impl NorFlash for FlashStorage<'_> {
279 const WRITE_SIZE: usize = FlashStorage::WRITE_SIZE;
280 const ERASE_SIZE: usize = FlashStorage::ERASE_SIZE;
281
282 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
283 FlashStorage::write_nor(self, offset, bytes)
284 }
285
286 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
287 FlashStorage::erase(self, from, to)
288 }
289 }
290
291 impl MultiwriteNorFlash for FlashStorage<'_> {}
292}
293
294#[cfg(test)]
296mod tests {
297 use super::*;
298 use crate::common::Flash;
299
300 const WORD_SIZE: u32 = 4;
301 const SECTOR_SIZE: u32 = 4 << 10;
302 const BLOCK_SIZE: u32 = 4 << 14;
303 const NUM_BLOCKS: u32 = 3;
304 const FLASH_SIZE: u32 = BLOCK_SIZE * NUM_BLOCKS;
305 const MAX_OFFSET: u32 = SECTOR_SIZE * 1;
306 const MAX_LENGTH: u32 = SECTOR_SIZE * 2;
307
308 #[repr(C, align(4))]
309 struct TestBuffer {
310 data: [u8; FLASH_SIZE as _],
311 }
312
313 impl TestBuffer {
314 const fn seq() -> Self {
315 let mut data = [0u8; FLASH_SIZE as _];
316 let mut index = 0;
317 while index < FLASH_SIZE {
318 data[index as usize] = (index & 0xff) as u8;
319 index += 1;
320 }
321 Self { data }
322 }
323 }
324
325 impl Default for TestBuffer {
326 fn default() -> Self {
327 Self {
328 data: [0u8; FLASH_SIZE as usize],
329 }
330 }
331 }
332
333 #[cfg(not(miri))]
334 fn range_gen<const ALIGN: u32, const MAX_OFF: u32, const MAX_LEN: u32>(
335 aligned: Option<bool>,
336 ) -> impl Iterator<Item = (u32, u32)> {
337 (0..=MAX_OFF).flat_map(move |off| {
338 (0..=MAX_LEN - off)
339 .filter(move |len| {
340 aligned
341 .map(|aligned| aligned == (off % ALIGN == 0 && len % ALIGN == 0))
342 .unwrap_or(true)
343 })
344 .map(move |len| (off, len))
345 })
346 }
347
348 #[cfg(miri)]
349 fn range_gen<const ALIGN: u32, const MAX_OFF: u32, const MAX_LEN: u32>(
350 aligned: Option<bool>,
351 ) -> impl Iterator<Item = (u32, u32)> {
352 match aligned {
354 Some(true) => vec![(0, 4), (0, 8), (0, 16), (0, 32), (0, 1024)],
355 Some(false) => vec![(3, 7), (11, 11)],
356 None => vec![
357 (0, 4),
358 (0, 8),
359 (0, 16),
360 (0, 32),
361 (0, 1024),
362 (3, 7),
363 (11, 11),
364 (0, 4098),
365 ],
366 }
367 .into_iter()
368 }
369
370 #[test]
371 #[cfg(not(feature = "bytewise-read"))]
372 fn aligned_read() {
373 let mut flash = FlashStorage::new(Flash::new());
374 flash.capacity = FLASH_SIZE as usize;
375 let src = TestBuffer::seq();
376 let mut data = TestBuffer::default();
377
378 flash.erase(0, FLASH_SIZE).unwrap();
379 flash.write_nor(0, &src.data).unwrap();
380
381 for (off, len) in range_gen::<WORD_SIZE, MAX_OFFSET, MAX_LENGTH>(Some(true)) {
382 flash.read_nor(off, &mut data.data[..len as usize]).unwrap();
383 assert_eq!(
384 data.data[..len as usize],
385 src.data[off as usize..][..len as usize]
386 );
387 }
388 }
389
390 #[test]
391 #[cfg(not(feature = "bytewise-read"))]
392 fn not_aligned_read_aligned_buffer() {
393 let mut flash = FlashStorage::new(Flash::new());
394 flash.capacity = FLASH_SIZE as usize;
395 let mut data = TestBuffer::default();
396
397 for (off, len) in range_gen::<WORD_SIZE, MAX_OFFSET, MAX_LENGTH>(Some(false)) {
398 flash
399 .read_nor(off, &mut data.data[..len as usize])
400 .unwrap_err();
401 }
402 }
403
404 #[test]
405 #[cfg(not(feature = "bytewise-read"))]
406 fn aligned_read_not_aligned_buffer() {
407 let mut flash = FlashStorage::new(Flash::new());
408 flash.capacity = FLASH_SIZE as usize;
409 let src = TestBuffer::seq();
410 let mut data = TestBuffer::default();
411
412 flash.erase(0, FLASH_SIZE).unwrap();
413 flash.write_nor(0, &src.data).unwrap();
414
415 for (off, len) in range_gen::<WORD_SIZE, MAX_OFFSET, MAX_LENGTH>(Some(true)) {
416 flash
417 .read_nor(off, &mut data.data[1..][..len as usize])
418 .unwrap();
419 assert_eq!(
420 data.data[1..][..len as usize],
421 src.data[off as usize..][..len as usize]
422 );
423 }
424 }
425
426 #[test]
427 #[cfg(feature = "bytewise-read")]
428 fn bytewise_read_aligned_buffer() {
429 let mut flash = FlashStorage::new(Flash::new());
430
431 flash.capacity = FLASH_SIZE as usize;
432 let src = TestBuffer::seq();
433 let mut data = TestBuffer::default();
434
435 flash.erase(0, FLASH_SIZE).unwrap();
436 flash.write_nor(0, &src.data).unwrap();
437
438 for (off, len) in range_gen::<WORD_SIZE, MAX_OFFSET, MAX_LENGTH>(None) {
439 flash.read_nor(off, &mut data.data[..len as usize]).unwrap();
440 assert_eq!(
441 data.data[..len as usize],
442 src.data[off as usize..][..len as usize]
443 );
444 }
445 }
446
447 #[test]
448 #[cfg(feature = "bytewise-read")]
449 fn bytewise_read_not_aligned_buffer() {
450 let mut flash = FlashStorage::new(Flash::new());
451
452 flash.capacity = FLASH_SIZE as usize;
453 let src = TestBuffer::seq();
454 let mut data = TestBuffer::default();
455
456 flash.erase(0, FLASH_SIZE).unwrap();
457 flash.write_nor(0, &src.data).unwrap();
458
459 for (off, len) in range_gen::<WORD_SIZE, MAX_OFFSET, MAX_LENGTH>(None) {
460 flash
461 .read_nor(off, &mut data.data[1..][..len as usize])
462 .unwrap();
463 assert_eq!(
464 data.data[1..][..len as usize],
465 src.data[off as usize..][..len as usize]
466 );
467 }
468 }
469
470 #[test]
471 fn write_not_aligned_buffer() {
472 let mut flash = FlashStorage::new(Flash::new());
473 flash.capacity = FLASH_SIZE as usize;
474 let mut read_data = TestBuffer::default();
475 let write_data = TestBuffer::seq();
476
477 flash.erase(0, FLASH_SIZE).unwrap();
478 flash.write_nor(0, &write_data.data[1..129]).unwrap();
479
480 flash.read_nor(0, &mut read_data.data[..128]).unwrap();
481
482 assert_eq!(&read_data.data[..128], &write_data.data[1..129]);
483 }
484
485 #[test]
486 fn erase_up_to_end_of_flash() {
487 let mut flash = FlashStorage::new(Flash::new());
488 flash.capacity = FLASH_SIZE as usize;
489 let mut read_data = TestBuffer::default();
490 let write_data = [0u8; SECTOR_SIZE as usize];
491
492 flash.erase(FLASH_SIZE - BLOCK_SIZE, FLASH_SIZE).unwrap();
493 flash
494 .write_nor(FLASH_SIZE - 2 * SECTOR_SIZE, &write_data)
495 .unwrap();
496 flash
497 .write_nor(FLASH_SIZE - SECTOR_SIZE, &write_data)
498 .unwrap();
499
500 flash.erase(FLASH_SIZE - SECTOR_SIZE, FLASH_SIZE).unwrap();
502
503 flash
504 .read(
505 FLASH_SIZE - 2 * SECTOR_SIZE,
506 &mut read_data.data[..(2 * SECTOR_SIZE) as usize],
507 )
508 .unwrap();
509 assert!(
510 read_data.data[..SECTOR_SIZE as usize]
511 .iter()
512 .all(|v| *v == 0x0)
513 );
514 assert!(
515 read_data.data[SECTOR_SIZE as usize..(2 * SECTOR_SIZE) as usize]
516 .iter()
517 .all(|v| *v == 0xFF)
518 );
519
520 flash.erase(FLASH_SIZE - BLOCK_SIZE, FLASH_SIZE).unwrap();
522
523 flash
524 .read(
525 FLASH_SIZE - 2 * SECTOR_SIZE,
526 &mut read_data.data[..(2 * SECTOR_SIZE) as usize],
527 )
528 .unwrap();
529 assert!(
530 read_data.data[..(2 * SECTOR_SIZE) as usize]
531 .iter()
532 .all(|v| *v == 0xFF)
533 );
534 }
535
536 #[test]
537 fn erase_reversed_range_is_rejected() {
538 let mut flash = FlashStorage::new(Flash::new());
539 flash.capacity = FLASH_SIZE as usize;
540
541 assert_eq!(
542 flash.erase(SECTOR_SIZE, 0),
543 Err(FlashStorageError::OutOfBounds)
544 );
545 }
546
547 #[test]
548 fn erase_across_blocks() {
549 let mut flash = FlashStorage::new(Flash::new());
550 flash.capacity = FLASH_SIZE as usize;
551 let mut read_data = TestBuffer::default();
552 let write_data = [0u8; SECTOR_SIZE as usize];
553
554 let from = BLOCK_SIZE - (2 * SECTOR_SIZE);
556 let to = (2 * BLOCK_SIZE) + (1 * SECTOR_SIZE);
557
558 flash.erase(from - SECTOR_SIZE, from).unwrap();
560 flash.write_nor(from - SECTOR_SIZE, &write_data).unwrap();
561 flash.erase(to, to + SECTOR_SIZE).unwrap();
562 flash.write_nor(to, &write_data).unwrap();
563
564 flash.erase(from, to).unwrap();
566 flash.read(0, &mut read_data.data).unwrap();
567 for i in from..to {
568 assert_eq!(read_data.data[i as usize], 0xFF);
569 }
570 assert_eq!(read_data.data[(from - 1) as usize], 0x0);
571 assert_eq!(read_data.data[to as usize], 0x0);
572 }
573}