1
- use crate :: { iter :: IterableByOverlaps , ReadStorage , Region , Storage } ;
1
+ use crate :: { ReadStorage , Region , Storage , iter :: { IterableByOverlaps , OverlapIterator } } ;
2
2
3
3
/// Read only NOR flash trait.
4
4
pub trait ReadNorFlash {
@@ -77,117 +77,143 @@ impl Page {
77
77
}
78
78
79
79
impl Region for Page {
80
+ /// Checks if an address offset is contained within the page
80
81
fn contains ( & self , address : u32 ) -> bool {
81
82
( self . start <= address) && ( self . end ( ) > address)
82
83
}
83
84
}
84
85
85
86
///
86
- pub struct RmwNorFlashStorage < S > ( S ) ;
87
+ pub struct RmwNorFlashStorage < ' a , S > {
88
+ storage : S ,
89
+ merge_buffer : & ' a mut [ u8 ]
90
+ }
87
91
88
- impl < S > RmwNorFlashStorage < S > {
92
+ impl < ' a , S > RmwNorFlashStorage < ' a , S >
93
+ where
94
+ S : NorFlash ,
95
+ {
89
96
/// Instantiate a new generic `Storage` from a `NorFlash` peripheral
90
- pub fn new ( nor_flash : S ) -> Self {
91
- Self ( nor_flash)
97
+ ///
98
+ /// **NOTE** This will panic if the provided merge buffer,
99
+ /// is smaller than the erase size of the flash peripheral
100
+ pub fn new ( nor_flash : S , merge_buffer : & ' a mut [ u8 ] ) -> Self {
101
+ if merge_buffer. len ( ) < S :: ERASE_SIZE {
102
+ panic ! ( "Merge buffer is too small" ) ;
103
+ }
104
+
105
+ Self {
106
+ storage : nor_flash,
107
+ merge_buffer
108
+ }
92
109
}
93
110
}
94
111
95
- impl < S > ReadStorage for RmwNorFlashStorage < S >
112
+ impl < ' a , S > ReadStorage for RmwNorFlashStorage < ' a , S >
96
113
where
97
114
S : ReadNorFlash ,
98
115
{
99
116
type Error = S :: Error ;
100
117
101
118
fn try_read ( & mut self , address : u32 , bytes : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > {
102
119
// Nothing special to be done for reads
103
- self . 0 . try_read ( address, bytes)
120
+ self . storage . try_read ( address, bytes)
104
121
}
105
122
106
123
fn capacity ( & self ) -> usize {
107
- self . 0 . capacity ( )
124
+ self . storage . capacity ( )
108
125
}
109
126
}
110
127
111
- impl < S > Storage for RmwNorFlashStorage < S >
128
+ impl < ' a , S > Storage for RmwNorFlashStorage < ' a , S >
112
129
where
113
130
S : NorFlash ,
114
- // [u8; S::ERASE_SIZE]: Sized,
115
131
{
116
132
fn try_write ( & mut self , address : u32 , bytes : & [ u8 ] ) -> Result < ( ) , Self :: Error > {
117
133
// Perform read/modify/write operations on the byte slice.
118
- let last_page = ( self . 0 . capacity ( ) / S :: ERASE_SIZE ) - 1 ;
134
+ let last_page = ( self . storage . capacity ( ) / S :: ERASE_SIZE ) - 1 ;
119
135
120
136
// `data` is the part of `bytes` contained within `page`,
121
137
// and `addr` in the address offset of `page` + any offset into the page as requested by `address`
122
138
for ( data, page, addr) in ( 0 ..last_page as u32 )
123
139
. map ( move |i| Page :: new ( i, S :: ERASE_SIZE ) )
124
140
. overlaps ( bytes, address)
125
141
{
126
- let merge_buffer = & mut [ 0u8 ; 2048 ] ;
127
142
let offset_into_page = addr. saturating_sub ( page. start ) as usize ;
128
143
129
- self . try_read ( page. start , merge_buffer) ?;
144
+ self . storage . try_read ( page. start , self . merge_buffer ) ?;
130
145
131
146
// If we cannot write multiple times to the same page, we will have to erase it
132
- self . 0 . try_erase ( page. start , page. end ( ) ) ?;
133
- merge_buffer
147
+ self . storage . try_erase ( page. start , page. end ( ) ) ?;
148
+ self . merge_buffer
134
149
. iter_mut ( )
135
150
. skip ( offset_into_page)
136
151
. zip ( data)
137
152
. for_each ( |( byte, input) | * byte = * input) ;
138
- self . 0 . try_write ( page. start , merge_buffer) ?;
153
+ self . storage . try_write ( page. start , self . merge_buffer ) ?;
139
154
}
140
155
Ok ( ( ) )
141
156
}
142
157
}
143
158
144
- // FIXME: Requires specialization to take advantage of MultiwriteNorFlash?
145
- // impl<S: MultiwriteNorFlash> Storage for RmwNorFlashStorage<S> {
146
- // type Error = S::Error;
147
-
148
- // fn try_read(&mut self, address: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
149
- // // Nothing special to be done for reads
150
- // self.0.try_read(address, bytes)
151
- // }
152
-
153
- // fn try_write(&mut self, address: u32, bytes: &[u8]) -> Result<(), Self::Error> {
154
- // // Perform read/modify/write operations on the byte slice.
155
- // let erase_size = self.0.erase_size();
156
- // let last_page = (self.0.capacity() / erase_size) - 1;
157
-
158
- // // `data` is the part of `bytes` contained within `page`,
159
- // // and `addr` in the address offset of `page` + any offset into the page as requested by `address`
160
- // for (data, page, addr) in (0..last_page)
161
- // .map(move |i| Page::new(i, erase_size))
162
- // .overlaps(bytes, address)
163
- // {
164
- // let merge_buffer = &mut [0u8; MAX_PAGE_SIZE][0..erase_size as usize];
165
- // let offset_into_page = addr.saturating_sub(page.start) as usize;
166
-
167
- // self.try_read(page.start, merge_buffer)?;
168
-
169
- // let rhs = &merge_buffer[offset_into_page..];
170
- // let is_subset =
171
- // data.len() < rhs.len() && data.iter().zip(rhs.iter()).all(|(a, b)| (*a | *b) == *b);
172
-
173
- // // Check if we can write the data block directly, under the limitations imposed by NorFlash:
174
- // // - We can only change 1's to 0's
175
- // if is_subset {
176
- // self.0.try_write(addr, data)?;
177
- // } else {
178
- // self.0.try_erase(page.start, page.end())?;
179
- // merge_buffer
180
- // .iter_mut()
181
- // .skip(offset_into_page)
182
- // .zip(data)
183
- // .for_each(|(byte, input)| *byte = *input);
184
- // self.0.try_write(page.start, merge_buffer)?;
185
- // }
186
- // }
187
- // Ok(())
188
- // }
189
-
190
- // fn capacity(&self) -> u32 {
191
- // self.0.capacity()
192
- // }
193
- // }
159
+ ///
160
+ pub struct RmwMultiwriteNorFlashStorage < ' a , S > {
161
+ storage : S ,
162
+ merge_buffer : & ' a mut [ u8 ]
163
+ }
164
+
165
+ impl < ' a , S > ReadStorage for RmwMultiwriteNorFlashStorage < ' a , S >
166
+ where
167
+ S : ReadNorFlash ,
168
+ {
169
+ type Error = S :: Error ;
170
+
171
+ fn try_read ( & mut self , address : u32 , bytes : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > {
172
+ // Nothing special to be done for reads
173
+ self . storage . try_read ( address, bytes)
174
+ }
175
+
176
+ fn capacity ( & self ) -> usize {
177
+ self . storage . capacity ( )
178
+ }
179
+ }
180
+
181
+ impl < ' a , S > Storage for RmwMultiwriteNorFlashStorage < ' a , S >
182
+ where
183
+ S : NorFlash ,
184
+ {
185
+ fn try_write ( & mut self , address : u32 , bytes : & [ u8 ] ) -> Result < ( ) , Self :: Error > {
186
+ // Perform read/modify/write operations on the byte slice.
187
+ let last_page = ( self . storage . capacity ( ) / S :: ERASE_SIZE ) - 1 ;
188
+
189
+ // `data` is the part of `bytes` contained within `page`,
190
+ // and `addr` in the address offset of `page` + any offset into the page as requested by `address`
191
+ for ( data, page, addr) in ( 0 ..last_page as u32 )
192
+ . map ( move |i| Page :: new ( i, S :: ERASE_SIZE ) )
193
+ . overlaps ( bytes, address)
194
+ {
195
+ let offset_into_page = addr. saturating_sub ( page. start ) as usize ;
196
+
197
+ self . storage . try_read ( page. start , self . merge_buffer ) ?;
198
+
199
+ let rhs = & self . merge_buffer [ offset_into_page..] ;
200
+ let is_subset =
201
+ data. len ( ) < rhs. len ( ) && data. iter ( ) . zip ( rhs. iter ( ) ) . all ( |( a, b) | ( * a | * b) == * b) ;
202
+
203
+ // Check if we can write the data block directly, under the limitations imposed by NorFlash:
204
+ // - We can only change 1's to 0's
205
+ if is_subset {
206
+ self . storage . try_write ( addr, data) ?;
207
+ } else {
208
+ self . storage . try_erase ( page. start , page. end ( ) ) ?;
209
+ self . merge_buffer
210
+ . iter_mut ( )
211
+ . skip ( offset_into_page)
212
+ . zip ( data)
213
+ . for_each ( |( byte, input) | * byte = * input) ;
214
+ self . storage . try_write ( page. start , self . merge_buffer ) ?;
215
+ }
216
+ }
217
+ Ok ( ( ) )
218
+ }
219
+ }
0 commit comments