aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatous Hybl <[email protected]>2022-05-02 15:36:02 +0200
committerMatous Hybl <[email protected]>2022-05-06 21:57:15 +0200
commitf3700b4e42fbb0e0e4876307ba5533b7b215f5e3 (patch)
treec58d85109262d006acc3c18ff07110900644ef69
parent4f5088d79d1a0f52ec2c12c87de0a280a0836e7d (diff)
Refactor flash handling to different modules for different families
-rw-r--r--embassy-stm32/src/flash/f3.rs104
-rw-r--r--embassy-stm32/src/flash/l.rs185
-rw-r--r--embassy-stm32/src/flash/mod.rs244
3 files changed, 298 insertions, 235 deletions
diff --git a/embassy-stm32/src/flash/f3.rs b/embassy-stm32/src/flash/f3.rs
new file mode 100644
index 000000000..a5dc8dd0a
--- /dev/null
+++ b/embassy-stm32/src/flash/f3.rs
@@ -0,0 +1,104 @@
1use core::convert::TryInto;
2use core::ptr::write_volatile;
3
4use crate::flash::Error;
5use crate::pac;
6
7pub(crate) unsafe fn lock() {
8 pac::FLASH.cr().modify(|w| w.set_lock(true));
9}
10
11pub(crate) unsafe fn unlock() {
12 pac::FLASH.keyr().write(|w| w.set_fkeyr(0x4567_0123));
13 pac::FLASH.keyr().write(|w| w.set_fkeyr(0xCDEF_89AB));
14}
15
16pub(crate) unsafe fn blocking_write(offset: u32, buf: &[u8]) -> Result<(), Error> {
17 pac::FLASH.cr().write(|w| w.set_pg(true));
18
19 let ret = {
20 let mut ret: Result<(), Error> = Ok(());
21 let mut offset = offset;
22 for chunk in buf.chunks(2) {
23 write_volatile(
24 offset as *mut u16,
25 u16::from_le_bytes(chunk[0..2].try_into().unwrap()),
26 );
27 offset += chunk.len() as u32;
28
29 ret = blocking_wait_ready();
30 if ret.is_err() {
31 break;
32 }
33 }
34 ret
35 };
36
37 pac::FLASH.cr().write(|w| w.set_pg(false));
38
39 ret
40}
41
42pub(crate) unsafe fn blocking_erase(from: u32, to: u32) -> Result<(), Error> {
43 for page in (from..to).step_by(super::ERASE_SIZE) {
44 pac::FLASH.cr().modify(|w| {
45 w.set_per(true);
46 });
47
48 pac::FLASH.ar().write(|w| w.set_far(page));
49
50 pac::FLASH.cr().modify(|w| {
51 w.set_strt(true);
52 });
53
54 let mut ret: Result<(), Error> = blocking_wait_ready();
55
56 if !pac::FLASH.sr().read().eop() {
57 trace!("FLASH: EOP not set");
58 ret = Err(Error::Prog);
59 } else {
60 pac::FLASH.sr().write(|w| w.set_eop(true));
61 }
62
63 pac::FLASH.cr().modify(|w| w.set_per(false));
64
65 clear_all_err();
66 if ret.is_err() {
67 return ret;
68 }
69 }
70
71 Ok(())
72}
73
74pub(crate) unsafe fn clear_all_err() {
75 pac::FLASH.sr().modify(|w| {
76 if w.pgerr() {
77 w.set_pgerr(true);
78 }
79 if w.wrprterr() {
80 w.set_wrprterr(true);
81 }
82 if w.eop() {
83 w.set_eop(true);
84 }
85 });
86}
87
88pub(crate) unsafe fn blocking_wait_ready() -> Result<(), Error> {
89 loop {
90 let sr = pac::FLASH.sr().read();
91
92 if !sr.bsy() {
93 if sr.wrprterr() {
94 return Err(Error::Protected);
95 }
96
97 if sr.pgerr() {
98 return Err(Error::Seq);
99 }
100
101 return Ok(());
102 }
103 }
104}
diff --git a/embassy-stm32/src/flash/l.rs b/embassy-stm32/src/flash/l.rs
new file mode 100644
index 000000000..6ec4796a5
--- /dev/null
+++ b/embassy-stm32/src/flash/l.rs
@@ -0,0 +1,185 @@
1use core::convert::TryInto;
2use core::ptr::write_volatile;
3
4use crate::flash::Error;
5use crate::pac;
6
7pub(crate) unsafe fn lock() {
8 #[cfg(any(flash_wl, flash_wb, flash_l4))]
9 pac::FLASH.cr().modify(|w| w.set_lock(true));
10
11 #[cfg(any(flash_l0))]
12 pac::FLASH.pecr().modify(|w| {
13 w.set_optlock(true);
14 w.set_prglock(true);
15 w.set_pelock(true);
16 });
17}
18
19pub(crate) unsafe fn unlock() {
20 #[cfg(any(flash_wl, flash_wb, flash_l4))]
21 {
22 pac::FLASH.keyr().write(|w| w.set_keyr(0x4567_0123));
23 pac::FLASH.keyr().write(|w| w.set_keyr(0xCDEF_89AB));
24 }
25
26 #[cfg(any(flash_l0, flash_l1))]
27 {
28 pac::FLASH.pekeyr().write(|w| w.set_pekeyr(0x89ABCDEF));
29 pac::FLASH.pekeyr().write(|w| w.set_pekeyr(0x02030405));
30
31 pac::FLASH.prgkeyr().write(|w| w.set_prgkeyr(0x8C9DAEBF));
32 pac::FLASH.prgkeyr().write(|w| w.set_prgkeyr(0x13141516));
33 }
34}
35
36pub(crate) unsafe fn blocking_write(offset: u32, buf: &[u8]) -> Result<(), Error> {
37 #[cfg(any(flash_wl, flash_wb, flash_l4))]
38 pac::FLASH.cr().write(|w| w.set_pg(true));
39
40 let ret = {
41 let mut ret: Result<(), Error> = Ok(());
42 let mut offset = offset;
43 for chunk in buf.chunks(super::WRITE_SIZE) {
44 for val in chunk.chunks(4) {
45 write_volatile(
46 offset as *mut u32,
47 u32::from_le_bytes(val[0..4].try_into().unwrap()),
48 );
49 offset += val.len() as u32;
50 }
51
52 ret = blocking_wait_ready();
53 if ret.is_err() {
54 break;
55 }
56 }
57 ret
58 };
59
60 #[cfg(any(flash_wl, flash_wb, flash_l4))]
61 pac::FLASH.cr().write(|w| w.set_pg(false));
62
63 ret
64}
65
66pub(crate) unsafe fn blocking_erase(from: u32, to: u32) -> Result<(), Error> {
67 for page in (from..to).step_by(super::ERASE_SIZE) {
68 #[cfg(any(flash_l0, flash_l1))]
69 {
70 pac::FLASH.pecr().modify(|w| {
71 w.set_erase(true);
72 w.set_prog(true);
73 });
74
75 write_volatile(page as *mut u32, 0xFFFFFFFF);
76 }
77
78 #[cfg(any(flash_wl, flash_wb, flash_l4))]
79 {
80 let idx = page / super::ERASE_SIZE as u32;
81
82 pac::FLASH.cr().modify(|w| {
83 w.set_per(true);
84 w.set_pnb(idx as u8);
85 #[cfg(any(flash_wl, flash_wb))]
86 w.set_strt(true);
87 #[cfg(any(flash_l4))]
88 w.set_start(true);
89 });
90 }
91
92 let ret: Result<(), Error> = blocking_wait_ready();
93
94 #[cfg(any(flash_wl, flash_wb, flash_l4))]
95 pac::FLASH.cr().modify(|w| w.set_per(false));
96
97 #[cfg(any(flash_l0, flash_l1))]
98 pac::FLASH.pecr().modify(|w| {
99 w.set_erase(false);
100 w.set_prog(false);
101 });
102
103 clear_all_err();
104 if ret.is_err() {
105 return ret;
106 }
107 }
108
109 Ok(())
110}
111
112pub(crate) unsafe fn clear_all_err() {
113 pac::FLASH.sr().modify(|w| {
114 #[cfg(any(flash_wl, flash_wb, flash_l4, flash_l0))]
115 if w.rderr() {
116 w.set_rderr(true);
117 }
118 #[cfg(any(flash_wl, flash_wb, flash_l4))]
119 if w.fasterr() {
120 w.set_fasterr(true);
121 }
122 #[cfg(any(flash_wl, flash_wb, flash_l4))]
123 if w.miserr() {
124 w.set_miserr(true);
125 }
126 #[cfg(any(flash_wl, flash_wb, flash_l4))]
127 if w.pgserr() {
128 w.set_pgserr(true);
129 }
130 if w.sizerr() {
131 w.set_sizerr(true);
132 }
133 if w.pgaerr() {
134 w.set_pgaerr(true);
135 }
136 if w.wrperr() {
137 w.set_wrperr(true);
138 }
139 #[cfg(any(flash_wl, flash_wb, flash_l4))]
140 if w.progerr() {
141 w.set_progerr(true);
142 }
143 #[cfg(any(flash_wl, flash_wb, flash_l4))]
144 if w.operr() {
145 w.set_operr(true);
146 }
147 });
148}
149
150pub(crate) unsafe fn blocking_wait_ready() -> Result<(), Error> {
151 loop {
152 let sr = pac::FLASH.sr().read();
153
154 if !sr.bsy() {
155 #[cfg(any(flash_wl, flash_wb, flash_l4))]
156 if sr.progerr() {
157 return Err(Error::Prog);
158 }
159
160 if sr.wrperr() {
161 return Err(Error::Protected);
162 }
163
164 if sr.pgaerr() {
165 return Err(Error::Unaligned);
166 }
167
168 if sr.sizerr() {
169 return Err(Error::Size);
170 }
171
172 #[cfg(any(flash_wl, flash_wb, flash_l4))]
173 if sr.miserr() {
174 return Err(Error::Miss);
175 }
176
177 #[cfg(any(flash_wl, flash_wb, flash_l4))]
178 if sr.pgserr() {
179 return Err(Error::Seq);
180 }
181
182 return Ok(());
183 }
184 }
185}
diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs
index 0ce74a5e4..8b2a77110 100644
--- a/embassy-stm32/src/flash/mod.rs
+++ b/embassy-stm32/src/flash/mod.rs
@@ -1,8 +1,5 @@
1use crate::pac;
2use crate::peripherals::FLASH; 1use crate::peripherals::FLASH;
3use core::convert::TryInto;
4use core::marker::PhantomData; 2use core::marker::PhantomData;
5use core::ptr::write_volatile;
6use embassy::util::Unborrow; 3use embassy::util::Unborrow;
7use embassy_hal_common::unborrow; 4use embassy_hal_common::unborrow;
8 5
@@ -17,6 +14,10 @@ pub use crate::pac::FLASH_SIZE;
17pub use crate::pac::WRITE_SIZE; 14pub use crate::pac::WRITE_SIZE;
18const FLASH_END: usize = FLASH_BASE + FLASH_SIZE; 15const FLASH_END: usize = FLASH_BASE + FLASH_SIZE;
19 16
17#[cfg_attr(any(flash_wl, flash_wb, flash_l0, flash_l1, flash_l4), path = "l.rs")]
18#[cfg_attr(flash_f3, path = "f3.rs")]
19mod family;
20
20pub struct Flash<'d> { 21pub struct Flash<'d> {
21 _inner: FLASH, 22 _inner: FLASH,
22 _phantom: PhantomData<&'d mut FLASH>, 23 _phantom: PhantomData<&'d mut FLASH>,
@@ -33,37 +34,13 @@ impl<'d> Flash<'d> {
33 34
34 pub fn unlock(p: impl Unborrow<Target = FLASH>) -> Self { 35 pub fn unlock(p: impl Unborrow<Target = FLASH>) -> Self {
35 let flash = Self::new(p); 36 let flash = Self::new(p);
36 #[cfg(any(flash_wl, flash_wb, flash_l4, flash_f3))]
37 unsafe {
38 pac::FLASH.keyr().write(|w| w.set_keyr(0x4567_0123));
39 pac::FLASH.keyr().write(|w| w.set_keyr(0xCDEF_89AB));
40 }
41
42 #[cfg(any(flash_l0, flash_l1))]
43 unsafe {
44 pac::FLASH.pekeyr().write(|w| w.set_pekeyr(0x89ABCDEF));
45 pac::FLASH.pekeyr().write(|w| w.set_pekeyr(0x02030405));
46 37
47 pac::FLASH.prgkeyr().write(|w| w.set_prgkeyr(0x8C9DAEBF)); 38 unsafe { family::unlock() };
48 pac::FLASH.prgkeyr().write(|w| w.set_prgkeyr(0x13141516));
49 }
50 flash 39 flash
51 } 40 }
52 41
53 pub fn lock(&mut self) { 42 pub fn lock(&mut self) {
54 #[cfg(any(flash_wl, flash_wb, flash_l4, flash_f3))] 43 unsafe { family::lock() };
55 unsafe {
56 pac::FLASH.cr().modify(|w| w.set_lock(true));
57 }
58
59 #[cfg(any(flash_l0))]
60 unsafe {
61 pac::FLASH.pecr().modify(|w| {
62 w.set_optlock(true);
63 w.set_prglock(true);
64 w.set_pelock(true);
65 });
66 }
67 } 44 }
68 45
69 pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { 46 pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
@@ -89,61 +66,7 @@ impl<'d> Flash<'d> {
89 66
90 self.clear_all_err(); 67 self.clear_all_err();
91 68
92 #[cfg(any(flash_wl, flash_wb, flash_l4, flash_f3))] 69 unsafe { family::blocking_write(offset, buf) }
93 unsafe {
94 pac::FLASH.cr().write(|w| w.set_pg(true))
95 }
96
97 #[cfg(not(flash_f3))]
98 let ret = {
99 let mut ret: Result<(), Error> = Ok(());
100 let mut offset = offset;
101 for chunk in buf.chunks(WRITE_SIZE) {
102 for val in chunk.chunks(4) {
103 unsafe {
104 write_volatile(
105 offset as *mut u32,
106 u32::from_le_bytes(val[0..4].try_into().unwrap()),
107 );
108 }
109 offset += val.len() as u32;
110 }
111
112 ret = self.blocking_wait_ready();
113 if ret.is_err() {
114 break;
115 }
116 }
117 ret
118 };
119
120 #[cfg(flash_f3)]
121 let ret = {
122 let mut ret: Result<(), Error> = Ok(());
123 let mut offset = offset;
124 for chunk in buf.chunks(2) {
125 unsafe {
126 write_volatile(
127 offset as *mut u16,
128 u16::from_le_bytes(chunk[0..2].try_into().unwrap()),
129 );
130 }
131 offset += chunk.len() as u32;
132
133 ret = self.blocking_wait_ready();
134 if ret.is_err() {
135 break;
136 }
137 }
138 ret
139 };
140
141 #[cfg(any(flash_wl, flash_wb, flash_l4, flash_f3))]
142 unsafe {
143 pac::FLASH.cr().write(|w| w.set_pg(false))
144 }
145
146 ret
147 } 70 }
148 71
149 pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { 72 pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
@@ -158,160 +81,11 @@ impl<'d> Flash<'d> {
158 81
159 self.clear_all_err(); 82 self.clear_all_err();
160 83
161 for page in (from..to).step_by(ERASE_SIZE) { 84 unsafe { family::blocking_erase(from, to) }
162 #[cfg(any(flash_l0, flash_l1))]
163 unsafe {
164 pac::FLASH.pecr().modify(|w| {
165 w.set_erase(true);
166 w.set_prog(true);
167 });
168
169 write_volatile(page as *mut u32, 0xFFFFFFFF);
170 }
171
172 #[cfg(any(flash_wl, flash_wb, flash_l4, flash_f3))]
173 unsafe {
174 #[cfg(not(flash_f3))]
175 let idx = page / ERASE_SIZE as u32;
176
177 pac::FLASH.cr().modify(|w| {
178 w.set_per(true);
179 #[cfg(not(flash_f3))]
180 w.set_pnb(idx as u8);
181 #[cfg(any(flash_wl, flash_wb))]
182 w.set_strt(true);
183 #[cfg(any(flash_l4))]
184 w.set_start(true);
185 });
186
187 #[cfg(flash_f3)]
188 pac::FLASH.ar().write(|w| w.set_far(page));
189
190 #[cfg(flash_f3)]
191 pac::FLASH.cr().modify(|w| {
192 w.set_strt(true);
193 });
194 }
195
196 let ret: Result<(), Error> = self.blocking_wait_ready();
197
198 unsafe {
199 if pac::FLASH.sr().read().eop() {
200 pac::FLASH.sr().modify(|w| w.set_eop(true));
201 } else {
202 panic!("wtf")
203 }
204 }
205
206 #[cfg(any(flash_wl, flash_wb, flash_l4, flash_f3))]
207 unsafe {
208 pac::FLASH.cr().modify(|w| w.set_per(false));
209 }
210
211 #[cfg(any(flash_l0, flash_l1))]
212 unsafe {
213 pac::FLASH.pecr().modify(|w| {
214 w.set_erase(false);
215 w.set_prog(false);
216 });
217 }
218
219 self.clear_all_err();
220 if ret.is_err() {
221 return ret;
222 }
223 }
224
225 Ok(())
226 }
227
228 fn blocking_wait_ready(&self) -> Result<(), Error> {
229 loop {
230 let sr = unsafe { pac::FLASH.sr().read() };
231
232 if !sr.bsy() {
233 #[cfg(any(flash_wl, flash_wb, flash_l4))]
234 if sr.progerr() {
235 return Err(Error::Prog);
236 }
237
238 if sr.wrperr() {
239 return Err(Error::Protected);
240 }
241
242 #[cfg(not(flash_f3))]
243 if sr.pgaerr() {
244 return Err(Error::Unaligned);
245 }
246
247 #[cfg(not(flash_f3))]
248 if sr.sizerr() {
249 return Err(Error::Size);
250 }
251
252 #[cfg(any(flash_wl, flash_wb, flash_l4))]
253 if sr.miserr() {
254 return Err(Error::Miss);
255 }
256
257 #[cfg(any(flash_wl, flash_wb, flash_l4))]
258 if sr.pgserr() {
259 return Err(Error::Seq);
260 }
261
262 #[cfg(flash_f3)]
263 if sr.pgerr() {
264 return Err(Error::Seq);
265 }
266 return Ok(());
267 }
268 }
269 } 85 }
270 86
271 fn clear_all_err(&mut self) { 87 fn clear_all_err(&mut self) {
272 unsafe { 88 unsafe { family::clear_all_err() };
273 pac::FLASH.sr().modify(|w| {
274 #[cfg(any(flash_wl, flash_wb, flash_l4, flash_l0))]
275 if w.rderr() {
276 w.set_rderr(true);
277 }
278 #[cfg(any(flash_wl, flash_wb, flash_l4))]
279 if w.fasterr() {
280 w.set_fasterr(true);
281 }
282 #[cfg(any(flash_wl, flash_wb, flash_l4))]
283 if w.miserr() {
284 w.set_miserr(true);
285 }
286 #[cfg(any(flash_wl, flash_wb, flash_l4))]
287 if w.pgserr() {
288 w.set_pgserr(true);
289 }
290 #[cfg(flash_f3)]
291 if w.pgerr() {
292 w.set_pgerr(true);
293 }
294 #[cfg(not(flash_f3))]
295 if w.sizerr() {
296 w.set_sizerr(true);
297 }
298 #[cfg(not(flash_f3))]
299 if w.pgaerr() {
300 w.set_pgaerr(true);
301 }
302 if w.wrperr() {
303 w.set_wrperr(true);
304 }
305 #[cfg(any(flash_wl, flash_wb, flash_l4))]
306 if w.progerr() {
307 w.set_progerr(true);
308 }
309 #[cfg(any(flash_wl, flash_wb, flash_l4))]
310 if w.operr() {
311 w.set_operr(true);
312 }
313 });
314 }
315 } 89 }
316} 90}
317 91