stm32f1xx_hal/
flash.rs

1//! Flash memory
2
3use crate::pac::{flash, FLASH};
4
5pub const FLASH_START: u32 = 0x0800_0000;
6pub const FLASH_END: u32 = 0x080F_FFFF;
7
8const _RDPRT_KEY: u16 = 0x00A5;
9const KEY1: u32 = 0x45670123;
10const KEY2: u32 = 0xCDEF89AB;
11
12pub const SZ_1K: u16 = 1024;
13
14pub type Result<T> = core::result::Result<T, Error>;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
17pub enum Error {
18    AddressLargerThanFlash,
19    AddressMisaligned,
20    LengthNotMultiple2,
21    LengthTooLong,
22    EraseError,
23    ProgrammingError,
24    WriteError,
25    VerifyError,
26    UnlockError,
27    LockError,
28}
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
31pub enum SectorSize {
32    Sz1K = 1,
33    Sz2K = 2,
34    Sz4K = 4,
35}
36impl SectorSize {
37    const fn kbytes(self) -> u16 {
38        SZ_1K * self as u16
39    }
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
43pub enum FlashSize {
44    Sz16K = 16,
45    Sz32K = 32,
46    Sz64K = 64,
47    Sz128K = 128,
48    Sz256K = 256,
49    Sz384K = 384,
50    Sz512K = 512,
51    Sz768K = 768,
52    Sz1M = 1024,
53}
54impl FlashSize {
55    const fn kbytes(self) -> u32 {
56        SZ_1K as u32 * self as u32
57    }
58}
59
60pub struct FlashWriter<'a> {
61    flash: &'a mut Parts,
62    sector_sz: SectorSize,
63    flash_sz: FlashSize,
64    verify: bool,
65}
66impl FlashWriter<'_> {
67    fn unlock(&mut self) -> Result<()> {
68        // Wait for any ongoing operations
69        while self.flash.sr.sr().read().bsy().bit_is_set() {}
70
71        // NOTE(unsafe) write Keys to the key register. This is safe because the
72        // only side effect of these writes is to unlock the flash control
73        // register, which is the intent of this function. Do not rearrange the
74        // order of these writes or the control register will be permanently
75        // locked out until reset.
76        unsafe {
77            self.flash.keyr.keyr().write(|w| w.key().bits(KEY1));
78        }
79        unsafe {
80            self.flash.keyr.keyr().write(|w| w.key().bits(KEY2));
81        }
82
83        // Verify success
84        match self.flash.cr.cr().read().lock().bit_is_clear() {
85            true => Ok(()),
86            false => Err(Error::UnlockError),
87        }
88    }
89
90    fn lock(&mut self) -> Result<()> {
91        //Wait for ongoing flash operations
92        while self.flash.sr.sr().read().bsy().bit_is_set() {}
93
94        // Set lock bit
95        self.flash.cr.cr().modify(|_, w| w.lock().set_bit());
96
97        // Verify success
98        match self.flash.cr.cr().read().lock().bit_is_set() {
99            true => Ok(()),
100            false => Err(Error::LockError),
101        }
102    }
103
104    fn valid_address(&self, offset: u32) -> Result<()> {
105        if FLASH_START + offset > FLASH_END {
106            Err(Error::AddressLargerThanFlash)
107        } else if offset & 0x1 != 0 {
108            Err(Error::AddressMisaligned)
109        } else {
110            Ok(())
111        }
112    }
113
114    fn valid_length(&self, offset: u32, length: usize) -> Result<()> {
115        if offset + length as u32 > self.flash_sz.kbytes() {
116            Err(Error::LengthTooLong)
117        } else if length & 0x1 != 0 {
118            Err(Error::LengthNotMultiple2)
119        } else {
120            Ok(())
121        }
122    }
123
124    /// Erase sector which contains `start_offset`
125    pub fn page_erase(&mut self, start_offset: u32) -> Result<()> {
126        self.valid_address(start_offset)?;
127
128        // Unlock Flash
129        self.unlock()?;
130
131        // Set Page Erase
132        self.flash.cr.cr().modify(|_, w| w.per().set_bit());
133
134        // Write address bits
135        // NOTE(unsafe) This sets the page address in the Address Register.
136        // The side-effect of this write is that the page will be erased when we
137        // set the STRT bit in the CR below. The address is validated by the
138        // call to self.valid_address() above.
139        unsafe {
140            self.flash
141                .ar
142                .ar()
143                .write(|w| w.far().bits(FLASH_START + start_offset));
144        }
145
146        // Start Operation
147        self.flash.cr.cr().modify(|_, w| w.strt().set_bit());
148
149        // Wait for at least one clock cycle before reading the
150        // BSY bit, because there is a one-cycle delay between
151        // setting the STRT bit and the BSY bit being asserted
152        // by hardware. See STM32F105xx, STM32F107xx device errata,
153        // section 2.2.8
154        cortex_m::asm::nop();
155
156        // Wait for operation to finish
157        while self.flash.sr.sr().read().bsy().bit_is_set() {}
158
159        // Check for errors
160        let sr = self.flash.sr.sr().read();
161
162        // Remove Page Erase Operation bit
163        self.flash.cr.cr().modify(|_, w| w.per().clear_bit());
164
165        // Re-lock flash
166        self.lock()?;
167
168        if sr.wrprterr().bit_is_set() {
169            // reset by writing 1
170            self.flash.sr.sr().modify(|_, w| w.wrprterr().bit(true));
171            Err(Error::EraseError)
172        } else {
173            if self.verify {
174                // By subtracting 1 from the sector size and masking with
175                // start_offset, we make 'start' point to the beginning of the
176                // page. We do this because the entire page should have been
177                // erased, regardless of where in the page the given
178                // 'start_offset' was.
179                let size = self.sector_sz.kbytes() as u32;
180                let start = start_offset & !(size - 1);
181                for idx in (start..start + size).step_by(2) {
182                    let write_address = (FLASH_START + idx) as *const u16;
183                    let verify: u16 = unsafe { core::ptr::read_volatile(write_address) };
184                    if verify != 0xFFFF {
185                        return Err(Error::VerifyError);
186                    }
187                }
188            }
189
190            Ok(())
191        }
192    }
193
194    /// Erase the Flash Sectors from `FLASH_START + start_offset` to `length`
195    pub fn erase(&mut self, start_offset: u32, length: usize) -> Result<()> {
196        self.valid_length(start_offset, length)?;
197
198        // Erase every sector touched by start_offset + length
199        for offset in
200            (start_offset..start_offset + length as u32).step_by(self.sector_sz.kbytes() as usize)
201        {
202            self.page_erase(offset)?;
203        }
204
205        // Report Success
206        Ok(())
207    }
208
209    /// Retrieve a slice of data from `FLASH_START + offset`
210    pub fn read(&self, offset: u32, length: usize) -> Result<&[u8]> {
211        self.valid_address(offset)?;
212
213        if offset + length as u32 > self.flash_sz.kbytes() {
214            return Err(Error::LengthTooLong);
215        }
216
217        let address = (FLASH_START + offset) as *const _;
218
219        Ok(
220            // NOTE(unsafe) read with no side effects. The data returned will
221            // remain valid for its lifetime because we take an immutable
222            // reference to this FlashWriter, and any operation that would
223            // invalidate the data returned would first require taking a mutable
224            // reference to this FlashWriter.
225            unsafe { core::slice::from_raw_parts(address, length) },
226        )
227    }
228
229    /// Write data to `FLASH_START + offset`
230    pub fn write(&mut self, offset: u32, data: &[u8]) -> Result<()> {
231        self.valid_length(offset, data.len())?;
232
233        // Unlock Flash
234        self.unlock()?;
235
236        for idx in (0..data.len()).step_by(2) {
237            self.valid_address(offset + idx as u32)?;
238
239            let write_address = (FLASH_START + offset + idx as u32) as *mut u16;
240
241            // Set Page Programming to 1
242            self.flash.cr.cr().modify(|_, w| w.pg().set_bit());
243
244            while self.flash.sr.sr().read().bsy().bit_is_set() {}
245
246            // Flash is written 16 bits at a time, so combine two bytes to get a
247            // half-word
248            let hword: u16 = (data[idx] as u16) | ((data[idx + 1] as u16) << 8);
249
250            // NOTE(unsafe) Write to FLASH area with no side effects
251            unsafe { core::ptr::write_volatile(write_address, hword) };
252
253            // Wait for write
254            while self.flash.sr.sr().read().bsy().bit_is_set() {}
255
256            // Set Page Programming to 0
257            self.flash.cr.cr().modify(|_, w| w.pg().clear_bit());
258
259            // Check for errors
260            if self.flash.sr.sr().read().pgerr().bit_is_set() {
261                // reset by writing 1
262                self.flash.sr.sr().modify(|_, w| w.pgerr().bit(true));
263
264                self.lock()?;
265                return Err(Error::ProgrammingError);
266            } else if self.flash.sr.sr().read().wrprterr().bit_is_set() {
267                // reset by writing 1
268                self.flash.sr.sr().modify(|_, w| w.wrprterr().bit(true));
269
270                self.lock()?;
271                return Err(Error::WriteError);
272            } else if self.verify {
273                // Verify written WORD
274                // NOTE(unsafe) read with no side effects within FLASH area
275                let verify: u16 = unsafe { core::ptr::read_volatile(write_address) };
276                if verify != hword {
277                    self.lock()?;
278                    return Err(Error::VerifyError);
279                }
280            }
281        }
282
283        // Lock Flash and report success
284        self.lock()?;
285        Ok(())
286    }
287
288    /// Enable/disable verifying that each erase or write operation completed
289    /// successfuly.
290    ///
291    /// When enabled, after each erase operation every address is read to make
292    /// sure it contains the erase value of 0xFFFF. After each write operation,
293    /// every address written is read and compared to the value that should have
294    /// been written. If any address does not contain the expected value, the
295    /// function will return Err.
296    /// When disabled, no verification is performed, erase/write operations are
297    /// assumed to have succeeded.
298    pub fn change_verification(&mut self, verify: bool) {
299        self.verify = verify;
300    }
301}
302
303/// Extension trait to constrain the FLASH peripheral
304pub trait FlashExt {
305    /// Constrains the FLASH peripheral to play nicely with the other abstractions
306    fn constrain(self) -> Parts;
307}
308
309impl FlashExt for FLASH {
310    fn constrain(self) -> Parts {
311        Parts {
312            acr: ACR,
313            ar: AR,
314            cr: CR,
315            keyr: KEYR,
316            _obr: OBR,
317            _optkeyr: OPTKEYR,
318            sr: SR,
319            _wrpr: WRPR,
320        }
321    }
322}
323
324/// Constrained FLASH peripheral
325pub struct Parts {
326    /// Opaque ACR register
327    pub acr: ACR,
328
329    /// Opaque AR register
330    pub(crate) ar: AR,
331
332    /// Opaque CR register
333    pub(crate) cr: CR,
334
335    /// Opaque KEYR register
336    pub(crate) keyr: KEYR,
337
338    /// Opaque OBR register
339    pub(crate) _obr: OBR,
340
341    /// Opaque OPTKEYR register
342    pub(crate) _optkeyr: OPTKEYR,
343
344    /// Opaque SR register
345    pub(crate) sr: SR,
346
347    /// Opaque WRPR register
348    pub(crate) _wrpr: WRPR,
349}
350impl Parts {
351    pub fn writer(&mut self, sector_sz: SectorSize, flash_sz: FlashSize) -> FlashWriter<'_> {
352        FlashWriter {
353            flash: self,
354            sector_sz,
355            flash_sz,
356            verify: true,
357        }
358    }
359}
360
361/// Opaque ACR register
362#[non_exhaustive]
363pub struct ACR;
364
365#[allow(dead_code)]
366impl ACR {
367    pub(crate) fn acr(&mut self) -> &flash::ACR {
368        // NOTE(unsafe) this proxy grants exclusive access to this register
369        unsafe { (*FLASH::ptr()).acr() }
370    }
371}
372
373/// Opaque AR register
374#[non_exhaustive]
375pub struct AR;
376
377#[allow(dead_code)]
378impl AR {
379    pub(crate) fn ar(&mut self) -> &flash::AR {
380        // NOTE(unsafe) this proxy grants exclusive access to this register
381        unsafe { (*FLASH::ptr()).ar() }
382    }
383}
384
385/// Opaque CR register
386#[non_exhaustive]
387pub struct CR;
388
389#[allow(dead_code)]
390impl CR {
391    pub(crate) fn cr(&mut self) -> &flash::CR {
392        // NOTE(unsafe) this proxy grants exclusive access to this register
393        unsafe { (*FLASH::ptr()).cr() }
394    }
395}
396
397/// Opaque KEYR register
398#[non_exhaustive]
399pub struct KEYR;
400
401#[allow(dead_code)]
402impl KEYR {
403    pub(crate) fn keyr(&mut self) -> &flash::KEYR {
404        // NOTE(unsafe) this proxy grants exclusive access to this register
405        unsafe { (*FLASH::ptr()).keyr() }
406    }
407}
408
409/// Opaque OBR register
410#[non_exhaustive]
411pub struct OBR;
412
413#[allow(dead_code)]
414impl OBR {
415    pub(crate) fn obr(&mut self) -> &flash::OBR {
416        // NOTE(unsafe) this proxy grants exclusive access to this register
417        unsafe { (*FLASH::ptr()).obr() }
418    }
419}
420
421/// Opaque OPTKEYR register
422#[non_exhaustive]
423pub struct OPTKEYR;
424
425#[allow(dead_code)]
426impl OPTKEYR {
427    pub(crate) fn optkeyr(&mut self) -> &flash::OPTKEYR {
428        // NOTE(unsafe) this proxy grants exclusive access to this register
429        unsafe { (*FLASH::ptr()).optkeyr() }
430    }
431}
432
433/// Opaque SR register
434#[non_exhaustive]
435pub struct SR;
436
437#[allow(dead_code)]
438impl SR {
439    pub(crate) fn sr(&mut self) -> &flash::SR {
440        // NOTE(unsafe) this proxy grants exclusive access to this register
441        unsafe { (*FLASH::ptr()).sr() }
442    }
443}
444
445/// Opaque WRPR register
446#[non_exhaustive]
447pub struct WRPR;
448
449#[allow(dead_code)]
450impl WRPR {
451    pub(crate) fn wrpr(&mut self) -> &flash::WRPR {
452        // NOTE(unsafe) this proxy grants exclusive access to this register
453        unsafe { (*FLASH::ptr()).wrpr() }
454    }
455}