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(®s);
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}