From 55ff397c0cde8a04c41cfc228645c3fd33383cd1 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 11 Aug 2023 19:47:24 +0200 Subject: [PATCH] boot: release flash after prepare and refactor api This refactoring of the chip specific bootloader creates the internal boot instance and aligned buffer in the prepare stage, so that they are automatically dropped after. This unlocks a use case where peripherals owning the flash need to be Drop'ed before load() happens. --- embassy-boot/nrf/src/lib.rs | 35 +++++++--------------- embassy-boot/rp/src/lib.rs | 33 +++++++------------- embassy-boot/stm32/src/lib.rs | 33 +++++++------------- examples/boot/bootloader/nrf/src/main.rs | 4 +-- examples/boot/bootloader/rp/src/main.rs | 4 +-- examples/boot/bootloader/stm32/src/main.rs | 4 +-- 6 files changed, 34 insertions(+), 79 deletions(-) diff --git a/embassy-boot/nrf/src/lib.rs b/embassy-boot/nrf/src/lib.rs index df94819f..b9d86eb1 100644 --- a/embassy-boot/nrf/src/lib.rs +++ b/embassy-boot/nrf/src/lib.rs @@ -14,28 +14,17 @@ use embassy_nrf::wdt; use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash}; /// A bootloader for nRF devices. -pub struct BootLoader { - boot: embassy_boot::BootLoader, - aligned_buf: AlignedBuffer, -} +pub struct BootLoader; -impl - BootLoader -{ - /// Create a new bootloader instance using the supplied partitions for active, dfu and state. - pub fn new(config: BootLoaderConfig) -> Self { - Self { - boot: embassy_boot::BootLoader::new(config), - aligned_buf: AlignedBuffer([0; BUFFER_SIZE]), - } - } - - /// Inspect the bootloader state and perform actions required before booting, such as swapping - /// firmware. - pub fn prepare(&mut self) { - self.boot - .prepare_boot(&mut self.aligned_buf.0) - .expect("Boot prepare error"); +impl BootLoader { + /// Inspect the bootloader state and perform actions required before booting, such as swapping firmware. + pub fn prepare( + config: BootLoaderConfig, + ) -> Self { + let mut aligned_buf = AlignedBuffer([0; BUFFER_SIZE]); + let mut boot = embassy_boot::BootLoader::new(config); + boot.prepare_boot(&mut aligned_buf.0).expect("Boot prepare error"); + Self } /// Boots the application without softdevice mechanisms. @@ -45,8 +34,6 @@ impl /// This modifies the stack pointer and reset vector and will run code placed in the active partition. #[cfg(not(feature = "softdevice"))] pub unsafe fn load(self, start: u32) -> ! { - core::mem::drop(self.boot); - let mut p = cortex_m::Peripherals::steal(); p.SCB.invalidate_icache(); p.SCB.vtor.write(start); @@ -59,7 +46,7 @@ impl /// /// This modifies the stack pointer and reset vector and will run code placed in the active partition. #[cfg(feature = "softdevice")] - pub unsafe fn load(&mut self, _app: u32) -> ! { + pub unsafe fn load(self, _app: u32) -> ! { use nrf_softdevice_mbr as mbr; const NRF_SUCCESS: u32 = 0; diff --git a/embassy-boot/rp/src/lib.rs b/embassy-boot/rp/src/lib.rs index f5aefa41..96bcf3bf 100644 --- a/embassy-boot/rp/src/lib.rs +++ b/embassy-boot/rp/src/lib.rs @@ -15,28 +15,17 @@ use embassy_time::Duration; use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash}; /// A bootloader for RP2040 devices. -pub struct BootLoader { - boot: embassy_boot::BootLoader, - aligned_buf: AlignedBuffer, -} +pub struct BootLoader; -impl - BootLoader -{ - /// Create a new bootloader instance using the supplied partitions for active, dfu and state. - pub fn new(config: BootLoaderConfig) -> Self { - Self { - boot: embassy_boot::BootLoader::new(config), - aligned_buf: AlignedBuffer([0; BUFFER_SIZE]), - } - } - - /// Inspect the bootloader state and perform actions required before booting, such as swapping - /// firmware. - pub fn prepare(&mut self) { - self.boot - .prepare_boot(self.aligned_buf.as_mut()) - .expect("Boot prepare error"); +impl BootLoader { + /// Inspect the bootloader state and perform actions required before booting, such as swapping firmware + pub fn prepare( + config: BootLoaderConfig, + ) -> Self { + let mut aligned_buf = AlignedBuffer([0; BUFFER_SIZE]); + let mut boot = embassy_boot::BootLoader::new(config); + boot.prepare_boot(aligned_buf.as_mut()).expect("Boot prepare error"); + Self } /// Boots the application. @@ -45,8 +34,6 @@ impl /// /// This modifies the stack pointer and reset vector and will run code placed in the active partition. pub unsafe fn load(self, start: u32) -> ! { - core::mem::drop(self.boot); - trace!("Loading app at 0x{:x}", start); #[allow(unused_mut)] let mut p = cortex_m::Peripherals::steal(); diff --git a/embassy-boot/stm32/src/lib.rs b/embassy-boot/stm32/src/lib.rs index 25f02942..c6350c49 100644 --- a/embassy-boot/stm32/src/lib.rs +++ b/embassy-boot/stm32/src/lib.rs @@ -11,28 +11,17 @@ pub use embassy_boot::{FirmwareState, FirmwareUpdater}; use embedded_storage::nor_flash::NorFlash; /// A bootloader for STM32 devices. -pub struct BootLoader { - boot: embassy_boot::BootLoader, - aligned_buf: AlignedBuffer, -} +pub struct BootLoader; -impl - BootLoader -{ - /// Create a new bootloader instance using the supplied partitions for active, dfu and state. - pub fn new(config: BootLoaderConfig) -> Self { - Self { - boot: embassy_boot::BootLoader::new(config), - aligned_buf: AlignedBuffer([0; BUFFER_SIZE]), - } - } - - /// Inspect the bootloader state and perform actions required before booting, such as swapping - /// firmware. - pub fn prepare(&mut self) { - self.boot - .prepare_boot(self.aligned_buf.as_mut()) - .expect("Boot prepare error"); +impl BootLoader { + /// Inspect the bootloader state and perform actions required before booting, such as swapping firmware + pub fn prepare( + config: BootLoaderConfig, + ) -> Self { + let mut aligned_buf = AlignedBuffer([0; BUFFER_SIZE]); + let mut boot = embassy_boot::BootLoader::new(config); + boot.prepare_boot(aligned_buf.as_mut()).expect("Boot prepare error"); + Self } /// Boots the application. @@ -41,8 +30,6 @@ impl /// /// This modifies the stack pointer and reset vector and will run code placed in the active partition. pub unsafe fn load(self, start: u32) -> ! { - core::mem::drop(self.boot); - trace!("Loading app at 0x{:x}", start); #[allow(unused_mut)] let mut p = cortex_m::Peripherals::steal(); diff --git a/examples/boot/bootloader/nrf/src/main.rs b/examples/boot/bootloader/nrf/src/main.rs index 72c95c02..74e2e293 100644 --- a/examples/boot/bootloader/nrf/src/main.rs +++ b/examples/boot/bootloader/nrf/src/main.rs @@ -33,9 +33,7 @@ fn main() -> ! { let config = BootLoaderConfig::from_linkerfile_blocking(&flash); let active_offset = config.active.offset(); - let mut bl: BootLoader<_, _, _> = BootLoader::new(config); - - bl.prepare(); + let bl: BootLoader = BootLoader::prepare(config); unsafe { bl.load(active_offset) } } diff --git a/examples/boot/bootloader/rp/src/main.rs b/examples/boot/bootloader/rp/src/main.rs index 6a81db80..c0e75d1e 100644 --- a/examples/boot/bootloader/rp/src/main.rs +++ b/examples/boot/bootloader/rp/src/main.rs @@ -29,9 +29,7 @@ fn main() -> ! { let config = BootLoaderConfig::from_linkerfile_blocking(&flash); let active_offset = config.active.offset(); - let mut bl: BootLoader<_, _, _> = BootLoader::new(config); - - bl.prepare(); + let bl: BootLoader = BootLoader::prepare(config); unsafe { bl.load(embassy_rp::flash::FLASH_BASE as u32 + active_offset) } } diff --git a/examples/boot/bootloader/stm32/src/main.rs b/examples/boot/bootloader/stm32/src/main.rs index 262eed20..5fd9ea58 100644 --- a/examples/boot/bootloader/stm32/src/main.rs +++ b/examples/boot/bootloader/stm32/src/main.rs @@ -27,9 +27,7 @@ fn main() -> ! { let config = BootLoaderConfig::from_linkerfile_blocking(&flash); let active_offset = config.active.offset(); - let mut bl: BootLoader<_, _, _, 2048> = BootLoader::new(config); - - bl.prepare(); + let bl = BootLoader::prepare::<_, _, _, 2048>(config); unsafe { bl.load(BANK1_REGION.base + active_offset) } }