1
+ use embedded_storage:: nor_flash:: { MultiwriteNorFlash , NorFlash , ReadNorFlash } ;
2
+
1
3
use crate :: pac:: FLASH ;
2
4
use crate :: signature:: FlashSize ;
3
5
use core:: { ptr, slice} ;
@@ -46,6 +48,10 @@ pub trait FlashExt {
46
48
/// Unlock flash for erasing/programming until this method's
47
49
/// result is dropped
48
50
fn unlocked ( & mut self ) -> UnlockedFlash ;
51
+ // Returns true if flash is in dual bank organization
52
+ fn dual_bank ( & self ) -> bool ;
53
+ /// Returns flash memory sector of a given offset. Returns none if offset is out of range.
54
+ fn sector ( & self , offset : usize ) -> Option < FlashSector > ;
49
55
}
50
56
51
57
impl FlashExt for FLASH {
@@ -61,11 +67,114 @@ impl FlashExt for FLASH {
61
67
unlock ( self ) ;
62
68
UnlockedFlash { flash : self }
63
69
}
70
+
71
+ fn dual_bank ( & self ) -> bool {
72
+ match self . len ( ) / 1024 {
73
+ // 1 MB devices depend on configuration
74
+ 1024 => {
75
+ if cfg ! ( any(
76
+ feature = "stm32f427" ,
77
+ feature = "stm32f429" ,
78
+ feature = "stm32f437" ,
79
+ feature = "stm32f439" ,
80
+ feature = "stm32f469" ,
81
+ feature = "stm32f479" ,
82
+ ) ) {
83
+ // DB1M bit is not present in all SVDs
84
+ // self.optcr.read().db1m().bit_is_set()
85
+ self . optcr . read ( ) . bits ( ) & ( 1 << 30 ) != 0
86
+ } else {
87
+ false
88
+ }
89
+ }
90
+ // 2 MB devices are always dual bank
91
+ 2048 => true ,
92
+ // All other devices are single bank
93
+ _ => false ,
94
+ }
95
+ }
96
+
97
+ fn sector ( & self , offset : usize ) -> Option < FlashSector > {
98
+ flash_sectors ( self . len ( ) , self . dual_bank ( ) ) . find ( |s| s. contains ( offset) )
99
+ }
64
100
}
65
101
66
102
const PSIZE_X8 : u8 = 0b00 ;
67
103
104
+ /// Read-only flash
105
+ ///
106
+ /// # Examples
107
+ ///
108
+ /// ```
109
+ /// use stm32f4xx_hal::pac::Peripherals;
110
+ /// use stm32f4xx_hal::flash::LockedFlash;
111
+ /// use embedded_storage::nor_flash::ReadNorFlash;
112
+ ///
113
+ /// let dp = Peripherals::take().unwrap();
114
+ /// let mut flash = LockedFlash::new(dp.FLASH);
115
+ /// println!("Flash capacity: {}", ReadNorFlash::capacity(&flash));
116
+ ///
117
+ /// let mut buf = [0u8; 64];
118
+ /// ReadNorFlash::read(&mut flash, 0x0, &mut buf).unwrap();
119
+ /// println!("First 64 bytes of flash memory: {:?}", buf);
120
+ /// ```
121
+ pub struct LockedFlash {
122
+ flash : FLASH ,
123
+ }
124
+
125
+ impl LockedFlash {
126
+ pub fn new ( flash : FLASH ) -> Self {
127
+ Self { flash }
128
+ }
129
+ }
130
+
131
+ impl FlashExt for LockedFlash {
132
+ fn address ( & self ) -> usize {
133
+ self . flash . address ( )
134
+ }
135
+
136
+ fn len ( & self ) -> usize {
137
+ self . flash . len ( )
138
+ }
139
+
140
+ fn unlocked ( & mut self ) -> UnlockedFlash {
141
+ self . flash . unlocked ( )
142
+ }
143
+
144
+ fn dual_bank ( & self ) -> bool {
145
+ self . flash . dual_bank ( )
146
+ }
147
+
148
+ fn sector ( & self , offset : usize ) -> Option < FlashSector > {
149
+ self . flash . sector ( offset)
150
+ }
151
+ }
152
+
68
153
/// Result of `FlashExt::unlocked()`
154
+ ///
155
+ /// # Examples
156
+ ///
157
+ /// ```
158
+ /// use stm32f4xx_hal::pac::Peripherals;
159
+ /// use stm32f4xx_hal::flash::{FlashExt, LockedFlash, UnlockedFlash};
160
+ /// use embedded_storage::nor_flash::NorFlash;
161
+ ///
162
+ /// let dp = Peripherals::take().unwrap();
163
+ /// let mut flash = LockedFlash::new(dp.FLASH);
164
+ ///
165
+ /// // Unlock flash for writing
166
+ /// let mut unlocked_flash = flash.unlocked();
167
+ ///
168
+ /// // Erase the second 128 KB sector.
169
+ /// NorFlash::erase(&mut unlocked_flash, 128 * 1024, 256 * 1024).unwrap();
170
+ ///
171
+ /// // Write some data at the start of the second 128 KB sector.
172
+ /// let buf = [0u8; 64];
173
+ /// NorFlash::write(&mut unlocked_flash, 128 * 1024, &buf).unwrap();
174
+ ///
175
+ /// // Lock flash by dropping
176
+ /// drop(unlocked_flash);
177
+ /// ```
69
178
pub struct UnlockedFlash < ' a > {
70
179
flash : & ' a mut FLASH ,
71
180
}
@@ -166,3 +275,145 @@ fn unlock(flash: &FLASH) {
166
275
fn lock ( flash : & FLASH ) {
167
276
flash. cr . modify ( |_, w| w. lock ( ) . set_bit ( ) ) ;
168
277
}
278
+
279
+ /// Flash memory sector
280
+ pub struct FlashSector {
281
+ /// Sector number
282
+ pub number : u8 ,
283
+ /// Offset from base memory address
284
+ pub offset : usize ,
285
+ /// Sector size in bytes
286
+ pub size : usize ,
287
+ }
288
+
289
+ impl FlashSector {
290
+ /// Returns true if given offset belongs to this sector
291
+ pub fn contains ( & self , offset : usize ) -> bool {
292
+ self . offset <= offset && offset < self . offset + self . size
293
+ }
294
+ }
295
+
296
+ /// Iterator of flash memory sectors in a single bank.
297
+ /// Yields a size sequence of [16, 16, 16, 64, 128, 128, ..]
298
+ pub struct FlashSectorIterator {
299
+ index : u8 ,
300
+ start_sector : u8 ,
301
+ start_offset : usize ,
302
+ end_offset : usize ,
303
+ }
304
+
305
+ impl FlashSectorIterator {
306
+ fn new ( start_sector : u8 , start_offset : usize , end_offset : usize ) -> Self {
307
+ Self {
308
+ index : 0 ,
309
+ start_sector,
310
+ start_offset,
311
+ end_offset,
312
+ }
313
+ }
314
+ }
315
+
316
+ impl Iterator for FlashSectorIterator {
317
+ type Item = FlashSector ;
318
+
319
+ fn next ( & mut self ) -> Option < Self :: Item > {
320
+ if self . start_offset >= self . end_offset {
321
+ None
322
+ } else {
323
+ // First 4 sectors are 16 KB, then one 64 KB and the rest are 128 KB
324
+ let size = match self . index {
325
+ 0 ..=3 => 16 * 1024 ,
326
+ 4 => 64 * 1024 ,
327
+ _ => 128 * 1024 ,
328
+ } ;
329
+
330
+ let sector = FlashSector {
331
+ number : self . start_sector + self . index ,
332
+ offset : self . start_offset ,
333
+ size,
334
+ } ;
335
+
336
+ self . index += 1 ;
337
+ self . start_offset += size;
338
+
339
+ Some ( sector)
340
+ }
341
+ }
342
+ }
343
+
344
+ /// Returns iterator of flash memory sectors for single and dual bank flash.
345
+ /// Sectors are returned in continuous memory order, while sector numbers can have spaces between banks.
346
+ pub fn flash_sectors ( flash_size : usize , dual_bank : bool ) -> impl Iterator < Item = FlashSector > {
347
+ if dual_bank {
348
+ // Second memory bank always starts from sector 12
349
+ FlashSectorIterator :: new ( 0 , 0 , flash_size / 2 ) . chain ( FlashSectorIterator :: new (
350
+ 12 ,
351
+ flash_size / 2 ,
352
+ flash_size,
353
+ ) )
354
+ } else {
355
+ // Chain an empty iterator to match types
356
+ FlashSectorIterator :: new ( 0 , 0 , flash_size) . chain ( FlashSectorIterator :: new ( 0 , 0 , 0 ) )
357
+ }
358
+ }
359
+
360
+ impl ReadNorFlash for LockedFlash {
361
+ type Error = Error ;
362
+
363
+ const READ_SIZE : usize = 1 ;
364
+
365
+ fn read ( & mut self , offset : u32 , bytes : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > {
366
+ let offset = offset as usize ;
367
+ Ok ( bytes. copy_from_slice ( & self . flash . read ( ) [ offset..offset + bytes. len ( ) ] ) )
368
+ }
369
+
370
+ fn capacity ( & self ) -> usize {
371
+ self . flash . len ( )
372
+ }
373
+ }
374
+
375
+ impl < ' a > ReadNorFlash for UnlockedFlash < ' a > {
376
+ type Error = Error ;
377
+
378
+ const READ_SIZE : usize = 1 ;
379
+
380
+ fn read ( & mut self , offset : u32 , bytes : & mut [ u8 ] ) -> Result < ( ) , Self :: Error > {
381
+ let offset = offset as usize ;
382
+ Ok ( bytes. copy_from_slice ( & self . flash . read ( ) [ offset..offset + bytes. len ( ) ] ) )
383
+ }
384
+
385
+ fn capacity ( & self ) -> usize {
386
+ self . flash . len ( )
387
+ }
388
+ }
389
+
390
+ impl < ' a > NorFlash for UnlockedFlash < ' a > {
391
+ const WRITE_SIZE : usize = 1 ;
392
+
393
+ // Use largest sector size of 128 KB. All smaller sectors will be erased together.
394
+ const ERASE_SIZE : usize = 128 * 1024 ;
395
+
396
+ fn erase ( & mut self , from : u32 , to : u32 ) -> Result < ( ) , Self :: Error > {
397
+ let mut current = from as usize ;
398
+
399
+ for sector in flash_sectors ( self . flash . len ( ) , self . flash . dual_bank ( ) ) {
400
+ if sector. contains ( current) {
401
+ UnlockedFlash :: erase ( self , sector. number ) ?;
402
+ current += sector. size ;
403
+ }
404
+
405
+ if current >= to as usize {
406
+ break ;
407
+ }
408
+ }
409
+
410
+ Ok ( ( ) )
411
+ }
412
+
413
+ fn write ( & mut self , offset : u32 , bytes : & [ u8 ] ) -> Result < ( ) , Self :: Error > {
414
+ self . program ( offset as usize , bytes. iter ( ) )
415
+ }
416
+ }
417
+
418
+ // STM32F4 supports multiple writes
419
+ impl < ' a > MultiwriteNorFlash for UnlockedFlash < ' a > { }
0 commit comments