1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//! Flash memory (FLASH)
use embedded_storage::nor_flash::{NorFlashError, NorFlashErrorKind};

#[cfg(flash_f4)]
mod asynch;
#[cfg(flash)]
mod common;

#[cfg(flash_f4)]
pub use asynch::InterruptHandler;
#[cfg(flash)]
pub use common::*;

pub use crate::_generated::flash_regions::*;
pub use crate::_generated::MAX_ERASE_SIZE;
pub use crate::pac::{FLASH_BASE, FLASH_SIZE, WRITE_SIZE};

/// Get whether the default flash layout is being used.
///
/// In some chips, dual-bank is not default. This will then return `false`
/// when dual-bank is enabled.
pub fn is_default_layout() -> bool {
    family::is_default_layout()
}

/// Get all flash regions.
pub fn get_flash_regions() -> &'static [&'static FlashRegion] {
    family::get_flash_regions()
}

/// Read size (always 1)
pub const READ_SIZE: usize = 1;

/// Blocking flash mode typestate.
pub enum Blocking {}
/// Async flash mode typestate.
pub enum Async {}

/// Flash memory region
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct FlashRegion {
    /// Bank number.
    pub bank: FlashBank,
    /// Absolute base address.
    pub base: u32,
    /// Size in bytes.
    pub size: u32,
    /// Erase size (sector size).
    pub erase_size: u32,
    /// Minimum write size.
    pub write_size: u32,
    /// Erase value (usually `0xFF`, but is `0x00` in some chips)
    pub erase_value: u8,
    pub(crate) _ensure_internal: (),
}

impl FlashRegion {
    /// Absolute end address.
    pub const fn end(&self) -> u32 {
        self.base + self.size
    }

    /// Number of sectors in the region.
    pub const fn sectors(&self) -> u8 {
        (self.size / self.erase_size) as u8
    }
}

/// Flash sector.
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct FlashSector {
    /// Bank number.
    pub bank: FlashBank,
    /// Sector number within the bank.
    pub index_in_bank: u8,
    /// Absolute start address.
    pub start: u32,
    /// Size in bytes.
    pub size: u32,
}

/// Flash bank.
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum FlashBank {
    /// Bank 1
    Bank1 = 0,
    /// Bank 2
    Bank2 = 1,
    /// OTP region
    Otp,
}

#[cfg_attr(any(flash_l0, flash_l1, flash_l4, flash_wl, flash_wb), path = "l.rs")]
#[cfg_attr(flash_f0, path = "f0.rs")]
#[cfg_attr(any(flash_f1, flash_f3), path = "f1f3.rs")]
#[cfg_attr(flash_f4, path = "f4.rs")]
#[cfg_attr(flash_f7, path = "f7.rs")]
#[cfg_attr(any(flash_g0, flash_g4), path = "g.rs")]
#[cfg_attr(flash_h7, path = "h7.rs")]
#[cfg_attr(flash_h7ab, path = "h7.rs")]
#[cfg_attr(
    not(any(
        flash_l0, flash_l1, flash_l4, flash_wl, flash_wb, flash_f0, flash_f1, flash_f3, flash_f4, flash_f7, flash_g0,
        flash_g4, flash_h7, flash_h7ab
    )),
    path = "other.rs"
)]
mod family;

#[allow(unused_imports)]
pub use family::*;

/// Flash error
///
/// See STM32 Reference Manual for your chip for details.
#[allow(missing_docs)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
    Prog,
    Size,
    Miss,
    Seq,
    Protected,
    Unaligned,
    Parallelism,
}

impl NorFlashError for Error {
    fn kind(&self) -> NorFlashErrorKind {
        match self {
            Self::Size => NorFlashErrorKind::OutOfBounds,
            Self::Unaligned => NorFlashErrorKind::NotAligned,
            _ => NorFlashErrorKind::Other,
        }
    }
}