-
Notifications
You must be signed in to change notification settings - Fork 935
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(boot): enhance firmware write functionality #2543
feat(boot): enhance firmware write functionality #2543
Conversation
embassy-usb-dfu/src/dfu.rs
Outdated
@@ -60,6 +60,21 @@ impl<'d, DFU: NorFlash, STATE: NorFlash, RST: Reset, const BLOCK_SIZE: usize> Ha | |||
} | |||
Ok(Request::Dnload) if self.attrs.contains(DfuAttributes::CAN_DOWNLOAD) => { | |||
if req.value == 0 { | |||
match self.updater.prepare_update() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think rather than introducing write_firmware_without_erase API, you should use the flash borrow returned from prepare_update to do the writing. Or is there something preventing that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was the first thing I tried, but I struggled with lifetimes. It was especially tricky when I had both a BootLoader
and a BlockingFirmwareUpdater
instances in different scopes of the bootloader. For example, if the bootloader starts and it detects that a specific button is pressed, it sets State::DfuDetach
and begins a USB DFU update.
I agree that the proposed API here isn't great though.
I think this can be fixed without extending (and therefore complicating) the FirmwareUpdater public API. The issue is For example, when having 4kb pages and writing 1kb chunks:
if written properly, this'd allow chunks to span across pages even. So the only requirement for chunk size is to be a multiple of WRITE_SIZE, but not necessarily a divisor of ERASE_SIZE. For example, with 4kb pages writing 2.5kb chunks:
Advantages:
|
@Dirbaio I like your suggestion! Let me give it a shot. |
I've implemented the mechanism suggested by @Dirbaio. Let me know what you think. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good, left one comment. And thanks for adding tests!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! I will give the async version a spin before merging.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Confirmed it works on nrf with async, thanks for the contribution! 🚀
This PR modifies the firmware update process via USB DFU, enhancing compatibility with high-capacity microcontrollers by optimizing how firmware images are received from a host.
Instead of erasing flash pages for each received chunk, which is not feasible for microcontrollers with large erase sizes like the STM32H747XI, we now erase the entire DFU partition upfront and sequentially write incoming chunks without further erasures.
This approach resolves compatibility issues with microcontrollers where the erase block size exceeds the USB control buffer capacity, which is often limited to 4KB. Such a mismatch makes it impossible to efficiently manage page erasures for each chunk received, as required by the standard USB DFU protocol which does not communicate the total number of chunks or their target addresses in advance (such mechanism is supported in DfuSe).
By introducing a
write_firmware_without_erase
method, used in conjunction withprepare_update
, this PR allows for a more efficient firmware update process.This method aligns with the third mechanism outlined in the USB DFU v1.1 spec, where a significant portion of memory is pre-erased, and firmware chunks are written into the prepared space without additional erasures.