aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/flash
diff options
context:
space:
mode:
authorRasmus Melchior Jacobsen <[email protected]>2023-05-24 17:24:28 +0200
committerRasmus Melchior Jacobsen <[email protected]>2023-05-25 20:07:42 +0200
commit44b6494ab7ec3e742aa9f82a8ca9ebdfc23ebbba (patch)
treeb1266b7f9f0488017098bcca3f7ba3fb9e93603e /embassy-stm32/src/flash
parent6df62397048778ce521c14b21b4aced7c22567c2 (diff)
Let FlashLayout and FlashRegion depends on a Blocking/Async mode generic
Diffstat (limited to 'embassy-stm32/src/flash')
-rw-r--r--embassy-stm32/src/flash/asynch.rs35
-rw-r--r--embassy-stm32/src/flash/common.rs218
-rw-r--r--embassy-stm32/src/flash/f4.rs114
-rw-r--r--embassy-stm32/src/flash/mod.rs3
4 files changed, 171 insertions, 199 deletions
diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs
index 44e23d9c4..3564bbff5 100644
--- a/embassy-stm32/src/flash/asynch.rs
+++ b/embassy-stm32/src/flash/asynch.rs
@@ -1,12 +1,21 @@
1use atomic_polyfill::{fence, Ordering}; 1use atomic_polyfill::{fence, Ordering};
2use embassy_hal_common::drop::OnDrop; 2use embassy_hal_common::drop::OnDrop;
3use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
4use embassy_sync::mutex::Mutex;
3 5
4use super::{ 6use super::{
5 ensure_sector_aligned, family, get_sector, Error, Flash, FLASH_BASE, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, 7 ensure_sector_aligned, family, get_sector, read_blocking, Async, Error, Flash, FlashLayout, FLASH_BASE, FLASH_SIZE,
6 REGION_ACCESS, WRITE_SIZE, 8 MAX_ERASE_SIZE, READ_SIZE, WRITE_SIZE,
7}; 9};
8 10
11pub(super) static REGION_ACCESS: Mutex<CriticalSectionRawMutex, ()> = Mutex::new(());
12
9impl<'d> Flash<'d> { 13impl<'d> Flash<'d> {
14 pub fn into_regions(self) -> FlashLayout<'d, Async> {
15 family::set_default_layout();
16 FlashLayout::new(self.inner)
17 }
18
10 pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { 19 pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
11 unsafe { write_chunked(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes).await } 20 unsafe { write_chunked(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes).await }
12 } 21 }
@@ -16,6 +25,18 @@ impl<'d> Flash<'d> {
16 } 25 }
17} 26}
18 27
28impl embedded_storage_async::nor_flash::ReadNorFlash for Flash<'_> {
29 const READ_SIZE: usize = READ_SIZE;
30
31 async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
32 self.read(offset, bytes)
33 }
34
35 fn capacity(&self) -> usize {
36 FLASH_SIZE
37 }
38}
39
19impl embedded_storage_async::nor_flash::NorFlash for Flash<'_> { 40impl embedded_storage_async::nor_flash::NorFlash for Flash<'_> {
20 const WRITE_SIZE: usize = WRITE_SIZE; 41 const WRITE_SIZE: usize = WRITE_SIZE;
21 const ERASE_SIZE: usize = MAX_ERASE_SIZE; 42 const ERASE_SIZE: usize = MAX_ERASE_SIZE;
@@ -89,7 +110,11 @@ pub(super) async unsafe fn erase_sectored(base: u32, from: u32, to: u32) -> Resu
89 110
90foreach_flash_region! { 111foreach_flash_region! {
91 ($type_name:ident, $write_size:literal, $erase_size:literal) => { 112 ($type_name:ident, $write_size:literal, $erase_size:literal) => {
92 impl crate::_generated::flash_regions::$type_name<'_> { 113 impl crate::_generated::flash_regions::$type_name<'_, Async> {
114 pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
115 read_blocking(self.0.base, self.0.size, offset, bytes)
116 }
117
93 pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { 118 pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
94 let _guard = REGION_ACCESS.lock().await; 119 let _guard = REGION_ACCESS.lock().await;
95 unsafe { write_chunked(self.0.base, self.0.size, offset, bytes).await } 120 unsafe { write_chunked(self.0.base, self.0.size, offset, bytes).await }
@@ -101,7 +126,7 @@ foreach_flash_region! {
101 } 126 }
102 } 127 }
103 128
104 impl embedded_storage_async::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_> { 129 impl embedded_storage_async::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_, Async> {
105 const READ_SIZE: usize = READ_SIZE; 130 const READ_SIZE: usize = READ_SIZE;
106 131
107 async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { 132 async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
@@ -113,7 +138,7 @@ foreach_flash_region! {
113 } 138 }
114 } 139 }
115 140
116 impl embedded_storage_async::nor_flash::NorFlash for crate::_generated::flash_regions::$type_name<'_> { 141 impl embedded_storage_async::nor_flash::NorFlash for crate::_generated::flash_regions::$type_name<'_, Async> {
117 const WRITE_SIZE: usize = $write_size; 142 const WRITE_SIZE: usize = $write_size;
118 const ERASE_SIZE: usize = $erase_size; 143 const ERASE_SIZE: usize = $erase_size;
119 144
diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs
index e1fe7e9da..8b38745cf 100644
--- a/embassy-stm32/src/flash/common.rs
+++ b/embassy-stm32/src/flash/common.rs
@@ -1,14 +1,12 @@
1use atomic_polyfill::{fence, Ordering}; 1use atomic_polyfill::{fence, Ordering};
2use embassy_cortex_m::interrupt::InterruptExt; 2use embassy_cortex_m::interrupt::InterruptExt;
3use embassy_futures::block_on;
4use embassy_hal_common::drop::OnDrop; 3use embassy_hal_common::drop::OnDrop;
5use embassy_hal_common::{into_ref, PeripheralRef}; 4use embassy_hal_common::{into_ref, PeripheralRef};
6use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
7use embassy_sync::mutex::Mutex;
8use stm32_metapac::FLASH_BASE; 5use stm32_metapac::FLASH_BASE;
9 6
10use super::{ 7use super::{
11 family, Error, FlashBank, FlashLayout, FlashRegion, FlashSector, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE, WRITE_SIZE, 8 family, Blocking, Error, FlashBank, FlashLayout, FlashRegion, FlashSector, FLASH_SIZE, MAX_ERASE_SIZE, READ_SIZE,
9 WRITE_SIZE,
12}; 10};
13use crate::peripherals::FLASH; 11use crate::peripherals::FLASH;
14use crate::Peripheral; 12use crate::Peripheral;
@@ -17,8 +15,6 @@ pub struct Flash<'d> {
17 pub(crate) inner: PeripheralRef<'d, FLASH>, 15 pub(crate) inner: PeripheralRef<'d, FLASH>,
18} 16}
19 17
20pub(crate) static REGION_ACCESS: Mutex<CriticalSectionRawMutex, ()> = Mutex::new(());
21
22impl<'d> Flash<'d> { 18impl<'d> Flash<'d> {
23 pub fn new(p: impl Peripheral<P = FLASH> + 'd, irq: impl Peripheral<P = crate::interrupt::FLASH> + 'd) -> Self { 19 pub fn new(p: impl Peripheral<P = FLASH> + 'd, irq: impl Peripheral<P = crate::interrupt::FLASH> + 'd) -> Self {
24 into_ref!(p, irq); 20 into_ref!(p, irq);
@@ -30,7 +26,7 @@ impl<'d> Flash<'d> {
30 Self { inner: p } 26 Self { inner: p }
31 } 27 }
32 28
33 pub fn into_regions(self) -> FlashLayout<'d> { 29 pub fn into_blocking_regions(self) -> FlashLayout<'d, Blocking> {
34 family::set_default_layout(); 30 family::set_default_layout();
35 FlashLayout::new(self.inner) 31 FlashLayout::new(self.inner)
36 } 32 }
@@ -40,11 +36,19 @@ impl<'d> Flash<'d> {
40 } 36 }
41 37
42 pub fn write_blocking(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { 38 pub fn write_blocking(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
43 unsafe { write_chunked_blocking(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes) } 39 unsafe {
40 write_blocking(
41 FLASH_BASE as u32,
42 FLASH_SIZE as u32,
43 offset,
44 bytes,
45 write_chunk_unlocked,
46 )
47 }
44 } 48 }
45 49
46 pub fn erase_blocking(&mut self, from: u32, to: u32) -> Result<(), Error> { 50 pub fn erase_blocking(&mut self, from: u32, to: u32) -> Result<(), Error> {
47 unsafe { erase_sectored_blocking(FLASH_BASE as u32, from, to) } 51 unsafe { erase_blocking(FLASH_BASE as u32, from, to, erase_sector_unlocked) }
48 } 52 }
49} 53}
50 54
@@ -59,7 +63,13 @@ pub(super) fn read_blocking(base: u32, size: u32, offset: u32, bytes: &mut [u8])
59 Ok(()) 63 Ok(())
60} 64}
61 65
62pub(super) unsafe fn write_chunked_blocking(base: u32, size: u32, offset: u32, bytes: &[u8]) -> Result<(), Error> { 66pub(super) unsafe fn write_blocking(
67 base: u32,
68 size: u32,
69 offset: u32,
70 bytes: &[u8],
71 write_chunk: unsafe fn(u32, &[u8]) -> Result<(), Error>,
72) -> Result<(), Error> {
63 if offset + bytes.len() as u32 > size { 73 if offset + bytes.len() as u32 > size {
64 return Err(Error::Size); 74 return Err(Error::Size);
65 } 75 }
@@ -71,26 +81,39 @@ pub(super) unsafe fn write_chunked_blocking(base: u32, size: u32, offset: u32, b
71 trace!("Writing {} bytes at 0x{:x}", bytes.len(), address); 81 trace!("Writing {} bytes at 0x{:x}", bytes.len(), address);
72 82
73 for chunk in bytes.chunks(WRITE_SIZE) { 83 for chunk in bytes.chunks(WRITE_SIZE) {
74 family::clear_all_err(); 84 write_chunk(address, chunk)?;
75 fence(Ordering::SeqCst);
76 family::unlock();
77 fence(Ordering::SeqCst);
78 family::enable_blocking_write();
79 fence(Ordering::SeqCst);
80
81 let _on_drop = OnDrop::new(|| {
82 family::disable_blocking_write();
83 fence(Ordering::SeqCst);
84 family::lock();
85 });
86
87 family::write_blocking(address, chunk.try_into().unwrap())?;
88 address += WRITE_SIZE as u32; 85 address += WRITE_SIZE as u32;
89 } 86 }
90 Ok(()) 87 Ok(())
91} 88}
92 89
93pub(super) unsafe fn erase_sectored_blocking(base: u32, from: u32, to: u32) -> Result<(), Error> { 90pub(super) unsafe fn write_chunk_unlocked(address: u32, chunk: &[u8]) -> Result<(), Error> {
91 family::clear_all_err();
92 fence(Ordering::SeqCst);
93 family::unlock();
94 fence(Ordering::SeqCst);
95 family::enable_blocking_write();
96 fence(Ordering::SeqCst);
97
98 let _on_drop = OnDrop::new(|| {
99 family::disable_blocking_write();
100 fence(Ordering::SeqCst);
101 family::lock();
102 });
103
104 family::write_blocking(address, chunk.try_into().unwrap())
105}
106
107pub(super) unsafe fn write_chunk_with_critical_section(address: u32, chunk: &[u8]) -> Result<(), Error> {
108 critical_section::with(|_| write_chunk_unlocked(address, chunk))
109}
110
111pub(super) unsafe fn erase_blocking(
112 base: u32,
113 from: u32,
114 to: u32,
115 erase_sector: unsafe fn(&FlashSector) -> Result<(), Error>,
116) -> Result<(), Error> {
94 let start_address = base + from; 117 let start_address = base + from;
95 let end_address = base + to; 118 let end_address = base + to;
96 let regions = family::get_flash_regions(); 119 let regions = family::get_flash_regions();
@@ -103,21 +126,28 @@ pub(super) unsafe fn erase_sectored_blocking(base: u32, from: u32, to: u32) -> R
103 while address < end_address { 126 while address < end_address {
104 let sector = get_sector(address, regions); 127 let sector = get_sector(address, regions);
105 trace!("Erasing sector: {:?}", sector); 128 trace!("Erasing sector: {:?}", sector);
106 129 erase_sector(&sector)?;
107 family::clear_all_err();
108 fence(Ordering::SeqCst);
109 family::unlock();
110 fence(Ordering::SeqCst);
111
112 let _on_drop = OnDrop::new(|| family::lock());
113
114 family::erase_sector_blocking(&sector)?;
115 address += sector.size; 130 address += sector.size;
116 } 131 }
117 Ok(()) 132 Ok(())
118} 133}
119 134
120pub(crate) fn get_sector(address: u32, regions: &[&FlashRegion]) -> FlashSector { 135pub(super) unsafe fn erase_sector_unlocked(sector: &FlashSector) -> Result<(), Error> {
136 family::clear_all_err();
137 fence(Ordering::SeqCst);
138 family::unlock();
139 fence(Ordering::SeqCst);
140
141 let _on_drop = OnDrop::new(|| family::lock());
142
143 family::erase_sector_blocking(&sector)
144}
145
146pub(super) unsafe fn erase_sector_with_critical_section(sector: &FlashSector) -> Result<(), Error> {
147 critical_section::with(|_| erase_sector_unlocked(sector))
148}
149
150pub(super) fn get_sector(address: u32, regions: &[&FlashRegion]) -> FlashSector {
121 let mut current_bank = FlashBank::Bank1; 151 let mut current_bank = FlashBank::Bank1;
122 let mut bank_offset = 0; 152 let mut bank_offset = 0;
123 for region in regions { 153 for region in regions {
@@ -142,7 +172,7 @@ pub(crate) fn get_sector(address: u32, regions: &[&FlashRegion]) -> FlashSector
142 panic!("Flash sector not found"); 172 panic!("Flash sector not found");
143} 173}
144 174
145pub(crate) fn ensure_sector_aligned( 175pub(super) fn ensure_sector_aligned(
146 start_address: u32, 176 start_address: u32,
147 end_address: u32, 177 end_address: u32,
148 regions: &[&FlashRegion], 178 regions: &[&FlashRegion],
@@ -190,121 +220,49 @@ impl embedded_storage::nor_flash::NorFlash for Flash<'_> {
190 } 220 }
191} 221}
192 222
193#[cfg(feature = "nightly")]
194impl embedded_storage_async::nor_flash::ReadNorFlash for Flash<'_> {
195 const READ_SIZE: usize = READ_SIZE;
196
197 async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
198 self.read(offset, bytes)
199 }
200
201 fn capacity(&self) -> usize {
202 FLASH_SIZE
203 }
204}
205
206pub struct BlockingFlashRegion<'d, const WRITE_SIZE: u32, const ERASE_SIZE: u32>(
207 &'static FlashRegion,
208 PeripheralRef<'d, FLASH>,
209);
210
211impl<const WRITE_SIZE: u32, const ERASE_SIZE: u32> BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE> {
212 pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
213 read_blocking(self.0.base, self.0.size, offset, bytes)
214 }
215
216 pub fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
217 let _guard = block_on(REGION_ACCESS.lock());
218 unsafe { write_chunked_blocking(self.0.base, self.0.size, offset, bytes) }
219 }
220
221 pub fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
222 let _guard = block_on(REGION_ACCESS.lock());
223 unsafe { erase_sectored_blocking(self.0.base, from, to) }
224 }
225}
226
227impl<const WRITE_SIZE: u32, const ERASE_SIZE: u32> embedded_storage::nor_flash::ErrorType
228 for BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE>
229{
230 type Error = Error;
231}
232
233impl<const WRITE_SIZE: u32, const ERASE_SIZE: u32> embedded_storage::nor_flash::ReadNorFlash
234 for BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE>
235{
236 const READ_SIZE: usize = READ_SIZE;
237
238 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
239 self.read(offset, bytes)
240 }
241
242 fn capacity(&self) -> usize {
243 self.0.size as usize
244 }
245}
246
247impl<const WRITE_SIZE: u32, const ERASE_SIZE: u32> embedded_storage::nor_flash::NorFlash
248 for BlockingFlashRegion<'_, WRITE_SIZE, ERASE_SIZE>
249{
250 const WRITE_SIZE: usize = WRITE_SIZE as usize;
251 const ERASE_SIZE: usize = ERASE_SIZE as usize;
252
253 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
254 self.write(offset, bytes)
255 }
256
257 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
258 self.erase(from, to)
259 }
260}
261
262foreach_flash_region! { 223foreach_flash_region! {
263 ($type_name:ident, $write_size:literal, $erase_size:literal) => { 224 ($type_name:ident, $write_size:literal, $erase_size:literal) => {
264 paste::paste! { 225 impl<'d> crate::_generated::flash_regions::$type_name<'d, Blocking> {
265 pub type [<Blocking $type_name>]<'d> = BlockingFlashRegion<'d, $write_size, $erase_size>; 226 pub fn read_blocking(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
266 }
267
268 impl<'d> crate::_generated::flash_regions::$type_name<'d> {
269 /// Make this flash region work in a blocking context.
270 ///
271 /// SAFETY
272 ///
273 /// This function is unsafe as incorect usage of parallel blocking operations
274 /// on multiple regions may cause a deadlock because each region requires mutual access to the flash.
275 pub unsafe fn into_blocking(self) -> BlockingFlashRegion<'d, $write_size, $erase_size> {
276 BlockingFlashRegion(self.0, self.1)
277 }
278
279 pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
280 read_blocking(self.0.base, self.0.size, offset, bytes) 227 read_blocking(self.0.base, self.0.size, offset, bytes)
281 } 228 }
282 229
283 pub fn try_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { 230 pub fn write_blocking(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
284 let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; 231 unsafe { write_blocking(self.0.base, self.0.size, offset, bytes, write_chunk_with_critical_section) }
285 unsafe { write_chunked_blocking(self.0.base, self.0.size, offset, bytes) }
286 } 232 }
287 233
288 pub fn try_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { 234 pub fn erase_blocking(&mut self, from: u32, to: u32) -> Result<(), Error> {
289 let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?; 235 unsafe { erase_blocking(self.0.base, from, to, erase_sector_with_critical_section) }
290 unsafe { erase_sectored_blocking(self.0.base, from, to) }
291 } 236 }
292 } 237 }
293 238
294 impl embedded_storage::nor_flash::ErrorType for crate::_generated::flash_regions::$type_name<'_> { 239 impl<MODE> embedded_storage::nor_flash::ErrorType for crate::_generated::flash_regions::$type_name<'_, MODE> {
295 type Error = Error; 240 type Error = Error;
296 } 241 }
297 242
298 impl embedded_storage::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_> { 243 impl embedded_storage::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_, Blocking> {
299 const READ_SIZE: usize = READ_SIZE; 244 const READ_SIZE: usize = READ_SIZE;
300 245
301 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { 246 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
302 self.read(offset, bytes) 247 self.read_blocking(offset, bytes)
303 } 248 }
304 249
305 fn capacity(&self) -> usize { 250 fn capacity(&self) -> usize {
306 self.0.size as usize 251 self.0.size as usize
307 } 252 }
308 } 253 }
254
255 impl embedded_storage::nor_flash::NorFlash for crate::_generated::flash_regions::$type_name<'_, Blocking> {
256 const WRITE_SIZE: usize = $write_size;
257 const ERASE_SIZE: usize = $erase_size;
258
259 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
260 self.write_blocking(offset, bytes)
261 }
262
263 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
264 self.erase_blocking(from, to)
265 }
266 }
309 }; 267 };
310} 268}
diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs
index 084bbdc6e..d50a35b41 100644
--- a/embassy-stm32/src/flash/f4.rs
+++ b/embassy-stm32/src/flash/f4.rs
@@ -11,6 +11,8 @@ use crate::pac;
11 11
12#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))] 12#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f469, stm32f479))]
13mod alt_regions { 13mod alt_regions {
14 use core::marker::PhantomData;
15
14 use embassy_hal_common::PeripheralRef; 16 use embassy_hal_common::PeripheralRef;
15 use stm32_metapac::FLASH_SIZE; 17 use stm32_metapac::FLASH_SIZE;
16 18
@@ -18,8 +20,7 @@ mod alt_regions {
18 #[cfg(feature = "nightly")] 20 #[cfg(feature = "nightly")]
19 use crate::flash::asynch; 21 use crate::flash::asynch;
20 use crate::flash::{ 22 use crate::flash::{
21 common, Bank1Region1, Bank1Region2, BlockingFlashRegion, Error, Flash, FlashBank, FlashRegion, READ_SIZE, 23 common, Async, Bank1Region1, Bank1Region2, Blocking, Error, Flash, FlashBank, FlashRegion, READ_SIZE,
22 REGION_ACCESS,
23 }; 24 };
24 use crate::peripherals::FLASH; 25 use crate::peripherals::FLASH;
25 26
@@ -53,101 +54,86 @@ mod alt_regions {
53 &ALT_BANK2_REGION3, 54 &ALT_BANK2_REGION3,
54 ]; 55 ];
55 56
56 pub struct AltBank1Region3<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); 57 pub struct AltBank1Region3<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData<MODE>);
57 pub struct AltBank2Region1<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); 58 pub struct AltBank2Region1<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData<MODE>);
58 pub struct AltBank2Region2<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); 59 pub struct AltBank2Region2<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData<MODE>);
59 pub struct AltBank2Region3<'d>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>); 60 pub struct AltBank2Region3<'d, MODE>(pub &'static FlashRegion, PeripheralRef<'d, FLASH>, PhantomData<MODE>);
60 61
61 pub type BlockingAltBank1Region3<'d> = 62 pub struct AltFlashLayout<'d, MODE> {
62 BlockingFlashRegion<'d, { ALT_BANK1_REGION3.write_size }, { ALT_BANK1_REGION3.erase_size }>; 63 pub bank1_region1: Bank1Region1<'d, MODE>,
63 pub type BlockingAltBank2Region1<'d> = 64 pub bank1_region2: Bank1Region2<'d, MODE>,
64 BlockingFlashRegion<'d, { ALT_BANK2_REGION1.write_size }, { ALT_BANK2_REGION1.erase_size }>; 65 pub bank1_region3: AltBank1Region3<'d, MODE>,
65 pub type BlockingAltBank2Region2<'d> = 66 pub bank2_region1: AltBank2Region1<'d, MODE>,
66 BlockingFlashRegion<'d, { ALT_BANK2_REGION2.write_size }, { ALT_BANK2_REGION2.erase_size }>; 67 pub bank2_region2: AltBank2Region2<'d, MODE>,
67 pub type BlockingAltBank2Region3<'d> = 68 pub bank2_region3: AltBank2Region3<'d, MODE>,
68 BlockingFlashRegion<'d, { ALT_BANK2_REGION3.write_size }, { ALT_BANK2_REGION3.erase_size }>; 69 pub otp_region: OTPRegion<'d, MODE>,
69
70 pub struct AltFlashLayout<'d> {
71 pub bank1_region1: Bank1Region1<'d>,
72 pub bank1_region2: Bank1Region2<'d>,
73 pub bank1_region3: AltBank1Region3<'d>,
74 pub bank2_region1: AltBank2Region1<'d>,
75 pub bank2_region2: AltBank2Region2<'d>,
76 pub bank2_region3: AltBank2Region3<'d>,
77 pub otp_region: OTPRegion<'d>,
78 } 70 }
79 71
80 impl<'d> Flash<'d> { 72 impl<'d> Flash<'d> {
81 pub fn into_alt_regions(self) -> AltFlashLayout<'d> { 73 pub fn into_alt_regions(self) -> AltFlashLayout<'d, Async> {
74 unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(true)) };
75
76 // SAFETY: We never expose the cloned peripheral references, and their instance is not public.
77 // Also, all async flash region operations are protected with a mutex.
78 let p = self.inner;
79 AltFlashLayout {
80 bank1_region1: Bank1Region1(&BANK1_REGION1, unsafe { p.clone_unchecked() }, PhantomData),
81 bank1_region2: Bank1Region2(&BANK1_REGION2, unsafe { p.clone_unchecked() }, PhantomData),
82 bank1_region3: AltBank1Region3(&ALT_BANK1_REGION3, unsafe { p.clone_unchecked() }, PhantomData),
83 bank2_region1: AltBank2Region1(&ALT_BANK2_REGION1, unsafe { p.clone_unchecked() }, PhantomData),
84 bank2_region2: AltBank2Region2(&ALT_BANK2_REGION2, unsafe { p.clone_unchecked() }, PhantomData),
85 bank2_region3: AltBank2Region3(&ALT_BANK2_REGION3, unsafe { p.clone_unchecked() }, PhantomData),
86 otp_region: OTPRegion(&OTP_REGION, unsafe { p.clone_unchecked() }, PhantomData),
87 }
88 }
89
90 pub fn into_alt_blocking_regions(self) -> AltFlashLayout<'d, Blocking> {
82 unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(true)) }; 91 unsafe { crate::pac::FLASH.optcr().modify(|r| r.set_db1m(true)) };
83 92
84 // SAFETY: We never expose the cloned peripheral references, and their instance is not public. 93 // SAFETY: We never expose the cloned peripheral references, and their instance is not public.
85 // Also, all blocking flash region operations are protected with a cs. 94 // Also, all blocking flash region operations are protected with a cs.
86 let p = self.inner; 95 let p = self.inner;
87 AltFlashLayout { 96 AltFlashLayout {
88 bank1_region1: Bank1Region1(&BANK1_REGION1, unsafe { p.clone_unchecked() }), 97 bank1_region1: Bank1Region1(&BANK1_REGION1, unsafe { p.clone_unchecked() }, PhantomData),
89 bank1_region2: Bank1Region2(&BANK1_REGION2, unsafe { p.clone_unchecked() }), 98 bank1_region2: Bank1Region2(&BANK1_REGION2, unsafe { p.clone_unchecked() }, PhantomData),
90 bank1_region3: AltBank1Region3(&ALT_BANK1_REGION3, unsafe { p.clone_unchecked() }), 99 bank1_region3: AltBank1Region3(&ALT_BANK1_REGION3, unsafe { p.clone_unchecked() }, PhantomData),
91 bank2_region1: AltBank2Region1(&ALT_BANK2_REGION1, unsafe { p.clone_unchecked() }), 100 bank2_region1: AltBank2Region1(&ALT_BANK2_REGION1, unsafe { p.clone_unchecked() }, PhantomData),
92 bank2_region2: AltBank2Region2(&ALT_BANK2_REGION2, unsafe { p.clone_unchecked() }), 101 bank2_region2: AltBank2Region2(&ALT_BANK2_REGION2, unsafe { p.clone_unchecked() }, PhantomData),
93 bank2_region3: AltBank2Region3(&ALT_BANK2_REGION3, unsafe { p.clone_unchecked() }), 102 bank2_region3: AltBank2Region3(&ALT_BANK2_REGION3, unsafe { p.clone_unchecked() }, PhantomData),
94 otp_region: OTPRegion(&OTP_REGION, unsafe { p.clone_unchecked() }), 103 otp_region: OTPRegion(&OTP_REGION, unsafe { p.clone_unchecked() }, PhantomData),
95 } 104 }
96 } 105 }
97 } 106 }
98 107
99 macro_rules! foreach_altflash_region { 108 macro_rules! foreach_altflash_region {
100 ($type_name:ident, $region:ident) => { 109 ($type_name:ident, $region:ident) => {
101 impl $type_name<'_> { 110 #[cfg(feature = "nightly")]
102 pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { 111 impl $type_name<'_, Async> {
112 pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
103 common::read_blocking(self.0.base, self.0.size, offset, bytes) 113 common::read_blocking(self.0.base, self.0.size, offset, bytes)
104 } 114 }
105 115
106 #[cfg(feature = "nightly")]
107 pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> { 116 pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
108 let _guard = REGION_ACCESS.lock().await; 117 let _guard = asynch::REGION_ACCESS.lock().await;
109 unsafe { asynch::write_chunked(self.0.base, self.0.size, offset, bytes).await } 118 unsafe { asynch::write_chunked(self.0.base, self.0.size, offset, bytes).await }
110 } 119 }
111 120
112 #[cfg(feature = "nightly")]
113 pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> { 121 pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
114 let _guard = REGION_ACCESS.lock().await; 122 let _guard = asynch::REGION_ACCESS.lock().await;
115 unsafe { asynch::erase_sectored(self.0.base, from, to).await } 123 unsafe { asynch::erase_sectored(self.0.base, from, to).await }
116 } 124 }
117
118 pub fn try_write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
119 let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?;
120 unsafe { common::write_chunked_blocking(self.0.base, self.0.size, offset, bytes) }
121 }
122
123 pub fn try_erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
124 let _guard = REGION_ACCESS.try_lock().map_err(|_| Error::TryLockError)?;
125 unsafe { common::erase_sectored_blocking(self.0.base, from, to) }
126 }
127 } 125 }
128 126
129 impl embedded_storage::nor_flash::ErrorType for $type_name<'_> { 127 impl embedded_storage::nor_flash::ErrorType for $type_name<'_, Async> {
130 type Error = Error; 128 type Error = Error;
131 } 129 }
132 130
133 impl embedded_storage::nor_flash::ReadNorFlash for $type_name<'_> {
134 const READ_SIZE: usize = READ_SIZE;
135
136 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
137 self.read(offset, bytes)
138 }
139
140 fn capacity(&self) -> usize {
141 self.0.size as usize
142 }
143 }
144
145 #[cfg(feature = "nightly")] 131 #[cfg(feature = "nightly")]
146 impl embedded_storage_async::nor_flash::ReadNorFlash for $type_name<'_> { 132 impl embedded_storage_async::nor_flash::ReadNorFlash for $type_name<'_, Async> {
147 const READ_SIZE: usize = READ_SIZE; 133 const READ_SIZE: usize = READ_SIZE;
148 134
149 async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { 135 async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
150 self.read(offset, bytes) 136 self.read(offset, bytes).await
151 } 137 }
152 138
153 fn capacity(&self) -> usize { 139 fn capacity(&self) -> usize {
@@ -156,7 +142,7 @@ mod alt_regions {
156 } 142 }
157 143
158 #[cfg(feature = "nightly")] 144 #[cfg(feature = "nightly")]
159 impl embedded_storage_async::nor_flash::NorFlash for $type_name<'_> { 145 impl embedded_storage_async::nor_flash::NorFlash for $type_name<'_, Async> {
160 const WRITE_SIZE: usize = $region.write_size as usize; 146 const WRITE_SIZE: usize = $region.write_size as usize;
161 const ERASE_SIZE: usize = $region.erase_size as usize; 147 const ERASE_SIZE: usize = $region.erase_size as usize;
162 148
diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs
index 1ef04e56f..56a680a86 100644
--- a/embassy-stm32/src/flash/mod.rs
+++ b/embassy-stm32/src/flash/mod.rs
@@ -14,6 +14,9 @@ pub use crate::pac::{FLASH_BASE, FLASH_SIZE, WRITE_SIZE};
14 14
15pub const READ_SIZE: usize = 1; 15pub const READ_SIZE: usize = 1;
16 16
17pub struct Blocking;
18pub struct Async;
19
17#[derive(Debug)] 20#[derive(Debug)]
18#[cfg_attr(feature = "defmt", derive(defmt::Format))] 21#[cfg_attr(feature = "defmt", derive(defmt::Format))]
19pub struct FlashRegion { 22pub struct FlashRegion {