lpc55_hal/drivers/
flash.rs1use core::convert::TryInto;
2use crate::{
5 peripherals::flash::Flash,
6 traits::flash::{Error, Read, Result, WriteErase},
7 typestates::init_state::Enabled,
8};
9
10pub use generic_array::{
11 typenum::{U16, U512, U8},
12 GenericArray,
13};
14
15pub const READ_SIZE: usize = 16;
22pub const WRITE_SIZE: usize = 512;
23pub const PAGE_SIZE: usize = 512;
24
25pub struct FlashGordon {
26 flash: Flash<Enabled>,
27}
28
29impl FlashGordon {
30 pub fn new(flash: Flash<Enabled>) -> Self {
31 flash.raw.event.write(|w| w.rst().set_bit());
32 while flash.raw.int_status.read().done().bit_is_clear() {}
34
35 debug_assert!(flash.raw.int_status.read().err().bit_is_clear());
37 debug_assert!(flash.raw.int_status.read().fail().bit_is_clear());
39
40 FlashGordon { flash }
41 }
42
43 fn clear_status(&self) {
44 self.flash.raw.int_clr_status.write(|w| {
45 w.done()
46 .set_bit()
47 .ecc_err()
48 .set_bit()
49 .err()
50 .set_bit()
51 .fail()
52 .set_bit()
53 });
54 }
55
56 fn status(&self) -> Result {
57 let status = self.flash.raw.int_status.read();
58 if status.err().bit_is_set() {
62 return Err(Error::Illegal);
63 }
64 if status.ecc_err().bit_is_set() {
65 return Err(Error::EccError);
66 }
67 if status.fail().bit_is_set() {
68 return Err(Error::Failure);
69 }
70
71 Ok(())
72 }
73
74 pub fn just_program_at(&mut self, address: usize) -> Result {
75 let flash = &self.flash.raw;
76 assert!(flash.int_status.read().done().bit_is_set());
77 self.clear_status();
78
79 flash.event.write(|w| w.rst().set_bit());
80 while flash.int_status.read().done().bit_is_clear() {}
82 self.status()?;
83 self.clear_status();
84
85 flash
86 .starta
87 .write(|w| unsafe { w.starta().bits((address >> 4) as u32) });
88 flash
89 .cmd
90 .write(|w| unsafe { w.bits(FlashCommands::Program as u32) });
91 while flash.int_status.read().done().bit_is_clear() {}
92 debug_assert!(flash.int_status.read().err().bit_is_clear());
93 debug_assert!(flash.int_status.read().fail().bit_is_clear());
94 self.status()?;
95
96 Ok(())
97 }
98
99 pub fn clear_page_register(&mut self) {
100 let flash = &self.flash.raw;
101 assert!(flash.int_status.read().done().bit_is_set());
102 self.clear_status();
103
104 for i in 0..32 {
105 for j in 0..4 {
106 flash.dataw[j].write(|w| unsafe { w.bits(0x0) });
107 }
108 flash.starta.write(|w| unsafe { w.starta().bits(i as u32) });
109 flash
110 .cmd
111 .write(|w| unsafe { w.bits(FlashCommands::Write as u32) });
112
113 while flash.int_status.read().done().bit_is_clear() {}
114 debug_assert!(flash.int_status.read().err().bit_is_clear());
115 debug_assert!(flash.int_status.read().fail().bit_is_clear());
116 assert!(self.status().is_ok());
117 }
118 }
119
120 pub fn write_u8(&mut self, address: usize, byte: u8) -> Result {
121 self.clear_page_register();
122 let flash = &self.flash.raw;
123 let page_register_column = (address & (512 - 1)) >> 4;
125 let mut word = [0u8; 4];
126 word[address % 4] = byte;
127 for j in 0..4 {
129 flash.dataw[j].write(|w| unsafe { w.bits(0) });
130 }
131 flash.dataw[(address >> 2) % 4].write(|w| unsafe { w.bits(u32::from_ne_bytes(word)) });
132 flash
133 .starta
134 .write(|w| unsafe { w.starta().bits(page_register_column as u32) });
135 self.clear_status();
136 flash
137 .cmd
138 .write(|w| unsafe { w.bits(FlashCommands::Write as u32) });
139 while flash.int_status.read().done().bit_is_clear() {}
140 self.status()?;
141
142 self.clear_status();
143 flash
145 .starta
146 .write(|w| unsafe { w.starta().bits((address >> 4) as u32) });
147 flash
148 .cmd
149 .write(|w| unsafe { w.bits(FlashCommands::Program as u32) });
150 while flash.int_status.read().done().bit_is_clear() {}
151 self.status()?;
152 Ok(())
153 }
154
155 pub fn write_u32(&mut self, address: usize, word: u32) -> Result {
156 self.clear_page_register();
157 let flash = &self.flash.raw;
158
159 let page_register_column = (address & (512 - 1)) >> 4;
161 for j in 0..4 {
163 flash.dataw[j].write(|w| unsafe { w.bits(0) });
164 }
165 flash.dataw[(address >> 2) % 4].write(|w| unsafe { w.bits(word) });
166 flash
167 .starta
168 .write(|w| unsafe { w.starta().bits(page_register_column as u32) });
169 self.clear_status();
170 flash
171 .cmd
172 .write(|w| unsafe { w.bits(FlashCommands::Write as u32) });
173 while flash.int_status.read().done().bit_is_clear() {}
174 self.status()?;
175
176 self.clear_status();
177 flash
179 .starta
180 .write(|w| unsafe { w.starta().bits((address >> 4) as u32) });
181 flash
182 .cmd
183 .write(|w| unsafe { w.bits(FlashCommands::Program as u32) });
184 while flash.int_status.read().done().bit_is_clear() {}
185 self.status()?;
186
187 Ok(())
188 }
189
190 pub fn write_u128(&mut self, address: usize, data: u128) -> Result {
191 let flash = &self.flash.raw;
194
195 let buf: [u8; 16] = data.to_ne_bytes();
196
197 for (i, chunk) in buf.chunks(4).enumerate() {
198 flash.dataw[i]
199 .write(|w| unsafe { w.bits(u32::from_ne_bytes(chunk.try_into().unwrap())) });
200 }
201 flash
202 .starta
203 .write(|w| unsafe { w.starta().bits((address >> 4) as u32) });
204 self.clear_status();
205 flash
206 .cmd
207 .write(|w| unsafe { w.bits(FlashCommands::Write as u32) });
208 while flash.int_status.read().done().bit_is_clear() {}
209 self.status()?;
210
211 self.clear_status();
212 flash
214 .starta
215 .write(|w| unsafe { w.starta().bits((address >> 4) as u32) });
216 flash
217 .cmd
218 .write(|w| unsafe { w.bits(FlashCommands::Program as u32) });
219 while flash.int_status.read().done().bit_is_clear() {}
220 self.status()?;
221
222 Ok(())
223 }
224
225 pub fn read_u128(&mut self, address: usize) -> u128 {
226 let mut buf = [0u8; 16];
227 self.read(address, &mut buf);
228 u128::from_ne_bytes(buf)
229 }
230}
231
232impl Read<U16> for FlashGordon {
233 fn read_native(&self, address: usize, array: &mut GenericArray<u8, U16>) {
237 let flash = &self.flash.raw;
239
240 assert!(flash.int_status.read().done().bit_is_set());
241 self.clear_status();
242 assert!(self.status().is_ok());
247
248 let addr = address as u32;
249 debug_assert!(addr & (READ_SIZE as u32 - 1) == 0);
250
251 flash
252 .starta
253 .write(|w| unsafe { w.starta().bits(addr >> 4) });
254 flash.dataw[0].write(|w| unsafe { w.bits(0) });
256 flash
257 .cmd
258 .write(|w| unsafe { w.bits(FlashCommands::ReadSingleWord as u32) });
259 while flash.int_status.read().done().bit_is_clear() {
260 continue;
261 }
262
263 assert!(flash.int_status.read().err().bit_is_clear());
264 debug_assert!(flash.int_status.read().fail().bit_is_clear());
265
266 for (i, chunk) in array.chunks_mut(4).enumerate() {
268 chunk.copy_from_slice(&flash.dataw[i].read().bits().to_ne_bytes());
269 }
270 }
271}
272
273impl WriteErase<U512, U512> for FlashGordon {
274 fn status(&self) -> Result {
275 self.status()
276 }
277
278 fn erase_page(&mut self, page: usize) -> Result {
280 let starta = page * 32;
282 let flash = &self.flash.raw;
285 assert!(flash.int_status.read().done().bit_is_set());
286 self.clear_status();
287 assert!(flash.int_status.read().done().bit_is_clear());
288
289 flash
290 .starta
291 .write(|w| unsafe { w.starta().bits(starta as u32) });
292 flash
293 .stopa
294 .write(|w| unsafe { w.stopa().bits(starta as u32) });
295 flash
296 .cmd
297 .write(|w| unsafe { w.bits(FlashCommands::EraseRange as u32) });
298 while flash.int_status.read().done().bit_is_clear() {}
299
300 debug_assert!(flash.int_status.read().err().bit_is_clear());
301 debug_assert!(flash.int_status.read().fail().bit_is_clear());
302 self.status()?;
304
305 Ok(())
306 }
307
308 fn write_native(
309 &mut self,
310 address: usize,
311 array: &GenericArray<u8, U512>,
312 ) -> Result {
314 let flash = &self.flash.raw;
316 assert!(flash.int_status.read().done().bit_is_set());
317 self.clear_status();
318
319 for (i, chunk) in array.chunks(16).enumerate() {
323 let starta = (address >> 4) + i;
324 flash
325 .starta
326 .write(|w| unsafe { w.starta().bits(starta as u32) });
327
328 for (j, word) in chunk.chunks(4).enumerate() {
329 flash.dataw[j]
330 .write(|w| unsafe { w.bits(u32::from_ne_bytes(word.try_into().unwrap())) });
331 }
332
333 flash
334 .cmd
335 .write(|w| unsafe { w.bits(FlashCommands::Write as u32) });
336 while flash.int_status.read().done().bit_is_clear() {}
338 debug_assert!(flash.int_status.read().err().bit_is_clear());
339 debug_assert!(flash.int_status.read().fail().bit_is_clear());
340 self.status()?;
341 }
342 self.clear_status();
343
344 let starta = address >> 4;
345 flash
346 .starta
347 .write(|w| unsafe { w.starta().bits(starta as u32) });
348 flash
349 .cmd
350 .write(|w| unsafe { w.bits(FlashCommands::Program as u32) });
351 while flash.int_status.read().done().bit_is_clear() {}
352 debug_assert!(flash.int_status.read().err().bit_is_clear());
353 debug_assert!(flash.int_status.read().fail().bit_is_clear());
354 self.status()?;
355
356 Ok(())
357 }
358}
359
360#[allow(dead_code)]
361#[repr(C)]
362pub enum FlashCommands {
363 Init = 0x0,
364 PowerDown = 0x1,
365 SetReadMode = 0x2,
366 ReadSingleWord = 0x3,
367 EraseRange = 0x4,
368 BlankCheck = 0x5,
369 MarginCheck = 0x6,
370 Checksum = 0x7,
371 Write = 0x8,
372 WriteProgram = 0xA,
373 Program = 0xC,
374 ReportEcc = 0xD,
376}
377
378#[cfg(feature = "littlefs")]
379#[allow(non_camel_case_types)]
380pub mod littlefs_params {
381 use super::*;
382 pub const READ_SIZE: usize = 16;
383 pub const WRITE_SIZE: usize = 512;
384 pub const BLOCK_SIZE: usize = 512;
385
386 pub const BLOCK_CYCLES: isize = -1;
388
389 pub type CACHE_SIZE = U512;
390 pub type LOOKAHEAD_SIZE = U8;
391}
392
393#[cfg(feature = "littlefs")]
394#[macro_export]
395macro_rules! littlefs2_filesystem {
396 ($Name:ident: (
397 $BASE_OFFSET:expr
398 )) => {
399 littlefs2_filesystem!(
400 $Name: (
401 $BASE_OFFSET,
402 ((631 * 1024 + 512) - $BASE_OFFSET) / 512
404 )
405 );
406 };
407 ($Name:ident: (
408 $BASE_OFFSET:expr,
409 $BLOCK_COUNT:expr
410 )) => {
411 const _ZERO_SIZED_CHECK: usize = ((core::mem::size_of::<[u8; ($BASE_OFFSET % 512)]>() == 0) as usize) - 1;
414 const _OVERFLOW_SIZE_CHECK: usize = ((
416 core::mem::size_of::<[u8; (($BASE_OFFSET + $BLOCK_COUNT * 512) <= (631 * 1024 + 512)) as usize]>() == 1) as usize) - 1;
417
418 pub struct $Name {
419 flash_gordon: $crate::drivers::flash::FlashGordon
420 }
421
422 impl $Name {
423 const BASE_OFFSET: usize = $BASE_OFFSET;
424
425 pub fn new (flash_gordon: $crate::drivers::flash::FlashGordon) -> Self {
426 Self { flash_gordon }
427 }
428 }
429
430 impl littlefs2::driver::Storage for $Name {
431 const READ_SIZE: usize = $crate::drivers::flash::littlefs_params::READ_SIZE;
432 const WRITE_SIZE: usize = $crate::drivers::flash::littlefs_params::WRITE_SIZE;
433 const BLOCK_SIZE: usize = $crate::drivers::flash::littlefs_params::BLOCK_SIZE;
434
435 const BLOCK_COUNT: usize = $BLOCK_COUNT;
436 const BLOCK_CYCLES: isize = $crate::drivers::flash::littlefs_params::BLOCK_CYCLES;
437
438 type CACHE_SIZE = $crate::drivers::flash::littlefs_params::CACHE_SIZE;
439 type LOOKAHEAD_SIZE = $crate::drivers::flash::littlefs_params::LOOKAHEAD_SIZE;
440
441
442 fn read(&mut self, off: usize, buf: &mut [u8]) -> littlefs2::io::Result<usize> {
443 <$crate::drivers::flash::FlashGordon as $crate::traits::flash::Read<$crate::drivers::flash::U16>>
444 ::read(&self.flash_gordon, Self::BASE_OFFSET + off, buf);
445 Ok(buf.len())
446 }
447
448 fn write(&mut self, off: usize, data: &[u8]) -> littlefs2::io::Result<usize> {
449 let ret = <$crate::drivers::flash::FlashGordon as $crate::traits::flash::WriteErase<$crate::drivers::flash::U512, $crate::drivers::flash::U512>>
450 ::write(&mut self.flash_gordon, Self::BASE_OFFSET + off, data);
451 ret
452 .map(|_| data.len())
453 .map_err(|_| littlefs2::io::Error::IO)
454 }
455
456 fn erase(&mut self, off: usize, len: usize) -> littlefs2::io::Result<usize> {
457 let first_page = (Self::BASE_OFFSET + off) / 512;
458 let pages = len / 512;
459 for i in 0..pages {
460 <$crate::drivers::flash::FlashGordon as $crate::traits::flash::WriteErase<$crate::drivers::flash::U512, $crate::drivers::flash::U512>>
461 ::erase_page(&mut self.flash_gordon, first_page + i)
462 .map_err(|_| littlefs2::io::Error::IO)?;
463 }
464 Ok(512 * len)
465 }
466
467 }
468 }
470}
471
472#[cfg(feature = "littlefs")]
473#[macro_export]
474macro_rules! littlefs2_prince_filesystem {
475 ($Name:ident: (
476 $BASE_OFFSET:expr
477 )) => {
478 littlefs2_prince_filesystem!(
479 $Name: (
480 $BASE_OFFSET,
481 ((631 * 1024 + 512) - $BASE_OFFSET) / 512
483 )
484 );
485 };
486 ($Name:ident: (
487 $BASE_OFFSET:expr,
488 $BLOCK_COUNT:expr
489 )) => {
490 const _ZERO_SIZED_CHECK_0: usize = ((core::mem::size_of::<[u8; ($BASE_OFFSET % 512)]>() == 0) as usize) - 1;
493 const _OVERFLOW_SIZE_CHECK_0: usize = ((
495 core::mem::size_of::<[u8; (($BASE_OFFSET + $BLOCK_COUNT * 512) <= (631 * 1024 + 512)) as usize]>() == 1) as usize) - 1;
496
497
498 pub struct $Name {
499 flash_gordon: $crate::drivers::flash::FlashGordon,
500 prince: $crate::peripherals::prince::Prince<$crate::typestates::init_state::Enabled>,
501 }
502
503 impl $Name {
504 const BASE_OFFSET: usize = $BASE_OFFSET;
505
506 pub fn new (
507 flash_gordon: $crate::drivers::flash::FlashGordon,
508 prince: $crate::peripherals::prince::Prince<$crate::typestates::init_state::Enabled>,
509 ) -> Self {
510 Self { flash_gordon, prince }
511 }
512 }
513
514 impl littlefs2::driver::Storage for $Name {
515 const READ_SIZE: usize = $crate::drivers::flash::littlefs_params::READ_SIZE;
516 const WRITE_SIZE: usize = $crate::drivers::flash::littlefs_params::WRITE_SIZE;
517 const BLOCK_SIZE: usize = $crate::drivers::flash::littlefs_params::BLOCK_SIZE;
518
519 const BLOCK_COUNT: usize = $BLOCK_COUNT;
520 const BLOCK_CYCLES: isize = $crate::drivers::flash::littlefs_params::BLOCK_CYCLES;
521
522 type CACHE_SIZE = $crate::drivers::flash::littlefs_params::CACHE_SIZE;
523 type LOOKAHEAD_SIZE = $crate::drivers::flash::littlefs_params::LOOKAHEAD_SIZE;
524
525
526 fn read(&mut self, off: usize, buf: &mut [u8]) -> littlefs2::io::Result<usize> {
527 self.prince.enable_region_2_for(||{
528 let flash: *const u8 = (Self::BASE_OFFSET + off) as *const u8;
529 for i in 0 .. buf.len() {
530 buf[i] = unsafe{ *flash.offset(i as isize) };
531 }
532 });
533 Ok(buf.len())
534 }
535
536 fn write(&mut self, off: usize, data: &[u8]) -> littlefs2::io::Result<usize> {
537 let prince = &mut self.prince;
538 let flash_gordon = &mut self.flash_gordon;
539 let ret = prince.write_encrypted(|prince| {
540 prince.enable_region_2_for(||{
541 <$crate::drivers::flash::FlashGordon as
542 $crate::traits::flash::WriteErase<$crate::drivers::flash::U512, $crate::drivers::flash::U512>>
543 ::write(flash_gordon, Self::BASE_OFFSET + off, data)
544 })
545 });
546 ret
547 .map(|_| data.len())
548 .map_err(|_| littlefs2::io::Error::IO)
549 }
550
551 fn erase(&mut self, off: usize, len: usize) -> littlefs2::io::Result<usize> {
552 let first_page = (Self::BASE_OFFSET + off) / 512;
553 let pages = len / 512;
554 for i in 0..pages {
555 <$crate::drivers::flash::FlashGordon as
556 $crate::traits::flash::WriteErase<$crate::drivers::flash::U512, $crate::drivers::flash::U512>>
557 ::erase_page(&mut self.flash_gordon, first_page + i)
558 .map_err(|_| littlefs2::io::Error::IO)?;
559 }
560 Ok(512 * len)
561 }
562
563 }
564 }
566}
567
568