lpc55_hal/traits/flash.rs
1use generic_array::{ArrayLength, GenericArray};
2
3/// Flash operation error
4#[derive(Copy, Clone, Debug)]
5pub enum Error {
6 /// Flash controller is not done yet
7 Busy,
8 /// Error detected (by command execution, or because no command could be executed)
9 Illegal,
10 /// Set during read if ECC decoding logic detects correctable or uncorrectable error
11 EccError,
12 /// (Legal) command failed
13 Failure,
14}
15
16// /// Flash program and erase controller failed to unlock
17// UnlockFailed,
18// /// Address to be programmed contains a value different from '0xFFFF' before programming
19// ProgrammingError,
20// /// Programming a write-protected address of the Flash memory
21// WriteProtectionError,
22// /// Programming and erase controller is busy
23// Busy
24// }
25
26/// A type alias for the result of a Flash operation.
27pub type Result = core::result::Result<(), Error>;
28
29// pub trait FlashOps: Locking + WriteErase + Read {}
30
31pub trait Read<ReadSize: ArrayLength<u8>> {
32 // Address alignment?
33 fn read_native(&self, address: usize, array: &mut GenericArray<u8, ReadSize>);
34
35 /// read a buffer of bytes from memory
36 /// checks that the address and buffer size are multiples of native
37 /// FLASH ReadSize.
38 fn read(&self, address: usize, buf: &mut [u8]) {
39 // TODO: offer a version without restrictions?
40 // can round down address, round up buffer length,
41 // but where to get the buffer from?
42 assert!(buf.len() % ReadSize::to_usize() == 0);
43 assert!(address % ReadSize::to_usize() == 0);
44
45 for i in (0..buf.len()).step_by(ReadSize::to_usize()) {
46 self.read_native(
47 address + i,
48 GenericArray::from_mut_slice(&mut buf[i..i + ReadSize::to_usize()]),
49 );
50 }
51 }
52}
53
54pub trait WriteErase<EraseSize: ArrayLength<u8>, WriteSize: ArrayLength<u8>> {
55 /// check flash status
56 fn status(&self) -> Result;
57
58 /// Erase specified flash page.
59 fn erase_page(&mut self, page: usize) -> Result;
60
61 /// The smallest possible write, depends on platform
62 /// TODO: can we typecheck/typehint whether `address` must be aligned?
63 fn write_native(
64 &mut self,
65 address: usize,
66 array: &GenericArray<u8, WriteSize>,
67 // cs: &CriticalSection,
68 ) -> Result;
69
70 fn write(&mut self, address: usize, data: &[u8]) -> Result {
71 let write_size = WriteSize::to_usize();
72 assert!(data.len() % write_size == 0);
73 assert!(address % write_size == 0);
74
75 // interrupt::free(|cs| {
76 for i in (0..data.len()).step_by(write_size) {
77 self.write_native(
78 address + i,
79 GenericArray::from_slice(&data[i..i + write_size]),
80 // cs,
81 )?;
82 }
83 Ok(())
84 // })
85 }
86
87 // probably not so useful, as only applicable after mass erase
88 // /// Faster programming
89 // fn program_sixtyfour_bytes(&self, address: usize, data: [u8; 64]) -> Result {
90
91 // /// Erase all Flash pages
92 // fn erase_all_pages(&mut self) -> Result;
93}