stm32f1_hal/
flash.rs

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