1use crate::{
2 flash::{
3 Bank, Command, Error, FLASH_MEMORY, Reader64K, SIZE_64KB, send_command, switch_bank,
4 verify_byte, verify_bytes,
5 },
6 log,
7 mmio::IME,
8};
9use core::{cmp::min, marker::PhantomData, ptr, time::Duration};
10use embedded_io::{ErrorType, Read, Write};
11
12#[derive(Debug)]
19pub struct Writer64K<'a> {
20 address: *mut u8,
21 len: usize,
22 lifetime: PhantomData<&'a ()>,
23}
24
25impl Writer64K<'_> {
26 pub(crate) unsafe fn new_unchecked(address: *mut u8, len: usize) -> Self {
27 log::info!(
28 "Creating Flash 64KiB writer at address 0x{:08x?} with length {len}",
29 address as usize
30 );
31 Self {
32 address,
33 len,
34 lifetime: PhantomData,
35 }
36 }
37}
38
39impl ErrorType for Writer64K<'_> {
40 type Error = Error;
41}
42
43impl Write for Writer64K<'_> {
44 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
45 let mut write_count = 0;
46 loop {
47 if write_count >= min(buf.len(), self.len) {
48 if self.len == 0 {
49 return Err(Error::EndOfWriter);
50 }
51 self.address = unsafe { self.address.add(write_count) };
52 self.len -= write_count;
53 return Ok(write_count);
54 }
55
56 let address = unsafe { self.address.add(write_count) };
57 let byte = unsafe { *buf.get_unchecked(write_count) };
58 send_command(Command::Write);
59 unsafe {
60 address.write_volatile(byte);
61 }
62 verify_byte(address, byte, Duration::from_millis(20))?;
63
64 write_count += 1;
65 }
66 }
67
68 fn flush(&mut self) -> Result<(), Self::Error> {
69 Ok(())
70 }
71}
72
73#[derive(Debug)]
80pub struct Writer128K<'a> {
81 address: *mut u8,
82 len: usize,
83 bank: Bank,
84 lifetime: PhantomData<&'a ()>,
85}
86
87impl Writer128K<'_> {
88 pub(crate) unsafe fn new_unchecked(address: *mut u8, len: usize) -> Self {
89 log::info!(
90 "Creating Flash 128KiB writer at address 0x{:08x?} with length {len}",
91 address as usize
92 );
93 let bank = if address < unsafe { FLASH_MEMORY.add(SIZE_64KB) } {
94 Bank::_0
95 } else {
96 Bank::_1
97 };
98 switch_bank(bank);
99
100 Self {
101 address,
102 len,
103 bank,
104 lifetime: PhantomData,
105 }
106 }
107}
108
109impl ErrorType for Writer128K<'_> {
110 type Error = Error;
111}
112
113impl Write for Writer128K<'_> {
114 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
115 let mut write_count = 0;
116 loop {
117 if write_count >= min(buf.len(), self.len) {
118 if self.len == 0 {
119 return Err(Error::EndOfWriter);
120 }
121 self.address = unsafe { self.address.add(write_count) };
122 self.len -= write_count;
123 return Ok(write_count);
124 }
125
126 let mut address = unsafe { self.address.add(write_count) };
127 if matches!(self.bank, Bank::_0) {
128 if ptr::eq(address, unsafe { FLASH_MEMORY.add(SIZE_64KB) }) {
129 self.bank = Bank::_1;
130 switch_bank(self.bank);
131 }
132 }
133 if matches!(self.bank, Bank::_1) {
134 address = unsafe { address.sub(SIZE_64KB) };
135 }
136
137 let byte = unsafe { *buf.get_unchecked(write_count) };
138 send_command(Command::Write);
139 unsafe {
140 address.write_volatile(byte);
141 }
142 verify_byte(address, byte, Duration::from_millis(20))?;
143
144 write_count += 1;
145 }
146 }
147
148 fn flush(&mut self) -> Result<(), Self::Error> {
149 Ok(())
150 }
151}
152
153#[derive(Debug)]
157pub struct Writer64KAtmel<'a> {
158 address: *mut u8,
159 len: usize,
160 buf: [u8; 128],
161 flushed: bool,
162 lifetime: PhantomData<&'a ()>,
163}
164
165impl Writer64KAtmel<'_> {
166 pub(crate) unsafe fn new_unchecked(address: *mut u8, len: usize) -> Self {
167 log::info!(
168 "Creating Flash 64KiB Atmel writer at address 0x{:08x?} with length {len}",
169 address as usize
170 );
171 let mut buf = [0xff; 128];
172 let mut flushed = true;
173
174 let offset = address.align_offset(128);
176 if offset != 0 {
177 let mut reader = unsafe { Reader64K::new_unchecked(address.sub(offset), offset) };
178 unsafe {
179 reader
180 .read_exact(buf.get_unchecked_mut(..offset))
181 .unwrap_unchecked()
182 };
183 flushed = false;
184 }
185
186 Self {
187 address,
188 len,
189 buf,
190 flushed,
191 lifetime: PhantomData,
192 }
193 }
194}
195
196impl ErrorType for Writer64KAtmel<'_> {
197 type Error = Error;
198}
199
200impl Write for Writer64KAtmel<'_> {
201 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
202 let mut write_count = 0;
203 loop {
204 if write_count >= min(buf.len(), self.len) {
205 if self.len == 0 {
206 return Err(Error::EndOfWriter);
207 }
208 self.len -= write_count;
209 return Ok(write_count);
210 }
211
212 unsafe {
213 *self.buf.get_unchecked_mut(self.address as usize % 128) =
214 *buf.get_unchecked(write_count);
215 }
216 self.flushed = false;
217
218 unsafe { self.address = self.address.add(1) };
219
220 if self.address as usize % 128 == 0 {
221 self.flush()?;
222 }
223
224 write_count += 1;
225 }
226 }
227
228 fn flush(&mut self) -> Result<(), Self::Error> {
229 if self.flushed {
230 return Ok(());
231 }
232
233 self.flushed = true;
234
235 let offset = self.address as usize % 128;
237 if offset != 0 {
238 let mut reader = unsafe { Reader64K::new_unchecked(self.address, 128 - offset) };
239 unsafe {
240 reader
241 .read_exact(self.buf.get_unchecked_mut(offset..))
242 .unwrap_unchecked()
243 };
244 }
245
246 let offset_address = unsafe { self.address.sub(if offset == 0 { 128 } else { offset }) };
247
248 let previous_ime = unsafe { IME.read_volatile() };
253 unsafe { IME.write_volatile(false) };
255
256 send_command(Command::Write);
257 for (i, &byte) in self.buf.iter().enumerate() {
258 unsafe { offset_address.add(i).write_volatile(byte) };
259 }
260
261 unsafe {
264 IME.write_volatile(previous_ime);
265 }
266
267 verify_bytes(offset_address, &self.buf, Duration::from_millis(20))?;
268
269 Ok(())
270 }
271}
272
273impl Drop for Writer64KAtmel<'_> {
274 fn drop(&mut self) {
275 if !self.flushed {
276 log::warn!(
277 "Dropped Flash Atmel 64KiB writer without flushing remaining {} bytes. They will be flushed automatically, but any errors will not be handled.",
278 self.address as usize % 128
279 );
280 }
281 let _ignored_result = self.flush();
283 }
284}