1#![deny(missing_docs)]
32
33use crate::stm32::{flash, FLASH};
34use crate::traits::flash as flash_trait;
35use core::convert::TryInto;
36use core::{mem, ops::Drop, ptr};
37pub use flash_trait::{Error, FlashPage, Read, WriteErase};
38
39pub trait FlashExt {
41 fn constrain(self) -> Parts;
43}
44
45impl FlashExt for FLASH {
46 fn constrain(self) -> Parts {
47 Parts {
48 acr: ACR {},
49 pdkeyr: PDKEYR {},
50 keyr: KEYR {},
51 optkeyr: OPTKEYR {},
52 sr: SR {},
53 cr: CR {},
54 eccr: ECCR {},
55 pcrop1sr: PCROP1SR {},
56 pcrop1er: PCROP1ER {},
57 wrp1ar: WRP1AR {},
58 wrp1br: WRP1BR {},
59 }
60 }
61}
62
63pub struct Parts {
65 pub acr: ACR,
67 pub pdkeyr: PDKEYR,
69 pub keyr: KEYR,
71 pub optkeyr: OPTKEYR,
73 pub sr: SR,
75 pub cr: CR,
77 pub eccr: ECCR,
79 pub pcrop1sr: PCROP1SR,
81 pub pcrop1er: PCROP1ER,
83 pub wrp1ar: WRP1AR,
85 pub wrp1br: WRP1BR,
87}
88
89macro_rules! generate_register {
90 ($a:ident, $b:ident, $name:expr) => {
91 #[doc = "Opaque "]
92 #[doc = $name]
93 #[doc = " register"]
94 pub struct $a;
95
96 impl $a {
97 #[allow(unused)]
98 pub(crate) fn $b(&mut self) -> &flash::$a {
99 unsafe { &(*FLASH::ptr()).$b }
101 }
102 }
103 };
104
105 ($a:ident, $b:ident) => {
106 generate_register!($a, $b, stringify!($a));
107 };
108}
109
110generate_register!(ACR, acr);
111generate_register!(PDKEYR, pdkeyr);
112generate_register!(KEYR, keyr);
113generate_register!(OPTKEYR, optkeyr);
114generate_register!(SR, sr);
115generate_register!(CR, cr);
116generate_register!(ECCR, eccr);
117generate_register!(PCROP1SR, pcrop1sr);
118generate_register!(PCROP1ER, pcrop1er);
119generate_register!(WRP1AR, wrp1ar);
120generate_register!(WRP1BR, wrp1br);
121
122const FLASH_KEY1: u32 = 0x4567_0123;
123const FLASH_KEY2: u32 = 0xCDEF_89AB;
124
125impl KEYR {
126 pub fn unlock_flash<'a>(
128 &'a mut self,
129 sr: &'a mut SR,
130 cr: &'a mut CR,
131 ) -> Result<FlashProgramming<'a>, Error> {
132 let keyr = self.keyr();
133 unsafe {
134 keyr.write(|w| w.bits(FLASH_KEY1));
135 keyr.write(|w| w.bits(FLASH_KEY2));
136 }
137
138 if cr.cr().read().lock().bit_is_clear() {
139 Ok(FlashProgramming { sr, cr })
140 } else {
141 Err(Error::Failure)
142 }
143 }
144}
145
146impl FlashPage {
147 pub const fn to_address(&self) -> usize {
149 0x0800_0000 + self.0 * 2048
150 }
151}
152
153pub struct FlashProgramming<'a> {
155 sr: &'a mut SR,
156 cr: &'a mut CR,
157}
158
159impl<'a> Drop for FlashProgramming<'a> {
160 fn drop(&mut self) {
161 self.lock();
163 }
164}
165
166impl<'a> Read for FlashProgramming<'a> {
167 type NativeType = u8;
168
169 #[inline]
170 fn read_native(&self, address: usize, array: &mut [Self::NativeType]) {
171 let mut address = address as *const Self::NativeType;
172
173 for data in array {
174 unsafe {
175 *data = ptr::read(address);
176 address = address.add(1);
177 }
178 }
179 }
180
181 #[inline]
182 fn read(&self, address: usize, buf: &mut [u8]) {
183 self.read_native(address, buf);
184 }
185}
186
187impl<'a> WriteErase for FlashProgramming<'a> {
188 type NativeType = u64;
189
190 fn status(&self) -> flash_trait::Result {
191 let sr = unsafe { &(*FLASH::ptr()).sr }.read();
192
193 if sr.bsy().bit_is_set() {
194 Err(flash_trait::Error::Busy)
195 } else if sr.pgaerr().bit_is_set() || sr.progerr().bit_is_set() || sr.wrperr().bit_is_set()
196 {
197 Err(flash_trait::Error::Illegal)
198 } else {
199 Ok(())
200 }
201 }
202
203 fn erase_page(&mut self, page: flash_trait::FlashPage) -> flash_trait::Result {
204 match page.0 {
205 0..=255 => {
206 self.cr.cr().modify(|_, w| unsafe {
207 w.bker()
208 .clear_bit()
209 .pnb()
210 .bits(page.0 as u8)
211 .per()
212 .set_bit()
213 });
214 }
215 256..=511 => {
216 self.cr.cr().modify(|_, w| unsafe {
217 w.bker()
218 .set_bit()
219 .pnb()
220 .bits((page.0 - 256) as u8)
221 .per()
222 .set_bit()
223 });
224 }
225 _ => {
226 return Err(flash_trait::Error::PageOutOfRange);
227 }
228 }
229
230 self.cr.cr().modify(|_, w| w.start().set_bit());
231
232 let res = self.wait();
233
234 self.cr.cr().modify(|_, w| w.per().clear_bit());
235
236 res
237 }
238
239 fn write_native(&mut self, address: usize, array: &[Self::NativeType]) -> flash_trait::Result {
240 let mut address = address as *mut u32;
243
244 self.cr.cr().modify(|_, w| w.pg().set_bit());
245
246 for dword in array {
247 unsafe {
248 ptr::write_volatile(address, *dword as u32);
249 ptr::write_volatile(address.add(1), (*dword >> 32) as u32);
250
251 address = address.add(2);
252 }
253
254 self.wait()?;
255
256 if self.sr.sr().read().eop().bit_is_set() {
257 self.sr.sr().modify(|_, w| w.eop().clear_bit());
258 }
259 }
260
261 self.cr.cr().modify(|_, w| w.pg().clear_bit());
262
263 Ok(())
264 }
265
266 fn write(&mut self, address: usize, data: &[u8]) -> flash_trait::Result {
267 let address_offset = address % mem::align_of::<Self::NativeType>();
268 let unaligned_size = (mem::size_of::<Self::NativeType>() - address_offset)
269 % mem::size_of::<Self::NativeType>();
270
271 if unaligned_size > 0 {
272 let unaligned_data = &data[..unaligned_size];
273 let mut data = 0xffff_ffff_ffff_ffffu64;
275 for b in unaligned_data {
276 data = (data >> 8) | ((*b as Self::NativeType) << 56);
277 }
278
279 let unaligned_address = address - address_offset;
280 let native = &[data];
281 self.write_native(unaligned_address, native)?;
282 }
283
284 let aligned_data = &data[unaligned_size..];
286 let mut aligned_address = if unaligned_size > 0 {
287 address - address_offset + mem::size_of::<Self::NativeType>()
288 } else {
289 address
290 };
291
292 let mut chunks = aligned_data.chunks_exact(mem::size_of::<Self::NativeType>());
293
294 while let Some(exact_chunk) = chunks.next() {
295 let native = &[Self::NativeType::from_ne_bytes(
297 exact_chunk.try_into().unwrap(),
298 )];
299 self.write_native(aligned_address, native)?;
300 aligned_address += mem::size_of::<Self::NativeType>();
301 }
302
303 let rem = chunks.remainder();
304
305 if !rem.is_empty() {
306 let mut data = 0xffff_ffff_ffff_ffffu64;
307 for b in rem.iter().rev() {
309 data = (data << 8) | *b as Self::NativeType;
310 }
311
312 let native = &[data];
313 self.write_native(aligned_address, native)?;
314 }
315
316 Ok(())
317 }
318}
319
320impl<'a> FlashProgramming<'a> {
321 fn lock(&mut self) {
323 self.cr.cr().modify(|_, w| w.lock().set_bit());
324 }
325
326 fn wait(&mut self) -> flash_trait::Result {
328 while self.sr.sr().read().bsy().bit_is_set() {}
329
330 self.status()
331 }
332
333 pub fn erase_all_pages(&mut self) -> flash_trait::Result {
336 self.cr.cr().modify(|_, w| w.mer1().set_bit());
337 self.cr.cr().modify(|_, w| w.start().set_bit());
338
339 let res = self.wait();
340
341 self.cr.cr().modify(|_, w| w.mer1().clear_bit());
342
343 res
344 }
345}