dfu-util requires -a X when flashing .dfu (DfuSE) files
Multiplatform USB DFU host utility
Brought to you by:
tormod
I thought that the DFU file format was meant to tell the flashing utility stuff like "the ALT port to use" and "The address to flash to".
So I created a DFU file, told it to use address 0x08000000, and when I dump it it says; "ALT 0". But when I try to program it, it sees the ALT0 (flash) and ALT1 (option bytes) as separate devices and requires me to sepecify -a 0 on the commandline. IMHO that is defeating the purpose of the DFU file format.
Anonymous
Defeating the purpose is maybe taking it too far, because the current behaviour still prevents users from mistakenly writing an image to the wrong memory device/partition, which is the most important about this feature. However from the view of convenience it could be nice if it automatically sets the correct alternate interface by itself. The reason it is like it currently is, is that dfu-util was not originally written for .dfu files (or DfuSe devices) and such support was added later. Allowing the DFU file to control which alternate interface to use will require more invasive changes. It can still be done, though!
Yes... I've been a dfu-util user since "before" the .dfu file format. I had a script that called dfu-util with the proper option to simply flash a binary. The current situation is a lot better as I can generate and test the .dfu file on Linux before passing it on the people using windows.
FYI: I don't agree with the label "doc" and I still think that an effort should be made to work towards the situation where something like dfu-util somefile.dfu simply does the right thing which is to flash the chip. I have less technical clients that may need to field-upgrade a board/module/system, so the less they have to type, the less that can go wrong.
But I don't have time to work on this, and probably you don't either....
The label "doc" means that this should be documented better, or pointed out clearer.
Yes, it is not a feature I intend to work on, but as they say, "patches are welcome" :)
I can only suggest a quick workaround by having a wrapper script extract the alternative interface values from the file (dfuse-pack.py can be of use) and run dfu-use with the values.
Diff:
Can someone test this patch? It should automatically set alternate interfaces and flash them for all images in the DfuSe file. It is of course important that the patch doesn't cause issues for other workflows.
Hello,
@tormod I build dfu-util with your patch applied. But it doesn't seem to do the trick. Dfu-util shows the message:
"More than one DFU capable USB device found! Try --list' and specify the serial number or disconnect all but one device",
even though the command was as following (with serial number specified):
dfu-util -s :leave -S "307637963237" -D file.DfuSe
:-)Thanks for testing! Can you please check what entries you have on the dfu_root chain, e.g. by debugger or printf's inside the while loop in dfuse_multiple_alt()?
Hello again, I was quite busy yesterday so I couldn't really check what was going on (and I'm still not really sure where the problem is). I'm able to download a Dfuse file to my device with the '-a 0' option in the commandline, but when I remove the alternate setting from commandline it seems to breaks. I think the last piece of the verbose log shows the most important information, like so:
As you can see the alternate seem to be set correct to alternate setting 0 ("Internal Flash"), shown as:
What seems to be out of order is "DfuSe interface name: "Device Feature", which is altSetting 3 in my case. This is supposed to be labeled as "Internal Flash" AFAICT.
I suspect that the parser (parse_memory_layout) is obtaining the wrong alternate settings from the interface description.
Perhaps because the interface description is in reverse order? The interface list from dfu-util looks like this:
When manually setting the alternate Setting, the output looks like this:
Hope this helps in finding the culprit. Maybe I can print some data later on (I have to go for today though).
Last edit: Tormod Volden 2020-10-14
It would have been good to see the dfu-util -l output for reference. No, scratch that, I see it now. What is this device?
It should not have printed "Multiple alternate interfaces for DfuSe file" when you specified alternate interface manually.
Last edit: Tormod Volden 2020-10-14
It's a custom PCB with a stm32F4 MCU and native USB where I'm working on :-)
People should be able to flash the firmware over USB and those files should match the board. DfuSe files have the VID/PID information (and more to verify) in the file to match the device with, which is the reason for using DfuSe files.
Here I printed the information from on top in the while loop in 'dfuse_multiple_alt()' as requested (the method returns 1/true when finished):
Good, thanks a lot. The logic seems to work correctly here, it detects a 1.1a file and that there is /one/ device with multiple alternate interfaces. However there seems to be another bug surfacing. The dfuse code was up to now always run having only one entry on the dfu_root list, now it has several, maybe that triggers a bug.
In this example (above), where you (presumably) have a DfuSe 1.1a file, and you have several alternate interfaces available (because the device has several and you are not filtering with -a) it should not complain about "More than one", unless there are other devices. I need to see what goes wrong in dfuse_multiple_alt(), possibly a typo or thinko that I am blind for.
Last edit: Tormod Volden 2020-10-14
Yes, that was my mistake, sorry for the misconception. Here I used the dfu-util in my environment path by accident (which is the default dfu-util v0.9) without the patch applied. That one returned the "More than one DFU capable USB device found! Try `--list`' and specify the serial number or disconnect all but one device" message. But in this case it actually should've given a message saying that I should specify an altSetting with '-a', because more than one alternate setting options are found in the same device interface, right?
Yes, you're right the wording is not precise in these cases, technically it is "More than one available alternate interfaces, possibly from multiple devices".
My "dfuse_multiple_alt()" could maybe be generalized and return "multipled devices" or "multiple configurations" or "multiple alternate interfaces" and so on, and then the message can be chosen based on this.
I had a new look at the code, seeing where the memory layout is parsed and used. It is all based on the assumption only one alternate interface is available. This would need a lot more rework, my patch is unfortunately far from complete. It would maybe do the right thing if you use the "force" modifier to ignore memory layout mismatch, but then without all the sanity checks.
Here is a new patch, which I only have tested with DfuSe files that have one image (thus one alternate interface) - this is what dfuse-pack.py currently is able to create.
Nice, that seems to be working well already!
The only log output to mention is probably this memory leakage at the end of the upload log, but the upload process seems to be working correct with a single image indeed.
Last edit: Hendry Kaak 2020-10-16
Thanks. Can you please also try a download with multiple images in one file?
I'll see what I can do. Perhaps I can write a few optional bytes for now to verify if dfu-util works with multiple images.
Last edit: Hendry Kaak 2020-10-19
@tormod
I did a couple of tests with the dfuse-pack.py script and it seems to work well if the alternateSetting is set with '@x'. The only con I saw when using this option is that people can still unknowingly enter 2 or more different '@x' parameters and depending on the sequence of the build parameters it will always pick the last alternateSetting in the command line as the alternateSetting for the whole target suffix (without warning the user). If this is the case, it should probably create a new target with different alternateSetting (but I know this is not implemented yet).
Further on I also tried to test downloading 2 images to a single alternate setting (flash memory). But for some reason I can't seem to download the second image to the specified address when the first build parameter of the packer script needs to be written at higher address than the other FSR, the first one seems to download just fine.
So let's say I create a DfuSe file with the following command:
This one ^^^ only downloads the firmware image to flash and not the "test2.bin", but the one below downloads both images as expected:
I made sure that the second image downloads some 0xDEADBEAF after the address index of the first complete firmware image, so they wouldn't overwrite one or another. Between each test I also mass-erased and checked the flash memory to make sure that nothing else is written.
Both the Dfuse files seem to be correct as well, when swapping the build parameters in the script both the images are swapped in the file, which is as expected (with correct addresses and image sizes).
I'll put the console output in text file in the attachments to prevent clogging this ticket too much :")
If I need to print some variables again, it's ok let me know.
Also a few remarks on the dfu-util output, I saw the following 2 lines in the output:
Looking at this can be a bit confusing, one could interpret both lines as the file image elements, but AFAICS the first output line is all about the amount of targets in the file read from the Dfuse Prefix right?
Maybe it's better to reword "file contains 1 DFU images" as "File contains x target(s)". And "parsing DFU image x" as "Parsing image element x" or even better would be to display the current target index with the image element that is being parsed at the time as in "Parsing image element x from target x".
Thanks :-)
Console output of the download that went well.
This should be implemented already. Maybe I don't understand the description. It is confusing because the terminology in dfuse-pack.py does not match ST's document 100%.
If your image elements are listed with alternate interface numbers in e.g. the order @1 @1 @2 it will make a DfuSe file with two DFU images, the first having two image elements. If the order is @1 @2 @1 you will get three DFU images.
The word "target" is only used internally in the script code. I think formally none of the parts of a DfuSe file is a "target", but each "DFU image" part has a target attribute, specifying for which alternate interface it is targeted.
EDIT: Yes, displaying the target (alternate interface) number for each DFU image would make sense.
Last edit: Tormod Volden 2020-10-21