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}