11use 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.
452pub 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.
2382pub 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