1
1
use core:: convert:: TryInto ;
2
- use core:: { ptr, slice} ;
2
+ use core:: { mem , ptr, slice} ;
3
3
4
4
use embedded_storage:: nor_flash:: {
5
5
ErrorType , MultiwriteNorFlash , NorFlash , NorFlashError , NorFlashErrorKind , ReadNorFlash ,
@@ -8,11 +8,60 @@ use embedded_storage::nor_flash::{
8
8
use crate :: pac:: FLASH ;
9
9
use crate :: signature:: FlashSize ;
10
10
11
+ /// First address of the flash memory
12
+ pub const FLASH_START : usize = 0x0800_0000 ;
13
+
14
+ // F03x, F04x and F05x pages are 1K long
15
+ #[ cfg( any(
16
+ feature = "stm32f030" ,
17
+ feature = "stm32f031" ,
18
+ feature = "stm32f038" ,
19
+ feature = "stm32f042" ,
20
+ feature = "stm32f048" ,
21
+ feature = "stm32f051" ,
22
+ feature = "stm32f058" ,
23
+ ) ) ]
24
+ pub const PAGE_SIZE : u32 = 1024 ;
25
+ // F03x, F04x and F05x have 64 flash pages
26
+ #[ cfg( any(
27
+ feature = "stm32f030" ,
28
+ feature = "stm32f031" ,
29
+ feature = "stm32f038" ,
30
+ feature = "stm32f042" ,
31
+ feature = "stm32f048" ,
32
+ feature = "stm32f051" ,
33
+ feature = "stm32f058" ,
34
+ ) ) ]
35
+ pub const NUM_PAGES : u32 = 64 ;
36
+
37
+ // F07x and F09x pages are 2K long
38
+ #[ cfg( any(
39
+ feature = "stm32f070" ,
40
+ feature = "stm32f071" ,
41
+ feature = "stm32f072" ,
42
+ feature = "stm32f078" ,
43
+ feature = "stm32f091" ,
44
+ feature = "stm32f098" ,
45
+ ) ) ]
46
+ pub const PAGE_SIZE : u32 = 2048 ;
47
+ // F07x and F09x have 128 flash pages
48
+ #[ cfg( any(
49
+ feature = "stm32f070" ,
50
+ feature = "stm32f071" ,
51
+ feature = "stm32f072" ,
52
+ feature = "stm32f078" ,
53
+ feature = "stm32f091" ,
54
+ feature = "stm32f098" ,
55
+ ) ) ]
56
+ pub const NUM_PAGES : u32 = 128 ;
57
+
11
58
/// Flash erase/program error
12
59
#[ derive( Debug , Clone , Copy ) ]
13
60
pub enum Error {
14
61
Programming ,
15
62
WriteProtection ,
63
+ /// STM32F0 can only write Half Words (16 Bit) to flash. Can not write to addresses not aligned to that.
64
+ Alignment ,
16
65
}
17
66
18
67
impl Error {
@@ -43,13 +92,11 @@ pub trait FlashExt {
43
92
/// Unlock flash for erasing/programming until this method's
44
93
/// result is dropped
45
94
fn unlocked ( & mut self ) -> UnlockedFlash ;
46
- /// Returns flash memory sector of a given offset. Returns none if offset is out of range.
47
- fn sector ( & self , offset : usize ) -> Option < FlashSector > ;
48
95
}
49
96
50
97
impl FlashExt for FLASH {
51
98
fn address ( & self ) -> usize {
52
- 0x0800_0000
99
+ FLASH_START
53
100
}
54
101
55
102
fn len ( & self ) -> usize {
@@ -60,10 +107,6 @@ impl FlashExt for FLASH {
60
107
unlock ( self ) ;
61
108
UnlockedFlash { flash : self }
62
109
}
63
-
64
- fn sector ( & self , offset : usize ) -> Option < FlashSector > {
65
- flash_sectors ( self . len ( ) ) . find ( |s| s. contains ( offset) )
66
- }
67
110
}
68
111
69
112
/// Read-only flash
@@ -105,10 +148,6 @@ impl FlashExt for LockedFlash {
105
148
fn unlocked ( & mut self ) -> UnlockedFlash {
106
149
self . flash . unlocked ( )
107
150
}
108
-
109
- fn sector ( & self , offset : usize ) -> Option < FlashSector > {
110
- self . flash . sector ( offset)
111
- }
112
151
}
113
152
114
153
/// Result of `FlashExt::unlocked()`
@@ -147,69 +186,110 @@ impl Drop for UnlockedFlash<'_> {
147
186
}
148
187
}
149
188
189
+ pub trait WriteErase {
190
+ /// Native type for the flash for writing with the correct alignment and size
191
+ ///
192
+ /// Can be `u8`, `u16`, `u32`, ... (`u16` for STM32F0xx devices)
193
+ type NativeType ;
194
+
195
+ /// The smallest possible write, depends on the platform
196
+ fn program_native ( & mut self , offset : usize , data : & [ Self :: NativeType ] ) -> Result < ( ) , Error > ;
197
+
198
+ /// Write a buffer of bytes to memory and use native writes internally.
199
+ /// If it is not the same length as a set of native writes the write will be padded to fill the
200
+ /// native write.
201
+ fn program ( & mut self , offset : usize , data : & [ u8 ] ) -> Result < ( ) , Error > ;
202
+ }
203
+
204
+ impl WriteErase for UnlockedFlash < ' _ > {
205
+ type NativeType = u16 ;
206
+
207
+ fn program_native (
208
+ & mut self ,
209
+ mut offset : usize ,
210
+ data : & [ Self :: NativeType ] ,
211
+ ) -> Result < ( ) , Error > {
212
+ // Wait for ready bit
213
+ self . wait_ready ( ) ;
214
+
215
+ let addr = self . flash . address ( ) as * mut u16 ;
216
+
217
+ // Write the data to flash
218
+ for & half_word in data {
219
+ self . flash . cr . modify ( |_, w| w. pg ( ) . set_bit ( ) ) ;
220
+ unsafe {
221
+ ptr:: write_volatile ( addr. add ( offset) , half_word) ;
222
+ }
223
+ offset += mem:: size_of :: < Self :: NativeType > ( ) ;
224
+ }
225
+
226
+ self . wait_ready ( ) ;
227
+
228
+ // Clear programming bit
229
+ self . flash . cr . modify ( |_, w| w. pg ( ) . clear_bit ( ) ) ;
230
+
231
+ self . ok ( )
232
+ }
233
+
234
+ fn program ( & mut self , mut offset : usize , data : & [ u8 ] ) -> Result < ( ) , Error > {
235
+ if offset % mem:: align_of :: < Self :: NativeType > ( ) != 0 {
236
+ return Err ( Error :: Alignment ) ;
237
+ }
238
+
239
+ let mut chunks = data. chunks_exact ( mem:: size_of :: < Self :: NativeType > ( ) ) ;
240
+
241
+ for exact_chunk in & mut chunks {
242
+ let native = & [ Self :: NativeType :: from_ne_bytes (
243
+ exact_chunk. try_into ( ) . unwrap ( ) ,
244
+ ) ] ;
245
+ self . program_native ( offset, native) ?;
246
+ offset += mem:: size_of :: < Self :: NativeType > ( ) ;
247
+ }
248
+
249
+ let remainder = chunks. remainder ( ) ;
250
+
251
+ if !remainder. is_empty ( ) {
252
+ let mut data = Self :: NativeType :: MAX ;
253
+
254
+ for b in remainder. iter ( ) . rev ( ) {
255
+ data = ( data << 8 ) | * b as Self :: NativeType ;
256
+ }
257
+
258
+ let native = & [ data] ;
259
+ self . program_native ( offset, native) ?;
260
+ }
261
+
262
+ self . ok ( )
263
+ }
264
+ }
265
+
150
266
impl UnlockedFlash < ' _ > {
151
267
/// Erase a flash page at offset
152
268
///
153
269
/// Refer to the reference manual to see which sector corresponds
154
270
/// to which memory address.
155
271
pub fn erase ( & mut self , offset : u32 ) -> Result < ( ) , Error > {
272
+ // Wait for ready bit
273
+ self . wait_ready ( ) ;
274
+
275
+ // Set the PER (page erase) bit in CR register
276
+ self . flash . cr . modify ( |_, w| w. per ( ) . set_bit ( ) ) ;
277
+
156
278
// Write address into the AR register
157
279
self . flash
158
280
. ar
159
281
. write ( |w| w. far ( ) . bits ( self . flash . address ( ) as u32 + offset) ) ;
160
- #[ rustfmt:: skip]
161
- self . flash . cr . modify ( |_, w|
162
- w
163
- // page erase
164
- . per ( ) . set_bit ( )
165
- // start
166
- . strt ( ) . set_bit ( )
167
- ) ;
282
+ // Set the STRT (start) Bit in CR register
283
+ self . flash . cr . modify ( |_, w| w. strt ( ) . set_bit ( ) ) ;
284
+
285
+ // Wait for the operation to finish
168
286
self . wait_ready ( ) ;
287
+
169
288
// Clear PER bit after operation is finished
170
289
self . flash . cr . modify ( |_, w| w. per ( ) . clear_bit ( ) ) ;
171
290
self . ok ( )
172
291
}
173
292
174
- /// Program bytes with offset into flash memory
175
- pub fn program < ' a , I > ( & mut self , mut offset : usize , mut bytes : I ) -> Result < ( ) , Error >
176
- where
177
- I : Iterator < Item = & ' a u8 > ,
178
- {
179
- if self . flash . cr . read ( ) . lock ( ) . bit_is_set ( ) {
180
- return Err ( Error :: Programming ) ;
181
- }
182
- let ptr = self . flash . address ( ) as * mut u8 ;
183
- let mut bytes_written = 1 ;
184
- while bytes_written > 0 {
185
- bytes_written = 0 ;
186
- let amount = 2 - ( offset % 2 ) ;
187
-
188
- #[ allow( unused_unsafe) ]
189
- self . flash . cr . modify ( |_, w| unsafe {
190
- // programming
191
- w. pg ( ) . set_bit ( )
192
- } ) ;
193
- for _ in 0 ..amount {
194
- match bytes. next ( ) {
195
- Some ( byte) => {
196
- unsafe {
197
- ptr:: write_volatile ( ptr. add ( offset) , * byte) ;
198
- }
199
- offset += 1 ;
200
- bytes_written += 1 ;
201
- }
202
- None => break ,
203
- }
204
- }
205
- self . wait_ready ( ) ;
206
- self . ok ( ) ?;
207
- }
208
- self . flash . cr . modify ( |_, w| w. pg ( ) . clear_bit ( ) ) ;
209
-
210
- Ok ( ( ) )
211
- }
212
-
213
293
fn ok ( & self ) -> Result < ( ) , Error > {
214
294
Error :: read ( self . flash ) . map ( Err ) . unwrap_or ( Ok ( ( ) ) )
215
295
}
@@ -364,10 +444,9 @@ impl<'a> ReadNorFlash for UnlockedFlash<'a> {
364
444
}
365
445
366
446
impl < ' a > NorFlash for UnlockedFlash < ' a > {
367
- const WRITE_SIZE : usize = 1 ;
447
+ const WRITE_SIZE : usize = 2 ;
368
448
369
- // Use largest sector size of 128 KB. All smaller sectors will be erased together.
370
- const ERASE_SIZE : usize = 128 * 1024 ;
449
+ const ERASE_SIZE : usize = PAGE_SIZE as usize ;
371
450
372
451
fn erase ( & mut self , from : u32 , to : u32 ) -> Result < ( ) , Self :: Error > {
373
452
let mut current = from as usize ;
@@ -387,7 +466,7 @@ impl<'a> NorFlash for UnlockedFlash<'a> {
387
466
}
388
467
389
468
fn write ( & mut self , offset : u32 , bytes : & [ u8 ] ) -> Result < ( ) , Self :: Error > {
390
- self . program ( offset as usize , bytes. iter ( ) )
469
+ self . program ( offset as usize , bytes)
391
470
}
392
471
}
393
472
0 commit comments