Skip to main content

embassy_utils/flash/
flash_util.rs

1use embassy_rp_plus::embassy_rp::flash;
2use embassy_rp_plus::embassy_rp::flash::{Instance, Mode};
3use crate::flash::err::FlashResult;
4use crate::flash::flash_lock::FlashLock;
5
6/// flash util
7pub struct FlashUtil<'a, T: Instance, M: Mode, const FLASH_SIZE: usize> {
8    /// flash device
9    pub flash: &'a FlashLock<'a, T, M, FLASH_SIZE>,
10    /// offset from the flash start, NOT an absolute address.
11    pub offset: u32,
12    /// flash minimum erase size
13    erase_size: u32,
14}
15
16/// custom method
17impl<'a, T: Instance, M: Mode, const FLASH_SIZE: usize> FlashUtil<'a, T, M, FLASH_SIZE> {
18    /// create flash util
19    #[inline]
20    pub fn new(flash: &'a FlashLock<'a, T, M, FLASH_SIZE>, offset: u32, erase_size: u32) -> Self {
21        Self { flash, offset, erase_size }
22    }
23
24    /// create flash util, default offset is 0x100000, default erase_size is 4096
25    #[inline]
26    pub fn new_default(flash: &'a FlashLock<'a, T, M, FLASH_SIZE>) -> Self {
27        Self::new(flash, 0x100000, 4096)
28    }
29
30    /// try read to buf, more see [FlashLock::blocking_read]
31    #[inline]
32    pub async fn try_read(&self, buf: &mut [u8]) -> Result<(), flash::Error> {
33        self.flash.blocking_read(self.offset, buf).await
34    }
35
36    /// try erase, more see [FlashLock::blocking_erase]
37    pub async fn try_erase(&self, num: u32) -> Result<(), flash::Error> {
38        if num == 0 { return Ok(()); }
39        self.flash.blocking_erase(self.offset, self.offset + self.erase_size * num).await
40    }
41
42    /// try erase and write data<br />
43    /// flash memories with lengths multiple of erase_size will be automatically erased.
44    /// ff data is not empty, at least one flash memory of erase_size block will be erased
45    pub async fn try_erase_write(&self, buf: &[u8]) -> FlashResult<()> {
46        if buf.is_empty() { return Ok(()); }
47
48        // calc to offset address
49        let len = u32::try_from(buf.len())?;
50        let sub_to = if len % self.offset == 0 { 0 } else { 1 };
51        let to = self.erase_size * (len / self.offset + sub_to) + self.offset;
52
53        // erase and write
54        self.flash.try_erase_write(self.offset, to, buf).await?;
55        Ok(())
56    }
57
58    /// erase and write data, more see [Self::try_erase_write]<br />
59    /// flash memories with lengths multiple of erase_size will be automatically erased.
60    /// ff data is not empty, at least one flash memory of erase_size block will be erased
61    #[inline]
62    pub async fn erase_write(&self, buf: &[u8]) {
63        self.try_erase_write(buf).await.ok();
64    }
65}