aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Lilleengen <[email protected]>2025-04-30 12:17:43 +0200
committerGitHub <[email protected]>2025-04-30 12:17:43 +0200
commite68713e9afa629eee9a04d9a1e68393f4fe242d8 (patch)
treedf27a37db5cc18d1dfeb5ec57cf7bbf2bb8bb489
parent5f0196cb29be2edd2de300f8a42a031062441f1a (diff)
parent3c9661cebc0f093d8d9a194adca2d1c815ebfd2e (diff)
Merge pull request #4120 from Gerharddc/dfu-app
[embassy-usb-dfu] Add generic DFU marking interface
-rw-r--r--embassy-usb-dfu/src/application.rs36
1 files changed, 25 insertions, 11 deletions
diff --git a/embassy-usb-dfu/src/application.rs b/embassy-usb-dfu/src/application.rs
index f0d7626f6..e93c241ad 100644
--- a/embassy-usb-dfu/src/application.rs
+++ b/embassy-usb-dfu/src/application.rs
@@ -13,9 +13,25 @@ use crate::consts::{
13}; 13};
14use crate::Reset; 14use crate::Reset;
15 15
16/// Generic interface for a system that can signal to the bootloader that USB DFU mode is needed on the next boot.
17///
18/// By default this trait is implemented for `BlockingFirmwareState<'d, STATE>` but you could also implement this generic
19/// interface yourself instead in more complex situations. This could for instance be when you cannot hand ownership of a
20/// `BlockingFirmwareState` instance over directly to the DFU `Control` instance and need to use a more complex mechanism.
21pub trait DfuMarker {
22 /// Signal to the bootloader that DFU mode should be used on the next boot.
23 fn mark_dfu(&mut self);
24}
25
26impl<'d, STATE: NorFlash> DfuMarker for BlockingFirmwareState<'d, STATE> {
27 fn mark_dfu(&mut self) {
28 self.mark_dfu().expect("Failed to mark DFU mode in bootloader")
29 }
30}
31
16/// Internal state for the DFU class 32/// Internal state for the DFU class
17pub struct Control<'d, STATE: NorFlash, RST: Reset> { 33pub struct Control<MARK: DfuMarker, RST: Reset> {
18 firmware_state: BlockingFirmwareState<'d, STATE>, 34 dfu_marker: MARK,
19 attrs: DfuAttributes, 35 attrs: DfuAttributes,
20 state: State, 36 state: State,
21 timeout: Option<Duration>, 37 timeout: Option<Duration>,
@@ -23,11 +39,11 @@ pub struct Control<'d, STATE: NorFlash, RST: Reset> {
23 _rst: PhantomData<RST>, 39 _rst: PhantomData<RST>,
24} 40}
25 41
26impl<'d, STATE: NorFlash, RST: Reset> Control<'d, STATE, RST> { 42impl<MARK: DfuMarker, RST: Reset> Control<MARK, RST> {
27 /// Create a new DFU instance to expose a DFU interface. 43 /// Create a new DFU instance to expose a DFU interface.
28 pub fn new(firmware_state: BlockingFirmwareState<'d, STATE>, attrs: DfuAttributes) -> Self { 44 pub fn new(dfu_marker: MARK, attrs: DfuAttributes) -> Self {
29 Control { 45 Control {
30 firmware_state, 46 dfu_marker,
31 attrs, 47 attrs,
32 state: State::AppIdle, 48 state: State::AppIdle,
33 detach_start: None, 49 detach_start: None,
@@ -37,7 +53,7 @@ impl<'d, STATE: NorFlash, RST: Reset> Control<'d, STATE, RST> {
37 } 53 }
38} 54}
39 55
40impl<'d, STATE: NorFlash, RST: Reset> Handler for Control<'d, STATE, RST> { 56impl<MARK: DfuMarker, RST: Reset> Handler for Control<MARK, RST> {
41 fn reset(&mut self) { 57 fn reset(&mut self) {
42 if let Some(start) = self.detach_start { 58 if let Some(start) = self.detach_start {
43 let delta = Instant::now() - start; 59 let delta = Instant::now() - start;
@@ -48,9 +64,7 @@ impl<'d, STATE: NorFlash, RST: Reset> Handler for Control<'d, STATE, RST> {
48 timeout.as_millis() 64 timeout.as_millis()
49 ); 65 );
50 if delta < timeout { 66 if delta < timeout {
51 self.firmware_state 67 self.dfu_marker.mark_dfu();
52 .mark_dfu()
53 .expect("Failed to mark DFU mode in bootloader");
54 RST::sys_reset() 68 RST::sys_reset()
55 } 69 }
56 } 70 }
@@ -109,9 +123,9 @@ impl<'d, STATE: NorFlash, RST: Reset> Handler for Control<'d, STATE, RST> {
109/// it should expose a DFU device, and a software reset will be issued. 123/// it should expose a DFU device, and a software reset will be issued.
110/// 124///
111/// To apply USB DFU updates, the bootloader must be capable of recognizing the DFU magic and exposing a device to handle the full DFU transaction with the host. 125/// To apply USB DFU updates, the bootloader must be capable of recognizing the DFU magic and exposing a device to handle the full DFU transaction with the host.
112pub fn usb_dfu<'d, D: Driver<'d>, STATE: NorFlash, RST: Reset>( 126pub fn usb_dfu<'d, D: Driver<'d>, MARK: DfuMarker, RST: Reset>(
113 builder: &mut Builder<'d, D>, 127 builder: &mut Builder<'d, D>,
114 handler: &'d mut Control<'d, STATE, RST>, 128 handler: &'d mut Control<MARK, RST>,
115 timeout: Duration, 129 timeout: Duration,
116) { 130) {
117 let mut func = builder.function(0x00, 0x00, 0x00); 131 let mut func = builder.function(0x00, 0x00, 0x00);