1use cfg_if::cfg_if;
10
11use crate::pac::FLASH;
12
13const BANK1_START_ADDR: usize = 0x0800_0000;
17
18cfg_if! {
19 if #[cfg(any(feature = "l5", feature = "g473", feature = "g474", feature = "g483", feature = "g484"))] {
20 const PAGE_SIZE_SINGLE_BANK: usize = 4_096;
21 const PAGE_SIZE_DUAL_BANK: usize = 2_048;
22 const BANK2_START_ADDR: usize = 0x0804_0000;
23 } else if #[cfg(feature = "h7")]{
24 const SECTOR_SIZE: usize = 0x2_0000;
25 const BANK2_START_ADDR: usize = 0x0810_0000;
26 } else {
27 const PAGE_SIZE: usize = 2_048;
28 #[allow(dead_code)] const BANK2_START_ADDR: usize = 0x0804_0000;
30 }
31}
32
33cfg_if! {
34 if #[cfg(any(feature = "l5", feature = "h5"))] {
35 mod trustzone;
36 pub use trustzone::*;
37 } else {
38 mod non_trustzone;
39 pub use non_trustzone::*;
40 }
41}
42
43#[cfg_attr(feature = "defmt", derive(defmt::Format))]
44#[derive(Debug, Clone, Copy, Eq, PartialEq)]
45pub enum FlashError {
47 Busy,
49 Illegal,
51 EccError,
53 PageOutOfRange,
55 Failure,
57}
58
59pub struct Flash {
60 pub regs: FLASH,
61 #[cfg(any(
62 feature = "g473",
63 feature = "g474",
64 feature = "g483",
65 feature = "g484",
66 feature = "l5"
67 ))]
68 pub dual_bank: DualBank,
69}
70
71impl Flash {
75 #[cfg(not(any(
76 feature = "g473",
77 feature = "g474",
78 feature = "g483",
79 feature = "g484",
80 feature = "l5"
81 )))]
82 pub fn new(regs: FLASH) -> Self {
84 Self { regs }
85 }
86
87 #[cfg(any(
88 feature = "g473",
89 feature = "g474",
90 feature = "g483",
91 feature = "g484",
92 feature = "l5"
93 ))]
94 pub fn new(regs: FLASH, dual_bank: DualBank) -> Self {
95 Self { regs, dual_bank }
97 }
98
99 #[allow(unused_variables)] pub fn read(&self, bank: Bank, page: usize, offset: usize, buf: &mut [u8]) {
102 cfg_if! {
110 if #[cfg(any(
111 feature = "g473",
112 feature = "g474",
113 feature = "g483",
114 feature = "g484",
115 feature = "l5",
116 ))] {
117 let mut addr = page_to_address(self.dual_bank, bank, page) as *mut u32;
118 } else if #[cfg(feature = "h7")]{
119 let mut addr = page_to_address(bank, page) as *mut u32;
120 } else {
121 let mut addr = page_to_address(page) as *mut u32;
122 }
123 }
124
125 unsafe {
126 addr = unsafe { addr.add(offset) };
128 for chunk in buf.chunks_mut(4) {
130 let word = unsafe { core::ptr::read_volatile(addr) };
131 let bytes = word.to_le_bytes();
132
133 let len = chunk.len();
134 if len < 4 {
135 chunk[0..len].copy_from_slice(&bytes[0..len]);
136 } else {
137 chunk[0..4].copy_from_slice(&bytes);
138 };
139
140 unsafe { addr = addr.add(1) };
141 }
142 }
143 }
144}
145
146#[cfg(not(any(
149 feature = "g473",
150 feature = "g474",
151 feature = "g483",
152 feature = "g484",
153 feature = "h5",
154 feature = "l5",
155 feature = "h7"
156)))]
157fn page_to_address(page: usize) -> usize {
158 BANK1_START_ADDR + page * PAGE_SIZE
159}
160
161#[cfg(any(
162 feature = "g473",
163 feature = "g474",
164 feature = "g483",
165 feature = "g484",
166 feature = "h5",
167 feature = "l5",
168))]
169fn page_to_address(dual_bank: DualBank, bank: Bank, page: usize) -> usize {
170 if dual_bank == DualBank::Single {
171 BANK1_START_ADDR + page * PAGE_SIZE_SINGLE_BANK
172 } else {
173 match bank {
174 Bank::B1 => BANK1_START_ADDR + page * PAGE_SIZE_DUAL_BANK,
175 Bank::B2 => BANK2_START_ADDR + page * PAGE_SIZE_DUAL_BANK,
176 }
177 }
178}
179
180#[cfg(feature = "h7")]
181fn page_to_address(bank: Bank, sector: usize) -> usize {
184 let starting_pt = match bank {
186 Bank::B1 => BANK1_START_ADDR,
187 #[cfg(not(any(feature = "h747cm4", feature = "h747cm7")))]
189 Bank::B2 => BANK2_START_ADDR,
190 };
191
192 starting_pt + sector * SECTOR_SIZE
193}