2023-03-31 10:18:19 +02:00
|
|
|
use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
|
2023-04-11 13:49:32 +02:00
|
|
|
#[cfg(feature = "nightly")]
|
2023-03-31 10:18:19 +02:00
|
|
|
use embedded_storage_async::nor_flash::{NorFlash as AsyncNorFlash, ReadNorFlash as AsyncReadNorFlash};
|
|
|
|
|
2023-03-31 08:05:37 +02:00
|
|
|
/// A region in flash used by the bootloader.
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
|
|
|
pub struct Partition {
|
2023-03-31 10:18:19 +02:00
|
|
|
/// The offset into the flash where the partition starts.
|
2023-04-05 08:28:31 +02:00
|
|
|
pub from: u32,
|
2023-03-31 10:18:19 +02:00
|
|
|
/// The offset into the flash where the partition ends.
|
2023-04-05 08:28:31 +02:00
|
|
|
pub to: u32,
|
2023-03-31 08:05:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Partition {
|
|
|
|
/// Create a new partition with the provided range
|
2023-04-05 08:28:31 +02:00
|
|
|
pub const fn new(from: u32, to: u32) -> Self {
|
2023-03-31 08:05:37 +02:00
|
|
|
Self { from, to }
|
|
|
|
}
|
|
|
|
|
2023-03-31 10:18:19 +02:00
|
|
|
/// Return the size of the partition
|
2023-04-05 08:28:31 +02:00
|
|
|
pub const fn size(&self) -> u32 {
|
2023-03-31 08:05:37 +02:00
|
|
|
self.to - self.from
|
|
|
|
}
|
2023-03-31 10:18:19 +02:00
|
|
|
|
|
|
|
/// Read from the partition on the provided flash
|
2023-04-11 13:49:32 +02:00
|
|
|
pub fn read_blocking<F: ReadNorFlash>(&self, flash: &mut F, offset: u32, bytes: &mut [u8]) -> Result<(), F::Error> {
|
2023-03-31 10:18:19 +02:00
|
|
|
let offset = self.from as u32 + offset;
|
2023-04-11 13:49:32 +02:00
|
|
|
flash.read(offset, bytes)
|
2023-03-31 10:18:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Write to the partition on the provided flash
|
2023-04-11 13:49:32 +02:00
|
|
|
pub fn write_blocking<F: NorFlash>(&self, flash: &mut F, offset: u32, bytes: &[u8]) -> Result<(), F::Error> {
|
2023-03-31 10:18:19 +02:00
|
|
|
let offset = self.from as u32 + offset;
|
2023-04-11 13:49:32 +02:00
|
|
|
flash.write(offset, bytes)?;
|
2023-03-31 10:18:19 +02:00
|
|
|
trace!("Wrote from 0x{:x} len {}", offset, bytes.len());
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Erase part of the partition on the provided flash
|
2023-04-11 13:49:32 +02:00
|
|
|
pub fn erase_blocking<F: NorFlash>(&self, flash: &mut F, from: u32, to: u32) -> Result<(), F::Error> {
|
2023-03-31 10:18:19 +02:00
|
|
|
let from = self.from as u32 + from;
|
|
|
|
let to = self.from as u32 + to;
|
2023-04-11 13:49:32 +02:00
|
|
|
flash.erase(from, to)?;
|
2023-03-31 10:18:19 +02:00
|
|
|
trace!("Erased from 0x{:x} to 0x{:x}", from, to);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Erase the entire partition
|
2023-04-11 13:49:32 +02:00
|
|
|
pub(crate) fn wipe_blocking<F: NorFlash>(&self, flash: &mut F) -> Result<(), F::Error> {
|
2023-03-31 10:18:19 +02:00
|
|
|
let from = self.from as u32;
|
|
|
|
let to = self.to as u32;
|
2023-04-11 13:49:32 +02:00
|
|
|
flash.erase(from, to)?;
|
2023-03-31 10:18:19 +02:00
|
|
|
trace!("Wiped from 0x{:x} to 0x{:x}", from, to);
|
|
|
|
Ok(())
|
|
|
|
}
|
2023-04-11 13:49:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Async API
|
|
|
|
#[cfg(feature = "nightly")]
|
|
|
|
impl Partition {
|
2023-03-31 10:18:19 +02:00
|
|
|
|
|
|
|
/// Read from the partition on the provided flash
|
2023-04-11 13:49:32 +02:00
|
|
|
pub async fn read<F: AsyncReadNorFlash>(
|
|
|
|
&self,
|
|
|
|
flash: &mut F,
|
|
|
|
offset: u32,
|
|
|
|
bytes: &mut [u8],
|
|
|
|
) -> Result<(), F::Error> {
|
2023-03-31 10:18:19 +02:00
|
|
|
let offset = self.from as u32 + offset;
|
2023-04-11 13:49:32 +02:00
|
|
|
flash.read(offset, bytes).await
|
2023-03-31 10:18:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Write to the partition on the provided flash
|
2023-04-11 13:49:32 +02:00
|
|
|
pub async fn write<F: AsyncNorFlash>(&self, flash: &mut F, offset: u32, bytes: &[u8]) -> Result<(), F::Error> {
|
2023-03-31 10:18:19 +02:00
|
|
|
let offset = self.from as u32 + offset;
|
2023-04-11 13:49:32 +02:00
|
|
|
flash.write(offset, bytes).await?;
|
2023-03-31 10:18:19 +02:00
|
|
|
trace!("Wrote from 0x{:x} len {}", offset, bytes.len());
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Erase part of the partition on the provided flash
|
2023-04-11 13:49:32 +02:00
|
|
|
pub async fn erase<F: AsyncNorFlash>(&self, flash: &mut F, from: u32, to: u32) -> Result<(), F::Error> {
|
2023-03-31 10:18:19 +02:00
|
|
|
let from = self.from as u32 + from;
|
|
|
|
let to = self.from as u32 + to;
|
2023-04-11 13:49:32 +02:00
|
|
|
flash.erase(from, to).await?;
|
2023-03-31 10:18:19 +02:00
|
|
|
trace!("Erased from 0x{:x} to 0x{:x}", from, to);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Erase the entire partition
|
2023-04-11 13:49:32 +02:00
|
|
|
pub(crate) async fn wipe<F: AsyncNorFlash>(&self, flash: &mut F) -> Result<(), F::Error> {
|
2023-03-31 10:18:19 +02:00
|
|
|
let from = self.from as u32;
|
|
|
|
let to = self.to as u32;
|
2023-04-11 13:49:32 +02:00
|
|
|
flash.erase(from, to).await?;
|
2023-03-31 10:18:19 +02:00
|
|
|
trace!("Wiped from 0x{:x} to 0x{:x}", from, to);
|
|
|
|
Ok(())
|
|
|
|
}
|
2023-03-31 08:05:37 +02:00
|
|
|
}
|
2023-03-31 10:28:47 +02:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2023-04-03 15:33:20 +02:00
|
|
|
use crate::mem_flash::MemFlash;
|
2023-03-31 10:28:47 +02:00
|
|
|
use crate::Partition;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn can_erase() {
|
2023-04-03 15:33:20 +02:00
|
|
|
let mut flash = MemFlash::<1024, 64, 4>::new(0x00);
|
2023-03-31 10:28:47 +02:00
|
|
|
let partition = Partition::new(256, 512);
|
|
|
|
|
|
|
|
partition.erase_blocking(&mut flash, 64, 192).unwrap();
|
|
|
|
|
2023-04-03 15:33:20 +02:00
|
|
|
for (index, byte) in flash.mem.iter().copied().enumerate().take(256 + 64) {
|
2023-03-31 10:28:47 +02:00
|
|
|
assert_eq!(0x00, byte, "Index {}", index);
|
|
|
|
}
|
|
|
|
|
2023-04-03 15:33:20 +02:00
|
|
|
for (index, byte) in flash.mem.iter().copied().enumerate().skip(256 + 64).take(128) {
|
2023-03-31 10:28:47 +02:00
|
|
|
assert_eq!(0xFF, byte, "Index {}", index);
|
|
|
|
}
|
|
|
|
|
2023-04-03 15:33:20 +02:00
|
|
|
for (index, byte) in flash.mem.iter().copied().enumerate().skip(256 + 64 + 128) {
|
2023-03-31 10:28:47 +02:00
|
|
|
assert_eq!(0x00, byte, "Index {}", index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn can_wipe() {
|
2023-04-03 15:33:20 +02:00
|
|
|
let mut flash = MemFlash::<1024, 64, 4>::new(0x00);
|
2023-03-31 10:28:47 +02:00
|
|
|
let partition = Partition::new(256, 512);
|
|
|
|
|
|
|
|
partition.wipe_blocking(&mut flash).unwrap();
|
|
|
|
|
2023-04-03 15:33:20 +02:00
|
|
|
for (index, byte) in flash.mem.iter().copied().enumerate().take(256) {
|
2023-03-31 10:28:47 +02:00
|
|
|
assert_eq!(0x00, byte, "Index {}", index);
|
|
|
|
}
|
|
|
|
|
2023-04-03 15:33:20 +02:00
|
|
|
for (index, byte) in flash.mem.iter().copied().enumerate().skip(256).take(256) {
|
2023-03-31 10:28:47 +02:00
|
|
|
assert_eq!(0xFF, byte, "Index {}", index);
|
|
|
|
}
|
|
|
|
|
2023-04-03 15:33:20 +02:00
|
|
|
for (index, byte) in flash.mem.iter().copied().enumerate().skip(512) {
|
2023-03-31 10:28:47 +02:00
|
|
|
assert_eq!(0x00, byte, "Index {}", index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|