Skip to content

Commit f111b38

Browse files
committed
Add RAM-backed MockFlash for tests
1 parent 3fddbf7 commit f111b38

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
}
@@ -379,3 +383,132 @@ where
379383
Ok(())
380384
}
381385
}
386+
387+
/// Simple RAM-backed flash storage implementation for tests
388+
#[derive(Clone, Copy, Debug)]
389+
pub struct MockFlash<
390+
const CAPACITY: usize,
391+
const READ_SIZE: usize = 1,
392+
const WRITE_SIZE: usize = 1,
393+
const ERASE_SIZE: usize = { 1 << 10 },
394+
const ERASE_BYTE: u8 = 0xff,
395+
const MULTI_WRITE: bool = false,
396+
> {
397+
data: [u8; CAPACITY],
398+
}
399+
400+
impl<
401+
const CAPACITY: usize,
402+
const READ_SIZE: usize,
403+
const WRITE_SIZE: usize,
404+
const ERASE_SIZE: usize,
405+
const ERASE_BYTE: u8,
406+
const MULTI_WRITE: bool,
407+
> Default for MockFlash<CAPACITY, READ_SIZE, WRITE_SIZE, ERASE_SIZE, ERASE_BYTE, MULTI_WRITE>
408+
{
409+
fn default() -> Self {
410+
Self {
411+
data: [ERASE_BYTE; CAPACITY],
412+
}
413+
}
414+
}
415+
416+
impl<
417+
const CAPACITY: usize,
418+
const READ_SIZE: usize,
419+
const WRITE_SIZE: usize,
420+
const ERASE_SIZE: usize,
421+
const ERASE_BYTE: u8,
422+
const MULTI_WRITE: bool,
423+
> core::ops::Deref
424+
for MockFlash<CAPACITY, READ_SIZE, WRITE_SIZE, ERASE_SIZE, ERASE_BYTE, MULTI_WRITE>
425+
{
426+
type Target = [u8; CAPACITY];
427+
428+
fn deref(&self) -> &Self::Target {
429+
&self.data
430+
}
431+
}
432+
433+
impl<
434+
const CAPACITY: usize,
435+
const READ_SIZE: usize,
436+
const WRITE_SIZE: usize,
437+
const ERASE_SIZE: usize,
438+
const ERASE_BYTE: u8,
439+
const MULTI_WRITE: bool,
440+
> core::ops::DerefMut
441+
for MockFlash<CAPACITY, READ_SIZE, WRITE_SIZE, ERASE_SIZE, ERASE_BYTE, MULTI_WRITE>
442+
{
443+
fn deref_mut(&mut self) -> &mut Self::Target {
444+
&mut self.data
445+
}
446+
}
447+
448+
impl<
449+
const CAPACITY: usize,
450+
const READ_SIZE: usize,
451+
const WRITE_SIZE: usize,
452+
const ERASE_SIZE: usize,
453+
const ERASE_BYTE: u8,
454+
const MULTI_WRITE: bool,
455+
> ErrorType for MockFlash<CAPACITY, READ_SIZE, WRITE_SIZE, ERASE_SIZE, ERASE_BYTE, MULTI_WRITE>
456+
{
457+
type Error = NorFlashErrorKind;
458+
}
459+
460+
impl<
461+
const CAPACITY: usize,
462+
const READ_SIZE: usize,
463+
const WRITE_SIZE: usize,
464+
const ERASE_SIZE: usize,
465+
const ERASE_BYTE: u8,
466+
const MULTI_WRITE: bool,
467+
> ReadNorFlash for MockFlash<CAPACITY, READ_SIZE, WRITE_SIZE, ERASE_SIZE, ERASE_BYTE, MULTI_WRITE>
468+
{
469+
const READ_SIZE: usize = READ_SIZE;
470+
471+
fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
472+
check_read(self, offset, bytes.len())?;
473+
bytes.copy_from_slice(&self.data[offset as usize..][..bytes.len()]);
474+
Ok(())
475+
}
476+
477+
fn capacity(&self) -> usize {
478+
CAPACITY
479+
}
480+
}
481+
482+
impl<
483+
const CAPACITY: usize,
484+
const READ_SIZE: usize,
485+
const WRITE_SIZE: usize,
486+
const ERASE_SIZE: usize,
487+
const ERASE_BYTE: u8,
488+
const MULTI_WRITE: bool,
489+
> NorFlash for MockFlash<CAPACITY, READ_SIZE, WRITE_SIZE, ERASE_SIZE, ERASE_BYTE, MULTI_WRITE>
490+
{
491+
const WRITE_SIZE: usize = WRITE_SIZE;
492+
const ERASE_SIZE: usize = ERASE_SIZE;
493+
494+
fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
495+
check_write(self, offset, bytes.len())?;
496+
for (dst, src) in self.data[offset as usize..].iter_mut().zip(bytes) {
497+
if !MULTI_WRITE && *dst != ERASE_BYTE {
498+
return Err(NorFlashErrorKind::DirtyWrite);
499+
}
500+
*dst &= *src;
501+
if *src != *dst {
502+
return Err(NorFlashErrorKind::DirtyWrite);
503+
}
504+
}
505+
Ok(())
506+
}
507+
508+
fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
509+
check_erase(self, from, to)?;
510+
self.data[from as usize..to as usize].fill(ERASE_BYTE);
511+
Ok(())
512+
}
513+
}
514+

0 commit comments

Comments
 (0)