stm32_hal2/flash/
non_trustzone.rs

1// todo: Between L5 and the rest, and L5 secure and non, there's a lot of DRY!
2// todo: The answer may be macros.
3
4use core;
5
6use cfg_if::cfg_if;
7
8use super::{Flash, FlashError, page_to_address};
9#[cfg(feature = "h7")]
10use crate::pac::flash::BANK;
11use crate::{
12    error::{Error, Result},
13    pac::FLASH,
14    util::bounded_loop,
15};
16
17const FLASH_KEY1: u32 = 0x4567_0123;
18const FLASH_KEY2: u32 = 0xCDEF_89AB;
19// const FLASH_OPT_KEY1: u32 = 0x0819_2A3B;
20// const FLASH_OPT_KEY2: u32 = 0x4C5D_6E7F;
21
22#[derive(Clone, Copy, PartialEq)]
23/// Set dual bank mode (DBANK option bit). Eg G4
24pub enum DualBank {
25    Dual,
26    Single,
27}
28
29#[derive(Clone, Copy)]
30#[repr(u8)]
31/// For dual-bank variants. u8 value is used for page erase: sets `CR` reg, `BKER` bit.
32pub enum Bank {
33    B1 = 0,
34    // todo: PAC bank 2 error
35    #[cfg(not(any(feature = "h747cm4", feature = "h747cm7")))]
36    B2 = 1,
37}
38
39// todo: Bank 2 support on H7 and others.
40
41#[cfg(any(feature = "h735", not(feature = "h7")))]
42/// Check and clear all non-secure error programming flags due to a previous
43/// programming. If not, PGSERR is set.
44fn clear_error_flags(regs: &FLASH) {
45    let sr = regs.sr().read();
46
47    cfg_if! {
48        if #[cfg(any(feature = "f3"))] {
49            if sr.wrprterr().bit_is_set() {
50                regs.sr().modify(|_, w| w.wrprterr().bit(true));
51            }
52            if sr.pgerr().bit_is_set() {
53                regs.sr().modify(|_, w| w.pgerr().bit(true));
54            }
55        } else if #[cfg(any(feature = "f4"))] {
56            // if sr.rderr().bit_is_set() {
57            //     regs.sr().modify(|_, w| w.rderr().bit(true));
58            // }
59            if sr.pgserr().bit_is_set() {
60                regs.sr().modify(|_, w| w.pgserr().bit(true));
61            }
62            if sr.pgperr().bit_is_set() {
63                regs.sr().modify(|_, w| w.pgperr().bit(true));
64            }
65            if sr.pgaerr().bit_is_set() {
66                regs.sr().modify(|_, w| w.pgaerr().bit(true));
67            }
68            if sr.wrperr().bit_is_set() {
69                regs.sr().modify(|_, w| w.wrperr().bit(true));
70            }
71            if sr.operr().bit_is_set() {
72                regs.sr().modify(|_, w| w.operr().bit(true));
73            }
74        } else {
75            #[cfg(not(feature = "h735"))]
76            if sr.optverr().bit_is_set() {
77                regs.sr().write(|w| w.optverr().bit(true));
78            }
79            #[cfg(not(any(feature = "h735", feature = "g0", feature = "g4", feature = "wl", feature = "wb", feature = "l4", feature = "c0")))]
80            if sr.rderr().bit_is_set() {
81                regs.sr().write(|w| w.rderr().bit(true));
82            }
83            #[cfg(not(any(feature = "h735", feature = "g0", feature = "g4", feature = "wl", feature = "wb", feature = "l4", feature = "c0")))]
84            if sr.rdperr().bit_is_set() {
85                regs.sr().write(|w| w.rdperr().bit(true));
86            }
87            if sr.fasterr().bit_is_set() {
88                regs.sr().write(|w| w.fasterr().bit(true));
89            }
90            #[cfg(not(any(feature = "wl", feature = "wb", feature = "l4", feature = "g4")))]
91            if sr.misserr().bit_is_set() {
92                regs.sr().write(|w| w.misserr().bit(true));
93            }
94            #[cfg(any(feature = "l4", feature = "wb", feature = "g4"))]
95            if sr.miserr().bit_is_set() {
96                regs.sr().write(|w| w.miserr().bit(true));
97            }
98            if sr.pgserr().bit_is_set() {
99                regs.sr().write(|w| w.pgserr().bit(true));
100            }
101            #[cfg(not(feature = "h735"))]
102            if sr.sizerr().bit_is_set() {
103                regs.sr().write(|w| w.sizerr().bit(true));
104            }
105            #[cfg(not(feature = "h735"))]
106            if sr.pgaerr().bit_is_set() {
107                regs.sr().write(|w| w.pgaerr().bit(true));
108            }
109            if sr.wrperr().bit_is_set() {
110                regs.sr().write(|w| w.wrperr().bit(true));
111            }
112            #[cfg(not(feature = "h735"))]
113            if sr.progerr().bit_is_set() {
114                regs.sr().write(|w| w.progerr().bit(true));
115            }
116            if sr.operr().bit_is_set() {
117                regs.sr().write(|w| w.operr().bit(true));
118            }
119
120        }
121    }
122}
123
124#[cfg(all(feature = "h7", not(feature = "h735")))]
125/// Check and clear all non-secure error programming flags due to a previous
126/// programming. If not, PGSERR is set.
127fn clear_error_flags(regs: &BANK) {
128    let sr = regs.sr().read();
129
130    if sr.dbeccerr().bit_is_set() {
131        regs.ccr().write(|w| w.clr_dbeccerr().bit(true));
132    }
133    if sr.sneccerr().bit_is_set() {
134        regs.ccr().write(|w| w.clr_sneccerr().bit(true));
135    }
136    if sr.rdserr().bit_is_set() {
137        regs.ccr().write(|w| w.clr_rdserr().bit(true));
138    }
139    if sr.rdperr().bit_is_set() {
140        regs.ccr().write(|w| w.clr_rdperr().bit(true));
141    }
142    if sr.operr().bit_is_set() {
143        regs.ccr().write(|w| w.clr_operr().bit(true));
144    }
145    if sr.incerr().bit_is_set() {
146        regs.ccr().write(|w| w.clr_incerr().bit(true));
147    }
148    if sr.strberr().bit_is_set() {
149        regs.ccr().write(|w| w.clr_strberr().bit(true));
150    }
151    if sr.pgserr().bit_is_set() {
152        regs.ccr().write(|w| w.clr_pgserr().bit(true));
153    }
154    if sr.wrperr().bit_is_set() {
155        regs.ccr().write(|w| w.clr_wrperr().bit(true));
156    }
157}
158
159impl Flash {
160    /// Unlock the flash memory, allowing writes. See L4 Reference manual, section 3.3.5.
161    /// (G4 RM section 5.3.5)
162    /// "After reset, write is not allowed in the Flash control register (FLASH_CR) to protect the
163    /// Flash memory against possible unwanted operations due, for example, to electric
164    /// disturbances."
165    pub fn unlock(&mut self) -> Result<()> {
166        #[cfg(not(feature = "h7"))]
167        let regs = &self.regs;
168        #[cfg(all(feature = "h7", not(feature = "h735")))]
169        let regs = self.regs.bank1();
170        #[cfg(feature = "h735")]
171        let regs = &self.regs;
172
173        if regs.cr().read().lock().bit_is_clear() {
174            return Ok(());
175        }
176
177        // The following sequence is used to unlock this register:
178        // 1. Write KEY1 = 0x45670123 in the Flash key register (FLASH_KEYR)
179        // 2. Write KEY2 = 0xCDEF89AB in the FLASH_KEYR register.
180        regs.keyr().write(|w| unsafe { w.bits(FLASH_KEY1) });
181        regs.keyr().write(|w| unsafe { w.bits(FLASH_KEY2) });
182
183        if regs.cr().read().lock().bit_is_clear() {
184            Ok(())
185        } else {
186            Err(Error::FlashError(FlashError::Failure))
187        }
188    }
189
190    // /// Unlock the FLASH_OPTCR register, for writing option bits.
191    // pub fn unlock_options(&mut self) -> Result<(), Error> {
192    //     #[cfg(not(feature = "h7"))]
193    //     let regs = &self.regs;
194    //     #[cfg(feature = "h7")]
195    //     let regs = self.regs.bank1();
196    //
197    //     if regs.cr().read().lock().bit_is_clear() {
198    //         return Ok(());
199    //     }
200    //
201    //     regs.optkeyr().write(|w| unsafe { w.bits(FLASH_OPT_KEY1) });
202    //     regs.optkeyr().write(|w| unsafe { w.bits(FLASH_OPT_KEY2) });
203    //
204    //     if regs.cr().read().lock().bit_is_clear() {
205    //         Ok(())
206    //     } else {
207    //         Err(Error::Failure)
208    //     }
209    // }
210
211    pub fn lock(&mut self) -> Result<()> {
212        // The FLASH_CR register cannot be written when the BSY bit in the Flash status register
213        // (FLASH_SR) is set. Any attempt to write to it with the BSY bit set causes the AHB bus to
214        // stall until the BSY bit is cleared.
215        // todo: bank
216
217        #[cfg(not(feature = "h7"))]
218        let regs = &self.regs;
219        #[cfg(all(feature = "h7", not(feature = "h735")))]
220        let regs = self.regs.bank1();
221        #[cfg(feature = "h735")]
222        let regs = &self.regs;
223
224        #[cfg(not(flash_bsy1))]
225        bounded_loop!(
226            regs.sr().read().bsy().bit_is_set(),
227            Error::RegisterUnchanged
228        );
229        #[cfg(flash_bsy1)]
230        bounded_loop!(
231            regs.sr().read().bsy1().bit_is_set(),
232            Error::RegisterUnchanged
233        );
234
235        regs.cr().modify(|_, w| w.lock().bit(true));
236        Ok(())
237    }
238
239    #[cfg(any(feature = "h735", not(feature = "h7")))]
240    #[allow(unused_variables)] // bank arg on single-bank MCUs.
241    /// Erase an entire page. See L4 Reference manual, section 3.3.5.
242    /// For why this is required, reference L4 RM, section 3.3.7:
243    /// "Programming in a previously programmed address is not allowed except if the data to write
244    /// is full zero, and any attempt will set PROGERR flag in the Flash status register
245    /// (FLASH_SR)."
246    pub fn erase_page(&mut self, bank: Bank, page: usize) -> Result<()> {
247        self.unlock()?;
248        let regs = &self.regs;
249
250        let sr = regs.sr().read();
251
252        #[cfg(not(flash_bsy1))]
253        let busy = sr.bsy().bit_is_set();
254        #[cfg(flash_bsy1)]
255        let busy = sr.bsy1().bit_is_set();
256
257        // 1. Check that no Flash memory operation is ongoing by checking the BSY bit in the Flash
258        // status register (FLASH_SR).
259        if busy {
260            self.lock()?;
261            return Err(Error::FlashError(FlashError::Busy));
262        }
263
264        // 2. Check and clear all error programming flags due to a previous programming. If not,
265        // PGSERR is set.
266        clear_error_flags(regs);
267
268        // 3. Set the PER bit and select the page you wish to erase (PNB). For dual bank variants:
269        //  - with the associated bank(BKER) in the Flash control register (FLASH_CR).
270        cfg_if! {
271            if #[cfg(feature = "f3")] {
272                // F3 RM: "Erase procedure"
273                // Set the PER bit in the FLASH_CR register
274                regs.cr().modify(|_, w| w.per().bit(true));
275
276                // Program the FLASH_CR register
277                // regs.ar.modify(|_, w| w.far().bits(page as u8));
278                regs.ar().write(|w| unsafe { w.bits(page as u32) }); // todo: Is this right?
279            } else if #[cfg(feature = "f4")] {
280                // Set the SER bit and select the sector out of the 12 sectors (for STM32F405xx/07xx and
281                // STM32F415xx/17xx) and out of 24 (for STM32F42xxx and STM32F43xxx) in the main
282                // memory block you wish to erase (SNB) in the FLASH_CR register
283                regs.cr().modify(|_, w| unsafe {
284                    w.ser().bit(true);
285                    w.snb().bits(page as u8) // todo: Probably not right?
286                });
287            } else if #[cfg(any(feature = "g473", feature = "g474", feature = "g483", feature = "g484"))] {
288                // 3. (G4 dual-bank devices: In dual bank mode (DBANK option bit is set), set the PER bit and
289                // select the page to
290                // erase (PNB) with the associated bank (BKER) in the Flash control register
291                // (FLASH_CR). In single bank mode (DBANK option bit is reset), set the PER bit and
292                // select the page to erase (PNB). The BKER bit in the Flash control register
293                // (FLASH_CR) must be kept cleared)
294                if self.dual_bank == DualBank::Dual {
295                     regs.cr().modify(|_, w| unsafe {
296                        // w.bker().bits(bank as u8); // todo: PAC error
297                        w.pnb().bits(page as u8);
298                        w.per().bit(true)
299                    });
300                } else {
301                     regs.cr().modify(|_, w| unsafe {
302                        w.pnb().bits(page as u8);
303                        w.per().bit(true)
304                    });
305                }
306            } else if #[cfg(any(feature = "l4", feature = "wb", feature = "wl", feature = "g4", feature = "c0"))] {
307                 regs.cr().modify(|_, w| unsafe {
308                    w.pnb().bits(page as u8);
309                    w.per().bit(true)
310                });
311            } else {
312                 regs.cr().modify(|_, w| unsafe {
313                    w.pnb().bits(page as u16);
314                    w.per().bit(true)
315                });
316            }
317        }
318
319        // 4. Set the STRT bit in the FLASH_CR register.
320        cfg_if! {
321            if #[cfg(not(any(feature = "l4", feature = "h7")))] {
322                regs.cr().modify(|_, w| w.strt().bit(true));
323            } else {
324                regs.cr().modify(|_, w| w.start().bit(true));
325            }
326        }
327
328        // 5. Wait for the BSY bit to be cleared in the FLASH_SR register.
329        #[cfg(not(flash_bsy1))]
330        bounded_loop!(
331            regs.sr().read().bsy().bit_is_set(),
332            Error::RegisterUnchanged
333        );
334        #[cfg(flash_bsy1)]
335        bounded_loop!(
336            regs.sr().read().bsy1().bit_is_set(),
337            Error::RegisterUnchanged
338        );
339
340        cfg_if! {
341            if #[cfg(any(feature = "f3", feature = "f4"))] {
342                // Check the EOP flag in the FLASH_SR register (it is set when the erase operation has
343                // succeeded), and then clear it by software.
344                bounded_loop!(
345                    regs.sr().read().eop().bit_is_clear(),
346                    Error::RegisterUnchanged
347                );
348                regs.sr().modify(|_, w| w.eop().bit(true));
349            }
350        }
351
352        #[cfg(not(feature = "f4"))]
353        regs.cr().modify(|_, w| w.per().clear_bit());
354        #[cfg(feature = "f4")]
355        regs.cr().modify(|_, w| w.ser().clear_bit());
356
357        self.lock()?;
358
359        Ok(())
360    }
361
362    #[cfg(all(feature = "h7", not(feature = "h735")))]
363    /// Erase a 128kb sector. See H743 RM, section 4.3.10: FLASH erase operations; subsection
364    /// Flash sector erase sequence. Note that this is similar to the procedure for other
365    /// families, but has a different name "sector" vice "page", and the RM instructions
366    /// are phrased differently.
367    pub fn erase_page(&mut self, bank: Bank, sector: usize) -> Result<()> {
368        self.unlock()?;
369
370        let regs = &match bank {
371            Bank::B1 => self.regs.bank1(),
372            // todo: PAC bank 2 error
373            #[cfg(not(any(feature = "h747cm4", feature = "h747cm7")))]
374            Bank::B2 => self.regs.bank2(),
375        };
376
377        // To erase a 128-Kbyte user sector, proceed as follows:
378        // 1. Check and clear (optional) all the error flags due to previous programming/erase
379        // operation. Refer to Section 4.7: FLASH error management for details.
380        clear_error_flags(&regs);
381
382        // 2.Unlock the FLASH_CR1/2 register, as described in Section 4.5.1: FLASH configuration
383        // protection (only if register is not already unlocked).
384        // self.unlock()?; // (Above; out of order due to borrow-checker issue)
385
386        // 3. Set the SER1/2 bit and SNB1/2 bitfield in the corresponding FLASH_CR1/2 register.
387        // SER1/2 indicates a sector erase operation, while SNB1/2 contains the target sector
388        // number.
389        regs.cr().modify(|_, w| unsafe {
390            w.ser().bit(true);
391            w.snb().bits(sector as u8) // todo: Probably not right?
392        });
393
394        // 4. Set the START1/2 bit in the FLASH_CR1/2 register.
395        regs.cr().modify(|_, w| w.start().bit(true));
396
397        // 5. Wait for the QW1/2 bit to be cleared in the corresponding FLASH_SR1/2 register.
398        bounded_loop!(regs.sr().read().qw().bit_is_set(), Error::RegisterUnchanged);
399
400        self.lock()
401    }
402
403    /// Erase one or both banks. Called "Mass erase" on single-bank variants like G4.
404    pub fn erase_bank(&mut self, bank: Bank) -> Result<()> {
405        // todo: DRY
406        // (H7): 2. Unlock the FLASH_CR1/2 register, as described in Section 4.5.1: FLASH configuration
407        // protection (only if register is not already unlocked).
408        self.unlock()?;
409
410        #[cfg(not(feature = "h7"))]
411        let regs = &self.regs;
412        #[cfg(all(feature = "h7", not(feature = "h735")))]
413        let regs = &match bank {
414            Bank::B1 => self.regs.bank1(),
415            // todo: PAC bank 2 error
416            #[cfg(not(any(feature = "h747cm4", feature = "h747cm7")))]
417            Bank::B2 => self.regs.bank2(),
418        };
419        #[cfg(feature = "h735")]
420        let regs = &self.regs;
421
422        // To perform a bank Mass Erase, follow the procedure below:
423        // RM0351 Rev 7 105/1903
424        // RM0351 Embedded Flash memory (FLASH)
425        // 1. Check that no Flash memory operation is ongoing by checking the BSY bit in the
426        // FLASH_SR register.
427        // (H7): 1. Check and clear (optional) all the error flags due to previous programming/erase
428        // operation. Refer to Section 4.7: FLASH error management for details.
429        let sr = regs.sr().read();
430
431        #[cfg(not(flash_bsy1))]
432        let busy = sr.bsy().bit_is_set();
433        #[cfg(flash_bsy1)]
434        let busy = sr.bsy1().bit_is_set();
435
436        if busy {
437            self.lock()?;
438            return Err(Error::FlashError(FlashError::Busy));
439        }
440
441        // 2. Check and clear all error programming flags due to a previous programming. If not,
442        // PGSERR is set.
443        clear_error_flags(regs);
444
445        // 3. Set the MER1 bit or/and MER2 (depending on the bank) in the Flash control register
446        // (FLASH_CR). Both banks can be selected in the same operation.
447        cfg_if! {
448            if #[cfg(any(feature = "f", feature = "wb", feature = "wl"))] {
449                regs.cr().modify(|_, w| w.mer().bit(true));
450            } else if #[cfg(any(feature = "g0", feature = "wl"))] {
451                regs.cr().modify(|_, w| w.mer1().bit(true));
452            } else if #[cfg(feature = "h7")] {
453                // 3. Set the BER1/2 bit in the FLASH_CR1/2 register corresponding to the targeted bank.
454                regs.cr().modify(|_, w| w.ber().bit(true));
455            } else { // L4, G4
456                match bank {
457                    Bank::B1 => {
458                        regs.cr().modify(|_, w| w.mer1().bit(true));
459                    }
460                    Bank::B2 => {
461                        // todo: Other families that have dual bank too!
462                        // #[cfg(any(feature = "g473", feature = "g474", feature = "g483", feature = "g484"))]
463                        // regs.cr().modify(|_, w| w.mer2().bit(true)); // todo PAC error
464                    }
465                }
466            }
467        }
468
469        // 4. Set the STRT bit in the FLASH_CR register.
470        cfg_if! {
471             if #[cfg(feature = "h7")] {
472                // 4. Set the START bit in the FLASH_CR1/2 register to start the bank erase operation. Then
473                // wait until the QW1/2 bit is cleared in the corresponding FLASH_SR1/2 register.
474                regs.cr().modify(|_, w| w.start().bit(true));
475                bounded_loop!(
476                    regs.sr().read().qw().bit_is_set(),
477                    Error::RegisterUnchanged
478                );
479            } else if #[cfg(feature = "l4")] {
480                regs.cr().modify( | _, w | w.start().bit(true));
481            } else {
482                regs.cr().modify(|_, w| w.strt().bit(true));
483            }
484        }
485
486        // 5. Wait for the BSY bit to be cleared in the FLASH_SR register.
487        #[cfg(not(flash_bsy1))]
488        bounded_loop!(
489            regs.sr().read().bsy().bit_is_set(),
490            Error::RegisterUnchanged
491        );
492        #[cfg(flash_bsy1)]
493        bounded_loop!(
494            regs.sr().read().bsy1().bit_is_set(),
495            Error::RegisterUnchanged
496        );
497
498        // (Some RMs describe this procedure, to clear mer, with ambiguity of if it's required)
499        cfg_if! {
500            if #[cfg(feature = "h7")] {
501                regs.cr().modify(|_, w| w.ber().clear_bit());
502            } else if #[cfg(any(feature = "f", feature = "wb", feature = "wl"))] {
503                regs.cr().modify(|_, w| w.mer().clear_bit());
504            } else {
505                regs.cr().modify(|_, w| w.mer1().clear_bit());
506            }
507        }
508
509        self.lock()?;
510
511        Ok(())
512    }
513
514    // todo: For multibank variants, accept a bank argument.
515    /// Write the contents of a page. Must be erased first. See L4 RM, section 3.3.7.
516    /// Make sure the page is one your MCU has, and isn't being used for the program itself.
517    #[cfg(not(feature = "h7"))]
518    #[allow(unused_variables)] // bank arg on single-bank MCUs.
519    pub fn write_page(&mut self, bank: Bank, page: usize, data: &[u8]) -> Result<()> {
520        // todo: Consider a u8-based approach.
521        // todo: DRY from `erase_page`.
522
523        self.unlock()?;
524
525        let regs = &self.regs;
526
527        // The Flash memory programming sequence in standard mode is as follows:
528        // 1. Check that no Flash main memory operation is ongoing by checking the BSY bit in the
529        // Flash status register (FLASH_SR).
530        let sr = regs.sr().read();
531
532        #[cfg(not(flash_bsy1))]
533        let busy = sr.bsy().bit_is_set();
534        #[cfg(flash_bsy1)]
535        let busy = sr.bsy1().bit_is_set();
536
537        if busy {
538            self.lock()?;
539            return Err(Error::FlashError(FlashError::Busy));
540        }
541
542        // 2. Check and clear all error programming flags due to a previous programming. If not,
543        // PGSERR is set.
544        clear_error_flags(regs);
545
546        // 3. Set the PG bit in the Flash control register (FLASH_CR).
547        regs.cr().modify(|_, w| w.pg().bit(true));
548
549        // 4. Perform the data write operation at the desired memory address, inside main memory
550        // block or OTP area. Only double word can be programmed.
551
552        cfg_if! {
553             if #[cfg(any(feature = "g473", feature = "g474", feature = "g483", feature = "g484"))] {
554                let mut address = page_to_address(self.dual_bank, bank, page) as *mut u32;
555            } else {
556                let mut address = page_to_address(page) as *mut u32;
557            }
558        }
559
560        // Map our 8-bit data input API to the 64-bit write API. (Used by all variants, even though
561        // they have different read sizes.)
562        // "The Flash memory is programmed 72 bits at a time (64 bits + 8 bits ECC)"
563        // G4 RM: "It is only possible to program double word (2 x 32-bit data). •
564        // Any attempt to write byte or half-word sets SIZERR flag in the FLASH_SR register.
565        // Any attempt to write a double word which is not aligned with a double word address
566        // sets PGAERR flag in the FLASH_SR register."
567
568        for chunk in data.chunks(8) {
569            // 8 bytes is 64 bits. (Double word)
570            // Pad to 64 bits if required, ie on the last word.
571            let mut padded = [0xff; 8];
572
573            let (word1, word2) = if chunk.len() < 8 {
574                // 0xff due to the default value of erased pages.
575                padded[0..chunk.len()].clone_from_slice(&chunk);
576
577                (
578                    u32::from_le_bytes(padded[0..4].try_into().unwrap()),
579                    u32::from_le_bytes(padded[4..8].try_into().unwrap()),
580                )
581            } else {
582                (
583                    u32::from_le_bytes(chunk[0..4].try_into().unwrap()),
584                    u32::from_le_bytes(chunk[4..8].try_into().unwrap()),
585                )
586            };
587
588            unsafe {
589                // Write a first word in an address aligned with double word
590                core::ptr::write_volatile(address, word1);
591                address = address.add(1);
592                // Write the second word
593                core::ptr::write_volatile(address, word2);
594                address = address.add(1);
595            }
596            // 5. Wait until the BSY bit is cleared in the FLASH_SR register.
597            #[cfg(not(flash_bsy1))]
598            bounded_loop!(
599                regs.sr().read().bsy().bit_is_set(),
600                Error::RegisterUnchanged
601            );
602            #[cfg(flash_bsy1)]
603            bounded_loop!(
604                regs.sr().read().bsy1().bit_is_set(),
605                Error::RegisterUnchanged
606            );
607
608            // 6. Check that EOP flag is set in the FLASH_SR register (meaning that the programming
609            // operation has succeed), and clear it by software.
610            if regs.sr().read().eop().bit_is_set() {
611                regs.sr().modify(|_, w| w.eop().bit(true)); // Clear
612            }
613        }
614
615        // 7. Clear the PG bit in the FLASH_CR register if there no more programming request
616        // anymore.
617        regs.cr().modify(|_, w| w.pg().clear_bit());
618
619        self.lock()?;
620
621        Ok(())
622    }
623
624    /// Write the contents of a sector. Must be erased first. See H742 or H723-35 RM, section 4.3.9.
625    /// Make sure the sector is one your MCU has, and isn't being used for the program itself. Writes
626    /// a byte array, 256 bits at a time.
627    #[cfg(feature = "h7")]
628    pub fn write_page(&mut self, bank: Bank, sector: usize, data: &[u8]) -> Result<()> {
629        // 1. Unlock the FLASH_CR1/2 register, as described in Section 4.5.1: FLASH configuration
630        // protection (only if register is not already unlocked).
631        self.unlock()?;
632
633        let regs = &self.regs.bank1(); // todo: Bank 2 support.
634
635        // 2. Enable write operations by setting the PG1/2 bit in the FLASH_CR1/2 register.
636        regs.cr().modify(|_, w| w.pg().bit(true));
637
638        // 3. Check the protection of the targeted memory area. (todo?)
639
640        // 4. Write one Flash-word corresponding to 32-byte data starting at a 32-byte aligned
641        // address.
642        let mut address = page_to_address(bank, sector) as *mut u32;
643
644        // Note that the key element separating each 256-bit writes is wating until the `qw` bit
645        // is cleared.
646        for chunk in data.chunks(32) {
647            // We use 8 pointer-sized (32-bit) words to meet our full 32-byte (256-bit) write.
648            // Pad to 256 bits if required, ie on the last word.
649            let mut padded = [0xff; 32];
650
651            for i in 0..8 {
652                // 0xff due to the default value of erased pages.
653                padded[0..chunk.len()].clone_from_slice(&chunk);
654
655                let word = u32::from_le_bytes(padded[i * 4..i * 4 + 4].try_into().unwrap());
656                unsafe {
657                    core::ptr::write_volatile(address, word);
658                    address = address.add(1);
659                }
660            }
661
662            // 5. Check that QW has been raised and wait until it is reset to 0.
663            bounded_loop!(regs.sr().read().qw().bit_is_set(), Error::RegisterUnchanged);
664        }
665
666        self.lock()?;
667
668        Ok(())
669    }
670
671    /// Erase a page, then write to it.
672    pub fn erase_write_page(&mut self, bank: Bank, page: usize, data: &[u8]) -> Result<()> {
673        self.erase_page(bank, page)?;
674        self.write_page(bank, page, data)?;
675
676        Ok(())
677    }
678}