stm32g473_hal_oppe/
flash.rs

1//! Flash memory
2
3use crate::stm32::{flash, FLASH};
4
5use core::convert::TryInto;
6
7pub const FLASH_START: u32 = 0x0800_0000;
8pub const FLASH_END: u32 = 0x080F_FFFF;
9
10const _RDPRT_KEY: u16 = 0x00A5;
11const KEY1: u32 = 0x45670123;
12const KEY2: u32 = 0xCDEF89AB;
13
14pub const SZ_1K: u32 = 1024;
15
16pub type Result<T> = core::result::Result<T, Error>;
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
19pub enum Error {
20    AddressLargerThanFlash,
21    AddressMisaligned,
22    LengthNotMultiple2,
23    LengthTooLong,
24    EraseError,
25    ProgrammingError,
26    WriteError,
27    VerifyError,
28    UnlockError,
29    LockError,
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
33pub enum FlashSize {
34    Sz16K = 16,
35    Sz32K = 32,
36    Sz64K = 64,
37    Sz128K = 128,
38    Sz256K = 256,
39    Sz384K = 384,
40    Sz512K = 512,
41    Sz768K = 768,
42    Sz1M = 1024,
43}
44impl FlashSize {
45    const fn kbytes(self) -> u32 {
46        SZ_1K * self as u32
47    }
48}
49
50pub struct FlashWriter<'a, const SECTOR_SZ_KB: u32> {
51    flash: &'a mut Parts,
52    flash_sz: FlashSize,
53    verify: bool,
54}
55impl<'a, const SECTOR_SZ_KB: u32> FlashWriter<'a, SECTOR_SZ_KB> {
56    fn unlock(&mut self) -> Result<()> {
57        // Wait for any ongoing operations
58        while self.flash.sr.sr().read().bsy().bit_is_set() {}
59
60        // NOTE(unsafe) write Keys to the key register. This is safe because the
61        // only side effect of these writes is to unlock the flash control
62        // register, which is the intent of this function. Do not rearrange the
63        // order of these writes or the control register will be permanently
64        // locked out until reset.
65        unsafe {
66            self.flash.keyr.keyr().write(|w| w.keyr().bits(KEY1));
67        }
68        unsafe {
69            self.flash.keyr.keyr().write(|w| w.keyr().bits(KEY2));
70        }
71
72        // Verify success
73        match self.flash.cr.cr().read().lock().bit_is_clear() {
74            true => Ok(()),
75            false => Err(Error::UnlockError),
76        }
77    }
78
79    fn lock(&mut self) -> Result<()> {
80        //Wait for ongoing flash operations
81        while self.flash.sr.sr().read().bsy().bit_is_set() {}
82
83        // Set lock bit
84        self.flash.cr.cr().modify(|_, w| w.lock().set_bit());
85
86        // Verify success
87        match self.flash.cr.cr().read().lock().bit_is_set() {
88            true => Ok(()),
89            false => Err(Error::LockError),
90        }
91    }
92
93    fn valid_address(&self, offset: u32) -> Result<()> {
94        if FLASH_START
95            .checked_add(offset)
96            .ok_or(Error::AddressLargerThanFlash)?
97            > FLASH_END
98        {
99            Err(Error::AddressLargerThanFlash)
100        } else if offset & 0x1 != 0 {
101            Err(Error::AddressMisaligned)
102        } else {
103            Ok(())
104        }
105    }
106
107    fn valid_length(&self, offset: u32, length: usize) -> Result<()> {
108        if offset
109            .checked_add(length as u32)
110            .ok_or(Error::LengthTooLong)?
111            > self.flash_sz.kbytes() as u32
112        {
113            Err(Error::LengthTooLong)
114        } else if length & 0x1 != 0 {
115            Err(Error::LengthNotMultiple2)
116        } else {
117            Ok(())
118        }
119    }
120
121    /// Erase sector which contains `start_offset`
122    pub fn page_erase(&mut self, start_offset: u32) -> Result<()> {
123        self.valid_address(start_offset)?;
124
125        // Unlock Flash
126        self.unlock()?;
127
128        // Set Page Erase
129        self.flash.cr.cr().modify(|_, w| w.per().set_bit());
130
131        let page = start_offset / (SECTOR_SZ_KB as u32);
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                .cr
141                .cr()
142                .write(|w| w.pnb().bits(page.try_into().unwrap()));
143        }
144
145        // Start Operation
146        self.flash.cr.cr().modify(|_, w| w.strt().set_bit());
147
148        // Wait for operation to finish
149        while self.flash.sr.sr().read().bsy().bit_is_set() {}
150
151        // Check for errors
152        let sr = self.flash.sr.sr().read();
153
154        // Remove Page Erase Operation bit
155        self.flash.cr.cr().modify(|_, w| w.per().clear_bit());
156
157        // Re-lock flash
158        self.lock()?;
159
160        if sr.wrperr().bit_is_set() {
161            self.flash.sr.sr().modify(|_, w| w.wrperr().set_bit());
162            Err(Error::EraseError)
163        } else {
164            if self.verify {
165                // By subtracting 1 from the sector size and masking with
166                // start_offset, we make 'start' point to the beginning of the
167                // page. We do this because the entire page should have been
168                // erased, regardless of where in the page the given
169                // 'start_offset' was.
170                let size = SECTOR_SZ_KB;
171                let start = start_offset & !(size - 1);
172                for idx in (start..start + size).step_by(2) {
173                    let write_address = (FLASH_START + idx as u32) as *const u16;
174                    let verify: u16 = unsafe { core::ptr::read_volatile(write_address) };
175                    if verify != 0xFFFF {
176                        return Err(Error::VerifyError);
177                    }
178                }
179            }
180
181            Ok(())
182        }
183    }
184
185    /// Erase the Flash Sectors from `FLASH_START + start_offset` to `length`
186    pub fn erase(&mut self, start_offset: u32, length: usize) -> Result<()> {
187        self.valid_length(start_offset, length)?;
188
189        // Erase every sector touched by start_offset + length
190        for offset in
191            (start_offset..start_offset + length as u32).step_by(SECTOR_SZ_KB.try_into().unwrap())
192        {
193            self.page_erase(offset)?;
194        }
195
196        // Report Success
197        Ok(())
198    }
199
200    /// Retrieve a slice of data from `FLASH_START + offset`
201    pub fn read(&self, offset: u32, length: usize) -> Result<&[u8]> {
202        self.valid_address(offset)?;
203
204        if offset + length as u32 > self.flash_sz.kbytes() as u32 {
205            return Err(Error::LengthTooLong);
206        }
207
208        let address = (FLASH_START + offset) as *const _;
209
210        Ok(
211            // NOTE(unsafe) read with no side effects. The data returned will
212            // remain valid for its lifetime because we take an immutable
213            // reference to this FlashWriter, and any operation that would
214            // invalidate the data returned would first require taking a mutable
215            // reference to this FlashWriter.
216            unsafe { core::slice::from_raw_parts(address, length) },
217        )
218    }
219
220    /// Write data to `FLASH_START + offset`
221    pub fn write(&mut self, offset: u32, data: &[u8]) -> Result<()> {
222        self.valid_length(offset, data.len())?;
223
224        // Unlock Flash
225        self.unlock()?;
226
227        for idx in (0..data.len()).step_by(2) {
228            self.valid_address(offset + idx as u32)?;
229
230            let write_address = (FLASH_START + offset + idx as u32) as *mut u16;
231
232            // Set Page Programming to 1
233            self.flash.cr.cr().modify(|_, w| w.pg().set_bit());
234
235            while self.flash.sr.sr().read().bsy().bit_is_set() {}
236
237            // Flash is written 16 bits at a time, so combine two bytes to get a
238            // half-word
239            let hword: u16 = (data[idx] as u16) | (data[idx + 1] as u16) << 8;
240
241            // NOTE(unsafe) Write to FLASH area with no side effects
242            unsafe { core::ptr::write_volatile(write_address, hword) };
243
244            // Wait for write
245            while self.flash.sr.sr().read().bsy().bit_is_set() {}
246
247            // Set Page Programming to 0
248            self.flash.cr.cr().modify(|_, w| w.pg().clear_bit());
249
250            // Check for errors
251            if self.flash.sr.sr().read().pgaerr().bit_is_set() {
252                self.flash.sr.sr().modify(|_, w| w.pgaerr().clear_bit());
253
254                self.lock()?;
255                return Err(Error::ProgrammingError);
256            } else if self.flash.sr.sr().read().wrperr().bit_is_set() {
257                self.flash.sr.sr().modify(|_, w| w.wrperr().clear_bit());
258
259                self.lock()?;
260                return Err(Error::WriteError);
261            } else if self.verify {
262                // Verify written WORD
263                // NOTE(unsafe) read with no side effects within FLASH area
264                let verify: u16 = unsafe { core::ptr::read_volatile(write_address) };
265                if verify != hword {
266                    self.lock()?;
267                    return Err(Error::VerifyError);
268                }
269            }
270        }
271
272        // Lock Flash and report success
273        self.lock()?;
274        Ok(())
275    }
276
277    /// Enable/disable verifying that each erase or write operation completed
278    /// successfuly.
279    ///
280    /// When enabled, after each erase operation every address is read to make
281    /// sure it contains the erase value of 0xFFFF. After each write operation,
282    /// every address written is read and compared to the value that should have
283    /// been written. If any address does not contain the expected value, the
284    /// function will return Err.
285    /// When disabled, no verification is performed, erase/write operations are
286    /// assumed to have succeeded.
287    pub fn change_verification(&mut self, verify: bool) {
288        self.verify = verify;
289    }
290}
291
292/// Extension trait to constrain the FLASH peripheral
293pub trait FlashExt {
294    /// Constrains the FLASH peripheral to play nicely with the other abstractions
295    fn constrain(self) -> Parts;
296}
297
298impl FlashExt for FLASH {
299    fn constrain(self) -> Parts {
300        Parts {
301            acr: ACR { _0: () },
302            cr: CR { _0: () },
303            eccr: ECCR { _0: () },
304            keyr: KEYR { _0: () },
305            _optkeyr: OPTKEYR { _0: () },
306            _optr: OPTR { _0: () },
307            _pcrop1sr: PCROP1SR { _0: () },
308            _pcrop1er: PCROP1ER { _0: () },
309            pdkeyr: PDKEYR { _0: () },
310            sec1r: SEC1R { _0: () },
311            sr: SR { _0: () },
312            _wrp1ar: WRP1AR { _0: () },
313            _wrp1br: WRP1BR { _0: () },
314        }
315    }
316}
317
318/// Constrained FLASH peripheral
319pub struct Parts {
320    /// Opaque ACR register
321    pub acr: ACR,
322
323    /// Opaque CR register
324    pub(crate) cr: CR,
325
326    /// Opaque ECCR register
327    pub(crate) eccr: ECCR,
328
329    /// Opaque KEYR register
330    pub(crate) keyr: KEYR,
331
332    /// Opaque OPTKEYR register
333    pub(crate) _optkeyr: OPTKEYR,
334
335    /// Opaque optr register
336    pub(crate) _optr: OPTR,
337
338    /// Opaque PCROP1SR register
339    pub(crate) _pcrop1sr: PCROP1SR,
340
341    /// Opaque PCROP1ER register
342    pub(crate) _pcrop1er: PCROP1ER,
343
344    /// Opaque PDKEYR register
345    pub(crate) pdkeyr: PDKEYR,
346
347    /// Opaque SEC1R register
348    pub(crate) sec1r: SEC1R,
349
350    /// Opaque SR register
351    pub(crate) sr: SR,
352
353    /// Opaque WRP1AR register
354    pub(crate) _wrp1ar: WRP1AR,
355
356    /// Opaque WRP1BR register
357    pub(crate) _wrp1br: WRP1BR,
358}
359impl Parts {
360    #[cfg(any(feature = "stm32g431", feature = "stm32g441",))]
361    pub fn writer(&mut self, flash_sz: FlashSize) -> FlashWriter<{ 2 * SZ_1K }> {
362        FlashWriter {
363            flash: self,
364            flash_sz,
365            verify: true,
366        }
367    }
368    #[cfg(any(
369        feature = "stm32g471",
370        feature = "stm32g473",
371        feature = "stm32g474",
372        feature = "stm32g483",
373        feature = "stm32g484",
374        feature = "stm32g491",
375        feature = "stm32g4a1",
376    ))]
377    pub fn writer(&mut self, flash_sz: FlashSize) -> FlashWriter<{ 4 * SZ_1K }> {
378        FlashWriter {
379            flash: self,
380            flash_sz,
381            verify: true,
382        }
383    }
384}
385
386/// Opaque ACR register
387pub struct ACR {
388    _0: (),
389}
390
391#[allow(dead_code)]
392impl ACR {
393    pub(crate) fn acr(&mut self) -> &flash::ACR {
394        // NOTE(unsafe) this proxy grants exclusive access to this register
395        unsafe { &(*FLASH::ptr()).acr }
396    }
397}
398
399/// Opaque CR register
400pub struct CR {
401    _0: (),
402}
403
404#[allow(dead_code)]
405impl CR {
406    pub(crate) fn cr(&mut self) -> &flash::CR {
407        // NOTE(unsafe) this proxy grants exclusive access to this register
408        unsafe { &(*FLASH::ptr()).cr }
409    }
410}
411
412/// Opaque ECCR register
413pub struct ECCR {
414    _0: (),
415}
416
417#[allow(dead_code)]
418impl ECCR {
419    pub(crate) fn eccr(&mut self) -> &flash::ECCR {
420        // NOTE(unsafe) this proxy grants exclusive access to this register
421        unsafe { &(*FLASH::ptr()).eccr }
422    }
423}
424
425/// Opaque KEYR register
426pub struct KEYR {
427    _0: (),
428}
429
430#[allow(dead_code)]
431impl KEYR {
432    pub(crate) fn keyr(&mut self) -> &flash::KEYR {
433        // NOTE(unsafe) this proxy grants exclusive access to this register
434        unsafe { &(*FLASH::ptr()).keyr }
435    }
436}
437
438/// Opaque OPTKEYR register
439pub struct OPTKEYR {
440    _0: (),
441}
442
443#[allow(dead_code)]
444impl OPTKEYR {
445    pub(crate) fn optkeyr(&mut self) -> &flash::OPTKEYR {
446        // NOTE(unsafe) this proxy grants exclusive access to this register
447        unsafe { &(*FLASH::ptr()).optkeyr }
448    }
449}
450
451/// Opaque OPTR register
452pub struct OPTR {
453    _0: (),
454}
455
456#[allow(dead_code)]
457impl OPTR {
458    pub(crate) fn optr(&mut self) -> &flash::OPTR {
459        // NOTE(unsafe) this proxy grants exclusive access to this register
460        unsafe { &(*FLASH::ptr()).optr }
461    }
462}
463
464/// Opaque PCROP1SR register
465pub struct PCROP1SR {
466    _0: (),
467}
468
469#[allow(dead_code)]
470impl PCROP1SR {
471    pub(crate) fn pcrop1sr(&mut self) -> &flash::PCROP1SR {
472        // NOTE(unsafe) this proxy grants exclusive access to this register
473        unsafe { &(*FLASH::ptr()).pcrop1sr }
474    }
475}
476
477/// Opaque PCROP1ER register
478pub struct PCROP1ER {
479    _0: (),
480}
481
482#[allow(dead_code)]
483impl PCROP1ER {
484    pub(crate) fn pcrop1er(&mut self) -> &flash::PCROP1ER {
485        // NOTE(unsafe) this proxy grants exclusive access to this register
486        unsafe { &(*FLASH::ptr()).pcrop1er }
487    }
488}
489
490/// Opaque PDKEYR register
491pub struct PDKEYR {
492    _0: (),
493}
494
495#[allow(dead_code)]
496impl PDKEYR {
497    pub(crate) fn pdkeyr(&mut self) -> &flash::PDKEYR {
498        // NOTE(unsafe) this proxy grants exclusive access to this register
499        unsafe { &(*FLASH::ptr()).pdkeyr }
500    }
501}
502
503/// Opaque SEC1R register
504pub struct SEC1R {
505    _0: (),
506}
507
508#[allow(dead_code)]
509impl SEC1R {
510    pub(crate) fn sec1r(&mut self) -> &flash::SEC1R {
511        // NOTE(unsafe) this proxy grants exclusive access to this register
512        unsafe { &(*FLASH::ptr()).sec1r }
513    }
514}
515
516/// Opaque SR register
517pub struct SR {
518    _0: (),
519}
520
521#[allow(dead_code)]
522impl SR {
523    pub(crate) fn sr(&mut self) -> &flash::SR {
524        // NOTE(unsafe) this proxy grants exclusive access to this register
525        unsafe { &(*FLASH::ptr()).sr }
526    }
527}
528
529/// Opaque WRP1AR register
530pub struct WRP1AR {
531    _0: (),
532}
533
534#[allow(dead_code)]
535impl WRP1AR {
536    pub(crate) fn wrp1ar(&mut self) -> &flash::WRP1AR {
537        // NOTE(unsafe) this proxy grants exclusive access to this register
538        unsafe { &(*FLASH::ptr()).wrp1ar }
539    }
540}
541
542/// Opaque WRP1BR register
543pub struct WRP1BR {
544    _0: (),
545}
546
547#[allow(dead_code)]
548impl WRP1BR {
549    pub(crate) fn wrp1br(&mut self) -> &flash::WRP1BR {
550        // NOTE(unsafe) this proxy grants exclusive access to this register
551        unsafe { &(*FLASH::ptr()).wrp1br }
552    }
553}