aboutsummaryrefslogtreecommitdiff
path: root/embassy-boot
diff options
context:
space:
mode:
authorKaitlyn Kenwell <[email protected]>2023-12-13 14:40:49 -0500
committerKaitlyn Kenwell <[email protected]>2023-12-13 14:40:49 -0500
commit976a7ae22aa222213861c12d515115aac87bd2e0 (patch)
tree88f802c7d57df011c02142ef309ff5cffe8bd3b0 /embassy-boot
parent14f41a71b6ea9dedb4ee5b9c741fe10575772c7d (diff)
Add embassy-usb-dfu
Diffstat (limited to 'embassy-boot')
-rw-r--r--embassy-boot/boot/src/boot_loader.rs4
-rw-r--r--embassy-boot/boot/src/firmware_updater/asynch.rs13
-rw-r--r--embassy-boot/boot/src/firmware_updater/blocking.rs17
-rw-r--r--embassy-boot/boot/src/lib.rs3
-rw-r--r--embassy-boot/stm32/src/lib.rs9
5 files changed, 39 insertions, 7 deletions
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;
5use embassy_sync::blocking_mutex::Mutex; 5use embassy_sync::blocking_mutex::Mutex;
6use embedded_storage::nor_flash::{NorFlash, NorFlashError, NorFlashErrorKind}; 6use embedded_storage::nor_flash::{NorFlash, NorFlashError, NorFlashErrorKind};
7 7
8use crate::{State, BOOT_MAGIC, STATE_ERASE_VALUE, SWAP_MAGIC}; 8use crate::{State, BOOT_MAGIC, STATE_ERASE_VALUE, SWAP_MAGIC, DFU_DETACH_MAGIC};
9 9
10/// Errors returned by bootloader 10/// Errors returned by bootloader
11#[derive(PartialEq, Eq, Debug)] 11#[derive(PartialEq, Eq, Debug)]
@@ -384,6 +384,8 @@ impl<ACTIVE: NorFlash, DFU: NorFlash, STATE: NorFlash> BootLoader<ACTIVE, DFU, S
384 384
385 if !state_word.iter().any(|&b| b != SWAP_MAGIC) { 385 if !state_word.iter().any(|&b| b != SWAP_MAGIC) {
386 Ok(State::Swap) 386 Ok(State::Swap)
387 } else if !state_word.iter().any(|&b| b != DFU_DETACH_MAGIC) {
388 Ok(State::DfuDetach)
387 } else { 389 } else {
388 Ok(State::Boot) 390 Ok(State::Boot)
389 } 391 }
diff --git a/embassy-boot/boot/src/firmware_updater/asynch.rs b/embassy-boot/boot/src/firmware_updater/asynch.rs
index ae713bb6f..0a3cbc136 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;
6use embedded_storage_async::nor_flash::NorFlash; 6use embedded_storage_async::nor_flash::NorFlash;
7 7
8use super::FirmwareUpdaterConfig; 8use super::FirmwareUpdaterConfig;
9use crate::{FirmwareUpdaterError, State, BOOT_MAGIC, STATE_ERASE_VALUE, SWAP_MAGIC}; 9use crate::{FirmwareUpdaterError, State, BOOT_MAGIC, STATE_ERASE_VALUE, SWAP_MAGIC, DFU_DETACH_MAGIC};
10 10
11/// FirmwareUpdater is an application API for interacting with the BootLoader without the ability to 11/// FirmwareUpdater is an application API for interacting with the BootLoader without the ability to
12/// 'mess up' the internal bootloader state 12/// 'mess up' the internal bootloader state
@@ -161,6 +161,12 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<'d, DFU, STATE> {
161 self.state.mark_updated().await 161 self.state.mark_updated().await
162 } 162 }
163 163
164 /// Mark to trigger USB DFU on next boot.
165 pub async fn mark_dfu(&mut self) -> Result<(), FirmwareUpdaterError> {
166 self.state.verify_booted().await?;
167 self.state.mark_dfu().await
168 }
169
164 /// Mark firmware boot successful and stop rollback on reset. 170 /// Mark firmware boot successful and stop rollback on reset.
165 pub async fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> { 171 pub async fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> {
166 self.state.mark_booted().await 172 self.state.mark_booted().await
@@ -247,6 +253,11 @@ impl<'d, STATE: NorFlash> FirmwareState<'d, STATE> {
247 self.set_magic(SWAP_MAGIC).await 253 self.set_magic(SWAP_MAGIC).await
248 } 254 }
249 255
256 /// Mark to trigger USB DFU on next boot.
257 pub async fn mark_dfu(&mut self) -> Result<(), FirmwareUpdaterError> {
258 self.set_magic(DFU_DETACH_MAGIC).await
259 }
260
250 /// Mark firmware boot successful and stop rollback on reset. 261 /// Mark firmware boot successful and stop rollback on reset.
251 pub async fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> { 262 pub async fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> {
252 self.set_magic(BOOT_MAGIC).await 263 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;
6use embedded_storage::nor_flash::NorFlash; 6use embedded_storage::nor_flash::NorFlash;
7 7
8use super::FirmwareUpdaterConfig; 8use super::FirmwareUpdaterConfig;
9use crate::{FirmwareUpdaterError, State, BOOT_MAGIC, STATE_ERASE_VALUE, SWAP_MAGIC}; 9use crate::{FirmwareUpdaterError, State, BOOT_MAGIC, STATE_ERASE_VALUE, SWAP_MAGIC, DFU_DETACH_MAGIC};
10 10
11/// Blocking FirmwareUpdater is an application API for interacting with the BootLoader without the ability to 11/// Blocking FirmwareUpdater is an application API for interacting with the BootLoader without the ability to
12/// 'mess up' the internal bootloader state 12/// 'mess up' the internal bootloader state
@@ -168,6 +168,12 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<'d, DFU, STATE>
168 self.state.mark_updated() 168 self.state.mark_updated()
169 } 169 }
170 170
171 /// Mark to trigger USB DFU device on next boot.
172 pub fn mark_dfu(&mut self) -> Result<(), FirmwareUpdaterError> {
173 self.state.verify_booted()?;
174 self.state.mark_dfu()
175 }
176
171 /// Mark firmware boot successful and stop rollback on reset. 177 /// Mark firmware boot successful and stop rollback on reset.
172 pub fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> { 178 pub fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> {
173 self.state.mark_booted() 179 self.state.mark_booted()
@@ -226,7 +232,7 @@ impl<'d, STATE: NorFlash> BlockingFirmwareState<'d, STATE> {
226 232
227 // Make sure we are running a booted firmware to avoid reverting to a bad state. 233 // Make sure we are running a booted firmware to avoid reverting to a bad state.
228 fn verify_booted(&mut self) -> Result<(), FirmwareUpdaterError> { 234 fn verify_booted(&mut self) -> Result<(), FirmwareUpdaterError> {
229 if self.get_state()? == State::Boot { 235 if self.get_state()? == State::Boot || self.get_state()? == State::DfuDetach {
230 Ok(()) 236 Ok(())
231 } else { 237 } else {
232 Err(FirmwareUpdaterError::BadState) 238 Err(FirmwareUpdaterError::BadState)
@@ -243,6 +249,8 @@ impl<'d, STATE: NorFlash> BlockingFirmwareState<'d, STATE> {
243 249
244 if !self.aligned.iter().any(|&b| b != SWAP_MAGIC) { 250 if !self.aligned.iter().any(|&b| b != SWAP_MAGIC) {
245 Ok(State::Swap) 251 Ok(State::Swap)
252 } else if !self.aligned.iter().any(|&b| b != DFU_DETACH_MAGIC) {
253 Ok(State::DfuDetach)
246 } else { 254 } else {
247 Ok(State::Boot) 255 Ok(State::Boot)
248 } 256 }
@@ -253,6 +261,11 @@ impl<'d, STATE: NorFlash> BlockingFirmwareState<'d, STATE> {
253 self.set_magic(SWAP_MAGIC) 261 self.set_magic(SWAP_MAGIC)
254 } 262 }
255 263
264 /// Mark to trigger USB DFU on next boot.
265 pub fn mark_dfu(&mut self) -> Result<(), FirmwareUpdaterError> {
266 self.set_magic(DFU_DETACH_MAGIC)
267 }
268
256 /// Mark firmware boot successful and stop rollback on reset. 269 /// Mark firmware boot successful and stop rollback on reset.
257 pub fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> { 270 pub fn mark_booted(&mut self) -> Result<(), FirmwareUpdaterError> {
258 self.set_magic(BOOT_MAGIC) 271 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::{
23 23
24pub(crate) const BOOT_MAGIC: u8 = 0xD0; 24pub(crate) const BOOT_MAGIC: u8 = 0xD0;
25pub(crate) const SWAP_MAGIC: u8 = 0xF0; 25pub(crate) const SWAP_MAGIC: u8 = 0xF0;
26pub(crate) const DFU_DETACH_MAGIC: u8 = 0xE0;
26 27
27/// The state of the bootloader after running prepare. 28/// The state of the bootloader after running prepare.
28#[derive(PartialEq, Eq, Debug)] 29#[derive(PartialEq, Eq, Debug)]
@@ -32,6 +33,8 @@ pub enum State {
32 Boot, 33 Boot,
33 /// Bootloader has swapped the active partition with the dfu partition and will attempt boot. 34 /// Bootloader has swapped the active partition with the dfu partition and will attempt boot.
34 Swap, 35 Swap,
36 /// Application has received a DFU_DETACH request over USB, and is rebooting into the bootloader to apply a DFU.
37 DfuDetach,
35} 38}
36 39
37/// Buffer aligned to 32 byte boundary, largest known alignment requirement for embassy-boot. 40/// 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::{
10use embedded_storage::nor_flash::NorFlash; 10use embedded_storage::nor_flash::NorFlash;
11 11
12/// A bootloader for STM32 devices. 12/// A bootloader for STM32 devices.
13pub struct BootLoader; 13pub struct BootLoader {
14 /// The reported state of the bootloader after preparing for boot
15 pub state: State,
16}
14 17
15impl BootLoader { 18impl BootLoader {
16 /// Inspect the bootloader state and perform actions required before booting, such as swapping firmware 19 /// Inspect the bootloader state and perform actions required before booting, such as swapping firmware
@@ -19,8 +22,8 @@ impl BootLoader {
19 ) -> Self { 22 ) -> Self {
20 let mut aligned_buf = AlignedBuffer([0; BUFFER_SIZE]); 23 let mut aligned_buf = AlignedBuffer([0; BUFFER_SIZE]);
21 let mut boot = embassy_boot::BootLoader::new(config); 24 let mut boot = embassy_boot::BootLoader::new(config);
22 boot.prepare_boot(aligned_buf.as_mut()).expect("Boot prepare error"); 25 let state = boot.prepare_boot(aligned_buf.as_mut()).expect("Boot prepare error");
23 Self 26 Self { state }
24 } 27 }
25 28
26 /// Boots the application. 29 /// Boots the application.