STSTM32 - Could not find the package with 'platformio/tool-dfuutil @ ~1.9.190708' requirements for your system 'linux_aarch64'

Hi, I’m trying to compile and upload a firmware for a Arduino Portenta H7, but I’m getting an error because of a missing package.

This is is somewhat similar to another issue I raised (Error getting toolchain-gccarmnoneeabi on Raspberry PI 4 for platform Atmelsam).

Would someone have an alternative version I could use on a Raspberry Pi 4 running Ubuntu 20.04 ?

(in the spirit of teaching a man to fish rather than feeding him a fish daily, where could I look myself for the available versions of these packages ?)

Many thanks in advance.

As answered in Make package registry searchable in the CLI or GUI · Issue #3836 · platformio/platformio-core · GitHub. Usually with API requests like https://api.registry.platformio.org/v3/packages/platformio/tool/toolchain-gccarmnoneeabi, replacing toolchain-gccarmnoneeabi with the needed tool name. So in your case https://api.registry.platformio.org/v3/packages/platformio/tool/tool-dfuutil.

A general explanation of PlatformIO packages is at the official docs and here.

You can compile it yourself as a fallback, then the devs can upload your package. The general gist is:

  1. Find out where the sources for a package live
  2. Compile it (install depenendencies, make and make install ...)
  3. package it
    3.1. write package.json
    3.2. use pio package pack to generate the archive file

Let’s go through the steps together. We know tool-dfuutil is missing for the linux_aarch64 (ARM64) system. For a Linux system it’s always a good idea to look at the package for other Linux systems for the same version (~1.9.190708 is a SemVer expression matching the latest “1.9.x” version). Using the API link above, we can see

So we grab that and extract that to have a look. We see…

grafik

grafik

grafik

etc.

So, where do we find where can compile that ourselves? Look at the contained package.json. It says

{
  "name": "tool-dfuutil",
  "version": "1.9.190708",
  "description": "Device Firmware Upgrade Utilities",
  "keywords": [
    "tools",
    "uploader"
  ],
  "homepage": "http://dfu-util.sourceforge.net/",
  "license": "GPL-2.0-or-later",
  "system": [
    "linux_armv6l",
    "linux_armv7l",
    "linux_armv8l"
  ],
  "repository": {
    "type": "git",
    "url": "https://sourceforge.net/p/dfu-util/dfu-util/ci/master/tree/"
  }
}

So there it clearly shows the repo for the package being dfu-util / Code / [7e1fc9].

So, we go there and take a look at the available version. PIO says, through the version encoding “1.9.190708”, that the package has version “0.0.9” (from SemVer “9”), Datecode 190708= 2019-July-8th. We want to get something close to that. We can also execute the original Linux (or Windows) binary and ask it for its version

C:\Users\Max\.platformio\packages\tool-dfuutil\bin>dfu-util --version
dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2020 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

So then, one might be compelled to use the repo with their tag “v0.9” (dfu-util / Code / [1d2bec]) to get version 0.9, the last source change from there being in 2016. I however vaguely remember some people having problems with this old DFU-util version in other platforms. Since it’s however that’s what PlatformIO is using, we’ll go with that. Feel free to compile from a newer dfu-util if you like.

So, on a system capable of compiling for AArch64 (aka your Raspberry Pi), we can start trying to copile dfu-util. The repository website already says we can clone the repo by doing

git clone https://git.code.sf.net/p/dfu-util/dfu-util dfu-util-dfu-util

(which will clone it in a folder named dfu-util-dfu-util in an author-projectname style).

After doing a sudo apt install git to get git as an available command in the first place, I execute the above command on my Pi (running on a 32-bit Raspbian system, just for demonstration…), and I get the dfu-util-dfu-util folder.

We still have to checkout the correct tag from the repo. So I

cd dfu-util-dfu-util
git checkout v0.9

which says HEAD is now at 1d2bec5 Release 0.9. Great.

How do we compile? We follow their instructions.

You will however notice that we’re missing some dependencies for even the first step, doing

pi@raspberrypi:~/dfu-util-dfu-util $ ./autogen.sh
./autogen.sh: 2: ./autogen.sh: autoreconf: not found

since I’m not having any build tools installed. A quick googling shows the missing package can be installed via sudo apt install autoconf. I also install the build-essentials package to make sure I have a basic compiler. After that

pi@raspberrypi:~/dfu-util-dfu-util $ ./autogen.sh
autoreconf: Entering directory `.'
autoreconf: configure.ac: not using Gettext
autoreconf: running: aclocal
autoreconf: configure.ac: tracing
autoreconf: configure.ac: creating directory m4
autoreconf: configure.ac: not using Libtool
autoreconf: running: /usr/bin/autoconf
autoreconf: running: /usr/bin/autoheader
autoreconf: running: automake --add-missing --copy --no-force
configure.ac:14: installing 'm4/compile'
configure.ac:7: installing 'm4/install-sh'
configure.ac:7: installing 'm4/missing'
src/Makefile.am: installing 'm4/depcomp'
autoreconf: Leaving directory `.'

