diff options
34 files changed, 162 insertions, 172 deletions
| @@ -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" | |||
| 21 | env_logger = "0.9" | 21 | env_logger = "0.9" |
| 22 | rand = "0.8" | 22 | rand = "0.8" |
| 23 | futures = { version = "0.3", features = ["executor"] } | 23 | futures = { version = "0.3", features = ["executor"] } |
| 24 | |||
| 25 | [features] | ||
| 26 | write-4 = [] | ||
| 27 | write-8 = [] | ||
| 28 | invert-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; | |||
| 17 | use embedded_storage::nor_flash::{NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; | 19 | use embedded_storage::nor_flash::{NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; |
| 18 | use embedded_storage_async::nor_flash::AsyncNorFlash; | 20 | use embedded_storage_async::nor_flash::AsyncNorFlash; |
| 19 | 21 | ||
| 20 | #[cfg(not(any(feature = "write-4", feature = "write-8",)))] | ||
| 21 | compile_error!("No write size/alignment specified. Must specify exactly one of the following features: write-4, write-8"); | ||
| 22 | |||
| 23 | const BOOT_MAGIC: u8 = 0xD0; | 22 | const BOOT_MAGIC: u8 = 0xD0; |
| 24 | const SWAP_MAGIC: u8 = 0xF0; | 23 | const SWAP_MAGIC: u8 = 0xF0; |
| 25 | 24 | ||
| 26 | #[cfg(feature = "write-4")] | ||
| 27 | const WRITE_SIZE: usize = 4; | ||
| 28 | |||
| 29 | #[cfg(feature = "write-8")] | ||
| 30 | const WRITE_SIZE: usize = 8; | ||
| 31 | |||
| 32 | #[cfg(feature = "invert-erase")] | ||
| 33 | const ERASE_VALUE: u8 = 0x00; | ||
| 34 | |||
| 35 | #[cfg(not(feature = "invert-erase"))] | ||
| 36 | const 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))] |
| 40 | pub struct Partition { | 27 | pub 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. |
| 99 | pub struct BootLoader<const PAGE_SIZE: usize> { | 86 | pub 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 | ||
| 111 | impl<const PAGE_SIZE: usize> BootLoader<PAGE_SIZE> { | 98 | impl<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))] |
| 456 | pub struct Aligned([u8; 4]); | 442 | pub struct Aligned<const N: usize>([u8; N]); |
| 457 | |||
| 458 | #[cfg(feature = "write-8")] | ||
| 459 | #[repr(align(8))] | ||
| 460 | pub struct Aligned([u8; 8]); | ||
| 461 | 443 | ||
| 462 | impl Default for FirmwareUpdater { | 444 | impl 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 | ||
| 14 | embassy = { path = "../../embassy", default-features = false } | 14 | embassy = { path = "../../embassy", default-features = false } |
| 15 | embassy-nrf = { path = "../../embassy-nrf", default-features = false, features = ["nightly"] } | 15 | embassy-nrf = { path = "../../embassy-nrf", default-features = false, features = ["nightly"] } |
| 16 | embassy-boot = { path = "../boot", default-features = false, features = ["write-4"] } | 16 | embassy-boot = { path = "../boot", default-features = false } |
| 17 | cortex-m = { version = "0.7" } | 17 | cortex-m = { version = "0.7" } |
| 18 | cortex-m-rt = { version = "0.7" } | 18 | cortex-m-rt = { version = "0.7" } |
| 19 | embedded-storage = "0.3.0" | 19 | embedded-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::{ | |||
| 13 | use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash}; | 13 | use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash}; |
| 14 | 14 | ||
| 15 | pub struct BootLoader { | 15 | pub struct BootLoader { |
| 16 | boot: embassy_boot::BootLoader<PAGE_SIZE>, | 16 | boot: embassy_boot::BootLoader<PAGE_SIZE, 4, 0xFF>, |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | impl BootLoader { | 19 | impl 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] |
| 48 | fn panic(_info: &core::panic::PanicInfo) -> ! { | 48 | fn 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 | ] |
| 29 | debug = ["defmt-rtt"] | 29 | debug = ["defmt-rtt"] |
| 30 | flash-2k = ["embassy-boot/write-8"] | ||
| 31 | flash-128 = ["embassy-boot/write-4"] | ||
| 32 | flash-256 = ["embassy-boot/write-4"] | ||
| 33 | invert-erase = ["embassy-boot/invert-erase"] | ||
| 34 | thumbv6 = [] | 30 | thumbv6 = [] |
| 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 @@ | |||
| 5 | mod fmt; | 5 | mod fmt; |
| 6 | 6 | ||
| 7 | pub use embassy_boot::{FirmwareUpdater, FlashProvider, Partition, SingleFlashProvider, State}; | 7 | pub use embassy_boot::{FirmwareUpdater, FlashProvider, Partition, SingleFlashProvider, State}; |
| 8 | use embassy_stm32::flash::{ERASE_SIZE, ERASE_VALUE, WRITE_SIZE}; | ||
| 8 | 9 | ||
| 9 | pub struct BootLoader<const PAGE_SIZE: usize> { | 10 | pub struct BootLoader { |
| 10 | boot: embassy_boot::BootLoader<PAGE_SIZE>, | 11 | boot: embassy_boot::BootLoader<ERASE_SIZE, WRITE_SIZE, ERASE_VALUE>, |
| 11 | } | 12 | } |
| 12 | 13 | ||
| 13 | impl<const PAGE_SIZE: usize> BootLoader<PAGE_SIZE> { | 14 | impl 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 _; | |||
| 9 | use embassy_boot_stm32::*; | 9 | use embassy_boot_stm32::*; |
| 10 | use embassy_stm32::flash::Flash; | 10 | use embassy_stm32::flash::Flash; |
| 11 | 11 | ||
| 12 | #[cfg(not(any(feature = "flash-2k", feature = "flash-256", feature = "flash-128")))] | ||
| 13 | compile_error!("No flash size specified. Must specify exactly one of the following features: flash-2k, flash-256, flash-128"); | ||
| 14 | |||
| 15 | #[entry] | 12 | #[entry] |
| 16 | fn main() -> ! { | 13 | fn 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] |
| 57 | fn panic(_info: &core::panic::PanicInfo) -> ! { | 46 | fn 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 | ||
| 13 | const FLASH_BASE: usize = 0x8000000; | 13 | pub use crate::pac::ERASE_SIZE; |
| 14 | 14 | pub use crate::pac::ERASE_VALUE; | |
| 15 | #[cfg(flash_l4)] | 15 | pub use crate::pac::FLASH_BASE; |
| 16 | mod config { | 16 | pub use crate::pac::FLASH_SIZE; |
| 17 | use super::*; | 17 | pub use crate::pac::WRITE_SIZE; |
| 18 | pub(crate) const FLASH_SIZE: usize = 0x100000; | 18 | const 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)] | ||
| 26 | mod 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)] | ||
| 36 | mod 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)] | ||
| 46 | mod 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)] | ||
| 56 | mod 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 | |||
| 65 | use config::*; | ||
| 66 | 19 | ||
| 67 | pub struct Flash<'d> { | 20 | pub 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 | ||
| 335 | impl<'d> ReadNorFlash for Flash<'d> { | 293 | impl<'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 | ||
| 347 | impl<'d> NorFlash for Flash<'d> { | 305 | impl<'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` | ||
| 3 | runner = "probe-run --chip nRF52840_xxAA" | ||
| 4 | |||
| 5 | [build] | ||
| 6 | target = "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] |
| 8 | embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] } | 8 | embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] } |
| 9 | embassy-nrf = { version = "0.1.0", path = "../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", "nightly"] } | 9 | embassy-nrf = { version = "0.1.0", path = "../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", "nightly", "nrf52840"] } |
| 10 | embassy-boot-nrf = { version = "0.1.0", path = "../../../embassy-boot/nrf" } | 10 | embassy-boot-nrf = { version = "0.1.0", path = "../../../embassy-boot/nrf" } |
| 11 | embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" } | 11 | embassy-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 |
| 20 | cargo flash --manifest-path ../../embassy-boot/nrf/Cargo.toml --release --features embassy-nrf/nrf52840 --chip nRF52840_xxAA | 20 | cargo flash --manifest-path ../../../embassy-boot/nrf/Cargo.toml --features embassy-nrf/nrf52840 --release --chip nRF52840_xxAA |
| 21 | # Build 'b' | 21 | # Build 'b' |
| 22 | cargo build --release --features embassy-nrf/nrf52840 --bin b | 22 | cargo build --release --bin b |
| 23 | # Generate binary for 'b' | 23 | # Generate binary for 'b' |
| 24 | cargo objcopy --release --features embassy-nrf/nrf52840 --bin b -- -O binary b.bin | 24 | cargo 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 | ``` |
| 30 | cargo flash --release --features embassy-nrf/nrf52840 --bin a --chip nRF52840_xxAA | 30 | cargo 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] |
| 8 | embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] } | 8 | embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] } |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l072cz", "time-driver-any", "exti", "memory-x"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l072cz", "time-driver-any", "exti", "memory-x"] } |
| 10 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../embassy-boot/stm32", features = ["flash-128", "invert-erase", "thumbv6"] } | 10 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../embassy-boot/stm32", features = ["thumbv6"] } |
| 11 | embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" } | 11 | embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" } |
| 12 | 12 | ||
| 13 | defmt = { version = "0.3", optional = true } | 13 | defmt = { 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 |
| 18 | cargo flash --manifest-path ../../../embassy-boot/stm32/Cargo.toml --release --features embassy-stm32/stm32l072cz,flash-128,invert-erase,thumbv6 --chip STM32L072CZTx | 18 | cargo flash --manifest-path ../../../embassy-boot/stm32/Cargo.toml --release --features embassy-stm32/stm32l072cz,thumbv6 --chip STM32L072CZTx |
| 19 | # Build 'b' | 19 | # Build 'b' |
| 20 | cargo build --release --bin b | 20 | cargo 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] |
| 8 | embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] } | 8 | embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] } |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l151cb-a", "time-driver-any", "exti"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l151cb-a", "time-driver-any", "exti"] } |
| 10 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../embassy-boot/stm32", features = ["flash-256", "invert-erase"] } | 10 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../embassy-boot/stm32" } |
| 11 | embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" } | 11 | embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" } |
| 12 | 12 | ||
| 13 | defmt = { version = "0.3", optional = true } | 13 | defmt = { 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 |
| 18 | cargo flash --manifest-path ../../../embassy-boot/stm32/Cargo.toml --release --features embassy-stm32/stm32l151cb-a,flash-256,invert-erase --chip STM32L151CBxxA | 18 | cargo flash --manifest-path ../../../embassy-boot/stm32/Cargo.toml --release --features embassy-stm32/stm32l151cb-a --chip STM32L151CBxxA |
| 19 | # Build 'b' | 19 | # Build 'b' |
| 20 | cargo build --release --bin b | 20 | cargo 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] |
| 8 | embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] } | 8 | embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] } |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l475vg", "time-driver-any", "exti"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l475vg", "time-driver-any", "exti"] } |
| 10 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../embassy-boot/stm32", features = ["flash-2k"] } | 10 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../embassy-boot/stm32" } |
| 11 | embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" } | 11 | embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" } |
| 12 | 12 | ||
| 13 | defmt = { version = "0.3", optional = true } | 13 | defmt = { 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 |
| 18 | cargo flash --manifest-path ../../../embassy-boot/stm32/Cargo.toml --release --features embassy-stm32/stm32l475vg,flash-2k --chip STM32L475VG | 18 | cargo flash --manifest-path ../../../embassy-boot/stm32/Cargo.toml --release --features embassy-stm32/stm32l475vg --chip STM32L475VG |
| 19 | # Build 'b' | 19 | # Build 'b' |
| 20 | cargo build --release --bin b | 20 | cargo 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] |
| 8 | embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] } | 8 | embassy = { version = "0.1.0", path = "../../../embassy", features = ["nightly"] } |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32wl55jc-cm4", "time-driver-any", "exti"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32wl55jc-cm4", "time-driver-any", "exti"] } |
| 10 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../embassy-boot/stm32", features = ["flash-2k"] } | 10 | embassy-boot-stm32 = { version = "0.1.0", path = "../../../embassy-boot/stm32" } |
| 11 | embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" } | 11 | embassy-traits = { version = "0.1.0", path = "../../../embassy-traits" } |
| 12 | 12 | ||
| 13 | defmt = { version = "0.3", optional = true } | 13 | defmt = { 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 |
| 18 | cargo flash --manifest-path ../../../embassy-boot/stm32/Cargo.toml --release --features embassy-stm32/stm32wl55jc-cm4,flash-2k --chip STM32WLE5JCIx | 18 | cargo flash --manifest-path ../../../embassy-boot/stm32/Cargo.toml --release --features embassy-stm32/stm32wl55jc-cm4 --chip STM32WLE5JCIx |
| 19 | # Build 'b' | 19 | # Build 'b' |
| 20 | cargo build --release --bin b | 20 | cargo 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] |
| 19 | async fn main(_s: embassy::executor::Spawner, p: Peripherals) { | 19 | async 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 _; | |||
| 15 | async fn main(_spawner: Spawner, p: Peripherals) { | 15 | async 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 _; | |||
| 15 | async fn main(_spawner: Spawner, p: Peripherals) { | 15 | async 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 _; | |||
| 15 | async fn main(_spawner: Spawner, p: Peripherals) { | 15 | async 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)] | ||
| 23 | pub 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)] | ||
| 22 | pub 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)] |
