gd32e2_hal/fmc.rs
1//! Flash memory controller.
2//!
3//! The wait states are not set from here: they have to be raised before the
4//! system clock speeds up, so
5//! [`UnfrozenRcu::freeze`](crate::rcu::UnfrozenRcu::freeze) borrows this type
6//! and writes them itself.
7//!
8//! Erasing and programming need `CTL` unlocked, which happens for the body of
9//! [`Fmc::with_unlocked`] and no longer. The option bytes are covered too, as a
10//! block: [`OptionBytes`] is read, changed and written back whole, because
11//! erasing them takes every byte at once. A written block only takes effect on
12//! the next load, [`Fmc::reload_option_bytes`] or a power-up.
13//!
14//! ```ignore
15//! let mut fmc = dp.fmc.constrain();
16//! let config = ClockConfig::default().sysclk(SysClk::Pll(PllFreq::Mhz48));
17//! let mut rcu = dp.rcu.constrain().freeze(&mut fmc, config);
18//!
19//! fmc.with_unlocked(|f| {
20//! f.erase_page(Page::P63)?;
21//! f.program(Page::P63, 0, 0xDEAD_BEEF)
22//! })?;
23//! ```
24
25use crate::pac;
26
27/// Highest `hclk` each wait-state setting can be read at.
28const WS0_MAX_HCLK: u32 = 24_000_000;
29const WS1_MAX_HCLK: u32 = 48_000_000;
30const WS2_MAX_HCLK: u32 = 72_000_000;
31const UNLOCK_KEY1: u32 = 0x4567_0123;
32const UNLOCK_KEY2: u32 = 0xCDEF_89AB;
33
34const BASE: u32 = 0x0800_0000;
35const PAGE_SIZE: u32 = 0x400;
36/// Pages covered by one `OB_WP` bit (user manual, Table 2-4).
37const PAGES_PER_WP_BIT: u32 = 4;
38/// Bytes per programmed word, `PGW` being left at its reset width of 32 bits.
39const WORD_SIZE: u32 = 4;
40
41/// `OB_WP` with every group free, protection being active low.
42const WP_ALL_FREE: u32 = 0xFFFF_FFFF;
43/// Start of the option byte block (user manual, Table 2-3).
44const OB_BASE: u32 = 0x1FFF_F800;
45
46/// Bit positions inside `OB_USER` (user manual, Table 2-3). Bits 3 and 7 are
47/// reserved and are carried through untouched.
48const BIT_NWDG_SW: u8 = 0;
49const BIT_NRST_DPSLP: u8 = 1;
50const BIT_NRST_STDBY: u8 = 2;
51const BIT_BOOT1_N: u8 = 4;
52const BIT_VDDA_VISOR: u8 = 5;
53const BIT_SRAM_PARITY: u8 = 6;
54
55/// Packs two option bytes and their complements into one programmed word.
56///
57/// Every byte of the block is stored next to its inverse, which is what `OBERR`
58/// checks on load; the pair is written out here rather than left to the
59/// controller.
60fn ob_word(low: u8, high: u8) -> u32 {
61 let pair = |byte: u8| byte as u32 | ((!byte as u32) << 8);
62 pair(low) | (pair(high) << 16)
63}
64
65/// The `OB_WP` bit covering `page`, one bit standing for four pages.
66const fn wp_bit(page: Page) -> u32 {
67 let number = (page as u32 - BASE) / PAGE_SIZE;
68 1 << (number / PAGES_PER_WP_BIT)
69}
70
71/// Whether an `OB_WP` mask protects the group holding `page`; a protected group
72/// reads 0.
73const fn wp_protected(wp: u32, page: Page) -> bool {
74 wp & wp_bit(page) == 0
75}
76
77/// Reads one bit of `OB_USER`.
78const fn user_bit(user: u8, bit: u8) -> bool {
79 user & (1 << bit) != 0
80}
81
82/// Returns `OB_USER` with one bit set to `on`, the rest untouched.
83const fn set_user_bit(user: u8, bit: u8, on: bool) -> u8 {
84 if on {
85 user | (1 << bit)
86 } else {
87 user & !(1 << bit)
88 }
89}
90
91macro_rules! pages {
92 ($($n:literal),* $(,)?) => {
93 paste::paste! {
94 /// An erasable 1 KB page of the main flash.
95 ///
96 /// How many pages exist follows the flash of the part being built
97 /// for: 16, 32 or 64.
98 #[allow(missing_docs)]
99 #[derive(Clone, Copy, PartialEq, Eq)]
100 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
101 #[repr(u32)]
102 pub enum Page {
103 $([<P $n>] = BASE + $n * PAGE_SIZE),*
104 }
105 }
106 };
107}
108
109#[cfg(chip_x4)]
110#[rustfmt::skip]
111pages!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
112
113#[cfg(chip_x6)]
114#[rustfmt::skip]
115pages!(
116 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
117 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
118);
119
120#[cfg(chip_x8)]
121#[rustfmt::skip]
122pages!(
123 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
124 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
125 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
126 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
127);
128
129/// An FMC event that can raise an interrupt.
130#[derive(Clone, Copy, PartialEq, Eq)]
131#[cfg_attr(feature = "defmt", derive(defmt::Format))]
132pub enum Event {
133 /// An erase or a program operation finished (`ENDIE`).
134 End,
135 /// An operation failed (`ERRIE`); which way is [`Fmc::take_error`].
136 Error,
137}
138
139/// What an erase or a program operation failed on.
140#[derive(Clone, Copy, PartialEq, Eq)]
141#[cfg_attr(feature = "defmt", derive(defmt::Format))]
142pub enum Error {
143 /// The page is protected by the option bytes.
144 WriteProtected,
145 /// The address is not aligned to the programming width.
146 ProgramAlignment,
147 /// The cell was not erased before programming.
148 Program,
149}
150
151/// How far the option bytes lock the flash against being read out.
152#[derive(Clone, Copy, PartialEq, Eq)]
153#[cfg_attr(feature = "defmt", derive(defmt::Format))]
154pub enum ProtectionLevel {
155 /// No protection: the debugger reads and writes the flash freely.
156 None,
157 /// Debugger access is refused. Leaving this level mass-erases the main
158 /// flash, so the contents cannot be recovered by lowering it.
159 Low,
160 /// As `Low`, and the option bytes themselves can no longer be erased or
161 /// reprogrammed — the part stays this way for good.
162 High,
163}
164
165impl ProtectionLevel {
166 /// The `OB_SPC` code standing for this level.
167 const fn spc(self) -> Spc {
168 match self {
169 ProtectionLevel::None => Spc::None,
170 ProtectionLevel::Low => Spc::Low,
171 ProtectionLevel::High => Spc::High,
172 }
173 }
174}
175
176/// The `OB_SPC` byte itself (user manual, Table 2-3).
177#[derive(Clone, Copy, PartialEq, Eq)]
178#[cfg_attr(feature = "defmt", derive(defmt::Format))]
179#[repr(u8)]
180enum Spc {
181 /// No protection.
182 None = 0xA5,
183 /// Low protection. Every code other than the two named here means this one
184 /// as well, so reading the byte back can yield a different number.
185 Low = 0x00,
186 /// High protection, which cannot be undone.
187 High = 0xCC,
188}
189
190/// Which free watchdog the part starts with (`nWDG_SW`).
191#[derive(Clone, Copy, PartialEq, Eq)]
192#[cfg_attr(feature = "defmt", derive(defmt::Format))]
193pub enum FreeWatchdog {
194 /// Started by hardware: the watchdog runs from reset and has to be fed from
195 /// the first instruction on.
196 Hardware,
197 /// Started by software, which is what
198 /// [`Fwdgt::start`](crate::watchdog::Fwdgt::start) expects.
199 Software,
200}
201
202/// What entering deep-sleep or standby does (`nRST_DPSLP`, `nRST_STDBY`).
203#[derive(Clone, Copy, PartialEq, Eq)]
204#[cfg_attr(feature = "defmt", derive(defmt::Format))]
205pub enum LowPowerEntry {
206 /// The part resets instead of entering the mode.
207 Reset,
208 /// The part enters the mode.
209 Enter,
210}
211
212/// The level `BOOT1` is taken to have (`BOOT1_n`, stored inverted).
213#[derive(Clone, Copy, PartialEq, Eq)]
214#[cfg_attr(feature = "defmt", derive(defmt::Format))]
215pub enum Boot1 {
216 /// `BOOT1` reads as 0.
217 Low,
218 /// `BOOT1` reads as 1.
219 High,
220}
221
222/// Whether the supply monitor watches VDDA (`VDDA_VISOR`).
223#[derive(Clone, Copy, PartialEq, Eq)]
224#[cfg_attr(feature = "defmt", derive(defmt::Format))]
225pub enum VddaMonitor {
226 /// Not watched.
227 Disabled,
228 /// Watched; the part is held in reset while VDDA is too low.
229 Enabled,
230}
231
232/// Whether the SRAM parity check is on (`SRAM_PARITY_CHECK`, stored inverted).
233#[derive(Clone, Copy, PartialEq, Eq)]
234#[cfg_attr(feature = "defmt", derive(defmt::Format))]
235pub enum SramParity {
236 /// Not checked.
237 Disabled,
238 /// Checked.
239 Enabled,
240}
241
242/// The option byte block as a whole, read with [`Fmc::read_option_bytes`] and
243/// written back with [`UnlockedFmc::write_option_bytes`].
244///
245/// Writing goes through the whole block because erasing does: option bytes lose
246/// every byte at once, so a single field cannot be changed on its own. Read the
247/// block, change what you need, write it back.
248#[derive(Clone, Copy, PartialEq, Eq)]
249#[cfg_attr(feature = "defmt", derive(defmt::Format))]
250#[must_use]
251pub struct OptionBytes {
252 protection: ProtectionLevel,
253 user: u8,
254 data: u16,
255 wp: u32,
256}
257
258impl Default for OptionBytes {
259 /// The state the part leaves the factory in: no protection, and every other
260 /// byte erased.
261 fn default() -> Self {
262 Self {
263 protection: ProtectionLevel::None,
264 user: 0xFF,
265 data: 0xFFFF,
266 wp: WP_ALL_FREE,
267 }
268 }
269}
270
271impl OptionBytes {
272 /// Leaves the flash readable by a debugger.
273 pub const fn no_protection(mut self) -> Self {
274 self.protection = ProtectionLevel::None;
275 self
276 }
277 /// Refuses debugger access. Going back to
278 /// [`no_protection`](Self::no_protection) later mass-erases the main flash.
279 pub const fn protection_low(mut self) -> Self {
280 self.protection = ProtectionLevel::Low;
281 self
282 }
283 /// Refuses debugger access **for good**: after this the option bytes
284 /// themselves can no longer be erased or reprogrammed, so no later call can
285 /// undo it and the part keeps this setting for the rest of its life.
286 pub const fn protection_high_forever(mut self) -> Self {
287 self.protection = ProtectionLevel::High;
288 self
289 }
290 /// Picks which free watchdog the part starts with.
291 pub const fn free_watchdog(mut self, watchdog: FreeWatchdog) -> Self {
292 self.user = set_user_bit(
293 self.user,
294 BIT_NWDG_SW,
295 matches!(watchdog, FreeWatchdog::Software),
296 );
297 self
298 }
299 /// Says what entering deep-sleep does.
300 pub const fn deep_sleep(mut self, entry: LowPowerEntry) -> Self {
301 self.user = set_user_bit(
302 self.user,
303 BIT_NRST_DPSLP,
304 matches!(entry, LowPowerEntry::Enter),
305 );
306 self
307 }
308 /// Says what entering standby does.
309 pub const fn standby(mut self, entry: LowPowerEntry) -> Self {
310 self.user = set_user_bit(
311 self.user,
312 BIT_NRST_STDBY,
313 matches!(entry, LowPowerEntry::Enter),
314 );
315 self
316 }
317 /// Sets the level `BOOT1` is taken to have.
318 pub const fn boot1(mut self, boot1: Boot1) -> Self {
319 self.user = set_user_bit(self.user, BIT_BOOT1_N, matches!(boot1, Boot1::Low));
320 self
321 }
322 /// Turns the VDDA monitor on or off.
323 pub const fn vdda_monitor(mut self, monitor: VddaMonitor) -> Self {
324 self.user = set_user_bit(
325 self.user,
326 BIT_VDDA_VISOR,
327 matches!(monitor, VddaMonitor::Enabled),
328 );
329 self
330 }
331 /// Turns the SRAM parity check on or off.
332 pub const fn sram_parity(mut self, parity: SramParity) -> Self {
333 self.user = set_user_bit(
334 self.user,
335 BIT_SRAM_PARITY,
336 matches!(parity, SramParity::Disabled),
337 );
338 self
339 }
340 /// Sets the two user data bytes, which the silicon never reads itself.
341 pub const fn data(mut self, data: u16) -> Self {
342 self.data = data;
343 self
344 }
345 /// Closes `page` to erasing and programming.
346 ///
347 /// One `OB_WP` bit covers four pages, so this closes the three neighbours of
348 /// `page` along with it.
349 pub const fn protect(mut self, page: Page) -> Self {
350 self.wp &= !wp_bit(page);
351 self
352 }
353 /// Opens `page`, and with it the three pages sharing its `OB_WP` bit.
354 pub const fn unprotect(mut self, page: Page) -> Self {
355 self.wp |= wp_bit(page);
356 self
357 }
358
359 /// The protection level this block asks for.
360 pub const fn protection(&self) -> ProtectionLevel {
361 self.protection
362 }
363 /// Which free watchdog the part starts with.
364 pub const fn get_free_watchdog(&self) -> FreeWatchdog {
365 if user_bit(self.user, BIT_NWDG_SW) {
366 FreeWatchdog::Software
367 } else {
368 FreeWatchdog::Hardware
369 }
370 }
371 /// What entering deep-sleep does.
372 pub const fn get_deep_sleep(&self) -> LowPowerEntry {
373 if user_bit(self.user, BIT_NRST_DPSLP) {
374 LowPowerEntry::Enter
375 } else {
376 LowPowerEntry::Reset
377 }
378 }
379 /// What entering standby does.
380 pub const fn get_standby(&self) -> LowPowerEntry {
381 if user_bit(self.user, BIT_NRST_STDBY) {
382 LowPowerEntry::Enter
383 } else {
384 LowPowerEntry::Reset
385 }
386 }
387 /// The level `BOOT1` is taken to have.
388 pub const fn get_boot1(&self) -> Boot1 {
389 if user_bit(self.user, BIT_BOOT1_N) {
390 Boot1::Low
391 } else {
392 Boot1::High
393 }
394 }
395 /// Whether the VDDA monitor is on.
396 pub const fn get_vdda_monitor(&self) -> VddaMonitor {
397 if user_bit(self.user, BIT_VDDA_VISOR) {
398 VddaMonitor::Enabled
399 } else {
400 VddaMonitor::Disabled
401 }
402 }
403 /// Whether the SRAM parity check is on.
404 pub const fn get_sram_parity(&self) -> SramParity {
405 if user_bit(self.user, BIT_SRAM_PARITY) {
406 SramParity::Disabled
407 } else {
408 SramParity::Enabled
409 }
410 }
411 /// The two user data bytes.
412 pub const fn data_bytes(&self) -> u16 {
413 self.data
414 }
415 /// Whether this block closes `page` to erasing and programming.
416 pub const fn is_protected(&self, page: Page) -> bool {
417 wp_protected(self.wp, page)
418 }
419}
420
421/// The flash controller with `CTL` unlocked, borrowed for the body of
422/// [`Fmc::with_unlocked`] and locked again when that call returns.
423pub struct UnlockedFmc<'a> {
424 fmc: &'a mut Fmc,
425}
426
427impl UnlockedFmc<'_> {
428 fn lock(self) {
429 self.fmc.fmc.ctl().modify(|_, w| w.lk().lock());
430 }
431
432 /// Erases one page, blocking until it is done.
433 ///
434 /// The whole page reads back as `0xFF`; nothing here checks what the page
435 /// holds.
436 ///
437 /// # Errors
438 ///
439 /// [`Error::WriteProtected`] if `page` is write-protected.
440 pub fn erase_page(&mut self, page: Page) -> Result<(), Error> {
441 self.fmc.fmc.ctl().modify(|_, w| w.per().page_erase());
442 self.fmc.fmc.addr().write(|w| w.addr().bits(page as u32));
443 self.fmc.fmc.ctl().modify(|_, w| w.start().start());
444 let result = self.fmc.wait_busy();
445 self.fmc.fmc.ctl().modify(|_, w| w.per().clear_bit());
446 result
447 }
448 /// Erases the whole main flash, blocking until it is done.
449 ///
450 /// That includes the code running the call, so this only makes sense from
451 /// SRAM or from a debugger.
452 ///
453 /// # Errors
454 ///
455 /// [`Error::WriteProtected`] if any page is write-protected.
456 pub fn mass_erase(&mut self) -> Result<(), Error> {
457 self.fmc.fmc.ctl().modify(|_, w| w.mer().mass_erase());
458 self.fmc.fmc.ctl().modify(|_, w| w.start().start());
459 let result = self.fmc.wait_busy();
460 self.fmc.fmc.ctl().modify(|_, w| w.mer().clear_bit());
461 result
462 }
463 /// Programs one 32-bit word, `index` counting words from the start of
464 /// `page`, and blocks until it is done.
465 ///
466 /// Programming only clears bits, so the word has to be erased first.
467 ///
468 /// # Errors
469 ///
470 /// [`Error::WriteProtected`] if `page` is write-protected, [`Error::Program`]
471 /// if the word holds anything but `0xFFFF_FFFF`.
472 pub fn program(&mut self, page: Page, index: u8, word: u32) -> Result<(), Error> {
473 self.fmc.fmc.ctl().modify(|_, w| w.pg().program());
474 let addr = page as u32 + index as u32 * WORD_SIZE;
475 // The write itself is the command: `PG` makes the FMC latch the address
476 // and the data off the bus, so there is no `ADDR` and no `START` here.
477 // SAFETY: the address is in the flash and a multiple of four by
478 // construction — `Page` gives the base and 256 words is exactly what `u8`
479 // counts.
480 unsafe {
481 core::ptr::write_volatile(addr as *mut u32, word);
482 };
483 let result = self.fmc.wait_busy();
484 self.fmc.fmc.ctl().modify(|_, w| w.pg().clear_bit());
485 result
486 }
487
488 /// Erases the option byte block and programs `ob` in its place, blocking
489 /// until it is done.
490 ///
491 /// The whole block goes at once because erasing takes it all: read it with
492 /// [`Fmc::read_option_bytes`], change what you need, write it back.
493 ///
494 /// Nothing here takes effect until the option bytes are loaded again, by
495 /// [`Fmc::reload_option_bytes`] or by the next power-up.
496 ///
497 /// # Errors
498 ///
499 /// The first error the erase or the programming reports. The rest of the
500 /// call is skipped, leaving the block erased or partly programmed.
501 pub fn write_option_bytes(&mut self, ob: &OptionBytes) -> Result<(), Error> {
502 // `OBER` and `OBPG` answer to a second lock of their own.
503 self.fmc.fmc.obkey().write(|w| w.obkey().bits(UNLOCK_KEY1));
504 self.fmc.fmc.obkey().write(|w| w.obkey().bits(UNLOCK_KEY2));
505 self.fmc.fmc.ctl().modify(|_, w| w.obwen().set_bit());
506 let result = self
507 .erase_option_bytes()
508 .and_then(|()| self.program_option_bytes(ob));
509 self.fmc.fmc.ctl().modify(|_, w| w.obwen().disable());
510 result
511 }
512 /// Erases the whole option byte block, every byte going back to `0xFF`.
513 fn erase_option_bytes(&mut self) -> Result<(), Error> {
514 self.fmc
515 .fmc
516 .ctl()
517 .modify(|_, w| w.ober().option_byte_erase());
518 self.fmc.fmc.ctl().modify(|_, w| w.start().start());
519 let result = self.fmc.wait_busy();
520 self.fmc.fmc.ctl().modify(|_, w| w.ober().clear_bit());
521 result
522 }
523 /// Programs the erased block, one word per pair of option bytes.
524 fn program_option_bytes(&mut self, ob: &OptionBytes) -> Result<(), Error> {
525 let data = ob.data.to_le_bytes();
526 let wp = ob.wp.to_le_bytes();
527 let words = [
528 ob_word(ob.protection.spc() as u8, ob.user),
529 ob_word(data[0], data[1]),
530 ob_word(wp[0], wp[1]),
531 ob_word(wp[2], wp[3]),
532 ];
533
534 self.fmc
535 .fmc
536 .ctl()
537 .modify(|_, w| w.obpg().option_byte_programming());
538 let mut result = Ok(());
539 for (index, word) in words.iter().enumerate() {
540 let addr = OB_BASE + index as u32 * WORD_SIZE;
541 // As in `program`, the write is the command.
542 // SAFETY: the address is a word of the option byte block, which the
543 // loop cannot leave.
544 unsafe { core::ptr::write_volatile(addr as *mut u32, *word) };
545 result = self.fmc.wait_busy();
546 if result.is_err() {
547 break;
548 }
549 }
550 self.fmc.fmc.ctl().modify(|_, w| w.obpg().clear_bit());
551 result
552 }
553
554 /// Raises an interrupt on `event`, which still has to be unmasked in the
555 /// NVIC.
556 ///
557 /// The interrupt outlives [`Fmc::with_unlocked`]: locking `CTL` again leaves
558 /// it enabled.
559 ///
560 /// `ENDF` is a level, and it rises while a blocking operation still holds
561 /// the controller, so a handler has nothing to clear it with: mask the line
562 /// in the NVIC inside the handler, then unpend and unmask it once the call
563 /// has returned.
564 pub fn listen(&mut self, event: Event) {
565 self.fmc.fmc.ctl().modify(|_, w| match event {
566 Event::End => w.endie().enabled(),
567 Event::Error => w.errie().enabled(),
568 });
569 }
570 /// Stops `event` from raising an interrupt.
571 pub fn unlisten(&mut self, event: Event) {
572 self.fmc.fmc.ctl().modify(|_, w| match event {
573 Event::End => w.endie().disabled(),
574 Event::Error => w.errie().disabled(),
575 });
576 }
577}
578
579/// Owns the flash memory controller.
580pub struct Fmc {
581 fmc: pac::Fmc,
582}
583
584impl Fmc {
585 /// Blocks until the running operation ends, then clears `ENDF` and reports
586 /// how it went.
587 fn wait_busy(&mut self) -> Result<(), Error> {
588 while self.fmc.stat().read().busy().is_active() {}
589 self.clear_interrupt(Event::End);
590 match self.take_error() {
591 Some(error) => Err(error),
592 None => Ok(()),
593 }
594 }
595
596 fn unlock(&mut self) -> UnlockedFmc<'_> {
597 self.fmc.key().write(|w| w.key().bits(UNLOCK_KEY1));
598 self.fmc.key().write(|w| w.key().bits(UNLOCK_KEY2));
599 UnlockedFmc { fmc: self }
600 }
601
602 /// Unlocks `CTL`, runs `f`, locks it again, and returns what `f` returned.
603 ///
604 /// The unlocked handle cannot outlive the call, so the flash is never left
605 /// writable.
606 pub fn with_unlocked<R>(&mut self, f: impl FnOnce(&mut UnlockedFmc) -> R) -> R {
607 let mut unlocked = self.unlock();
608 let result = f(&mut unlocked);
609 unlocked.lock();
610 result
611 }
612
613 /// Returns the peripheral with its interrupts off.
614 pub fn release(mut self) -> pac::Fmc {
615 self.with_unlocked(|fmc| {
616 fmc.unlisten(Event::End);
617 fmc.unlisten(Event::Error);
618 });
619 self.fmc
620 }
621
622 /// Sets the wait states `hclk` can be read at, `hclk` given in Hz.
623 ///
624 /// Must run before the system clock rises and after it falls, so the flash
625 /// is never read faster than it responds.
626 pub(crate) fn set_ws(&mut self, hclk: u32) {
627 self.fmc.ws().modify(|_, w| {
628 if hclk <= WS0_MAX_HCLK {
629 w.wscnt().ws0()
630 } else if hclk <= WS1_MAX_HCLK {
631 w.wscnt().ws1()
632 } else if hclk <= WS2_MAX_HCLK {
633 w.wscnt().ws2()
634 } else {
635 unreachable!()
636 }
637 });
638 }
639
640 /// Whether the option bytes protect `page` from being erased or programmed.
641 ///
642 /// This is what stands behind [`Error::WriteProtected`]. Protection comes
643 /// in groups of four pages, so neighbours share the answer.
644 pub fn is_protected(&self, page: Page) -> bool {
645 wp_protected(self.fmc.wp().read().bits(), page)
646 }
647 /// The security protection level the option bytes ask for.
648 pub fn protection_level(&self) -> ProtectionLevel {
649 let plevel = self.fmc.obstat().read().plevel();
650 if plevel.is_none() {
651 ProtectionLevel::None
652 } else if plevel.is_low() {
653 ProtectionLevel::Low
654 } else {
655 ProtectionLevel::High
656 }
657 }
658 /// Whether the option bytes failed their checksum, in which case the
659 /// defaults were loaded instead of them.
660 pub fn option_error(&self) -> bool {
661 self.fmc.obstat().read().oberr().is_error()
662 }
663 /// The user option byte, raw;
664 /// [`read_option_bytes`](Self::read_option_bytes) decodes it.
665 pub fn user_option(&self) -> u8 {
666 self.fmc.obstat().read().ob_user().bits()
667 }
668 /// The two user data bytes of the option block, raw — the silicon attaches
669 /// no meaning to them.
670 pub fn data_option(&self) -> u16 {
671 self.fmc.obstat().read().ob_data().bits()
672 }
673 /// The product ID code, fixed in silicon and read-only.
674 pub fn product_id_code(&self) -> u32 {
675 self.fmc.pid().read().pid().bits()
676 }
677
678 /// The option bytes as they were loaded at reset.
679 ///
680 /// This is the block to change and hand to
681 /// [`UnlockedFmc::write_option_bytes`]; it reads what is in force, so a
682 /// block written since the last reset is not what comes back.
683 pub fn read_option_bytes(&self) -> OptionBytes {
684 OptionBytes {
685 protection: self.protection_level(),
686 user: self.user_option(),
687 data: self.data_option(),
688 wp: self.fmc.wp().read().bits(),
689 }
690 }
691
692 /// Reloads the option bytes, which resets the part and therefore never
693 /// returns.
694 ///
695 /// This is how a written block takes effect without cycling the power.
696 pub fn reload_option_bytes(&mut self) -> ! {
697 self.fmc.ctl().modify(|_, w| w.obrld().set_bit());
698 loop {
699 cortex_m::asm::nop();
700 }
701 }
702
703 /// Turns the prefetch buffer on or off; it comes up on after reset.
704 ///
705 /// Off, every fetch waits out the wait states of its own, which is slower on
706 /// average but takes the buffer out of the timing.
707 pub fn set_prefetch(&mut self, on: bool) {
708 self.fmc.ws().modify(|_, w| w.pfen().bit(on));
709 }
710 /// Whether the prefetch buffer is on.
711 pub fn is_prefetch_enabled(&self) -> bool {
712 self.fmc.ws().read().pfen().bit_is_set()
713 }
714
715 /// Returns the error the last operation ended with, clearing its flag.
716 pub fn take_error(&mut self) -> Option<Error> {
717 let stat = self.fmc.stat().read();
718 if stat.wperr().is_error() {
719 self.fmc.stat().write(|w| w.wperr().clear());
720 Some(Error::WriteProtected)
721 } else if stat.pgaerr().bit_is_set() {
722 self.fmc.stat().write(|w| w.pgaerr().bit(true));
723 Some(Error::ProgramAlignment)
724 } else if stat.pgerr().is_error() {
725 self.fmc.stat().write(|w| w.pgerr().clear());
726 Some(Error::Program)
727 } else {
728 None
729 }
730 }
731
732 /// Whether `event` currently raises an interrupt.
733 pub fn is_listening(&self, event: Event) -> bool {
734 let ctl = self.fmc.ctl().read();
735 match event {
736 Event::End => ctl.endie().is_enabled(),
737 Event::Error => ctl.errie().is_enabled(),
738 }
739 }
740
741 /// Clears the flag behind `event`, which is what stops it re-entering the
742 /// handler.
743 ///
744 /// For [`Event::Error`] this drops every error flag at once; use
745 /// [`take_error`](Self::take_error) instead to learn which one it was, it
746 /// clears the flag as well.
747 pub fn clear_interrupt(&mut self, event: Event) {
748 self.fmc.stat().write(|w| match event {
749 Event::End => w.endf().clear(),
750 Event::Error => w.wperr().clear().pgaerr().bit(true).pgerr().clear(),
751 });
752 }
753}
754
755/// Entry point on the raw peripheral.
756pub trait FmcExt {
757 /// Takes the peripheral.
758 ///
759 /// Nothing is written and no clock is gated — the flash controller is always
760 /// clocked.
761 fn constrain(self) -> Fmc;
762}
763
764impl FmcExt for pac::Fmc {
765 fn constrain(self) -> Fmc {
766 Fmc { fmc: self }
767 }
768}