the output looks better. The next step in their INSTALL guide says to

pi@raspberrypi:~/dfu-util-dfu-util $ ./configure
autoreconf: Entering directory `.'
[...]
checking pkg-config is at least version 0.9.0... yes
checking for USB... no
configure: error: *** Required libusb-1.0 >= 1.0.0 not installed ***

which leads us to the next missing dependency, libusb-1.0. After doing a quick search via sudo apt search libusb-1.0 we get that we need the libusb-1.0-0-dev (development package) to compile stuff for LibUSB-1.0. So, one sudo apt install libusb-1.0-0-dev later and rerunning the command…

pi@raspberrypi:~/dfu-util-dfu-util $ ./configure
[...]
config.status: creating Makefile
config.status: creating src/Makefile
config.status: creating doc/Makefile
config.status: creating config.h
config.status: executing depfiles commands

And that has now created the Makefiles successfully. So, we follow next command (make) but take the liberty to add -j4 to it, to make compilation multi-threaded on 4 cores.

It should quickly end in

  CCLD     dfu-util
  CCLD     dfu-suffix
  CCLD     dfu-prefix
make[2]: Leaving directory '/home/pi/dfu-util-dfu-util/src'
Making all in doc
make[2]: Entering directory '/home/pi/dfu-util-dfu-util/doc'
make[2]: Nothing to be done for 'all'.
make[2]: Leaving directory '/home/pi/dfu-util-dfu-util/doc'
make[2]: Entering directory '/home/pi/dfu-util-dfu-util'
make[2]: Leaving directory '/home/pi/dfu-util-dfu-util'
make[1]: Leaving directory '/home/pi/dfu-util-dfu-util'

showing that the needed binaries have been created in some build output folders.

Now we want to install the package to a specific folder so that we get the same nice bin/, lib/, share/ folder structure we saw in the reference Linux package, we don’t want to hand-pick the needed binaries and libraries.

One could now do the next step in the guide, (sudo) make install, but that will install the system package-wide. We don’t want that, we want to just copy the package to a specific folder. So we use the DESTDIR option for make to specify a destination directory, a new folder which we create.

pi@raspberrypi:~/dfu-util-dfu-util $ mkdir installed
pi@raspberrypi:~/dfu-util-dfu-util $ make DESTDIR=$(pwd)/installed install
[..]
make[1]: Leaving directory '/home/pi/dfu-util-dfu-util'

If I look into the newly cleared installed directory with the tree command…

pi@raspberrypi:~/dfu-util-dfu-util $ tree installed/
installed/
└── usr
    └── local
        ├── bin
        │   ├── dfu-prefix
        │   ├── dfu-suffix
        │   └── dfu-util
        └── share
            └── man
                └── man1
                    └── dfu-util.1

We get almost the needed folder structure. It did not generate the lib/ folder with

grafik

in it that the reference package had – and to be honest, I don’t think that’s even necessary. But for consistency, we will copy in those files too.

By going into the installed/usr/local/bin directory and using the loader (ldd) to show us where all the loaded libraries come from, we see

pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local/bin $ ldd dfu-util
        linux-vdso.so.1 (0x7eff7000)
        /usr/lib/arm-linux-gnueabihf/libarmmem-${PLATFORM}.so => /usr/lib/arm-linux-gnueabihf/libarmmem-v7l.so (0x76ec1000)
        libusb-1.0.so.0 => /lib/arm-linux-gnueabihf/libusb-1.0.so.0 (0x76e9c000)
        ..

where we need to copy the file from. So we create the lib/ directory, copy in that file, which is a symbolic link to

$ ls -l /lib/arm-linux-gnueabihf/libusb-1.0.so.0
lrwxrwxrwx 1 root root 19 May  5  2018 /lib/arm-linux-gnueabihf/libusb-1.0.so.0 -> libusb-1.0.so.0.1.0

and also recreate the symbolic link from libusb-1.0.so.0 to libusb-1.0.so.0.1.0.

pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local $ mkdir lib
pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local $ cd lib
pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local/lib $ cp /lib/arm-linux-gnueabihf/libusb-1.0.so.0.1.0  .
pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local/lib $ ln -s libusb-1.0.so.0.1.0 libusb-1.0.so.0
pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local/lib $ ls -la
total 92
drwxr-xr-x 2 pi pi  4096 Oct 20 13:11 .
drwxr-xr-x 5 pi pi  4096 Oct 20 13:10 ..
lrwxrwxrwx 1 pi pi    19 Oct 20 13:11 libusb-1.0.so.0 -> libusb-1.0.so.0.1.0
-rw-r--r-- 1 pi pi 83828 Oct 20 13:10 libusb-1.0.so.0.1.0

And while we’re there it’s also good to do a quick sanity check that the binary is actually working…

pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local/bin $ ./dfu-util --version
dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

which it does, and it outputs the correct version as before.

Now we have the nice

pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local $ tree
.
├── bin
│   ├── dfu-prefix
│   ├── dfu-suffix
│   └── dfu-util
├── lib
│   ├── libusb-1.0.so.0 -> libusb-1.0.so.0.1.0
│   └── libusb-1.0.so.0.1.0
└── share
    └── man
        └── man1
            └── dfu-util.1

package folder. It’s missing however the package.json in the root of the package.

So to fix that, we copy in the original package.json from the reference Linux ARMv6L package then adjust the systems array to declare compatibility for the needed linux_aarch64 architecture (that info comes from the error message), and we also update the version field to reflect the build date. So end up having this package.json

{
  "name": "tool-dfuutil",
  "version": "1.9.211020",
  "description": "Device Firmware Upgrade Utilities",
  "keywords": [
    "tools",
    "uploader"
  ],
  "homepage": "http://dfu-util.sourceforge.net/",
  "license": "GPL-2.0-or-later",
  "system": [
    "linux_aarch64"
  ],
  "repository": {
    "type": "git",
    "url": "https://sourceforge.net/p/dfu-util/dfu-util/ci/master/tree/"
  }
}

saved in ~/dfu-util-dfu-util/installed/usr/local. (I just nano package.json at the appropriate place and copy-paste in the file contents.)

We can now finally create the PlatformIO package using

pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local $ pio package pack
Wrote a tarball to "/home/pi/dfu-util-dfu-util/installed/usr/local/tool-dfuutil-linux_aarch64-1.9.211020.tar.gz"

And that is the needed tarball. For convenience I also copy it my home folder

pi@raspberrypi:~/dfu-util-dfu-util/installed/usr/local $ cp tool-dfuutil-linux_aarch64-1.9.211020.tar.gz ~/.

So if I now have a PlatformIO project, I can reference the package using platform_packages with a file:// URI and the absolute path to the file (/home/pi/tool-dfuutil-linux_aarch64-1.9.211020.tar.gz in my case). Add

platform_packages =
   tool-dfuutil@file:///home/pi/tool-dfuutil-linux_aarch64-1.9.211020.tar.gz

to the platformio.ini of the project to use the generated package and try uploading again.

Let me know if that gives you a working DFU-UTIL package for AArch64, and please share the generated tarball :slight_smile:

1 Like

Thanks !!!

It is rather overwelming, but I was able to build the package. I had to install one dependency (apt install pkg-config), as I had an issue running ./configure (similar to what’s described here: PKG_CHECK_MODULES USB unexpected token · Issue #83 · stlink-org/stlink · GitHub).

How can I share the package ?

I was however less successful on my Mac M1, it compiles, but I get an error when building my project:

Building .pio/build/portenta_h7_m7/firmware.bin
Adding dfu suffix to firmware.bin
sh: bin/dfu-suffix: No such file or directory
*** [.pio/build/portenta_h7_m7/firmware.bin] Error 127

The file bin/dfu-suffix is there…

Hm that doesn’t look good, like the produced file is not there or it was compiled for the wrong architecture. Does ~/.platformio/packages/tool-dfuutil/bin/dfu-suffix exist now after you referenced your created package? Can you execute the binary manually and see if it outputs something?

I updated my previous post, some stuff were missing. In summary, on the Pi, it worked great, would only need to know how I could share this package.

The issue with dfu-suffix occure when building on my Mac M1 (I followed the same approach as you described).

1 Like

All the Apple stuff on PlatformIO relies on the Rosetta x86->ARM recompiler, the binaries aren’t native to the ARM M1 processor. And the package should be there already, for darwin_arm64 and darwin_x86_64: https://dl.registry.platformio.org/download/platformio/tool/tool-dfuutil/1.9.200310/tool-dfuutil-darwin_x86_64-1.9.200310.tar.gz, so no generating the package yourself should be necessary. You can remove the whole ~/.platformio/packages/tool-dfuutil folder (and take out any platform_packages command from the platformio.ini) to force a clean redownload of the package on the M1.

If you’re still having problems, file an issue at Issues · platformio/platform-ststm32 · GitHub regarding the M1, and another regarding the missing AArch64 package (where you can also upload your package file).

Understood. The issue with the available package is that it uses libusb installed on the Mac, and mine is for arm64…

How can I share the package I built for AArch64 ? Should I publish under my own account ?

Hmm I was under the impression that Rosetta would take care of this. Definitely file an issue about that.

When you open a new issue in platform-ststm32 you can just drag-and-drop your file into the comment text and it’ll upload.

I have open issue 572, with the package attached.

1 Like