1use core::marker::PhantomData;
2use core::sync::atomic::{Ordering, fence};
3
4use embassy_hal_internal::drop::OnDrop;
5use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
6use embassy_sync::mutex::Mutex;
7
8use super::{
9 Async, Error, FLASH_BASE, FLASH_SIZE, Flash, FlashLayout, WRITE_SIZE, blocking_read, ensure_sector_aligned, family,
10 get_flash_regions, get_sector,
11};
12use crate::interrupt::InterruptExt;
13use crate::peripherals::FLASH;
14use crate::{Peri, interrupt};
15
16pub(super) static REGION_ACCESS: Mutex<CriticalSectionRawMutex, ()> = Mutex::new(());
17
18impl<'d> Flash<'d, Async> {
19 pub fn new(
21 p: Peri<'d, FLASH>,
22 _irq: impl interrupt::typelevel::Binding<crate::interrupt::typelevel::FLASH, InterruptHandler> + 'd,
23 ) -> Self {
24 crate::interrupt::FLASH.unpend();
25 unsafe { crate::interrupt::FLASH.enable() };
26
27 Self {
28 inner: p,
29 _mode: PhantomData,
30 }
31 }
32
33 pub fn into_regions(self) -> FlashLayout<'d, Async> {
37 FlashLayout::new(self.inner)
38 }
39
40 pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
45 unsafe { write_chunked(FLASH_BASE as u32, FLASH_SIZE as u32, offset, bytes).await }
46 }
47
48 pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
53 unsafe { erase_sectored(FLASH_BASE as u32, from, to).await }
54 }
55}
56
57pub struct InterruptHandler;
59
60impl interrupt::typelevel::Handler<crate::interrupt::typelevel::FLASH> for InterruptHandler {
61 unsafe fn on_interrupt() {
62 family::on_interrupt();
63 }
64}
65
66impl embedded_storage_async::nor_flash::ReadNorFlash for Flash<'_, Async> {
67 const READ_SIZE: usize = super::READ_SIZE;
68
69 async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
70 self.blocking_read(offset, bytes)
71 }
72
73 fn capacity(&self) -> usize {
74 FLASH_SIZE
75 }
76}
77
78impl embedded_storage_async::nor_flash::NorFlash for Flash<'_, Async> {
79 const WRITE_SIZE: usize = WRITE_SIZE;
80 const ERASE_SIZE: usize = super::MAX_ERASE_SIZE;
81
82 async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
83 self.write(offset, bytes).await
84 }
85
86 async fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
87 self.erase(from, to).await
88 }
89}
90
91pub(super) async unsafe fn write_chunked(base: u32, size: u32, offset: u32, bytes: &[u8]) -> Result<(), Error> {
92 if offset + bytes.len() as u32 > size {
93 return Err(Error::Size);
94 }
95 if offset % WRITE_SIZE as u32 != 0 || bytes.len() % WRITE_SIZE != 0 {
96 return Err(Error::Unaligned);
97 }
98
99 let mut address = base + offset;
100 trace!("Writing {} bytes at 0x{:x}", bytes.len(), address);
101
102 for chunk in bytes.chunks(WRITE_SIZE) {
103 family::clear_all_err();
104 fence(Ordering::SeqCst);
105 family::unlock();
106 fence(Ordering::SeqCst);
107 family::enable_write();
108 fence(Ordering::SeqCst);
109
110 let _on_drop = OnDrop::new(|| {
111 family::disable_write();
112 fence(Ordering::SeqCst);
113 family::lock();
114 });
115
116 family::write(address, unwrap!(chunk.try_into())).await?;
117 address += WRITE_SIZE as u32;
118 }
119 Ok(())
120}
121
122pub(super) async unsafe fn erase_sectored(base: u32, from: u32, to: u32) -> Result<(), Error> {
123 let start_address = base + from;
124 let end_address = base + to;
125 let regions = get_flash_regions();
126
127 ensure_sector_aligned(start_address, end_address, regions)?;
128
129 trace!("Erasing from 0x{:x} to 0x{:x}", start_address, end_address);
130
131 let mut address = start_address;
132 while address < end_address {
133 let sector = get_sector(address, regions);
134 trace!("Erasing sector: {:?}", sector);
135
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(§or).await?;
144 address += sector.size;
145 }
146 Ok(())
147}
148
149foreach_flash_region! {
150 ($type_name:ident, $write_size:literal, $erase_size:literal) => {
151 impl crate::_generated::flash_regions::$type_name<'_, Async> {
152 pub async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
156 blocking_read(self.0.base(), self.0.size, offset, bytes)
157 }
158
159 pub async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Error> {
161 let _guard = REGION_ACCESS.lock().await;
162 unsafe { write_chunked(self.0.base(), self.0.size, offset, bytes).await }
163 }
164
165 pub async fn erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
167 let _guard = REGION_ACCESS.lock().await;
168 unsafe { erase_sectored(self.0.base(), from, to).await }
169 }
170 }
171
172 impl embedded_storage_async::nor_flash::ReadNorFlash for crate::_generated::flash_regions::$type_name<'_, Async> {
173 const READ_SIZE: usize = super::READ_SIZE;
174
175 async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
176 self.read(offset, bytes).await
177 }
178
179 fn capacity(&self) -> usize {
180 self.0.size as usize
181 }
182 }
183
184 impl embedded_storage_async::nor_flash::NorFlash for crate::_generated::flash_regions::$type_name<'_, Async> {
185 const WRITE_SIZE: usize = $write_size;
186 const ERASE_SIZE: usize = $erase_size;
187
188 async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
189 self.write(offset, bytes).await
190 }
191
192 async fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
193 self.erase(from, to).await
194 }
195 }
196 };
197}