Skip to content

Commit 16025cd

Browse files
committed
Nest ReadNorFlash::Error in NorFlash
1 parent c391eda commit 16025cd

File tree

2 files changed

+114
-8
lines changed

2 files changed

+114
-8
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
77

88
## Unreleased
99

10+
- Require Nor flashes error types to be convertible to generic errors.
11+
- Provide helper functions for Nor flashes to check for generic errors.
12+
1013
## [0.2.0] - 2021-09-15
1114

1215
- Removed `try_` prefix from all trait methods.

src/nor_flash.rs

Lines changed: 111 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,83 @@
11
use crate::{iter::IterableByOverlaps, ReadStorage, Region, Storage};
22

3+
/// NOR flash errors.
4+
///
5+
/// NOR flash implementations must use an error type implementing this trait. This permits generic
6+
/// code to extract a generic error kind.
7+
pub trait NorFlashError: core::fmt::Debug {
8+
/// Convert a specific NOR flash error into a generic error kind.
9+
fn kind(&self) -> NorFlashErrorKind;
10+
}
11+
12+
impl NorFlashError for core::convert::Infallible {
13+
fn kind(&self) -> NorFlashErrorKind {
14+
match *self {}
15+
}
16+
}
17+
18+
/// NOR flash error kinds.
19+
///
20+
/// NOR flash implementations must map their error to those generic error kinds through the
21+
/// [`NorFlashError`] trait.
22+
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
23+
#[non_exhaustive]
24+
pub enum NorFlashErrorKind {
25+
/// The arguments are not properly aligned.
26+
NotAligned,
27+
28+
/// The arguments are out of bounds.
29+
OutOfBounds,
30+
31+
/// Error specific to the implementation.
32+
Other,
33+
}
34+
35+
impl NorFlashError for NorFlashErrorKind {
36+
fn kind(&self) -> NorFlashErrorKind {
37+
*self
38+
}
39+
}
40+
41+
impl core::fmt::Display for NorFlashErrorKind {
42+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
43+
match self {
44+
Self::NotAligned => write!(f, "Arguments are not properly aligned"),
45+
Self::OutOfBounds => write!(f, "Arguments are out of bounds"),
46+
Self::Other => write!(f, "An implementation specific error occurred"),
47+
}
48+
}
49+
}
50+
351
/// Read only NOR flash trait.
452
pub trait ReadNorFlash {
5-
/// An enumeration of storage errors
6-
type Error;
53+
/// Errors returned by this NOR flash.
54+
type Error: NorFlashError;
755

856
/// The minumum number of bytes the storage peripheral can read
957
const READ_SIZE: usize;
1058

1159
/// Read a slice of data from the storage peripheral, starting the read
1260
/// operation at the given address offset, and reading `bytes.len()` bytes.
1361
///
14-
/// This should throw an error in case `bytes.len()` will be larger than
15-
/// the peripheral end address.
62+
/// # Errors
63+
///
64+
/// Returns an error if the arguments are not aligned or out of bounds. The implementation
65+
/// can use the [`check_read`] helper function.
1666
fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error>;
1767

1868
/// The capacity of the peripheral in bytes.
1969
fn capacity(&self) -> usize;
2070
}
2171

72+
/// Return whether a read operation is within bounds.
73+
pub fn check_read<T: ReadNorFlash>(
74+
flash: &T,
75+
offset: u32,
76+
length: usize,
77+
) -> Result<(), NorFlashErrorKind> {
78+
check_slice(flash, T::READ_SIZE, offset, length)
79+
}
80+
2281
/// NOR flash trait.
2382
pub trait NorFlash: ReadNorFlash {
2483
/// The minumum number of bytes the storage peripheral can write
@@ -30,19 +89,63 @@ pub trait NorFlash: ReadNorFlash {
3089
/// Erase the given storage range, clearing all data within `[from..to]`.
3190
/// The given range will contain all 1s afterwards.
3291
///
33-
/// This should return an error if the range is not aligned to a proper
34-
/// erase resolution
3592
/// If power is lost during erase, contents of the page are undefined.
36-
/// `from` and `to` must both be multiples of `ERASE_SIZE` and `from` <= `to`.
93+
///
94+
/// # Errors
95+
///
96+
/// Returns an error if the arguments are not aligned or out of bounds (the case where `to >
97+
/// from` is considered out of bounds). The implementation can use the [`check_erase`]
98+
/// helper function.
3799
fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error>;
38100

39101
/// If power is lost during write, the contents of the written words are undefined,
40102
/// but the rest of the page is guaranteed to be unchanged.
41103
/// It is not allowed to write to the same word twice.
42-
/// `offset` and `bytes.len()` must both be multiples of `WRITE_SIZE`.
104+
///
105+
/// # Errors
106+
///
107+
/// Returns an error if the arguments are not aligned or out of bounds. The implementation
108+
/// can use the [`check_write`] helper function.
43109
fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error>;
44110
}
45111

112+
/// Return whether an erase operation is aligned and within bounds.
113+
pub fn check_erase<T: NorFlash>(flash: &T, from: u32, to: u32) -> Result<(), NorFlashErrorKind> {
114+
let (from, to) = (from as usize, to as usize);
115+
if from > to || to > flash.capacity() {
116+
return Err(NorFlashErrorKind::OutOfBounds);
117+
}
118+
if from % T::ERASE_SIZE != 0 || to % T::ERASE_SIZE != 0 {
119+
return Err(NorFlashErrorKind::NotAligned);
120+
}
121+
Ok(())
122+
}
123+
124+
/// Return whether a write operation is aligned and within bounds.
125+
pub fn check_write<T: NorFlash>(
126+
flash: &T,
127+
offset: u32,
128+
length: usize,
129+
) -> Result<(), NorFlashErrorKind> {
130+
check_slice(flash, T::WRITE_SIZE, offset, length)
131+
}
132+
133+
fn check_slice<T: ReadNorFlash>(
134+
flash: &T,
135+
align: usize,
136+
offset: u32,
137+
length: usize,
138+
) -> Result<(), NorFlashErrorKind> {
139+
let offset = offset as usize;
140+
if length > flash.capacity() || offset > flash.capacity() - length {
141+
return Err(NorFlashErrorKind::OutOfBounds);
142+
}
143+
if offset % align != 0 || length % align != 0 {
144+
return Err(NorFlashErrorKind::NotAligned);
145+
}
146+
Ok(())
147+
}
148+
46149
/// Marker trait for NorFlash relaxing the restrictions on `write`.
47150
///
48151
/// Writes to the same word twice are now allowed. The result is the logical AND of the

0 commit comments

Comments
 (0)