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.
This commit is contained in:
parent
c1da2c0219
commit
55ff397c0c
@ -14,28 +14,17 @@ use embassy_nrf::wdt;
|
|||||||
use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash};
|
use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash};
|
||||||
|
|
||||||
/// A bootloader for nRF devices.
|
/// A bootloader for nRF devices.
|
||||||
pub struct BootLoader<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize = PAGE_SIZE> {
|
pub struct BootLoader<const BUFFER_SIZE: usize = PAGE_SIZE>;
|
||||||
boot: embassy_boot::BootLoader<ACTIVE, DFU, STATE>,
|
|
||||||
aligned_buf: AlignedBuffer<BUFFER_SIZE>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>
|
impl<const BUFFER_SIZE: usize> BootLoader<BUFFER_SIZE> {
|
||||||
BootLoader<ACTIVE, DFU, STATE, BUFFER_SIZE>
|
/// Inspect the bootloader state and perform actions required before booting, such as swapping firmware.
|
||||||
{
|
pub fn prepare<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash>(
|
||||||
/// Create a new bootloader instance using the supplied partitions for active, dfu and state.
|
config: BootLoaderConfig<ACTIVE, DFU, STATE>,
|
||||||
pub fn new(config: BootLoaderConfig<ACTIVE, DFU, STATE>) -> Self {
|
) -> Self {
|
||||||
Self {
|
let mut aligned_buf = AlignedBuffer([0; BUFFER_SIZE]);
|
||||||
boot: embassy_boot::BootLoader::new(config),
|
let mut boot = embassy_boot::BootLoader::new(config);
|
||||||
aligned_buf: AlignedBuffer([0; BUFFER_SIZE]),
|
boot.prepare_boot(&mut aligned_buf.0).expect("Boot prepare error");
|
||||||
}
|
Self
|
||||||
}
|
|
||||||
|
|
||||||
/// 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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Boots the application without softdevice mechanisms.
|
/// Boots the application without softdevice mechanisms.
|
||||||
@ -45,8 +34,6 @@ impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>
|
|||||||
/// This modifies the stack pointer and reset vector and will run code placed in the active partition.
|
/// This modifies the stack pointer and reset vector and will run code placed in the active partition.
|
||||||
#[cfg(not(feature = "softdevice"))]
|
#[cfg(not(feature = "softdevice"))]
|
||||||
pub unsafe fn load(self, start: u32) -> ! {
|
pub unsafe fn load(self, start: u32) -> ! {
|
||||||
core::mem::drop(self.boot);
|
|
||||||
|
|
||||||
let mut p = cortex_m::Peripherals::steal();
|
let mut p = cortex_m::Peripherals::steal();
|
||||||
p.SCB.invalidate_icache();
|
p.SCB.invalidate_icache();
|
||||||
p.SCB.vtor.write(start);
|
p.SCB.vtor.write(start);
|
||||||
@ -59,7 +46,7 @@ impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>
|
|||||||
///
|
///
|
||||||
/// This modifies the stack pointer and reset vector and will run code placed in the active partition.
|
/// This modifies the stack pointer and reset vector and will run code placed in the active partition.
|
||||||
#[cfg(feature = "softdevice")]
|
#[cfg(feature = "softdevice")]
|
||||||
pub unsafe fn load(&mut self, _app: u32) -> ! {
|
pub unsafe fn load(self, _app: u32) -> ! {
|
||||||
use nrf_softdevice_mbr as mbr;
|
use nrf_softdevice_mbr as mbr;
|
||||||
const NRF_SUCCESS: u32 = 0;
|
const NRF_SUCCESS: u32 = 0;
|
||||||
|
|
||||||
|
@ -15,28 +15,17 @@ use embassy_time::Duration;
|
|||||||
use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash};
|
use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash};
|
||||||
|
|
||||||
/// A bootloader for RP2040 devices.
|
/// A bootloader for RP2040 devices.
|
||||||
pub struct BootLoader<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize = ERASE_SIZE> {
|
pub struct BootLoader<const BUFFER_SIZE: usize = ERASE_SIZE>;
|
||||||
boot: embassy_boot::BootLoader<ACTIVE, DFU, STATE>,
|
|
||||||
aligned_buf: AlignedBuffer<BUFFER_SIZE>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>
|
impl<const BUFFER_SIZE: usize> BootLoader<BUFFER_SIZE> {
|
||||||
BootLoader<ACTIVE, DFU, STATE, BUFFER_SIZE>
|
/// Inspect the bootloader state and perform actions required before booting, such as swapping firmware
|
||||||
{
|
pub fn prepare<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash>(
|
||||||
/// Create a new bootloader instance using the supplied partitions for active, dfu and state.
|
config: BootLoaderConfig<ACTIVE, DFU, STATE>,
|
||||||
pub fn new(config: BootLoaderConfig<ACTIVE, DFU, STATE>) -> Self {
|
) -> Self {
|
||||||
Self {
|
let mut aligned_buf = AlignedBuffer([0; BUFFER_SIZE]);
|
||||||
boot: embassy_boot::BootLoader::new(config),
|
let mut boot = embassy_boot::BootLoader::new(config);
|
||||||
aligned_buf: AlignedBuffer([0; BUFFER_SIZE]),
|
boot.prepare_boot(aligned_buf.as_mut()).expect("Boot prepare error");
|
||||||
}
|
Self
|
||||||
}
|
|
||||||
|
|
||||||
/// 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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Boots the application.
|
/// Boots the application.
|
||||||
@ -45,8 +34,6 @@ impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>
|
|||||||
///
|
///
|
||||||
/// This modifies the stack pointer and reset vector and will run code placed in the active partition.
|
/// This modifies the stack pointer and reset vector and will run code placed in the active partition.
|
||||||
pub unsafe fn load(self, start: u32) -> ! {
|
pub unsafe fn load(self, start: u32) -> ! {
|
||||||
core::mem::drop(self.boot);
|
|
||||||
|
|
||||||
trace!("Loading app at 0x{:x}", start);
|
trace!("Loading app at 0x{:x}", start);
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
let mut p = cortex_m::Peripherals::steal();
|
let mut p = cortex_m::Peripherals::steal();
|
||||||
|
@ -11,28 +11,17 @@ pub use embassy_boot::{FirmwareState, FirmwareUpdater};
|
|||||||
use embedded_storage::nor_flash::NorFlash;
|
use embedded_storage::nor_flash::NorFlash;
|
||||||
|
|
||||||
/// A bootloader for STM32 devices.
|
/// A bootloader for STM32 devices.
|
||||||
pub struct BootLoader<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize> {
|
pub struct BootLoader;
|
||||||
boot: embassy_boot::BootLoader<ACTIVE, DFU, STATE>,
|
|
||||||
aligned_buf: AlignedBuffer<BUFFER_SIZE>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>
|
impl BootLoader {
|
||||||
BootLoader<ACTIVE, DFU, STATE, BUFFER_SIZE>
|
/// Inspect the bootloader state and perform actions required before booting, such as swapping firmware
|
||||||
{
|
pub fn prepare<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>(
|
||||||
/// Create a new bootloader instance using the supplied partitions for active, dfu and state.
|
config: BootLoaderConfig<ACTIVE, DFU, STATE>,
|
||||||
pub fn new(config: BootLoaderConfig<ACTIVE, DFU, STATE>) -> Self {
|
) -> Self {
|
||||||
Self {
|
let mut aligned_buf = AlignedBuffer([0; BUFFER_SIZE]);
|
||||||
boot: embassy_boot::BootLoader::new(config),
|
let mut boot = embassy_boot::BootLoader::new(config);
|
||||||
aligned_buf: AlignedBuffer([0; BUFFER_SIZE]),
|
boot.prepare_boot(aligned_buf.as_mut()).expect("Boot prepare error");
|
||||||
}
|
Self
|
||||||
}
|
|
||||||
|
|
||||||
/// 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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Boots the application.
|
/// Boots the application.
|
||||||
@ -41,8 +30,6 @@ impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash, const BUFFER_SIZE: usize>
|
|||||||
///
|
///
|
||||||
/// This modifies the stack pointer and reset vector and will run code placed in the active partition.
|
/// This modifies the stack pointer and reset vector and will run code placed in the active partition.
|
||||||
pub unsafe fn load(self, start: u32) -> ! {
|
pub unsafe fn load(self, start: u32) -> ! {
|
||||||
core::mem::drop(self.boot);
|
|
||||||
|
|
||||||
trace!("Loading app at 0x{:x}", start);
|
trace!("Loading app at 0x{:x}", start);
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
let mut p = cortex_m::Peripherals::steal();
|
let mut p = cortex_m::Peripherals::steal();
|
||||||
|
@ -33,9 +33,7 @@ fn main() -> ! {
|
|||||||
|
|
||||||
let config = BootLoaderConfig::from_linkerfile_blocking(&flash);
|
let config = BootLoaderConfig::from_linkerfile_blocking(&flash);
|
||||||
let active_offset = config.active.offset();
|
let active_offset = config.active.offset();
|
||||||
let mut bl: BootLoader<_, _, _> = BootLoader::new(config);
|
let bl: BootLoader = BootLoader::prepare(config);
|
||||||
|
|
||||||
bl.prepare();
|
|
||||||
|
|
||||||
unsafe { bl.load(active_offset) }
|
unsafe { bl.load(active_offset) }
|
||||||
}
|
}
|
||||||
|
@ -29,9 +29,7 @@ fn main() -> ! {
|
|||||||
|
|
||||||
let config = BootLoaderConfig::from_linkerfile_blocking(&flash);
|
let config = BootLoaderConfig::from_linkerfile_blocking(&flash);
|
||||||
let active_offset = config.active.offset();
|
let active_offset = config.active.offset();
|
||||||
let mut bl: BootLoader<_, _, _> = BootLoader::new(config);
|
let bl: BootLoader = BootLoader::prepare(config);
|
||||||
|
|
||||||
bl.prepare();
|
|
||||||
|
|
||||||
unsafe { bl.load(embassy_rp::flash::FLASH_BASE as u32 + active_offset) }
|
unsafe { bl.load(embassy_rp::flash::FLASH_BASE as u32 + active_offset) }
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,7 @@ fn main() -> ! {
|
|||||||
|
|
||||||
let config = BootLoaderConfig::from_linkerfile_blocking(&flash);
|
let config = BootLoaderConfig::from_linkerfile_blocking(&flash);
|
||||||
let active_offset = config.active.offset();
|
let active_offset = config.active.offset();
|
||||||
let mut bl: BootLoader<_, _, _, 2048> = BootLoader::new(config);
|
let bl = BootLoader::prepare::<_, _, _, 2048>(config);
|
||||||
|
|
||||||
bl.prepare();
|
|
||||||
|
|
||||||
unsafe { bl.load(BANK1_REGION.base + active_offset) }
|
unsafe { bl.load(BANK1_REGION.base + active_offset) }
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user