1
1
use crate :: { iter:: IterableByOverlaps , ReadStorage , Region , Storage } ;
2
2
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
+
3
51
/// Read only NOR flash trait.
4
52
pub trait ReadNorFlash {
5
- /// An enumeration of storage errors
6
- type Error ;
53
+ /// Errors returned by this NOR flash.
54
+ type Error : NorFlashError ;
7
55
8
56
/// The minumum number of bytes the storage peripheral can read
9
57
const READ_SIZE : usize ;
10
58
11
59
/// Read a slice of data from the storage peripheral, starting the read
12
60
/// operation at the given address offset, and reading `bytes.len()` bytes.
13
61
///
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.
16
66
fn read ( & mut self , offset : u32 , bytes : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > ;
17
67
18
68
/// The capacity of the peripheral in bytes.
19
69
fn capacity ( & self ) -> usize ;
20
70
}
21
71
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
+
22
81
/// NOR flash trait.
23
82
pub trait NorFlash : ReadNorFlash {
24
83
/// The minumum number of bytes the storage peripheral can write
@@ -30,19 +89,63 @@ pub trait NorFlash: ReadNorFlash {
30
89
/// Erase the given storage range, clearing all data within `[from..to]`.
31
90
/// The given range will contain all 1s afterwards.
32
91
///
33
- /// This should return an error if the range is not aligned to a proper
34
- /// erase resolution
35
92
/// 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.
37
99
fn erase ( & mut self , from : u32 , to : u32 ) -> Result < ( ) , Self :: Error > ;
38
100
39
101
/// If power is lost during write, the contents of the written words are undefined,
40
102
/// but the rest of the page is guaranteed to be unchanged.
41
103
/// 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.
43
109
fn write ( & mut self , offset : u32 , bytes : & [ u8 ] ) -> Result < ( ) , Self :: Error > ;
44
110
}
45
111
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
+
46
149
/// Marker trait for NorFlash relaxing the restrictions on `write`.
47
150
///
48
151
/// Writes to the same word twice are now allowed. The result is the logical AND of the
0 commit comments