1use crate::pac::FLASH;
4use nb::block;
5
6const FLASH_BASE: *mut u8 = 0x800_0000 as *mut u8;
8
9const MAX_FLASH_ADDRESS: *mut u8 = 0x81F_FFFF as *mut u8;
11
12#[derive(Debug, PartialEq, Eq)]
14pub enum Error {
15 Busy,
16 Locked,
17 EraseSequence,
18 ProgrammingParallelism,
19 ProgrammingAlignment,
20 WriteProtection,
21}
22
23pub struct Flash {
25 registers: FLASH,
26}
27
28impl Flash {
29 pub fn new(flash: FLASH) -> Self {
31 Self { registers: flash }
32 }
33
34 pub fn unlock(&mut self) {
36 if !self.is_locked() {
37 return;
40 }
41
42 self.registers.keyr.write(|w| w.key().bits(0x45670123));
43 self.registers.keyr.write(|w| w.key().bits(0xCDEF89AB));
44 }
45
46 pub fn lock(&mut self) {
48 self.registers.cr.modify(|_, w| w.lock().set_bit());
49 }
50
51 fn is_locked(&self) -> bool {
53 self.registers.cr.read().lock().is_locked()
54 }
55
56 fn is_busy(&self) -> bool {
58 self.registers.sr.read().bsy().bit_is_set()
59 }
60
61 pub fn erase_sector(&mut self, sector_number: u8) -> Result<EraseSequence<'_>, Error> {
66 EraseSequence::new_erase_sector(self, sector_number)
67 }
68
69 pub fn blocking_erase_sector(&mut self, sector_number: u8) -> Result<(), Error> {
73 let mut sequence = self.erase_sector(sector_number)?;
74 block!(sequence.wait())
75 }
76
77 pub fn mass_erase(&mut self) -> Result<EraseSequence<'_>, Error> {
82 EraseSequence::new_mass_erase(self)
83 }
84
85 pub fn blocking_mass_erase(&mut self) -> Result<(), Error> {
89 let mut sequence = self.mass_erase()?;
90 block!(sequence.wait())
91 }
92
93 pub fn program<'a, 'b>(
98 &'a mut self,
99 start_offset: usize,
100 data: &'b [u8],
101 ) -> Result<ProgrammingSequence<'a, 'b>, Error> {
102 ProgrammingSequence::new(self, start_offset, data)
103 }
104
105 pub fn blocking_program(&mut self, start_offset: usize, data: &[u8]) -> Result<(), Error> {
109 let mut sequence = self.program(start_offset, data)?;
110 block!(sequence.wait())
111 }
112
113 pub fn free(self) -> FLASH {
115 self.registers
116 }
117
118 fn check_locked_or_busy(&self) -> Result<(), Error> {
120 if self.is_locked() {
121 Err(Error::Locked)
122 } else if self.is_busy() {
123 Err(Error::Busy)
124 } else {
125 Ok(())
126 }
127 }
128
129 fn check_errors(&self) -> Result<(), Error> {
131 let sr = self.registers.sr.read();
132
133 if sr.erserr().bit_is_set() {
134 Err(Error::EraseSequence)
135 } else if sr.pgperr().bit_is_set() {
136 Err(Error::ProgrammingParallelism)
137 } else if sr.pgaerr().bit_is_set() {
138 Err(Error::ProgrammingAlignment)
139 } else if sr.wrperr().bit_is_set() {
140 Err(Error::WriteProtection)
141 } else {
142 Ok(())
143 }
144 }
145
146 fn clear_errors(&mut self) {
148 self.registers.sr.write(|w| {
149 w.erserr()
150 .set_bit()
151 .pgperr()
152 .set_bit()
153 .pgaerr()
154 .set_bit()
155 .wrperr()
156 .set_bit()
157 });
158 }
159}
160
161pub struct EraseSequence<'a> {
163 flash: &'a mut Flash,
164}
165
166impl<'a> EraseSequence<'a> {
167 fn new_erase_sector(flash: &'a mut Flash, sector_number: u8) -> Result<Self, Error> {
169 flash.check_locked_or_busy()?;
170 flash.clear_errors();
171
172 flash.registers.cr.modify(|_, w| unsafe {
175 #[cfg(any(
176 feature = "stm32f765",
177 feature = "stm32f767",
178 feature = "stm32f769",
179 feature = "stm32f777",
180 feature = "stm32f778",
181 feature = "stm32f779",
182 ))]
183 w.mer1().clear_bit().mer2().clear_bit();
184 #[cfg(not(any(
185 feature = "stm32f765",
186 feature = "stm32f767",
187 feature = "stm32f769",
188 feature = "stm32f777",
189 feature = "stm32f778",
190 feature = "stm32f779",
191 )))]
192 w.mer().clear_bit();
193 w.ser().set_bit().snb().bits(sector_number)
194 });
195 flash.registers.cr.modify(|_, w| w.strt().start());
196
197 Ok(Self { flash })
198 }
199
200 fn new_mass_erase(flash: &'a mut Flash) -> Result<Self, Error> {
202 flash.check_locked_or_busy()?;
203 flash.clear_errors();
204
205 flash.registers.cr.modify(|_, w| {
206 #[cfg(any(
207 feature = "stm32f765",
208 feature = "stm32f767",
209 feature = "stm32f769",
210 feature = "stm32f777",
211 feature = "stm32f778",
212 feature = "stm32f779",
213 ))]
214 w.mer1().set_bit().mer2().set_bit();
215 #[cfg(not(any(
216 feature = "stm32f765",
217 feature = "stm32f767",
218 feature = "stm32f769",
219 feature = "stm32f777",
220 feature = "stm32f778",
221 feature = "stm32f779",
222 )))]
223 w.mer().set_bit();
224 w.ser().clear_bit()
225 });
226
227 flash.registers.cr.modify(|_, w| w.strt().start());
228
229 Ok(Self { flash })
230 }
231
232 pub fn wait(&mut self) -> nb::Result<(), Error> {
234 self.flash.check_errors().map_err(nb::Error::from)?;
235
236 if self.flash.is_busy() {
237 Err(nb::Error::WouldBlock)
238 } else {
239 Ok(())
240 }
241 }
242}
243
244pub struct ProgrammingSequence<'a, 'b> {
246 flash: &'a mut Flash,
247 data: &'b [u8],
248 address: *mut u8,
249}
250
251impl<'a, 'b> ProgrammingSequence<'a, 'b> {
252 fn new(flash: &'a mut Flash, start_offset: usize, data: &'b [u8]) -> Result<Self, Error> {
254 flash.check_locked_or_busy()?;
255 flash.clear_errors();
256
257 flash
258 .registers
259 .cr
260 .modify(|_, w| w.psize().psize8().pg().set_bit());
261
262 let address = unsafe { FLASH_BASE.add(start_offset) };
263
264 Ok(Self {
265 flash,
266 data,
267 address,
268 })
269 }
270
271 pub fn wait(&mut self) -> nb::Result<(), Error> {
273 if self.flash.is_busy() {
274 return Err(nb::Error::WouldBlock);
275 }
276
277 if let Err(error) = self.flash.check_errors() {
278 self.flash.registers.cr.modify(|_, w| w.pg().clear_bit());
280
281 return Err(error.into());
282 }
283
284 if let Some((first, rest)) = self.data.split_first() {
285 if self.address >= FLASH_BASE && self.address <= MAX_FLASH_ADDRESS {
286 unsafe {
287 core::ptr::write_volatile(self.address, *first);
288 }
289 }
290
291 cortex_m::asm::dmb();
293
294 self.address = unsafe { self.address.add(1) };
295 self.data = rest;
296
297 Err(nb::Error::WouldBlock)
298 } else {
299 self.flash.registers.cr.modify(|_, w| w.pg().clear_bit());
300
301 Ok(())
302 }
303 }
304}