aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-boot/boot/src/firmware_updater.rs25
-rw-r--r--embassy-boot/boot/src/firmware_writer.rs55
-rw-r--r--embassy-boot/boot/src/lib.rs8
-rw-r--r--rust-toolchain.toml2
-rw-r--r--tests/nrf/src/bin/timer.rs25
5 files changed, 38 insertions, 77 deletions
diff --git a/embassy-boot/boot/src/firmware_updater.rs b/embassy-boot/boot/src/firmware_updater.rs
index 90157036a..22e3e6b00 100644
--- a/embassy-boot/boot/src/firmware_updater.rs
+++ b/embassy-boot/boot/src/firmware_updater.rs
@@ -1,7 +1,7 @@
1use embedded_storage::nor_flash::{NorFlash, NorFlashError, NorFlashErrorKind}; 1use embedded_storage::nor_flash::{NorFlash, NorFlashError, NorFlashErrorKind};
2use embedded_storage_async::nor_flash::NorFlash as AsyncNorFlash; 2use embedded_storage_async::nor_flash::NorFlash as AsyncNorFlash;
3 3
4use crate::{FirmwareWriter, Partition, State, BOOT_MAGIC, SWAP_MAGIC}; 4use crate::{Partition, State, BOOT_MAGIC, SWAP_MAGIC};
5 5
6/// Errors returned by FirmwareUpdater 6/// Errors returned by FirmwareUpdater
7#[derive(Debug)] 7#[derive(Debug)]
@@ -253,7 +253,6 @@ impl FirmwareUpdater {
253 offset: usize, 253 offset: usize,
254 data: &[u8], 254 data: &[u8],
255 dfu_flash: &mut F, 255 dfu_flash: &mut F,
256 block_size: usize,
257 ) -> Result<(), FirmwareUpdaterError> { 256 ) -> Result<(), FirmwareUpdaterError> {
258 assert!(data.len() >= F::ERASE_SIZE); 257 assert!(data.len() >= F::ERASE_SIZE);
259 258
@@ -261,25 +260,23 @@ impl FirmwareUpdater {
261 .erase(dfu_flash, offset as u32, (offset + data.len()) as u32) 260 .erase(dfu_flash, offset as u32, (offset + data.len()) as u32)
262 .await?; 261 .await?;
263 262
264 FirmwareWriter(self.dfu) 263 self.dfu.write(dfu_flash, offset as u32, data).await?;
265 .write_block(offset, data, dfu_flash, block_size)
266 .await?;
267 264
268 Ok(()) 265 Ok(())
269 } 266 }
270 267
271 /// Prepare for an incoming DFU update by erasing the entire DFU area and 268 /// Prepare for an incoming DFU update by erasing the entire DFU area and
272 /// returning a `FirmwareWriter`. 269 /// returning its `Partition`.
273 /// 270 ///
274 /// Using this instead of `write_firmware` allows for an optimized API in 271 /// Using this instead of `write_firmware` allows for an optimized API in
275 /// exchange for added complexity. 272 /// exchange for added complexity.
276 pub async fn prepare_update<F: AsyncNorFlash>( 273 pub async fn prepare_update<F: AsyncNorFlash>(
277 &mut self, 274 &mut self,
278 dfu_flash: &mut F, 275 dfu_flash: &mut F,
279 ) -> Result<FirmwareWriter, FirmwareUpdaterError> { 276 ) -> Result<Partition, FirmwareUpdaterError> {
280 self.dfu.wipe(dfu_flash).await?; 277 self.dfu.wipe(dfu_flash).await?;
281 278
282 Ok(FirmwareWriter(self.dfu)) 279 Ok(self.dfu)
283 } 280 }
284 281
285 // 282 //
@@ -460,29 +457,25 @@ impl FirmwareUpdater {
460 offset: usize, 457 offset: usize,
461 data: &[u8], 458 data: &[u8],
462 dfu_flash: &mut F, 459 dfu_flash: &mut F,
463 block_size: usize,
464 ) -> Result<(), FirmwareUpdaterError> { 460 ) -> Result<(), FirmwareUpdaterError> {
465 assert!(data.len() >= F::ERASE_SIZE); 461 assert!(data.len() >= F::ERASE_SIZE);
466 462
467 self.dfu 463 self.dfu
468 .erase_blocking(dfu_flash, offset as u32, (offset + data.len()) as u32)?; 464 .erase_blocking(dfu_flash, offset as u32, (offset + data.len()) as u32)?;
469 465
470 FirmwareWriter(self.dfu).write_block_blocking(offset, data, dfu_flash, block_size)?; 466 self.dfu.write_blocking(dfu_flash, offset as u32, data)?;
471 467
472 Ok(()) 468 Ok(())
473 } 469 }
474 470
475 /// Prepare for an incoming DFU update by erasing the entire DFU area and 471 /// Prepare for an incoming DFU update by erasing the entire DFU area and
476 /// returning a `FirmwareWriter`. 472 /// returning its `Partition`.
477 /// 473 ///
478 /// Using this instead of `write_firmware_blocking` allows for an optimized 474 /// Using this instead of `write_firmware_blocking` allows for an optimized
479 /// API in exchange for added complexity. 475 /// API in exchange for added complexity.
480 pub fn prepare_update_blocking<F: NorFlash>( 476 pub fn prepare_update_blocking<F: NorFlash>(&mut self, flash: &mut F) -> Result<Partition, FirmwareUpdaterError> {
481 &mut self,
482 flash: &mut F,
483 ) -> Result<FirmwareWriter, FirmwareUpdaterError> {
484 self.dfu.wipe_blocking(flash)?; 477 self.dfu.wipe_blocking(flash)?;
485 478
486 Ok(FirmwareWriter(self.dfu)) 479 Ok(self.dfu)
487 } 480 }
488} 481}
diff --git a/embassy-boot/boot/src/firmware_writer.rs b/embassy-boot/boot/src/firmware_writer.rs
deleted file mode 100644
index 46079e731..000000000
--- a/embassy-boot/boot/src/firmware_writer.rs
+++ /dev/null
@@ -1,55 +0,0 @@
1use embedded_storage::nor_flash::NorFlash;
2use embedded_storage_async::nor_flash::NorFlash as AsyncNorFlash;
3
4use crate::Partition;
5
6/// FirmwareWriter allows writing blocks to an already erased flash.
7pub struct FirmwareWriter(pub(crate) Partition);
8
9impl FirmwareWriter {
10 /// Write data to a flash page.
11 ///
12 /// The buffer must follow alignment requirements of the target flash and a multiple of page size big.
13 ///
14 /// # Safety
15 ///
16 /// Failing to meet alignment and size requirements may result in a panic.
17 pub async fn write_block<F: AsyncNorFlash>(
18 &mut self,
19 offset: usize,
20 data: &[u8],
21 flash: &mut F,
22 block_size: usize,
23 ) -> Result<(), F::Error> {
24 let mut offset = offset as u32;
25 for chunk in data.chunks(block_size) {
26 self.0.write(flash, offset, chunk).await?;
27 offset += chunk.len() as u32;
28 }
29
30 Ok(())
31 }
32
33 /// Write data to a flash page.
34 ///
35 /// The buffer must follow alignment requirements of the target flash and a multiple of page size big.
36 ///
37 /// # Safety
38 ///
39 /// Failing to meet alignment and size requirements may result in a panic.
40 pub fn write_block_blocking<F: NorFlash>(
41 &mut self,
42 offset: usize,
43 data: &[u8],
44 flash: &mut F,
45 block_size: usize,
46 ) -> Result<(), F::Error> {
47 let mut offset = offset as u32;
48 for chunk in data.chunks(block_size) {
49 self.0.write_blocking(flash, offset, chunk)?;
50 offset += chunk.len() as u32;
51 }
52
53 Ok(())
54 }
55}
diff --git a/embassy-boot/boot/src/lib.rs b/embassy-boot/boot/src/lib.rs
index 6d0e2d8c2..6888a8055 100644
--- a/embassy-boot/boot/src/lib.rs
+++ b/embassy-boot/boot/src/lib.rs
@@ -7,12 +7,10 @@ mod fmt;
7 7
8mod boot_loader; 8mod boot_loader;
9mod firmware_updater; 9mod firmware_updater;
10mod firmware_writer;
11mod partition; 10mod partition;
12 11
13pub use boot_loader::{BootError, BootFlash, BootLoader, Flash, FlashConfig, MultiFlashConfig, SingleFlashConfig}; 12pub use boot_loader::{BootError, BootFlash, BootLoader, Flash, FlashConfig, MultiFlashConfig, SingleFlashConfig};
14pub use firmware_updater::{FirmwareUpdater, FirmwareUpdaterError}; 13pub use firmware_updater::{FirmwareUpdater, FirmwareUpdaterError};
15pub use firmware_writer::FirmwareWriter;
16pub use partition::Partition; 14pub use partition::Partition;
17 15
18pub(crate) const BOOT_MAGIC: u8 = 0xD0; 16pub(crate) const BOOT_MAGIC: u8 = 0xD0;
@@ -109,7 +107,7 @@ mod tests {
109 let mut updater = FirmwareUpdater::new(DFU, STATE); 107 let mut updater = FirmwareUpdater::new(DFU, STATE);
110 let mut offset = 0; 108 let mut offset = 0;
111 for chunk in update.chunks(4096) { 109 for chunk in update.chunks(4096) {
112 block_on(updater.write_firmware(offset, chunk, &mut flash, 4096)).unwrap(); 110 block_on(updater.write_firmware(offset, chunk, &mut flash)).unwrap();
113 offset += chunk.len(); 111 offset += chunk.len();
114 } 112 }
115 block_on(updater.mark_updated(&mut flash, &mut aligned)).unwrap(); 113 block_on(updater.mark_updated(&mut flash, &mut aligned)).unwrap();
@@ -182,7 +180,7 @@ mod tests {
182 180
183 let mut offset = 0; 181 let mut offset = 0;
184 for chunk in update.chunks(2048) { 182 for chunk in update.chunks(2048) {
185 block_on(updater.write_firmware(offset, chunk, &mut dfu, chunk.len())).unwrap(); 183 block_on(updater.write_firmware(offset, chunk, &mut dfu)).unwrap();
186 offset += chunk.len(); 184 offset += chunk.len();
187 } 185 }
188 block_on(updater.mark_updated(&mut state, &mut aligned)).unwrap(); 186 block_on(updater.mark_updated(&mut state, &mut aligned)).unwrap();
@@ -235,7 +233,7 @@ mod tests {
235 233
236 let mut offset = 0; 234 let mut offset = 0;
237 for chunk in update.chunks(4096) { 235 for chunk in update.chunks(4096) {
238 block_on(updater.write_firmware(offset, chunk, &mut dfu, chunk.len())).unwrap(); 236 block_on(updater.write_firmware(offset, chunk, &mut dfu)).unwrap();
239 offset += chunk.len(); 237 offset += chunk.len();
240 } 238 }
241 block_on(updater.mark_updated(&mut state, &mut aligned)).unwrap(); 239 block_on(updater.mark_updated(&mut state, &mut aligned)).unwrap();
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
index da75fa53a..22abacdea 100644
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,7 +1,7 @@
1# Before upgrading check that everything is available on all tier1 targets here: 1# Before upgrading check that everything is available on all tier1 targets here:
2# https://rust-lang.github.io/rustup-components-history 2# https://rust-lang.github.io/rustup-components-history
3[toolchain] 3[toolchain]
4channel = "nightly-2023-02-07" 4channel = "nightly-2023-04-02"
5components = [ "rust-src", "rustfmt", "llvm-tools-preview" ] 5components = [ "rust-src", "rustfmt", "llvm-tools-preview" ]
6targets = [ 6targets = [
7 "thumbv7em-none-eabi", 7 "thumbv7em-none-eabi",
diff --git a/tests/nrf/src/bin/timer.rs b/tests/nrf/src/bin/timer.rs
new file mode 100644
index 000000000..9b9b5fb28
--- /dev/null
+++ b/tests/nrf/src/bin/timer.rs
@@ -0,0 +1,25 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::{assert, info};
6use embassy_executor::Spawner;
7use embassy_time::{Duration, Instant, Timer};
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let _p = embassy_nrf::init(Default::default());
13 info!("Hello World!");
14
15 let start = Instant::now();
16 Timer::after(Duration::from_millis(100)).await;
17 let end = Instant::now();
18 let ms = (end - start).as_millis();
19 info!("slept for {} ms", ms);
20 assert!(ms >= 99);
21 assert!(ms < 110);
22
23 info!("Test OK");
24 cortex_m::asm::bkpt();
25}