From 976a7ae22aa222213861c12d515115aac87bd2e0 Mon Sep 17 00:00:00 2001 From: Kaitlyn Kenwell Date: Wed, 13 Dec 2023 14:40:49 -0500 Subject: Add embassy-usb-dfu --- embassy-boot/boot/src/boot_loader.rs | 4 +++- embassy-boot/boot/src/firmware_updater/asynch.rs | 13 ++++++++++++- embassy-boot/boot/src/firmware_updater/blocking.rs | 17 +++++++++++++++-- embassy-boot/boot/src/lib.rs | 3 +++ embassy-boot/stm32/src/lib.rs | 9 ++++++--- 5 files changed, 39 insertions(+), 7 deletions(-) (limited to 'embassy-boot') diff --git a/embassy-boot/boot/src/boot_loader.rs b/embassy-boot/boot/src/boot_loader.rs index a8c19197b..c0deca22b 100644 --- a/embassy-boot/boot/src/boot_loader.rs +++ b/embassy-boot/boot/src/boot_loader.rs @@ -5,7 +5,7 @@ use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::blocking_mutex::Mutex; use embedded_storage::nor_flash::{NorFlash, NorFlashError, NorFlashErrorKind}; -use crate::{State, BOOT_MAGIC, STATE_ERASE_VALUE, SWAP_MAGIC}; +use crate::{State, BOOT_MAGIC, STATE_ERASE_VALUE, SWAP_MAGIC, DFU_DETACH_MAGIC}; /// Errors returned by bootloader #[derive(PartialEq, Eq, Debug)] @@ -384,6 +384,8 @@ impl BootLoader FirmwareUpdater<'d, DFU, STATE> { self.state.mark_updated().await } + /// Mark to trigger USB DFU on next boot. + pub async fn mark_dfu(&mut self) -> Result<(), FirmwareUpdaterError> { + self.state.verify_booted().await?; + self.state.mark_dfu().await + } + /// Mark firmware boot successful and stop rollback on reset. pub async fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> { self.state.mark_booted().await @@ -247,6 +253,11 @@ impl<'d, STATE: NorFlash> FirmwareState<'d, STATE> { self.set_magic(SWAP_MAGIC).await } + /// Mark to trigger USB DFU on next boot. + pub async fn mark_dfu(&mut self) -> Result<(), FirmwareUpdaterError> { + self.set_magic(DFU_DETACH_MAGIC).await + } + /// Mark firmware boot successful and stop rollback on reset. pub async fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> { self.set_magic(BOOT_MAGIC).await diff --git a/embassy-boot/boot/src/firmware_updater/blocking.rs b/embassy-boot/boot/src/firmware_updater/blocking.rs index 76e4264a0..b2a633d1e 100644 --- a/embassy-boot/boot/src/firmware_updater/blocking.rs +++ b/embassy-boot/boot/src/firmware_updater/blocking.rs @@ -6,7 +6,7 @@ use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embedded_storage::nor_flash::NorFlash; use super::FirmwareUpdaterConfig; -use crate::{FirmwareUpdaterError, State, BOOT_MAGIC, STATE_ERASE_VALUE, SWAP_MAGIC}; +use crate::{FirmwareUpdaterError, State, BOOT_MAGIC, STATE_ERASE_VALUE, SWAP_MAGIC, DFU_DETACH_MAGIC}; /// Blocking FirmwareUpdater is an application API for interacting with the BootLoader without the ability to /// 'mess up' the internal bootloader state @@ -168,6 +168,12 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<'d, DFU, STATE> self.state.mark_updated() } + /// Mark to trigger USB DFU device on next boot. + pub fn mark_dfu(&mut self) -> Result<(), FirmwareUpdaterError> { + self.state.verify_booted()?; + self.state.mark_dfu() + } + /// Mark firmware boot successful and stop rollback on reset. pub fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> { self.state.mark_booted() @@ -226,7 +232,7 @@ impl<'d, STATE: NorFlash> BlockingFirmwareState<'d, STATE> { // Make sure we are running a booted firmware to avoid reverting to a bad state. fn verify_booted(&mut self) -> Result<(), FirmwareUpdaterError> { - if self.get_state()? == State::Boot { + if self.get_state()? == State::Boot || self.get_state()? == State::DfuDetach { Ok(()) } else { Err(FirmwareUpdaterError::BadState) @@ -243,6 +249,8 @@ impl<'d, STATE: NorFlash> BlockingFirmwareState<'d, STATE> { if !self.aligned.iter().any(|&b| b != SWAP_MAGIC) { Ok(State::Swap) + } else if !self.aligned.iter().any(|&b| b != DFU_DETACH_MAGIC) { + Ok(State::DfuDetach) } else { Ok(State::Boot) } @@ -253,6 +261,11 @@ impl<'d, STATE: NorFlash> BlockingFirmwareState<'d, STATE> { self.set_magic(SWAP_MAGIC) } + /// Mark to trigger USB DFU on next boot. + pub fn mark_dfu(&mut self) -> Result<(), FirmwareUpdaterError> { + self.set_magic(DFU_DETACH_MAGIC) + } + /// Mark firmware boot successful and stop rollback on reset. pub fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> { self.set_magic(BOOT_MAGIC) diff --git a/embassy-boot/boot/src/lib.rs b/embassy-boot/boot/src/lib.rs index 9e70a4dca..451992945 100644 --- a/embassy-boot/boot/src/lib.rs +++ b/embassy-boot/boot/src/lib.rs @@ -23,6 +23,7 @@ pub use firmware_updater::{ pub(crate) const BOOT_MAGIC: u8 = 0xD0; pub(crate) const SWAP_MAGIC: u8 = 0xF0; +pub(crate) const DFU_DETACH_MAGIC: u8 = 0xE0; /// The state of the bootloader after running prepare. #[derive(PartialEq, Eq, Debug)] @@ -32,6 +33,8 @@ pub enum State { Boot, /// Bootloader has swapped the active partition with the dfu partition and will attempt boot. Swap, + /// Application has received a DFU_DETACH request over USB, and is rebooting into the bootloader to apply a DFU. + DfuDetach, } /// Buffer aligned to 32 byte boundary, largest known alignment requirement for embassy-boot. diff --git a/embassy-boot/stm32/src/lib.rs b/embassy-boot/stm32/src/lib.rs index c418cb262..4b4091ac9 100644 --- a/embassy-boot/stm32/src/lib.rs +++ b/embassy-boot/stm32/src/lib.rs @@ -10,7 +10,10 @@ pub use embassy_boot::{ use embedded_storage::nor_flash::NorFlash; /// A bootloader for STM32 devices. -pub struct BootLoader; +pub struct BootLoader { + /// The reported state of the bootloader after preparing for boot + pub state: State, +} impl BootLoader { /// Inspect the bootloader state and perform actions required before booting, such as swapping firmware @@ -19,8 +22,8 @@ impl BootLoader { ) -> 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 + let state = boot.prepare_boot(aligned_buf.as_mut()).expect("Boot prepare error"); + Self { state } } /// Boots the application. -- cgit From 702d2a1a193985c9b8da6fc5e532ac55b5485464 Mon Sep 17 00:00:00 2001 From: Kaitlyn Kenwell Date: Wed, 13 Dec 2023 16:08:20 -0500 Subject: Formatting fixes, add example using stm32wb55 --- embassy-boot/boot/src/firmware_updater/asynch.rs | 2 +- embassy-boot/boot/src/firmware_updater/blocking.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'embassy-boot') diff --git a/embassy-boot/boot/src/firmware_updater/asynch.rs b/embassy-boot/boot/src/firmware_updater/asynch.rs index 0a3cbc136..82e99965b 100644 --- a/embassy-boot/boot/src/firmware_updater/asynch.rs +++ b/embassy-boot/boot/src/firmware_updater/asynch.rs @@ -6,7 +6,7 @@ use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embedded_storage_async::nor_flash::NorFlash; use super::FirmwareUpdaterConfig; -use crate::{FirmwareUpdaterError, State, BOOT_MAGIC, STATE_ERASE_VALUE, SWAP_MAGIC, DFU_DETACH_MAGIC}; +use crate::{FirmwareUpdaterError, State, BOOT_MAGIC, DFU_DETACH_MAGIC, STATE_ERASE_VALUE, SWAP_MAGIC}; /// FirmwareUpdater is an application API for interacting with the BootLoader without the ability to /// 'mess up' the internal bootloader state diff --git a/embassy-boot/boot/src/firmware_updater/blocking.rs b/embassy-boot/boot/src/firmware_updater/blocking.rs index b2a633d1e..ae4179ba3 100644 --- a/embassy-boot/boot/src/firmware_updater/blocking.rs +++ b/embassy-boot/boot/src/firmware_updater/blocking.rs @@ -6,7 +6,7 @@ use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embedded_storage::nor_flash::NorFlash; use super::FirmwareUpdaterConfig; -use crate::{FirmwareUpdaterError, State, BOOT_MAGIC, STATE_ERASE_VALUE, SWAP_MAGIC, DFU_DETACH_MAGIC}; +use crate::{FirmwareUpdaterError, State, BOOT_MAGIC, DFU_DETACH_MAGIC, STATE_ERASE_VALUE, SWAP_MAGIC}; /// Blocking FirmwareUpdater is an application API for interacting with the BootLoader without the ability to /// 'mess up' the internal bootloader state -- cgit From b60b3f4eb8f22ecda1c30d63213010f1b6b47686 Mon Sep 17 00:00:00 2001 From: Kaitlyn Kenwell Date: Wed, 13 Dec 2023 16:19:59 -0500 Subject: Last fmt hopefully --- embassy-boot/boot/src/boot_loader.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'embassy-boot') diff --git a/embassy-boot/boot/src/boot_loader.rs b/embassy-boot/boot/src/boot_loader.rs index 340962a7a..b3970d867 100644 --- a/embassy-boot/boot/src/boot_loader.rs +++ b/embassy-boot/boot/src/boot_loader.rs @@ -5,7 +5,7 @@ use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::blocking_mutex::Mutex; use embedded_storage::nor_flash::{NorFlash, NorFlashError, NorFlashErrorKind}; -use crate::{State, BOOT_MAGIC, STATE_ERASE_VALUE, SWAP_MAGIC, DFU_DETACH_MAGIC}; +use crate::{State, BOOT_MAGIC, DFU_DETACH_MAGIC, STATE_ERASE_VALUE, SWAP_MAGIC}; /// Errors returned by bootloader #[derive(PartialEq, Eq, Debug)] -- cgit From e27e00f6280683293f427d0731aa69ca32dbbe60 Mon Sep 17 00:00:00 2001 From: Kaitlyn Kenwell Date: Thu, 14 Dec 2023 09:36:22 -0500 Subject: Address reviews --- embassy-boot/boot/src/firmware_updater/asynch.rs | 10 ++++++++++ embassy-boot/boot/src/firmware_updater/blocking.rs | 10 ++++++++++ embassy-boot/boot/src/lib.rs | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) (limited to 'embassy-boot') diff --git a/embassy-boot/boot/src/firmware_updater/asynch.rs b/embassy-boot/boot/src/firmware_updater/asynch.rs index 82e99965b..d8d85c3d2 100644 --- a/embassy-boot/boot/src/firmware_updater/asynch.rs +++ b/embassy-boot/boot/src/firmware_updater/asynch.rs @@ -213,6 +213,16 @@ pub struct FirmwareState<'d, STATE> { } impl<'d, STATE: NorFlash> FirmwareState<'d, STATE> { + /// Create a firmware state instance from a FirmwareUpdaterConfig with a buffer for magic content and state partition. + /// + /// # Safety + /// + /// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being read from + /// and written to. + pub fn from_config(config: FirmwareUpdaterConfig, aligned: &'d mut [u8]) -> Self { + Self::new(config.state, aligned) + } + /// Create a firmware state instance with a buffer for magic content and state partition. /// /// # Safety diff --git a/embassy-boot/boot/src/firmware_updater/blocking.rs b/embassy-boot/boot/src/firmware_updater/blocking.rs index ae4179ba3..4f56f152d 100644 --- a/embassy-boot/boot/src/firmware_updater/blocking.rs +++ b/embassy-boot/boot/src/firmware_updater/blocking.rs @@ -219,6 +219,16 @@ pub struct BlockingFirmwareState<'d, STATE> { } impl<'d, STATE: NorFlash> BlockingFirmwareState<'d, STATE> { + /// Creates a firmware state instance from a FirmwareUpdaterConfig, with a buffer for magic content and state partition. + /// + /// # Safety + /// + /// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being read from + /// and written to. + pub fn from_config(config: FirmwareUpdaterConfig, aligned: &'d mut [u8]) -> Self { + Self::new(config.state, aligned) + } + /// Create a firmware state instance with a buffer for magic content and state partition. /// /// # Safety diff --git a/embassy-boot/boot/src/lib.rs b/embassy-boot/boot/src/lib.rs index 451992945..15b69f69d 100644 --- a/embassy-boot/boot/src/lib.rs +++ b/embassy-boot/boot/src/lib.rs @@ -33,7 +33,7 @@ pub enum State { Boot, /// Bootloader has swapped the active partition with the dfu partition and will attempt boot. Swap, - /// Application has received a DFU_DETACH request over USB, and is rebooting into the bootloader to apply a DFU. + /// Application has received a request to reboot into DFU mode to apply an update. DfuDetach, } -- cgit From c1438fe87bf363b018231bd36e188c72679eb202 Mon Sep 17 00:00:00 2001 From: Kaitlyn Kenwell Date: Thu, 14 Dec 2023 09:38:02 -0500 Subject: fmt --- embassy-boot/boot/src/firmware_updater/blocking.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'embassy-boot') diff --git a/embassy-boot/boot/src/firmware_updater/blocking.rs b/embassy-boot/boot/src/firmware_updater/blocking.rs index 4f56f152d..c4c142169 100644 --- a/embassy-boot/boot/src/firmware_updater/blocking.rs +++ b/embassy-boot/boot/src/firmware_updater/blocking.rs @@ -220,9 +220,9 @@ pub struct BlockingFirmwareState<'d, STATE> { impl<'d, STATE: NorFlash> BlockingFirmwareState<'d, STATE> { /// Creates a firmware state instance from a FirmwareUpdaterConfig, with a buffer for magic content and state partition. - /// + /// /// # Safety - /// + /// /// The `aligned` buffer must have a size of STATE::WRITE_SIZE, and follow the alignment rules for the flash being read from /// and written to. pub fn from_config(config: FirmwareUpdaterConfig, aligned: &'d mut [u8]) -> Self { -- cgit