Skip to content

Commit 64a32f9

Browse files
committed
Add RAM-backed MockFlash for tests
1 parent 3e98f1c commit 64a32f9

File tree

1 file changed

+133
-0
lines changed

1 file changed

+133
-0
lines changed

src/nor_flash.rs

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ pub enum NorFlashErrorKind {
3434
/// The arguments are out of bounds.
3535
OutOfBounds,
3636

37+
/// The cell already was written or cannot be written properly with provided value
38+
DirtyWrite,
39+
3740
/// Error specific to the implementation.
3841
Other,
3942
}
@@ -49,6 +52,7 @@ impl core::fmt::Display for NorFlashErrorKind {
4952
match self {
5053
Self::NotAligned => write!(f, "Arguments are not properly aligned"),
5154
Self::OutOfBounds => write!(f, "Arguments are out of bounds"),
55+
Self::DirtyWrite => write!(f, "Dirty write operation"),
5256
Self::Other => write!(f, "An implementation specific error occurred"),
5357
}
5458
}
@@ -385,3 +389,132 @@ where
385389
Ok(())
386390
}
387391
}
392+
393+
/// Simple RAM-backed flash storage implementation for tests
394+
#[derive(Clone, Copy, Debug)]
395+
pub struct MockFlash<
396+
const CAPACITY: usize,
397+
const READ_SIZE: usize = 1,
398+
const WRITE_SIZE: usize = 1,
399+
const ERASE_SIZE: usize = { 1 << 10 },
400+
const ERASE_BYTE: u8 = 0xff,
401+
const MULTI_WRITE: bool = false,
402+
> {
403+
data: [u8; CAPACITY],
404+
}
405+
406+
impl<
407+
const CAPACITY: usize,
408+
const READ_SIZE: usize,
409+
const WRITE_SIZE: usize,
410+
const ERASE_SIZE: usize,
411+
const ERASE_BYTE: u8,
412+
const MULTI_WRITE: bool,
413+
> Default for MockFlash<CAPACITY, READ_SIZE, WRITE_SIZE, ERASE_SIZE, ERASE_BYTE, MULTI_WRITE>
414+
{
415+
fn default() -> Self {
416+
Self {
417+
data: [ERASE_BYTE; CAPACITY],
418+
}
419+
}
420+
}
421+
422+
impl<
423+
const CAPACITY: usize,
424+
const READ_SIZE: usize,
425+
const WRITE_SIZE: usize,
426+
const ERASE_SIZE: usize,
427+
const ERASE_BYTE: u8,
428+
const MULTI_WRITE: bool,
429+
> core::ops::Deref
430+
for MockFlash<CAPACITY, READ_SIZE, WRITE_SIZE, ERASE_SIZE, ERASE_BYTE, MULTI_WRITE>
431+
{
432+
type Target = [u8; CAPACITY];
433+
434+
fn deref(&self) -> &Self::Target {
435+
&self.data
436+
}
437+
}
438+
439+
impl<
440+
const CAPACITY: usize,
441+
const READ_SIZE: usize,
442+
const WRITE_SIZE: usize,
443+
const ERASE_SIZE: usize,
444+
const ERASE_BYTE: u8,
445+
const MULTI_WRITE: bool,
446+
> core::ops::DerefMut
447+
for MockFlash<CAPACITY, READ_SIZE, WRITE_SIZE, ERASE_SIZE, ERASE_BYTE, MULTI_WRITE>
448+
{
449+
fn deref_mut(&mut self) -> &mut Self::Target {
450+
&mut self.data
451+
}
452+
}
453+
454+
impl<
455+
const CAPACITY: usize,
456+
const READ_SIZE: usize,
457+
const WRITE_SIZE: usize,
458+
const ERASE_SIZE: usize,
459+
const ERASE_BYTE: u8,
460+
const MULTI_WRITE: bool,
461+
> ErrorType for MockFlash<CAPACITY, READ_SIZE, WRITE_SIZE, ERASE_SIZE, ERASE_BYTE, MULTI_WRITE>
462+
{
463+
type Error = NorFlashErrorKind;
464+
}
465+
466+
impl<
467+
const CAPACITY: usize,
468+
const READ_SIZE: usize,
469+
const WRITE_SIZE: usize,
470+
const ERASE_SIZE: usize,
471+
const ERASE_BYTE: u8,
472+
const MULTI_WRITE: bool,
473+
> ReadNorFlash for MockFlash<CAPACITY, READ_SIZE, WRITE_SIZE, ERASE_SIZE, ERASE_BYTE, MULTI_WRITE>
474+
{
475+
const READ_SIZE: usize = READ_SIZE;
476+
477+
fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
478+
check_read(self, offset, bytes.len())?;
479+
bytes.copy_from_slice(&self.data[offset as usize..][..bytes.len()]);
480+
Ok(())
481+
}
482+
483+
fn capacity(&self) -> usize {
484+
CAPACITY
485+
}
486+
}
487+
488+
impl<
489+
const CAPACITY: usize,
490+
const READ_SIZE: usize,
491+
const WRITE_SIZE: usize,
492+
const ERASE_SIZE: usize,
493+
const ERASE_BYTE: u8,
494+
const MULTI_WRITE: bool,
495+
> NorFlash for MockFlash<CAPACITY, READ_SIZE, WRITE_SIZE, ERASE_SIZE, ERASE_BYTE, MULTI_WRITE>
496+
{
497+
const WRITE_SIZE: usize = WRITE_SIZE;
498+
const ERASE_SIZE: usize = ERASE_SIZE;
499+
const ERASE_BYTE: u8 = ERASE_BYTE;
500+
501+
fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
502+
check_write(self, offset, bytes.len())?;
503+
for (dst, src) in self.data[offset as usize..].iter_mut().zip(bytes) {
504+
if !MULTI_WRITE && *dst != ERASE_BYTE {
505+
return Err(NorFlashErrorKind::DirtyWrite);
506+
}
507+
*dst &= *src;
508+
if *src != *dst {
509+
return Err(NorFlashErrorKind::DirtyWrite);
510+
}
511+
}
512+
Ok(())
513+
}
514+
515+
fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
516+
check_erase(self, from, to)?;
517+
self.data[from as usize..to as usize].fill(ERASE_BYTE);
518+
Ok(())
519+
}
520+
}

0 commit comments

Comments
 (0)