-
Notifications
You must be signed in to change notification settings - Fork 2k
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
usbus/dfu: add Device Firmware Upgrade support for USBUS (2nd attempt) #15460
Conversation
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.
Some initial comments because of the flashpage rename.
95cc041
to
4fceb34
Compare
rebase and push a fixup at the same time to reflect lastest changes in the flashpage API. |
Update this PR to use riotboot/flashwrite instead of periph_flashpage. |
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 pretty straightforward.
Would be nice to have the flash process integrated into the build system, so make PROGRAMMER=dfu-util flash
flash works instead of having to manually invoke dfu-util
.
I tried to flash a third firmware:
APP_VER=5 BOARD=same54-xpro USEMODULE=usbus_dfu make -C tests/usbus_cdc_acm_stdio riotboot/slot
sudo dfu-util -a 0 -R -D tests/usbus_cdc_acm_stdio/bin/same54-xpro/tests_usbus_cdc_acm_stdio-slot0.bin
However, this didn't seem to work - the firmware in slot 1 is always booted.
Also, do we always have to flash alternating slots?
It's seems like I can't flash into slot 1 when the last firmware is running from slot1, but that shouldn't matter for riotboot.
It's also a bit strange that the user has to take care about the firmware version - shouldn't the firmware that was flashed by the user always be booted, not matter what version the previously installed firmware had?
for (unsigned i = 0; i < riotboot_slot_numof; i++) { | ||
const riotboot_hdr_t *riot_hdr = riotboot_slot_get_hdr(i); | ||
if (riotboot_slot_validate(i)) { | ||
/* skip slot if metadata broken */ | ||
continue; | ||
} | ||
if (riot_hdr->start_addr != riotboot_slot_get_image_startaddr(i)) { | ||
continue; | ||
} | ||
if (slot == -1 || riot_hdr->version > version) { | ||
version = riot_hdr->version; | ||
slot = i; | ||
} | ||
} |
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.
Should we also be able to use 'raw' images (without a riotboot header) when not using the riotboot_slot
module?
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.
In theory, if there is no slot, we could flash the firmware right after the bootloader. The main issue I have with this now: If something is wrong with the firmware resulting in a unbootable app. We will have no way to retrigger the bootloader DFU as it is called by dfu-utils
if it find a device declaring a dfu application interface. If the application doesn't boot, this interface will not exist.
Hopefully, we can add other way to trigger the bootloader DFU: douple-tap reset, GPIO state at boottime, etc. But I like to keep this for another PR.
ifneq (,$(filter usbus_dfu,$(USEMODULE))) | ||
CFLAGS += -DCPU_RAM_BASE=$(RAM_START_ADDR) | ||
CFLAGS += -DCPU_RAM_SIZE=$(RAM_LEN) | ||
endif |
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 wonder if we should set this unconditionally
I didn't implement it yet because I'm not that familiar with RIOT build system. I can add it here now or in another PR later (I prefer the latter :) )
I'll look into this. This is not a normal behavior.
Indeed, but since there is no way to tell which slot or address we want to flash with dfu-utils (and DFU 1.1 spec) I had to take a decision about the slot selection. Basically, we let riotboot check which slot SHOULD start and we flash the other slot available with the newer firmware.
I'll rework it when I'll integrate dfu-utils to the build system. |
I read the DFU spec 1.1 once again. I think I have found the missing piece of the puzzle. I'll come up with a better solution in a couple of days. |
16932eb
to
fcec827
Compare
Force push the branch.
|
I managed to get this working on the nrf52840dk by modifying the advertised transaction size to 64 B. The length field in the setup requests during download indicates the full length of the transaction, not the per-request chunk size, so my nrf52840dk thought there was 4KB data ready to write to the flash after a single setup request. |
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.
Tested this on the nrf52840dk, works fine as long as the binaries transferred are compiled for the nrf52840dk and not for the samr21-xpro 😇
Give it a try on Windows 10 using dfu-util win64 binary. Works as expected after installing winusb driver for the board with Zadig tool. |
c21ac97
to
4c2922c
Compare
CI still has some complaints 😉 |
I'll fix them with the next round of comments. |
4c2922c
to
a95267b
Compare
Forced push and squashed to fix CI complaints ! |
a95267b
to
56ca22c
Compare
56ca22c
to
7c30a8d
Compare
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.
One minor nit remaining, feel free to squash immediately
8d3bf95
to
7fc5bb4
Compare
Squashed and rebased to fix conflict introduced by #14629 |
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.
All green! Go!
Contribution description
This is the second attempt to add Device Firmware Upgrade (DFU) support to USBUS and thus replace #13856
This PR provides the same features from the previous one but with the following additions/changes:
no_idle_thread
feature is now needed by riotboot bootloader when DFU is usedxtimer
is required for the bootloaderdfu-util
integration to RIOT buildsystem usingmake riotboot/flash-slotX
Currently, the DFU bootloader mode is triggered by
dfu_utils
only and riotboot checks the last 4-bytes of RAM for a magic word to enter in DFU mode (otherwise we skip it)Of course, other mechanisms could be implement in follow-up PRs.
This PR was tested with SAME54-XPRO and a Linux host machine. It would be great to test on nRF52 and STM32 but I don't own such hardware.
Note: periph_flashpage must be supported by your MCU to use DFU.
Testing procedure
Consider erasing the whole flash before starting.
#FLASH RIOTBOOT BOOTLOADER
USEMODULE=riotboot_usb_dfu BOARD=same54-xpro make -C bootloaders/riotboot_dfu flash
You can now flash any test app you want on riotboot slot0 or slot1 with the following command:
USB_VID=1209 USB_PID=7d01 DFU_ALT=0 USEMODULE=usbus_dfu PROGRAMMER=dfu-util make BOARD=same54-xpro -C tests/leds riotboot/flash-slot0
to flash slot1, please modify the DFU_ALT to 1 and use riotboot/flash-slot1
Slot selection is now made through the alt settings selection
you can use
dfu-util --list
so you'll get in runtime mode:
and DFU mode:
Issues/PRs references
Replaces #13856
Required #15555 #15565 #15566