@@ -77,117 +77,143 @@ impl Page {
7777}
7878
7979impl Region for Page {
80+ /// Checks if an address offset is contained within the page
8081 fn contains ( & self , address : u32 ) -> bool {
8182 ( self . start <= address) && ( self . end ( ) > address)
8283 }
8384}
8485
8586///
86- pub struct RmwNorFlashStorage < S > ( S ) ;
87+ pub struct RmwNorFlashStorage < ' a , S > {
88+ storage : S ,
89+ merge_buffer : & ' a mut [ u8 ] ,
90+ }
8791
88- impl < S > RmwNorFlashStorage < S > {
92+ impl < ' a , S > RmwNorFlashStorage < ' a , S >
93+ where
94+ S : NorFlash ,
95+ {
8996 /// 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+ }
92109 }
93110}
94111
95- impl < S > ReadStorage for RmwNorFlashStorage < S >
112+ impl < ' a , S > ReadStorage for RmwNorFlashStorage < ' a , S >
96113where
97114 S : ReadNorFlash ,
98115{
99116 type Error = S :: Error ;
100117
101118 fn try_read ( & mut self , address : u32 , bytes : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > {
102119 // Nothing special to be done for reads
103- self . 0 . try_read ( address, bytes)
120+ self . storage . try_read ( address, bytes)
104121 }
105122
106123 fn capacity ( & self ) -> usize {
107- self . 0 . capacity ( )
124+ self . storage . capacity ( )
108125 }
109126}
110127
111- impl < S > Storage for RmwNorFlashStorage < S >
128+ impl < ' a , S > Storage for RmwNorFlashStorage < ' a , S >
112129where
113130 S : NorFlash ,
114- // [u8; S::ERASE_SIZE]: Sized,
115131{
116132 fn try_write ( & mut self , address : u32 , bytes : & [ u8 ] ) -> Result < ( ) , Self :: Error > {
117133 // 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 ;
119135
120136 // `data` is the part of `bytes` contained within `page`,
121137 // and `addr` in the address offset of `page` + any offset into the page as requested by `address`
122138 for ( data, page, addr) in ( 0 ..last_page as u32 )
123139 . map ( move |i| Page :: new ( i, S :: ERASE_SIZE ) )
124140 . overlaps ( bytes, address)
125141 {
126- let merge_buffer = & mut [ 0u8 ; 2048 ] ;
127142 let offset_into_page = addr. saturating_sub ( page. start ) as usize ;
128143
129- self . try_read ( page. start , merge_buffer) ?;
144+ self . storage . try_read ( page. start , self . merge_buffer ) ?;
130145
131146 // 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
134149 . iter_mut ( )
135150 . skip ( offset_into_page)
136151 . zip ( data)
137152 . 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 ) ?;
139154 }
140155 Ok ( ( ) )
141156 }
142157}
143158
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