aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Lilleengen <[email protected]>2022-04-26 18:33:09 +0200
committerUlf Lilleengen <[email protected]>2022-04-27 15:17:18 +0200
commitda61611f8f57410a87106961efd24d80e6a8f63e (patch)
tree81bf5f96a052be8cc74fa4f513592adf1f4bb1db
parent484e0acc638c27366e19275c32db9c8487ea8fba (diff)
Add bootloader to CI
-rwxr-xr-xci.sh7
-rw-r--r--embassy-boot/boot/Cargo.toml5
-rw-r--r--embassy-boot/boot/src/lib.rs57
-rw-r--r--embassy-boot/nrf/Cargo.toml2
-rw-r--r--embassy-boot/nrf/src/lib.rs2
-rw-r--r--embassy-boot/nrf/src/main.rs5
-rw-r--r--embassy-boot/stm32/Cargo.toml4
-rw-r--r--embassy-boot/stm32/memory.x12
-rw-r--r--embassy-boot/stm32/src/lib.rs8
-rw-r--r--embassy-boot/stm32/src/main.rs18
-rw-r--r--embassy-stm32/src/flash/mod.rs84
-rw-r--r--examples/boot/nrf/.cargo/config.toml6
-rw-r--r--examples/boot/nrf/Cargo.toml2
-rw-r--r--examples/boot/nrf/README.md8
-rw-r--r--examples/boot/stm32l0/Cargo.toml2
-rw-r--r--examples/boot/stm32l0/README.md2
-rw-r--r--examples/boot/stm32l0/memory.x8
-rw-r--r--examples/boot/stm32l1/Cargo.toml2
-rw-r--r--examples/boot/stm32l1/README.md2
-rw-r--r--examples/boot/stm32l1/memory.x8
-rw-r--r--examples/boot/stm32l4/Cargo.toml2
-rw-r--r--examples/boot/stm32l4/README.md2
-rw-r--r--examples/boot/stm32l4/memory.x10
-rw-r--r--examples/boot/stm32wl/Cargo.toml2
-rw-r--r--examples/boot/stm32wl/README.md2
-rw-r--r--examples/boot/stm32wl/memory.x8
-rw-r--r--examples/boot/stm32wl/src/bin/a.rs8
-rw-r--r--examples/stm32l0/src/bin/flash.rs2
-rw-r--r--examples/stm32l1/src/bin/flash.rs2
-rw-r--r--examples/stm32wl/src/bin/flash.rs2
m---------stm32-data0
-rw-r--r--stm32-metapac-gen/src/data.rs8
-rw-r--r--stm32-metapac-gen/src/lib.rs34
-rw-r--r--stm32-metapac/src/metadata.rs8
34 files changed, 162 insertions, 172 deletions
diff --git a/ci.sh b/ci.sh
index 69fa08047..c6fe9c4aa 100755
--- a/ci.sh
+++ b/ci.sh
@@ -58,6 +58,8 @@ cargo batch \
58 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features nightly,stm32l552ze,defmt,exti,time-driver-any,unstable-traits \ 58 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features nightly,stm32l552ze,defmt,exti,time-driver-any,unstable-traits \
59 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32wl54jc-cm0p,defmt,exti,time-driver-any,unstable-traits \ 59 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features nightly,stm32wl54jc-cm0p,defmt,exti,time-driver-any,unstable-traits \
60 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32wle5ub,defmt,exti,time-driver-any,unstable-traits \ 60 --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features nightly,stm32wle5ub,defmt,exti,time-driver-any,unstable-traits \
61 --- build --release --manifest-path embassy-boot/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840 \
62 --- build --release --manifest-path embassy-boot/stm32/Cargo.toml --target thumbv7em-none-eabi --features embassy-stm32/stm32wl55jc-cm4 \
61 --- build --release --manifest-path docs/modules/ROOT/examples/basic/Cargo.toml --target thumbv7em-none-eabi \ 63 --- build --release --manifest-path docs/modules/ROOT/examples/basic/Cargo.toml --target thumbv7em-none-eabi \
62 --- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-pac/Cargo.toml --target thumbv7em-none-eabi \ 64 --- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-pac/Cargo.toml --target thumbv7em-none-eabi \
63 --- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-hal/Cargo.toml --target thumbv7em-none-eabi \ 65 --- build --release --manifest-path docs/modules/ROOT/examples/layer-by-layer/blinky-hal/Cargo.toml --target thumbv7em-none-eabi \
@@ -81,6 +83,11 @@ cargo batch \
81 --- build --release --manifest-path examples/stm32u5/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/stm32u5 \ 83 --- build --release --manifest-path examples/stm32u5/Cargo.toml --target thumbv8m.main-none-eabihf --out-dir out/examples/stm32u5 \
82 --- build --release --manifest-path examples/stm32wb/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32wb \ 84 --- build --release --manifest-path examples/stm32wb/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32wb \
83 --- build --release --manifest-path examples/stm32wl/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32wl \ 85 --- build --release --manifest-path examples/stm32wl/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32wl \
86 --- build --release --manifest-path examples/boot/nrf/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/boot/nrf --bin b \
87 --- build --release --manifest-path examples/boot/stm32l0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/boot/stm32l0 --bin b \
88 --- build --release --manifest-path examples/boot/stm32l1/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/boot/stm32l1 --bin b \
89 --- build --release --manifest-path examples/boot/stm32l4/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/boot/stm32l4 --bin b \
90 --- build --release --manifest-path examples/boot/stm32wl/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/boot/stm32wl --bin b \
84 --- build --release --manifest-path examples/wasm/Cargo.toml --target wasm32-unknown-unknown --out-dir out/examples/wasm \ 91 --- build --release --manifest-path examples/wasm/Cargo.toml --target wasm32-unknown-unknown --out-dir out/examples/wasm \
85 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f103c8 --out-dir out/tests/bluepill-stm32f103c8 \ 92 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7m-none-eabi --features stm32f103c8 --out-dir out/tests/bluepill-stm32f103c8 \
86 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi --out-dir out/tests/nucleo-stm32f429zi \ 93 --- build --release --manifest-path tests/stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi --out-dir out/tests/nucleo-stm32f429zi \
diff --git a/embassy-boot/boot/Cargo.toml b/embassy-boot/boot/Cargo.toml
index 04deab30b..0a3006ffc 100644
--- a/embassy-boot/boot/Cargo.toml
+++ b/embassy-boot/boot/Cargo.toml
@@ -21,8 +21,3 @@ log = "0.4"
21env_logger = "0.9" 21env_logger = "0.9"
22rand = "0.8" 22rand = "0.8"
23futures = { version = "0.3", features = ["executor"] } 23futures = { version = "0.3", features = ["executor"] }
24
25[features]
26write-4 = []
27write-8 = []
28invert-erase = []
diff --git a/embassy-boot/boot/src/lib.rs b/embassy-boot/boot/src/lib.rs
index 080ea2426..554709250 100644
--- a/embassy-boot/boot/src/lib.rs
+++ b/embassy-boot/boot/src/lib.rs
@@ -1,5 +1,7 @@
1#![feature(type_alias_impl_trait)] 1#![feature(type_alias_impl_trait)]
2#![feature(generic_associated_types)] 2#![feature(generic_associated_types)]
3#![feature(generic_const_exprs)]
4#![allow(incomplete_features)]
3#![no_std] 5#![no_std]
4///! embassy-boot is a bootloader and firmware updater for embedded devices with flash 6///! embassy-boot is a bootloader and firmware updater for embedded devices with flash
5///! storage implemented using embedded-storage 7///! storage implemented using embedded-storage
@@ -17,24 +19,9 @@ mod fmt;
17use embedded_storage::nor_flash::{NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; 19use embedded_storage::nor_flash::{NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash};
18use embedded_storage_async::nor_flash::AsyncNorFlash; 20use embedded_storage_async::nor_flash::AsyncNorFlash;
19 21
20#[cfg(not(any(feature = "write-4", feature = "write-8",)))]
21compile_error!("No write size/alignment specified. Must specify exactly one of the following features: write-4, write-8");
22
23const BOOT_MAGIC: u8 = 0xD0; 22const BOOT_MAGIC: u8 = 0xD0;
24const SWAP_MAGIC: u8 = 0xF0; 23const SWAP_MAGIC: u8 = 0xF0;
25 24
26#[cfg(feature = "write-4")]
27const WRITE_SIZE: usize = 4;
28
29#[cfg(feature = "write-8")]
30const WRITE_SIZE: usize = 8;
31
32#[cfg(feature = "invert-erase")]
33const ERASE_VALUE: u8 = 0x00;
34
35#[cfg(not(feature = "invert-erase"))]
36const ERASE_VALUE: u8 = 0xFF;
37
38#[derive(Copy, Clone, Debug)] 25#[derive(Copy, Clone, Debug)]
39#[cfg_attr(feature = "defmt", derive(defmt::Format))] 26#[cfg_attr(feature = "defmt", derive(defmt::Format))]
40pub struct Partition { 27pub struct Partition {
@@ -96,7 +83,7 @@ pub trait FlashProvider {
96 83
97/// BootLoader works with any flash implementing embedded_storage and can also work with 84/// BootLoader works with any flash implementing embedded_storage and can also work with
98/// different page sizes and flash write sizes. 85/// different page sizes and flash write sizes.
99pub struct BootLoader<const PAGE_SIZE: usize> { 86pub struct BootLoader<const PAGE_SIZE: usize, const WRITE_SIZE: usize, const ERASE_VALUE: u8> {
100 // Page with current state of bootloader. The state partition has the following format: 87 // Page with current state of bootloader. The state partition has the following format:
101 // | Range | Description | 88 // | Range | Description |
102 // | 0 - WRITE_SIZE | Magic indicating bootloader state. BOOT_MAGIC means boot, SWAP_MAGIC means swap. | 89 // | 0 - WRITE_SIZE | Magic indicating bootloader state. BOOT_MAGIC means boot, SWAP_MAGIC means swap. |
@@ -108,7 +95,9 @@ pub struct BootLoader<const PAGE_SIZE: usize> {
108 dfu: Partition, 95 dfu: Partition,
109} 96}
110 97
111impl<const PAGE_SIZE: usize> BootLoader<PAGE_SIZE> { 98impl<const PAGE_SIZE: usize, const WRITE_SIZE: usize, const ERASE_VALUE: u8>
99 BootLoader<PAGE_SIZE, WRITE_SIZE, ERASE_VALUE>
100{
112 pub fn new(active: Partition, dfu: Partition, state: Partition) -> Self { 101 pub fn new(active: Partition, dfu: Partition, state: Partition) -> Self {
113 assert_eq!(active.len() % PAGE_SIZE, 0); 102 assert_eq!(active.len() % PAGE_SIZE, 0);
114 assert_eq!(dfu.len() % PAGE_SIZE, 0); 103 assert_eq!(dfu.len() % PAGE_SIZE, 0);
@@ -352,8 +341,6 @@ impl<const PAGE_SIZE: usize> BootLoader<PAGE_SIZE> {
352 self.copy_page_once_to_active(page * 2 + 1, dfu_page, active_page, p)?; 341 self.copy_page_once_to_active(page * 2 + 1, dfu_page, active_page, p)?;
353 } 342 }
354 343
355 info!("DONE COPYING");
356
357 Ok(()) 344 Ok(())
358 } 345 }
359 346
@@ -379,7 +366,6 @@ impl<const PAGE_SIZE: usize> BootLoader<PAGE_SIZE> {
379 let flash = p.flash(); 366 let flash = p.flash();
380 flash.read(self.state.from as u32, &mut magic)?; 367 flash.read(self.state.from as u32, &mut magic)?;
381 368
382 info!("Read magic: {:x}", magic);
383 if magic == [SWAP_MAGIC; WRITE_SIZE] { 369 if magic == [SWAP_MAGIC; WRITE_SIZE] {
384 Ok(State::Swap) 370 Ok(State::Swap)
385 } else { 371 } else {
@@ -451,13 +437,9 @@ pub struct FirmwareUpdater {
451 dfu: Partition, 437 dfu: Partition,
452} 438}
453 439
454#[cfg(feature = "write-4")] 440// NOTE: Aligned to the largest write size supported by flash
455#[repr(align(4))] 441#[repr(align(32))]
456pub struct Aligned([u8; 4]); 442pub struct Aligned<const N: usize>([u8; N]);
457
458#[cfg(feature = "write-8")]
459#[repr(align(8))]
460pub struct Aligned([u8; 8]);
461 443
462impl Default for FirmwareUpdater { 444impl Default for FirmwareUpdater {
463 fn default() -> Self { 445 fn default() -> Self {
@@ -480,6 +462,9 @@ impl Default for FirmwareUpdater {
480 &__bootloader_state_end as *const u32 as usize, 462 &__bootloader_state_end as *const u32 as usize,
481 ) 463 )
482 }; 464 };
465
466 trace!("DFU: 0x{:x} - 0x{:x}", dfu.from, dfu.to);
467 trace!("STATE: 0x{:x} - 0x{:x}", state.from, state.to);
483 FirmwareUpdater::new(dfu, state) 468 FirmwareUpdater::new(dfu, state)
484 } 469 }
485} 470}
@@ -496,14 +481,20 @@ impl FirmwareUpdater {
496 481
497 /// Instruct bootloader that DFU should commence at next boot. 482 /// Instruct bootloader that DFU should commence at next boot.
498 /// Must be provided with an aligned buffer to use for reading and writing magic; 483 /// Must be provided with an aligned buffer to use for reading and writing magic;
499 pub async fn mark_update<F: AsyncNorFlash>(&mut self, flash: &mut F) -> Result<(), F::Error> { 484 pub async fn mark_update<F: AsyncNorFlash>(&mut self, flash: &mut F) -> Result<(), F::Error>
500 let mut aligned = Aligned([0; WRITE_SIZE]); 485 where
486 [(); F::WRITE_SIZE]:,
487 {
488 let mut aligned = Aligned([0; { F::WRITE_SIZE }]);
501 self.set_magic(&mut aligned.0, SWAP_MAGIC, flash).await 489 self.set_magic(&mut aligned.0, SWAP_MAGIC, flash).await
502 } 490 }
503 491
504 /// Mark firmware boot successfully 492 /// Mark firmware boot successfully
505 pub async fn mark_booted<F: AsyncNorFlash>(&mut self, flash: &mut F) -> Result<(), F::Error> { 493 pub async fn mark_booted<F: AsyncNorFlash>(&mut self, flash: &mut F) -> Result<(), F::Error>
506 let mut aligned = Aligned([0; WRITE_SIZE]); 494 where
495 [(); F::WRITE_SIZE]:,
496 {
497 let mut aligned = Aligned([0; { F::WRITE_SIZE }]);
507 self.set_magic(&mut aligned.0, BOOT_MAGIC, flash).await 498 self.set_magic(&mut aligned.0, BOOT_MAGIC, flash).await
508 } 499 }
509 500
@@ -626,7 +617,7 @@ mod tests {
626 flash.0[0..4].copy_from_slice(&[BOOT_MAGIC; 4]); 617 flash.0[0..4].copy_from_slice(&[BOOT_MAGIC; 4]);
627 let mut flash = SingleFlashProvider::new(&mut flash); 618 let mut flash = SingleFlashProvider::new(&mut flash);
628 619
629 let mut bootloader = BootLoader::<4096>::new(ACTIVE, DFU, STATE); 620 let mut bootloader = BootLoader::<4096, 4, 0xFF>::new(ACTIVE, DFU, STATE);
630 621
631 assert_eq!(State::Boot, bootloader.prepare_boot(&mut flash).unwrap()); 622 assert_eq!(State::Boot, bootloader.prepare_boot(&mut flash).unwrap());
632 } 623 }
@@ -643,7 +634,7 @@ mod tests {
643 flash.0[i] = original[i - ACTIVE.from]; 634 flash.0[i] = original[i - ACTIVE.from];
644 } 635 }
645 636
646 let mut bootloader = BootLoader::<4096>::new(ACTIVE, DFU, STATE); 637 let mut bootloader = BootLoader::<4096, 4, 0xFF>::new(ACTIVE, DFU, STATE);
647 let mut updater = FirmwareUpdater::new(DFU, STATE); 638 let mut updater = FirmwareUpdater::new(DFU, STATE);
648 let mut offset = 0; 639 let mut offset = 0;
649 for chunk in update.chunks(4096) { 640 for chunk in update.chunks(4096) {
diff --git a/embassy-boot/nrf/Cargo.toml b/embassy-boot/nrf/Cargo.toml
index 78157d246..97207ac29 100644
--- a/embassy-boot/nrf/Cargo.toml
+++ b/embassy-boot/nrf/Cargo.toml
@@ -13,7 +13,7 @@ defmt-rtt = { version = "0.3", optional = true }
13 13
14embassy = { path = "../../embassy", default-features = false } 14embassy = { path = "../../embassy", default-features = false }
15embassy-nrf = { path = "../../embassy-nrf", default-features = false, features = ["nightly"] } 15embassy-nrf = { path = "../../embassy-nrf", default-features = false, features = ["nightly"] }
16embassy-boot = { path = "../boot", default-features = false, features = ["write-4"] } 16embassy-boot = { path = "../boot", default-features = false }
17cortex-m = { version = "0.7" } 17cortex-m = { version = "0.7" }
18cortex-m-rt = { version = "0.7" } 18cortex-m-rt = { version = "0.7" }
19embedded-storage = "0.3.0" 19embedded-storage = "0.3.0"
diff --git a/embassy-boot/nrf/src/lib.rs b/embassy-boot/nrf/src/lib.rs
index 500cae500..c12899d77 100644
--- a/embassy-boot/nrf/src/lib.rs
+++ b/embassy-boot/nrf/src/lib.rs
@@ -13,7 +13,7 @@ use embassy_nrf::{
13use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash}; 13use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash};
14 14
15pub struct BootLoader { 15pub struct BootLoader {
16 boot: embassy_boot::BootLoader<PAGE_SIZE>, 16 boot: embassy_boot::BootLoader<PAGE_SIZE, 4, 0xFF>,
17} 17}
18 18
19impl BootLoader { 19impl BootLoader {
diff --git a/embassy-boot/nrf/src/main.rs b/embassy-boot/nrf/src/main.rs
index 63de7c869..0ccd3774d 100644
--- a/embassy-boot/nrf/src/main.rs
+++ b/embassy-boot/nrf/src/main.rs
@@ -46,8 +46,5 @@ unsafe fn DefaultHandler(_: i16) -> ! {
46 46
47#[panic_handler] 47#[panic_handler]
48fn panic(_info: &core::panic::PanicInfo) -> ! { 48fn panic(_info: &core::panic::PanicInfo) -> ! {
49 unsafe { 49 cortex_m::asm::udf();
50 cortex_m::asm::udf();
51 core::hint::unreachable_unchecked();
52 }
53} 50}
diff --git a/embassy-boot/stm32/Cargo.toml b/embassy-boot/stm32/Cargo.toml
index 76bc480bf..a706e4c06 100644
--- a/embassy-boot/stm32/Cargo.toml
+++ b/embassy-boot/stm32/Cargo.toml
@@ -27,10 +27,6 @@ defmt = [
27 "embassy-stm32/defmt", 27 "embassy-stm32/defmt",
28] 28]
29debug = ["defmt-rtt"] 29debug = ["defmt-rtt"]
30flash-2k = ["embassy-boot/write-8"]
31flash-128 = ["embassy-boot/write-4"]
32flash-256 = ["embassy-boot/write-4"]
33invert-erase = ["embassy-boot/invert-erase"]
34thumbv6 = [] 30thumbv6 = []
35 31
36[profile.dev] 32[profile.dev]
diff --git a/embassy-boot/stm32/memory.x b/embassy-boot/stm32/memory.x
index c5356ed37..110c23259 100644
--- a/embassy-boot/stm32/memory.x
+++ b/embassy-boot/stm32/memory.x
@@ -8,11 +8,11 @@ MEMORY
8 RAM (rwx) : ORIGIN = 0x20000008, LENGTH = 16K 8 RAM (rwx) : ORIGIN = 0x20000008, LENGTH = 16K
9} 9}
10 10
11__bootloader_state_start = ORIGIN(BOOTLOADER_STATE); 11__bootloader_state_start = ORIGIN(BOOTLOADER_STATE) - ORIGIN(FLASH);
12__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE); 12__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE) - ORIGIN(FLASH);
13 13
14__bootloader_active_start = ORIGIN(ACTIVE); 14__bootloader_active_start = ORIGIN(ACTIVE) - ORIGIN(FLASH);
15__bootloader_active_end = ORIGIN(ACTIVE) + LENGTH(ACTIVE); 15__bootloader_active_end = ORIGIN(ACTIVE) + LENGTH(ACTIVE) - ORIGIN(FLASH);
16 16
17__bootloader_dfu_start = ORIGIN(DFU); 17__bootloader_dfu_start = ORIGIN(DFU) - ORIGIN(FLASH);
18__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU); 18__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU) - ORIGIN(FLASH);
diff --git a/embassy-boot/stm32/src/lib.rs b/embassy-boot/stm32/src/lib.rs
index d1754a310..68220780c 100644
--- a/embassy-boot/stm32/src/lib.rs
+++ b/embassy-boot/stm32/src/lib.rs
@@ -5,12 +5,13 @@
5mod fmt; 5mod fmt;
6 6
7pub use embassy_boot::{FirmwareUpdater, FlashProvider, Partition, SingleFlashProvider, State}; 7pub use embassy_boot::{FirmwareUpdater, FlashProvider, Partition, SingleFlashProvider, State};
8use embassy_stm32::flash::{ERASE_SIZE, ERASE_VALUE, WRITE_SIZE};
8 9
9pub struct BootLoader<const PAGE_SIZE: usize> { 10pub struct BootLoader {
10 boot: embassy_boot::BootLoader<PAGE_SIZE>, 11 boot: embassy_boot::BootLoader<ERASE_SIZE, WRITE_SIZE, ERASE_VALUE>,
11} 12}
12 13
13impl<const PAGE_SIZE: usize> BootLoader<PAGE_SIZE> { 14impl BootLoader {
14 /// Create a new bootloader instance using parameters from linker script 15 /// Create a new bootloader instance using parameters from linker script
15 pub fn default() -> Self { 16 pub fn default() -> Self {
16 extern "C" { 17 extern "C" {
@@ -65,6 +66,7 @@ impl<const PAGE_SIZE: usize> BootLoader<PAGE_SIZE> {
65 66
66 pub unsafe fn load(&mut self, start: usize) -> ! { 67 pub unsafe fn load(&mut self, start: usize) -> ! {
67 trace!("Loading app at 0x{:x}", start); 68 trace!("Loading app at 0x{:x}", start);
69 #[allow(unused_mut)]
68 let mut p = cortex_m::Peripherals::steal(); 70 let mut p = cortex_m::Peripherals::steal();
69 #[cfg(not(feature = "thumbv6"))] 71 #[cfg(not(feature = "thumbv6"))]
70 p.SCB.invalidate_icache(); 72 p.SCB.invalidate_icache();
diff --git a/embassy-boot/stm32/src/main.rs b/embassy-boot/stm32/src/main.rs
index 6fe0fb66d..563bc55d3 100644
--- a/embassy-boot/stm32/src/main.rs
+++ b/embassy-boot/stm32/src/main.rs
@@ -9,9 +9,6 @@ use defmt_rtt as _;
9use embassy_boot_stm32::*; 9use embassy_boot_stm32::*;
10use embassy_stm32::flash::Flash; 10use embassy_stm32::flash::Flash;
11 11
12#[cfg(not(any(feature = "flash-2k", feature = "flash-256", feature = "flash-128")))]
13compile_error!("No flash size specified. Must specify exactly one of the following features: flash-2k, flash-256, flash-128");
14
15#[entry] 12#[entry]
16fn main() -> ! { 13fn main() -> ! {
17 let p = embassy_stm32::init(Default::default()); 14 let p = embassy_stm32::init(Default::default());
@@ -24,15 +21,7 @@ fn main() -> ! {
24 } 21 }
25 */ 22 */
26 23
27 #[cfg(feature = "flash-2k")] 24 let mut bl = BootLoader::default();
28 let mut bl: BootLoader<2048> = BootLoader::default();
29
30 #[cfg(feature = "flash-256")]
31 let mut bl: BootLoader<256> = BootLoader::default();
32
33 #[cfg(feature = "flash-128")]
34 let mut bl: BootLoader<128> = BootLoader::default();
35
36 let mut flash = Flash::unlock(p.FLASH); 25 let mut flash = Flash::unlock(p.FLASH);
37 let start = bl.prepare(&mut SingleFlashProvider::new(&mut flash)); 26 let start = bl.prepare(&mut SingleFlashProvider::new(&mut flash));
38 core::mem::drop(flash); 27 core::mem::drop(flash);
@@ -55,8 +44,5 @@ unsafe fn DefaultHandler(_: i16) -> ! {
55 44
56#[panic_handler] 45#[panic_handler]
57fn panic(_info: &core::panic::PanicInfo) -> ! { 46fn panic(_info: &core::panic::PanicInfo) -> ! {
58 unsafe { 47 cortex_m::asm::udf();
59 cortex_m::asm::udf();
60 core::hint::unreachable_unchecked();
61 }
62} 48}
diff --git a/embassy-stm32/src/flash/mod.rs b/embassy-stm32/src/flash/mod.rs
index 7a282497f..cff3119fd 100644
--- a/embassy-stm32/src/flash/mod.rs
+++ b/embassy-stm32/src/flash/mod.rs
@@ -10,59 +10,12 @@ use embedded_storage::nor_flash::{
10 ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash, 10 ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash,
11}; 11};
12 12
13const FLASH_BASE: usize = 0x8000000; 13pub use crate::pac::ERASE_SIZE;
14 14pub use crate::pac::ERASE_VALUE;
15#[cfg(flash_l4)] 15pub use crate::pac::FLASH_BASE;
16mod config { 16pub use crate::pac::FLASH_SIZE;
17 use super::*; 17pub use crate::pac::WRITE_SIZE;
18 pub(crate) const FLASH_SIZE: usize = 0x100000; 18const FLASH_END: usize = FLASH_BASE + FLASH_SIZE;
19 pub(crate) const FLASH_START: usize = FLASH_BASE;
20 pub(crate) const FLASH_END: usize = FLASH_START + FLASH_SIZE;
21 pub(crate) const PAGE_SIZE: usize = 2048;
22 pub(crate) const WORD_SIZE: usize = 8;
23}
24
25#[cfg(flash_wb)]
26mod config {
27 use super::*;
28 pub(crate) const FLASH_SIZE: usize = 0x100000;
29 pub(crate) const FLASH_START: usize = FLASH_BASE;
30 pub(crate) const FLASH_END: usize = FLASH_START + FLASH_SIZE;
31 pub(crate) const PAGE_SIZE: usize = 4096;
32 pub(crate) const WORD_SIZE: usize = 8;
33}
34
35#[cfg(flash_wl)]
36mod config {
37 use super::*;
38 pub(crate) const FLASH_SIZE: usize = 0x40000;
39 pub(crate) const FLASH_START: usize = FLASH_BASE;
40 pub(crate) const FLASH_END: usize = FLASH_START + FLASH_SIZE;
41 pub(crate) const PAGE_SIZE: usize = 2048;
42 pub(crate) const WORD_SIZE: usize = 8;
43}
44
45#[cfg(flash_l0)]
46mod config {
47 use super::*;
48 pub(crate) const FLASH_SIZE: usize = 0x30000;
49 pub(crate) const FLASH_START: usize = FLASH_BASE;
50 pub(crate) const FLASH_END: usize = FLASH_START + FLASH_SIZE;
51 pub(crate) const PAGE_SIZE: usize = 128;
52 pub(crate) const WORD_SIZE: usize = 4;
53}
54
55#[cfg(flash_l1)]
56mod config {
57 use super::*;
58 pub(crate) const FLASH_SIZE: usize = 0x80000;
59 pub(crate) const FLASH_START: usize = FLASH_BASE;
60 pub(crate) const FLASH_END: usize = FLASH_START + FLASH_SIZE;
61 pub(crate) const PAGE_SIZE: usize = 256;
62 pub(crate) const WORD_SIZE: usize = 4;
63}
64
65use config::*;
66 19
67pub struct Flash<'d> { 20pub struct Flash<'d> {
68 _inner: FLASH, 21 _inner: FLASH,
@@ -114,6 +67,7 @@ impl<'d> Flash<'d> {
114 } 67 }
115 68
116 pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { 69 pub fn blocking_read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> {
70 let offset = FLASH_BASE as u32 + offset;
117 if offset as usize >= FLASH_END || offset as usize + bytes.len() > FLASH_END { 71 if offset as usize >= FLASH_END || offset as usize + bytes.len() > FLASH_END {
118 return Err(Error::Size); 72 return Err(Error::Size);
119 } 73 }
@@ -124,23 +78,25 @@ impl<'d> Flash<'d> {
124 } 78 }
125 79
126 pub fn blocking_write(&mut self, offset: u32, buf: &[u8]) -> Result<(), Error> { 80 pub fn blocking_write(&mut self, offset: u32, buf: &[u8]) -> Result<(), Error> {
81 let offset = FLASH_BASE as u32 + offset;
127 if offset as usize + buf.len() > FLASH_END { 82 if offset as usize + buf.len() > FLASH_END {
128 return Err(Error::Size); 83 return Err(Error::Size);
129 } 84 }
130 if offset as usize % WORD_SIZE != 0 || buf.len() as usize % WORD_SIZE != 0 { 85 if offset as usize % WRITE_SIZE != 0 || buf.len() as usize % WRITE_SIZE != 0 {
131 return Err(Error::Unaligned); 86 return Err(Error::Unaligned);
132 } 87 }
88 trace!("Writing {} bytes at 0x{:x}", buf.len(), offset);
133 89
134 self.clear_all_err(); 90 self.clear_all_err();
135 91
136 #[cfg(any(flash_wl, flash_wb, flash_l4))] 92 #[cfg(any(flash_wl, flash_wb, flash_l4))]
137 unsafe { 93 unsafe {
138 pac::FLASH.cr().write(|w| w.set_pg(true)); 94 pac::FLASH.cr().write(|w| w.set_pg(true))
139 } 95 }
140 96
141 let mut ret: Result<(), Error> = Ok(()); 97 let mut ret: Result<(), Error> = Ok(());
142 let mut offset = offset; 98 let mut offset = offset;
143 for chunk in buf.chunks(WORD_SIZE) { 99 for chunk in buf.chunks(WRITE_SIZE) {
144 for val in chunk.chunks(4) { 100 for val in chunk.chunks(4) {
145 unsafe { 101 unsafe {
146 write_volatile( 102 write_volatile(
@@ -159,23 +115,25 @@ impl<'d> Flash<'d> {
159 115
160 #[cfg(any(flash_wl, flash_wb, flash_l4))] 116 #[cfg(any(flash_wl, flash_wb, flash_l4))]
161 unsafe { 117 unsafe {
162 pac::FLASH.cr().write(|w| w.set_pg(false)); 118 pac::FLASH.cr().write(|w| w.set_pg(false))
163 } 119 }
164 120
165 ret 121 ret
166 } 122 }
167 123
168 pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> { 124 pub fn blocking_erase(&mut self, from: u32, to: u32) -> Result<(), Error> {
125 let from = FLASH_BASE as u32 + from;
126 let to = FLASH_BASE as u32 + to;
169 if to < from || to as usize > FLASH_END { 127 if to < from || to as usize > FLASH_END {
170 return Err(Error::Size); 128 return Err(Error::Size);
171 } 129 }
172 if from as usize % PAGE_SIZE != 0 || to as usize % PAGE_SIZE != 0 { 130 if from as usize % ERASE_SIZE != 0 || to as usize % ERASE_SIZE != 0 {
173 return Err(Error::Unaligned); 131 return Err(Error::Unaligned);
174 } 132 }
175 133
176 self.clear_all_err(); 134 self.clear_all_err();
177 135
178 for page in (from..to).step_by(PAGE_SIZE) { 136 for page in (from..to).step_by(ERASE_SIZE) {
179 #[cfg(any(flash_l0, flash_l1))] 137 #[cfg(any(flash_l0, flash_l1))]
180 unsafe { 138 unsafe {
181 pac::FLASH.pecr().modify(|w| { 139 pac::FLASH.pecr().modify(|w| {
@@ -188,7 +146,7 @@ impl<'d> Flash<'d> {
188 146
189 #[cfg(any(flash_wl, flash_wb, flash_l4))] 147 #[cfg(any(flash_wl, flash_wb, flash_l4))]
190 unsafe { 148 unsafe {
191 let idx = page / PAGE_SIZE as u32; 149 let idx = page / ERASE_SIZE as u32;
192 150
193 pac::FLASH.cr().modify(|w| { 151 pac::FLASH.cr().modify(|w| {
194 w.set_per(true); 152 w.set_per(true);
@@ -333,7 +291,7 @@ impl NorFlashError for Error {
333} 291}
334 292
335impl<'d> ReadNorFlash for Flash<'d> { 293impl<'d> ReadNorFlash for Flash<'d> {
336 const READ_SIZE: usize = WORD_SIZE; 294 const READ_SIZE: usize = WRITE_SIZE;
337 295
338 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { 296 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
339 self.blocking_read(offset, bytes) 297 self.blocking_read(offset, bytes)
@@ -345,8 +303,8 @@ impl<'d> ReadNorFlash for Flash<'d> {
345} 303}
346 304
347impl<'d> NorFlash for Flash<'d> { 305impl<'d> NorFlash for Flash<'d> {
348 const WRITE_SIZE: usize = WORD_SIZE; 306 const WRITE_SIZE: usize = WRITE_SIZE;
349 const ERASE_SIZE: usize = PAGE_SIZE; 307 const ERASE_SIZE: usize = ERASE_SIZE;
350 308
351 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { 309 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
352 self.blocking_erase(from, to) 310 self.blocking_erase(from, to)
diff --git a/examples/boot/nrf/.cargo/config.toml b/examples/boot/nrf/.cargo/config.toml
new file mode 100644
index 000000000..c75b5c539
--- /dev/null
+++ b/examples/boot/nrf/.cargo/config.toml
@@ -0,0 +1,6 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace nRF82840_xxAA with your chip as listed in `probe-run --list-chips`
3runner = "probe-run --chip nRF52840_xxAA"
4
5[build]
6target = "thumbv7em-none-eabi"
diff --git a/examples/boot/nrf/Cargo.toml b/examples/boot/nrf/Cargo.toml
index 0a5bb8f9d..da8333b7c 100644
--- a/examples/boot/nrf/Cargo.toml
+++ b/examples/boot/nrf/Cargo.toml
@@ -6,7 +6,7 @@ version = "0.1.0"
6 6
7[dependencies] 7[dependencies]
8embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] } 8embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] }
9embassy-nrf = { version = "0.1.0", path = "../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", "nightly"] } 9embassy-nrf = { version = "0.1.0", path = "../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", "nightly", "nrf52840"] }
10embassy-boot-nrf = { version = "0.1.0", path = "../../../embassy-boot/nrf" } 10embassy-boot-nrf = { version = "0.1.0", path = "../../../embassy-boot/nrf" }
11embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" } 11embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" }
12 12
diff --git a/examples/boot/nrf/README.md b/examples/boot/nrf/README.md
index b97513a9d..453df7f31 100644
--- a/examples/boot/nrf/README.md
+++ b/examples/boot/nrf/README.md
@@ -17,15 +17,15 @@ application.
17 17
18``` 18```
19# Flash bootloader 19# Flash bootloader
20cargo flash --manifest-path ../../embassy-boot/nrf/Cargo.toml --release --features embassy-nrf/nrf52840 --chip nRF52840_xxAA 20cargo flash --manifest-path ../../../embassy-boot/nrf/Cargo.toml --features embassy-nrf/nrf52840 --release --chip nRF52840_xxAA
21# Build 'b' 21# Build 'b'
22cargo build --release --features embassy-nrf/nrf52840 --bin b 22cargo build --release --bin b
23# Generate binary for 'b' 23# Generate binary for 'b'
24cargo objcopy --release --features embassy-nrf/nrf52840 --bin b -- -O binary b.bin 24cargo objcopy --release --bin b -- -O binary b.bin
25``` 25```
26 26
27# Flash `a` (which includes b.bin) 27# Flash `a` (which includes b.bin)
28 28
29``` 29```
30cargo flash --release --features embassy-nrf/nrf52840 --bin a --chip nRF52840_xxAA 30cargo flash --release --bin a --chip nRF52840_xxAA
31``` 31```
diff --git a/examples/boot/stm32l0/Cargo.toml b/examples/boot/stm32l0/Cargo.toml
index 2e093d771..5cb1add5b 100644
--- a/examples/boot/stm32l0/Cargo.toml
+++ b/examples/boot/stm32l0/Cargo.toml
@@ -7,7 +7,7 @@ version = "0.1.0"
7[dependencies] 7[dependencies]
8embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] } 8embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] }
9embassy-stm32 = { version = "0.1.0", path = "../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l072cz", "time-driver-any", "exti", "memory-x"] } 9embassy-stm32 = { version = "0.1.0", path = "../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l072cz", "time-driver-any", "exti", "memory-x"] }
10embassy-boot-stm32 = { version = "0.1.0", path = "../../../embassy-boot/stm32", features = ["flash-128", "invert-erase", "thumbv6"] } 10embassy-boot-stm32 = { version = "0.1.0", path = "../../../embassy-boot/stm32", features = ["thumbv6"] }
11embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" } 11embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" }
12 12
13defmt = { version = "0.3", optional = true } 13defmt = { version = "0.3", optional = true }
diff --git a/examples/boot/stm32l0/README.md b/examples/boot/stm32l0/README.md
index 9c8660821..b498fdc2d 100644
--- a/examples/boot/stm32l0/README.md
+++ b/examples/boot/stm32l0/README.md
@@ -15,7 +15,7 @@ application.
15 15
16``` 16```
17# Flash bootloader 17# Flash bootloader
18cargo flash --manifest-path ../../../embassy-boot/stm32/Cargo.toml --release --features embassy-stm32/stm32l072cz,flash-128,invert-erase,thumbv6 --chip STM32L072CZTx 18cargo flash --manifest-path ../../../embassy-boot/stm32/Cargo.toml --release --features embassy-stm32/stm32l072cz,thumbv6 --chip STM32L072CZTx
19# Build 'b' 19# Build 'b'
20cargo build --release --bin b 20cargo build --release --bin b
21# Generate binary for 'b' 21# Generate binary for 'b'
diff --git a/examples/boot/stm32l0/memory.x b/examples/boot/stm32l0/memory.x
index fd5bf1a5d..d0d2bd7bb 100644
--- a/examples/boot/stm32l0/memory.x
+++ b/examples/boot/stm32l0/memory.x
@@ -8,8 +8,8 @@ MEMORY
8 RAM (rwx) : ORIGIN = 0x20000008, LENGTH = 16K 8 RAM (rwx) : ORIGIN = 0x20000008, LENGTH = 16K
9} 9}
10 10
11__bootloader_state_start = ORIGIN(BOOTLOADER_STATE); 11__bootloader_state_start = ORIGIN(BOOTLOADER_STATE) - ORIGIN(BOOTLOADER);
12__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE); 12__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE) - ORIGIN(BOOTLOADER);
13 13
14__bootloader_dfu_start = ORIGIN(DFU); 14__bootloader_dfu_start = ORIGIN(DFU) - ORIGIN(BOOTLOADER);
15__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU); 15__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU) - ORIGIN(BOOTLOADER);
diff --git a/examples/boot/stm32l1/Cargo.toml b/examples/boot/stm32l1/Cargo.toml
index ec396bef2..9f97462f6 100644
--- a/examples/boot/stm32l1/Cargo.toml
+++ b/examples/boot/stm32l1/Cargo.toml
@@ -7,7 +7,7 @@ version = "0.1.0"
7[dependencies] 7[dependencies]
8embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] } 8embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] }
9embassy-stm32 = { version = "0.1.0", path = "../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l151cb-a", "time-driver-any", "exti"] } 9embassy-stm32 = { version = "0.1.0", path = "../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l151cb-a", "time-driver-any", "exti"] }
10embassy-boot-stm32 = { version = "0.1.0", path = "../../../embassy-boot/stm32", features = ["flash-256", "invert-erase"] } 10embassy-boot-stm32 = { version = "0.1.0", path = "../../../embassy-boot/stm32" }
11embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" } 11embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" }
12 12
13defmt = { version = "0.3", optional = true } 13defmt = { version = "0.3", optional = true }
diff --git a/examples/boot/stm32l1/README.md b/examples/boot/stm32l1/README.md
index 1a9e85a75..0d4accbff 100644
--- a/examples/boot/stm32l1/README.md
+++ b/examples/boot/stm32l1/README.md
@@ -15,7 +15,7 @@ application.
15 15
16``` 16```
17# Flash bootloader 17# Flash bootloader
18cargo flash --manifest-path ../../../embassy-boot/stm32/Cargo.toml --release --features embassy-stm32/stm32l151cb-a,flash-256,invert-erase --chip STM32L151CBxxA 18cargo flash --manifest-path ../../../embassy-boot/stm32/Cargo.toml --release --features embassy-stm32/stm32l151cb-a --chip STM32L151CBxxA
19# Build 'b' 19# Build 'b'
20cargo build --release --bin b 20cargo build --release --bin b
21# Generate binary for 'b' 21# Generate binary for 'b'
diff --git a/examples/boot/stm32l1/memory.x b/examples/boot/stm32l1/memory.x
index fd5bf1a5d..d0d2bd7bb 100644
--- a/examples/boot/stm32l1/memory.x
+++ b/examples/boot/stm32l1/memory.x
@@ -8,8 +8,8 @@ MEMORY
8 RAM (rwx) : ORIGIN = 0x20000008, LENGTH = 16K 8 RAM (rwx) : ORIGIN = 0x20000008, LENGTH = 16K
9} 9}
10 10
11__bootloader_state_start = ORIGIN(BOOTLOADER_STATE); 11__bootloader_state_start = ORIGIN(BOOTLOADER_STATE) - ORIGIN(BOOTLOADER);
12__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE); 12__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE) - ORIGIN(BOOTLOADER);
13 13
14__bootloader_dfu_start = ORIGIN(DFU); 14__bootloader_dfu_start = ORIGIN(DFU) - ORIGIN(BOOTLOADER);
15__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU); 15__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU) - ORIGIN(BOOTLOADER);
diff --git a/examples/boot/stm32l4/Cargo.toml b/examples/boot/stm32l4/Cargo.toml
index 394f26a12..53424a666 100644
--- a/examples/boot/stm32l4/Cargo.toml
+++ b/examples/boot/stm32l4/Cargo.toml
@@ -7,7 +7,7 @@ version = "0.1.0"
7[dependencies] 7[dependencies]
8embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] } 8embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] }
9embassy-stm32 = { version = "0.1.0", path = "../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l475vg", "time-driver-any", "exti"] } 9embassy-stm32 = { version = "0.1.0", path = "../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l475vg", "time-driver-any", "exti"] }
10embassy-boot-stm32 = { version = "0.1.0", path = "../../../embassy-boot/stm32", features = ["flash-2k"] } 10embassy-boot-stm32 = { version = "0.1.0", path = "../../../embassy-boot/stm32" }
11embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" } 11embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" }
12 12
13defmt = { version = "0.3", optional = true } 13defmt = { version = "0.3", optional = true }
diff --git a/examples/boot/stm32l4/README.md b/examples/boot/stm32l4/README.md
index 09e09d6ef..8966c2fb5 100644
--- a/examples/boot/stm32l4/README.md
+++ b/examples/boot/stm32l4/README.md
@@ -15,7 +15,7 @@ application.
15 15
16``` 16```
17# Flash bootloader 17# Flash bootloader
18cargo flash --manifest-path ../../../embassy-boot/stm32/Cargo.toml --release --features embassy-stm32/stm32l475vg,flash-2k --chip STM32L475VG 18cargo flash --manifest-path ../../../embassy-boot/stm32/Cargo.toml --release --features embassy-stm32/stm32l475vg --chip STM32L475VG
19# Build 'b' 19# Build 'b'
20cargo build --release --bin b 20cargo build --release --bin b
21# Generate binary for 'b' 21# Generate binary for 'b'
diff --git a/examples/boot/stm32l4/memory.x b/examples/boot/stm32l4/memory.x
index fd5bf1a5d..14b2a2c9f 100644
--- a/examples/boot/stm32l4/memory.x
+++ b/examples/boot/stm32l4/memory.x
@@ -5,11 +5,11 @@ MEMORY
5 BOOTLOADER_STATE : ORIGIN = 0x08006000, LENGTH = 4K 5 BOOTLOADER_STATE : ORIGIN = 0x08006000, LENGTH = 4K
6 FLASH : ORIGIN = 0x08008000, LENGTH = 32K 6 FLASH : ORIGIN = 0x08008000, LENGTH = 32K
7 DFU : ORIGIN = 0x08010000, LENGTH = 36K 7 DFU : ORIGIN = 0x08010000, LENGTH = 36K
8 RAM (rwx) : ORIGIN = 0x20000008, LENGTH = 16K 8 RAM (rwx) : ORIGIN = 0x20000008, LENGTH = 32K
9} 9}
10 10
11__bootloader_state_start = ORIGIN(BOOTLOADER_STATE); 11__bootloader_state_start = ORIGIN(BOOTLOADER_STATE) - ORIGIN(BOOTLOADER);
12__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE); 12__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE) - ORIGIN(BOOTLOADER);
13 13
14__bootloader_dfu_start = ORIGIN(DFU); 14__bootloader_dfu_start = ORIGIN(DFU) - ORIGIN(BOOTLOADER);
15__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU); 15__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU) - ORIGIN(BOOTLOADER);
diff --git a/examples/boot/stm32wl/Cargo.toml b/examples/boot/stm32wl/Cargo.toml
index 9c69f4a65..fb64886e6 100644
--- a/examples/boot/stm32wl/Cargo.toml
+++ b/examples/boot/stm32wl/Cargo.toml
@@ -7,7 +7,7 @@ version = "0.1.0"
7[dependencies] 7[dependencies]
8embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] } 8embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] }
9embassy-stm32 = { version = "0.1.0", path = "../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32wl55jc-cm4", "time-driver-any", "exti"] } 9embassy-stm32 = { version = "0.1.0", path = "../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32wl55jc-cm4", "time-driver-any", "exti"] }
10embassy-boot-stm32 = { version = "0.1.0", path = "../../../embassy-boot/stm32", features = ["flash-2k"] } 10embassy-boot-stm32 = { version = "0.1.0", path = "../../../embassy-boot/stm32" }
11embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" } 11embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" }
12 12
13defmt = { version = "0.3", optional = true } 13defmt = { version = "0.3", optional = true }
diff --git a/examples/boot/stm32wl/README.md b/examples/boot/stm32wl/README.md
index a26a23852..edcdacf91 100644
--- a/examples/boot/stm32wl/README.md
+++ b/examples/boot/stm32wl/README.md
@@ -15,7 +15,7 @@ application.
15 15
16``` 16```
17# Flash bootloader 17# Flash bootloader
18cargo flash --manifest-path ../../../embassy-boot/stm32/Cargo.toml --release --features embassy-stm32/stm32wl55jc-cm4,flash-2k --chip STM32WLE5JCIx 18cargo flash --manifest-path ../../../embassy-boot/stm32/Cargo.toml --release --features embassy-stm32/stm32wl55jc-cm4 --chip STM32WLE5JCIx
19# Build 'b' 19# Build 'b'
20cargo build --release --bin b 20cargo build --release --bin b
21# Generate binary for 'b' 21# Generate binary for 'b'
diff --git a/examples/boot/stm32wl/memory.x b/examples/boot/stm32wl/memory.x
index 78dd69c35..14b2a2c9f 100644
--- a/examples/boot/stm32wl/memory.x
+++ b/examples/boot/stm32wl/memory.x
@@ -8,8 +8,8 @@ MEMORY
8 RAM (rwx) : ORIGIN = 0x20000008, LENGTH = 32K 8 RAM (rwx) : ORIGIN = 0x20000008, LENGTH = 32K
9} 9}
10 10
11__bootloader_state_start = ORIGIN(BOOTLOADER_STATE); 11__bootloader_state_start = ORIGIN(BOOTLOADER_STATE) - ORIGIN(BOOTLOADER);
12__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE); 12__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE) - ORIGIN(BOOTLOADER);
13 13
14__bootloader_dfu_start = ORIGIN(DFU); 14__bootloader_dfu_start = ORIGIN(DFU) - ORIGIN(BOOTLOADER);
15__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU); 15__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU) - ORIGIN(BOOTLOADER);
diff --git a/examples/boot/stm32wl/src/bin/a.rs b/examples/boot/stm32wl/src/bin/a.rs
index b1f4a4a03..d01a72f2d 100644
--- a/examples/boot/stm32wl/src/bin/a.rs
+++ b/examples/boot/stm32wl/src/bin/a.rs
@@ -17,16 +17,18 @@ static APP_B: &[u8] = include_bytes!("../../b.bin");
17 17
18#[embassy::main] 18#[embassy::main]
19async fn main(_s: embassy::executor::Spawner, p: Peripherals) { 19async fn main(_s: embassy::executor::Spawner, p: Peripherals) {
20 let flash = Flash::new(p.FLASH); 20 let flash = Flash::unlock(p.FLASH);
21 let mut flash = BlockingAsync::new(flash); 21 let mut flash = BlockingAsync::new(flash);
22 22
23 let button = Input::new(p.PA0, Pull::Up); 23 let button = Input::new(p.PA0, Pull::Up);
24 let mut button = ExtiInput::new(button, p.EXTI0); 24 let mut button = ExtiInput::new(button, p.EXTI0);
25 25
26 let mut led = Output::new(p.PB9, Level::Low, Speed::Low); 26 let mut led = Output::new(p.PB9, Level::Low, Speed::Low);
27 led.set_high();
27 28
28 let mut updater = FirmwareUpdater::default(); 29 let mut updater = FirmwareUpdater::default();
29 button.wait_for_falling_edge().await; 30 button.wait_for_falling_edge().await;
31 //defmt::info!("Starting update");
30 let mut offset = 0; 32 let mut offset = 0;
31 for chunk in APP_B.chunks(2048) { 33 for chunk in APP_B.chunks(2048) {
32 let mut buf: [u8; 2048] = [0; 2048]; 34 let mut buf: [u8; 2048] = [0; 2048];
@@ -39,7 +41,7 @@ async fn main(_s: embassy::executor::Spawner, p: Peripherals) {
39 offset += chunk.len(); 41 offset += chunk.len();
40 } 42 }
41 updater.mark_update(&mut flash).await.unwrap(); 43 updater.mark_update(&mut flash).await.unwrap();
42 // defmt::info!("Marked as updated"); 44 //defmt::info!("Marked as updated");
43 led.set_high(); 45 led.set_low();
44 cortex_m::peripheral::SCB::sys_reset(); 46 cortex_m::peripheral::SCB::sys_reset();
45} 47}
diff --git a/examples/stm32l0/src/bin/flash.rs b/examples/stm32l0/src/bin/flash.rs
index 0ab7b133b..c2ccb5b69 100644
--- a/examples/stm32l0/src/bin/flash.rs
+++ b/examples/stm32l0/src/bin/flash.rs
@@ -15,7 +15,7 @@ use panic_probe as _;
15async fn main(_spawner: Spawner, p: Peripherals) { 15async fn main(_spawner: Spawner, p: Peripherals) {
16 info!("Hello Flash!"); 16 info!("Hello Flash!");
17 17
18 const ADDR: u32 = 0x8026000; 18 const ADDR: u32 = 0x26000;
19 19
20 let mut f = Flash::unlock(p.FLASH); 20 let mut f = Flash::unlock(p.FLASH);
21 21
diff --git a/examples/stm32l1/src/bin/flash.rs b/examples/stm32l1/src/bin/flash.rs
index b234289af..eea838cba 100644
--- a/examples/stm32l1/src/bin/flash.rs
+++ b/examples/stm32l1/src/bin/flash.rs
@@ -15,7 +15,7 @@ use panic_probe as _;
15async fn main(_spawner: Spawner, p: Peripherals) { 15async fn main(_spawner: Spawner, p: Peripherals) {
16 info!("Hello Flash!"); 16 info!("Hello Flash!");
17 17
18 const ADDR: u32 = 0x8026000; 18 const ADDR: u32 = 0x26000;
19 19
20 let mut f = Flash::unlock(p.FLASH); 20 let mut f = Flash::unlock(p.FLASH);
21 21
diff --git a/examples/stm32wl/src/bin/flash.rs b/examples/stm32wl/src/bin/flash.rs
index 9e13c702a..f84818224 100644
--- a/examples/stm32wl/src/bin/flash.rs
+++ b/examples/stm32wl/src/bin/flash.rs
@@ -15,7 +15,7 @@ use panic_probe as _;
15async fn main(_spawner: Spawner, p: Peripherals) { 15async fn main(_spawner: Spawner, p: Peripherals) {
16 info!("Hello Flash!"); 16 info!("Hello Flash!");
17 17
18 const ADDR: u32 = 0x8036000; 18 const ADDR: u32 = 0x36000;
19 19
20 let mut f = Flash::unlock(p.FLASH); 20 let mut f = Flash::unlock(p.FLASH);
21 21
diff --git a/stm32-data b/stm32-data
Subproject 419701c835dd0da3c37d8de02c95115f500dfa6 Subproject 5d25777521bfdb493674d43944b6df191606ef0
diff --git a/stm32-metapac-gen/src/data.rs b/stm32-metapac-gen/src/data.rs
index a74c60ac0..17eccfe9a 100644
--- a/stm32-metapac-gen/src/data.rs
+++ b/stm32-metapac-gen/src/data.rs
@@ -16,6 +16,14 @@ pub struct MemoryRegion {
16 pub kind: MemoryRegionKind, 16 pub kind: MemoryRegionKind,
17 pub address: u32, 17 pub address: u32,
18 pub size: u32, 18 pub size: u32,
19 pub settings: Option<FlashSettings>,
20}
21
22#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
23pub struct FlashSettings {
24 pub erase_size: u32,
25 pub write_size: u32,
26 pub erase_value: u8,
19} 27}
20 28
21#[derive(Debug, Eq, PartialEq, Clone, Deserialize)] 29#[derive(Debug, Eq, PartialEq, Clone, Deserialize)]
diff --git a/stm32-metapac-gen/src/lib.rs b/stm32-metapac-gen/src/lib.rs
index c959e1a61..f5d61ca31 100644
--- a/stm32-metapac-gen/src/lib.rs
+++ b/stm32-metapac-gen/src/lib.rs
@@ -129,6 +129,40 @@ impl Gen {
129 ) 129 )
130 .unwrap(); 130 .unwrap();
131 131
132 let flash = chip.memory.iter().find(|r| r.name == "BANK_1").unwrap();
133 write!(
134 &mut extra,
135 "pub const FLASH_BASE: usize = {};\n",
136 flash.address,
137 )
138 .unwrap();
139 write!(
140 &mut extra,
141 "pub const FLASH_SIZE: usize = {};\n",
142 flash.size,
143 )
144 .unwrap();
145 if let Some(settings) = &flash.settings {
146 write!(
147 &mut extra,
148 "pub const ERASE_SIZE: usize = {};\n",
149 settings.erase_size,
150 )
151 .unwrap();
152 write!(
153 &mut extra,
154 "pub const WRITE_SIZE: usize = {};\n",
155 settings.write_size,
156 )
157 .unwrap();
158 write!(
159 &mut extra,
160 "pub const ERASE_VALUE: u8 = {};\n",
161 settings.erase_value,
162 )
163 .unwrap();
164 }
165
132 // Cleanups! 166 // Cleanups!
133 transform::sort::Sort {}.run(&mut ir).unwrap(); 167 transform::sort::Sort {}.run(&mut ir).unwrap();
134 transform::Sanitize {}.run(&mut ir).unwrap(); 168 transform::Sanitize {}.run(&mut ir).unwrap();
diff --git a/stm32-metapac/src/metadata.rs b/stm32-metapac/src/metadata.rs
index 23b759f6c..d05830e94 100644
--- a/stm32-metapac/src/metadata.rs
+++ b/stm32-metapac/src/metadata.rs
@@ -15,6 +15,14 @@ pub struct MemoryRegion {
15 pub kind: MemoryRegionKind, 15 pub kind: MemoryRegionKind,
16 pub address: u32, 16 pub address: u32,
17 pub size: u32, 17 pub size: u32,
18 pub settings: Option<FlashSettings>,
19}
20
21#[derive(Debug, Eq, PartialEq, Clone)]
22pub struct FlashSettings {
23 pub erase_size: u32,
24 pub write_size: u32,
25 pub erase_value: u8,
18} 26}
19 27
20#[derive(Debug, Eq, PartialEq, Clone)] 28#[derive(Debug, Eq, PartialEq, Clone)]