Merge remote-tracking branch 'upstream/master' into avoid-write-before-erase
This commit is contained in:
commit
c38eb9660b
@ -1,7 +1,7 @@
|
|||||||
use embedded_storage::nor_flash::{NorFlash, NorFlashError, NorFlashErrorKind};
|
use embedded_storage::nor_flash::{NorFlash, NorFlashError, NorFlashErrorKind};
|
||||||
use embedded_storage_async::nor_flash::NorFlash as AsyncNorFlash;
|
use embedded_storage_async::nor_flash::NorFlash as AsyncNorFlash;
|
||||||
|
|
||||||
use crate::{FirmwareWriter, Partition, State, BOOT_MAGIC, SWAP_MAGIC};
|
use crate::{Partition, State, BOOT_MAGIC, SWAP_MAGIC};
|
||||||
|
|
||||||
/// Errors returned by FirmwareUpdater
|
/// Errors returned by FirmwareUpdater
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -256,7 +256,6 @@ impl FirmwareUpdater {
|
|||||||
offset: usize,
|
offset: usize,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
dfu_flash: &mut F,
|
dfu_flash: &mut F,
|
||||||
block_size: usize,
|
|
||||||
) -> Result<(), FirmwareUpdaterError> {
|
) -> Result<(), FirmwareUpdaterError> {
|
||||||
assert!(data.len() >= F::ERASE_SIZE);
|
assert!(data.len() >= F::ERASE_SIZE);
|
||||||
|
|
||||||
@ -264,25 +263,23 @@ impl FirmwareUpdater {
|
|||||||
.erase(dfu_flash, offset as u32, (offset + data.len()) as u32)
|
.erase(dfu_flash, offset as u32, (offset + data.len()) as u32)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
FirmwareWriter(self.dfu)
|
self.dfu.write(dfu_flash, offset as u32, data).await?;
|
||||||
.write_block(offset, data, dfu_flash, block_size)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prepare for an incoming DFU update by erasing the entire DFU area and
|
/// Prepare for an incoming DFU update by erasing the entire DFU area and
|
||||||
/// returning a `FirmwareWriter`.
|
/// returning its `Partition`.
|
||||||
///
|
///
|
||||||
/// Using this instead of `write_firmware` allows for an optimized API in
|
/// Using this instead of `write_firmware` allows for an optimized API in
|
||||||
/// exchange for added complexity.
|
/// exchange for added complexity.
|
||||||
pub async fn prepare_update<F: AsyncNorFlash>(
|
pub async fn prepare_update<F: AsyncNorFlash>(
|
||||||
&mut self,
|
&mut self,
|
||||||
dfu_flash: &mut F,
|
dfu_flash: &mut F,
|
||||||
) -> Result<FirmwareWriter, FirmwareUpdaterError> {
|
) -> Result<Partition, FirmwareUpdaterError> {
|
||||||
self.dfu.wipe(dfu_flash).await?;
|
self.dfu.wipe(dfu_flash).await?;
|
||||||
|
|
||||||
Ok(FirmwareWriter(self.dfu))
|
Ok(self.dfu)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -469,29 +466,25 @@ impl FirmwareUpdater {
|
|||||||
offset: usize,
|
offset: usize,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
dfu_flash: &mut F,
|
dfu_flash: &mut F,
|
||||||
block_size: usize,
|
|
||||||
) -> Result<(), FirmwareUpdaterError> {
|
) -> Result<(), FirmwareUpdaterError> {
|
||||||
assert!(data.len() >= F::ERASE_SIZE);
|
assert!(data.len() >= F::ERASE_SIZE);
|
||||||
|
|
||||||
self.dfu
|
self.dfu
|
||||||
.erase_blocking(dfu_flash, offset as u32, (offset + data.len()) as u32)?;
|
.erase_blocking(dfu_flash, offset as u32, (offset + data.len()) as u32)?;
|
||||||
|
|
||||||
FirmwareWriter(self.dfu).write_block_blocking(offset, data, dfu_flash, block_size)?;
|
self.dfu.write_blocking(dfu_flash, offset as u32, data)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prepare for an incoming DFU update by erasing the entire DFU area and
|
/// Prepare for an incoming DFU update by erasing the entire DFU area and
|
||||||
/// returning a `FirmwareWriter`.
|
/// returning its `Partition`.
|
||||||
///
|
///
|
||||||
/// Using this instead of `write_firmware_blocking` allows for an optimized
|
/// Using this instead of `write_firmware_blocking` allows for an optimized
|
||||||
/// API in exchange for added complexity.
|
/// API in exchange for added complexity.
|
||||||
pub fn prepare_update_blocking<F: NorFlash>(
|
pub fn prepare_update_blocking<F: NorFlash>(&mut self, flash: &mut F) -> Result<Partition, FirmwareUpdaterError> {
|
||||||
&mut self,
|
|
||||||
flash: &mut F,
|
|
||||||
) -> Result<FirmwareWriter, FirmwareUpdaterError> {
|
|
||||||
self.dfu.wipe_blocking(flash)?;
|
self.dfu.wipe_blocking(flash)?;
|
||||||
|
|
||||||
Ok(FirmwareWriter(self.dfu))
|
Ok(self.dfu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
use embedded_storage::nor_flash::NorFlash;
|
|
||||||
use embedded_storage_async::nor_flash::NorFlash as AsyncNorFlash;
|
|
||||||
|
|
||||||
use crate::Partition;
|
|
||||||
|
|
||||||
/// FirmwareWriter allows writing blocks to an already erased flash.
|
|
||||||
pub struct FirmwareWriter(pub(crate) Partition);
|
|
||||||
|
|
||||||
impl FirmwareWriter {
|
|
||||||
/// Write data to a flash page.
|
|
||||||
///
|
|
||||||
/// The buffer must follow alignment requirements of the target flash and a multiple of page size big.
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
///
|
|
||||||
/// Failing to meet alignment and size requirements may result in a panic.
|
|
||||||
pub async fn write_block<F: AsyncNorFlash>(
|
|
||||||
&mut self,
|
|
||||||
offset: usize,
|
|
||||||
data: &[u8],
|
|
||||||
flash: &mut F,
|
|
||||||
block_size: usize,
|
|
||||||
) -> Result<(), F::Error> {
|
|
||||||
let mut offset = offset as u32;
|
|
||||||
for chunk in data.chunks(block_size) {
|
|
||||||
self.0.write(flash, offset, chunk).await?;
|
|
||||||
offset += chunk.len() as u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write data to a flash page.
|
|
||||||
///
|
|
||||||
/// The buffer must follow alignment requirements of the target flash and a multiple of page size big.
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
///
|
|
||||||
/// Failing to meet alignment and size requirements may result in a panic.
|
|
||||||
pub fn write_block_blocking<F: NorFlash>(
|
|
||||||
&mut self,
|
|
||||||
offset: usize,
|
|
||||||
data: &[u8],
|
|
||||||
flash: &mut F,
|
|
||||||
block_size: usize,
|
|
||||||
) -> Result<(), F::Error> {
|
|
||||||
let mut offset = offset as u32;
|
|
||||||
for chunk in data.chunks(block_size) {
|
|
||||||
self.0.write_blocking(flash, offset, chunk)?;
|
|
||||||
offset += chunk.len() as u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,13 +7,11 @@ mod fmt;
|
|||||||
|
|
||||||
mod boot_loader;
|
mod boot_loader;
|
||||||
mod firmware_updater;
|
mod firmware_updater;
|
||||||
mod firmware_writer;
|
|
||||||
mod mem_flash;
|
mod mem_flash;
|
||||||
mod partition;
|
mod partition;
|
||||||
|
|
||||||
pub use boot_loader::{BootError, BootFlash, BootLoader, Flash, FlashConfig, MultiFlashConfig, SingleFlashConfig};
|
pub use boot_loader::{BootError, BootFlash, BootLoader, Flash, FlashConfig, MultiFlashConfig, SingleFlashConfig};
|
||||||
pub use firmware_updater::{FirmwareUpdater, FirmwareUpdaterError};
|
pub use firmware_updater::{FirmwareUpdater, FirmwareUpdaterError};
|
||||||
pub use firmware_writer::FirmwareWriter;
|
|
||||||
pub use partition::Partition;
|
pub use partition::Partition;
|
||||||
|
|
||||||
pub(crate) const BOOT_MAGIC: u8 = 0xD0;
|
pub(crate) const BOOT_MAGIC: u8 = 0xD0;
|
||||||
@ -107,7 +105,7 @@ mod tests {
|
|||||||
let mut updater = FirmwareUpdater::new(DFU, STATE);
|
let mut updater = FirmwareUpdater::new(DFU, STATE);
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
for chunk in update.chunks(4096) {
|
for chunk in update.chunks(4096) {
|
||||||
block_on(updater.write_firmware(offset, chunk, &mut flash, 4096)).unwrap();
|
block_on(updater.write_firmware(offset, chunk, &mut flash)).unwrap();
|
||||||
offset += chunk.len();
|
offset += chunk.len();
|
||||||
}
|
}
|
||||||
block_on(updater.mark_updated(&mut flash, &mut aligned)).unwrap();
|
block_on(updater.mark_updated(&mut flash, &mut aligned)).unwrap();
|
||||||
@ -180,7 +178,7 @@ mod tests {
|
|||||||
|
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
for chunk in update.chunks(2048) {
|
for chunk in update.chunks(2048) {
|
||||||
block_on(updater.write_firmware(offset, chunk, &mut dfu, chunk.len())).unwrap();
|
block_on(updater.write_firmware(offset, chunk, &mut dfu)).unwrap();
|
||||||
offset += chunk.len();
|
offset += chunk.len();
|
||||||
}
|
}
|
||||||
block_on(updater.mark_updated(&mut state, &mut aligned)).unwrap();
|
block_on(updater.mark_updated(&mut state, &mut aligned)).unwrap();
|
||||||
@ -233,7 +231,7 @@ mod tests {
|
|||||||
|
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
for chunk in update.chunks(4096) {
|
for chunk in update.chunks(4096) {
|
||||||
block_on(updater.write_firmware(offset, chunk, &mut dfu, chunk.len())).unwrap();
|
block_on(updater.write_firmware(offset, chunk, &mut dfu)).unwrap();
|
||||||
offset += chunk.len();
|
offset += chunk.len();
|
||||||
}
|
}
|
||||||
block_on(updater.mark_updated(&mut state, &mut aligned)).unwrap();
|
block_on(updater.mark_updated(&mut state, &mut aligned)).unwrap();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# Before upgrading check that everything is available on all tier1 targets here:
|
# Before upgrading check that everything is available on all tier1 targets here:
|
||||||
# https://rust-lang.github.io/rustup-components-history
|
# https://rust-lang.github.io/rustup-components-history
|
||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly-2023-02-07"
|
channel = "nightly-2023-04-02"
|
||||||
components = [ "rust-src", "rustfmt", "llvm-tools-preview" ]
|
components = [ "rust-src", "rustfmt", "llvm-tools-preview" ]
|
||||||
targets = [
|
targets = [
|
||||||
"thumbv7em-none-eabi",
|
"thumbv7em-none-eabi",
|
||||||
|
25
tests/nrf/src/bin/timer.rs
Normal file
25
tests/nrf/src/bin/timer.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
use defmt::{assert, info};
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_time::{Duration, Instant, Timer};
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(_spawner: Spawner) {
|
||||||
|
let _p = embassy_nrf::init(Default::default());
|
||||||
|
info!("Hello World!");
|
||||||
|
|
||||||
|
let start = Instant::now();
|
||||||
|
Timer::after(Duration::from_millis(100)).await;
|
||||||
|
let end = Instant::now();
|
||||||
|
let ms = (end - start).as_millis();
|
||||||
|
info!("slept for {} ms", ms);
|
||||||
|
assert!(ms >= 99);
|
||||||
|
assert!(ms < 110);
|
||||||
|
|
||||||
|
info!("Test OK");
|
||||||
|
cortex_m::asm::bkpt();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user