1use embedded_storage::nor_flash::{
2 ErrorType, MultiwriteNorFlash, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash,
3};
4
5use crate::pac::flash::cr::PSIZE;
6use crate::pac::FLASH;
7use crate::signature::FlashSize;
8use core::{ptr, slice};
9
10#[derive(Debug, Clone, Copy)]
12pub enum Error {
13 ProgrammingSequence,
14 ProgrammingParallelism,
15 ProgrammingAlignment,
16 WriteProtection,
17 Operation,
18}
19
20impl Error {
21 fn read(flash: &FLASH) -> Option<Self> {
22 let sr = flash.sr().read();
23 if sr.pgserr().bit() {
24 Some(Error::ProgrammingSequence)
25 } else if sr.pgperr().bit() {
26 Some(Error::ProgrammingParallelism)
27 } else if sr.pgaerr().bit() {
28 Some(Error::ProgrammingAlignment)
29 } else if sr.wrperr().bit() {
30 Some(Error::WriteProtection)
31 } else if sr.operr().bit() {
32 Some(Error::Operation)
33 } else {
34 None
35 }
36 }
37}
38
39#[allow(clippy::len_without_is_empty)]
41pub trait FlashExt {
42 fn address(&self) -> usize;
44 fn len(&self) -> usize;
46 fn read(&self) -> &[u8] {
48 let ptr = self.address() as *const _;
49 unsafe { slice::from_raw_parts(ptr, self.len()) }
50 }
51 fn unlocked(&mut self) -> UnlockedFlash;
54 fn dual_bank(&self) -> bool;
56 fn sector(&self, offset: usize) -> Option<FlashSector>;
58}
59
60impl FlashExt for FLASH {
61 fn address(&self) -> usize {
62 0x0800_0000
63 }
64
65 fn len(&self) -> usize {
66 FlashSize::get().bytes()
67 }
68
69 fn unlocked(&mut self) -> UnlockedFlash {
70 unlock(self);
71 UnlockedFlash { flash: self }
72 }
73
74 fn dual_bank(&self) -> bool {
75 match self.len() / 1024 {
76 1024 => {
78 if cfg!(any(
79 feature = "stm32f427",
80 feature = "stm32f429",
81 feature = "stm32f437",
82 feature = "stm32f439",
83 feature = "stm32f469",
84 feature = "stm32f479",
85 )) {
86 self.optcr().read().bits() & (1 << 30) != 0
89 } else {
90 false
91 }
92 }
93 2048 => true,
95 _ => false,
97 }
98 }
99
100 fn sector(&self, offset: usize) -> Option<FlashSector> {
101 flash_sectors(self.len(), self.dual_bank()).find(|s| s.contains(offset))
102 }
103}
104
105pub struct LockedFlash {
123 flash: FLASH,
124}
125
126impl LockedFlash {
127 pub fn new(flash: FLASH) -> Self {
128 Self { flash }
129 }
130}
131
132impl FlashExt for LockedFlash {
133 fn address(&self) -> usize {
134 self.flash.address()
135 }
136
137 fn len(&self) -> usize {
138 self.flash.len()
139 }
140
141 fn unlocked(&mut self) -> UnlockedFlash {
142 self.flash.unlocked()
143 }
144
145 fn dual_bank(&self) -> bool {
146 self.flash.dual_bank()
147 }
148
149 fn sector(&self, offset: usize) -> Option<FlashSector> {
150 self.flash.sector(offset)
151 }
152}
153
154pub struct UnlockedFlash<'a> {
180 flash: &'a mut FLASH,
181}
182
183impl Drop for UnlockedFlash<'_> {
185 fn drop(&mut self) {
186 lock(self.flash);
187 }
188}
189
190impl UnlockedFlash<'_> {
191 pub fn erase(&mut self, sector: u8) -> Result<(), Error> {
196 let snb = if sector < 12 { sector } else { sector + 4 };
197
198 self.flash.cr().modify(|_, w| {
199 w.strt().set_bit();
201 w.psize().variant(PSIZE::Psize8);
202 unsafe {
204 w.snb().bits(snb);
205 }
206 w.ser().set_bit();
208 w.pg().clear_bit()
210 });
211 self.wait_ready();
212 self.ok()
213 }
214
215 pub fn program<'a, I>(&mut self, mut offset: usize, mut bytes: I) -> Result<(), Error>
218 where
219 I: Iterator<Item = &'a u8>,
220 {
221 let ptr = self.flash.address() as *mut u8;
222 let mut bytes_written = 1;
223 while bytes_written > 0 {
224 bytes_written = 0;
225 let amount = 16 - (offset % 16);
226
227 self.flash.cr().modify(|_, w| {
228 w.psize().variant(PSIZE::Psize8);
229 w.ser().clear_bit();
231 w.pg().set_bit()
233 });
234 for _ in 0..amount {
235 match bytes.next() {
236 Some(byte) => {
237 unsafe {
238 ptr::write_volatile(ptr.add(offset), *byte);
239 }
240 offset += 1;
241 bytes_written += 1;
242 }
243 None => break,
244 }
245 }
246 self.wait_ready();
247 self.ok()?;
248 }
249 self.flash.cr().modify(|_, w| w.pg().clear_bit());
250
251 Ok(())
252 }
253
254 fn ok(&self) -> Result<(), Error> {
255 Error::read(self.flash).map(Err).unwrap_or(Ok(()))
256 }
257
258 fn wait_ready(&self) {
259 while self.flash.sr().read().bsy().bit() {}
260 }
261}
262
263const UNLOCK_KEY1: u32 = 0x45670123;
264const UNLOCK_KEY2: u32 = 0xCDEF89AB;
265
266fn unlock(flash: &FLASH) {
267 flash.keyr().write(|w| unsafe { w.key().bits(UNLOCK_KEY1) });
268 flash.keyr().write(|w| unsafe { w.key().bits(UNLOCK_KEY2) });
269 assert!(!flash.cr().read().lock().bit())
270}
271
272fn lock(flash: &FLASH) {
273 flash.cr().modify(|_, w| w.lock().set_bit());
274}
275
276pub struct FlashSector {
278 pub number: u8,
280 pub offset: usize,
282 pub size: usize,
284}
285
286impl FlashSector {
287 pub fn contains(&self, offset: usize) -> bool {
289 self.offset <= offset && offset < self.offset + self.size
290 }
291}
292
293pub struct FlashSectorIterator {
296 index: u8,
297 start_sector: u8,
298 start_offset: usize,
299 end_offset: usize,
300}
301
302impl FlashSectorIterator {
303 fn new(start_sector: u8, start_offset: usize, end_offset: usize) -> Self {
304 Self {
305 index: 0,
306 start_sector,
307 start_offset,
308 end_offset,
309 }
310 }
311}
312
313impl Iterator for FlashSectorIterator {
314 type Item = FlashSector;
315
316 fn next(&mut self) -> Option<Self::Item> {
317 if self.start_offset >= self.end_offset {
318 None
319 } else {
320 let size = match self.index {
322 0..=3 => 16 * 1024,
323 4 => 64 * 1024,
324 _ => 128 * 1024,
325 };
326
327 let sector = FlashSector {
328 number: self.start_sector + self.index,
329 offset: self.start_offset,
330 size,
331 };
332
333 self.index += 1;
334 self.start_offset += size;
335
336 Some(sector)
337 }
338 }
339}
340
341pub fn flash_sectors(flash_size: usize, dual_bank: bool) -> impl Iterator<Item = FlashSector> {
344 if dual_bank {
345 FlashSectorIterator::new(0, 0, flash_size / 2).chain(FlashSectorIterator::new(
347 12,
348 flash_size / 2,
349 flash_size,
350 ))
351 } else {
352 FlashSectorIterator::new(0, 0, flash_size).chain(FlashSectorIterator::new(0, 0, 0))
354 }
355}
356
357impl NorFlashError for Error {
358 fn kind(&self) -> NorFlashErrorKind {
359 match self {
360 Error::ProgrammingAlignment => NorFlashErrorKind::NotAligned,
361 _ => NorFlashErrorKind::Other,
362 }
363 }
364}
365
366impl ErrorType for LockedFlash {
367 type Error = Error;
368}
369
370impl ErrorType for UnlockedFlash<'_> {
371 type Error = Error;
372}
373
374impl ReadNorFlash for LockedFlash {
375 const READ_SIZE: usize = 1;
376
377 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
378 let offset = offset as usize;
379 bytes.copy_from_slice(&self.flash.read()[offset..offset + bytes.len()]);
380 Ok(())
381 }
382
383 fn capacity(&self) -> usize {
384 self.flash.len()
385 }
386}
387
388impl<'a> ReadNorFlash for UnlockedFlash<'a> {
389 const READ_SIZE: usize = 1;
390
391 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
392 let offset = offset as usize;
393 bytes.copy_from_slice(&self.flash.read()[offset..offset + bytes.len()]);
394 Ok(())
395 }
396
397 fn capacity(&self) -> usize {
398 self.flash.len()
399 }
400}
401
402impl<'a> NorFlash for UnlockedFlash<'a> {
403 const WRITE_SIZE: usize = 1;
404
405 const ERASE_SIZE: usize = 128 * 1024;
407
408 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
409 let mut current = from as usize;
410
411 for sector in flash_sectors(self.flash.len(), self.flash.dual_bank()) {
412 if sector.contains(current) {
413 UnlockedFlash::erase(self, sector.number)?;
414 current += sector.size;
415 }
416
417 if current >= to as usize {
418 break;
419 }
420 }
421
422 Ok(())
423 }
424
425 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
426 self.program(offset as usize, bytes.iter())
427 }
428}
429
430impl<'a> MultiwriteNorFlash for UnlockedFlash<'a> {}