Blue Pill DFU Upload in PlatformIO = unable to enumerate USB device

Log showing USB errors

Another day another problem 😅. Previously I managed to program the Blue Pill board directly (using the on-board micro USB connector) from PlatformIO using DFU upload method. The problem is: while the program did get uploaded to the board, the computer spouted errors:

24/05/20 22.51	kernel	cdc_acm 2-1.5:1.0: failed to set dtr/rts
24/05/20 22.51	kernel	usb 2-1.5: USB disconnect, device number 53
24/05/20 22.51	kernel	usb 2-1.5: new full-speed USB device number 54 using ehci-pci
24/05/20 22.51	kernel	usb 2-1.5: New USB device found, idVendor=1eaf, idProduct=0003, bcdDevice= 2.01
24/05/20 22.51	kernel	usb 2-1.5: New USB device strings: Mfr=1, Product=2, SerialNumber=3
24/05/20 22.51	kernel	usb 2-1.5: Product: Maple 003
24/05/20 22.51	kernel	usb 2-1.5: Manufacturer: LeafLabs
24/05/20 22.51	kernel	usb 2-1.5: SerialNumber: LLM 003
24/05/20 22.51	mtp-probe	checking bus 2, device 54: "/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.5"
24/05/20 22.51	mtp-probe	bus: 2, device: 54 was not an MTP device
24/05/20 22.51	fwupd	15:51:21:0438 FuPluginDfu          DFU version 0x0000 invalid, v1.1 assumed
24/05/20 22.51	mtp-probe	checking bus 2, device 54: "/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.5"
24/05/20 22.51	mtp-probe	bus: 2, device: 54 was not an MTP device
24/05/20 22.51	fwupd	15:51:21:0446 FuPluginDfu          DFU version 0x0000 invalid, v1.1 assumed
24/05/20 22.51	fwupd	15:51:21:0455 FuPluginDfu          DFU version 0x0000 invalid, v1.1 assumed
24/05/20 22.51	kernel	usb 2-1.5: reset full-speed USB device number 54 using ehci-pci
24/05/20 22.51	kernel	usb 2-1.5: device descriptor read/64, error -32
24/05/20 22.51	kernel	usb 2-1.5: device descriptor read/64, error -32
24/05/20 22.51	kernel	usb 2-1.5: reset full-speed USB device number 54 using ehci-pci
24/05/20 22.51	kernel	usb 2-1.5: device descriptor read/64, error -32
24/05/20 22.51	kernel	usb 2-1.5: device descriptor read/64, error -32
24/05/20 22.51	kernel	usb 2-1.5: reset full-speed USB device number 54 using ehci-pci
24/05/20 22.51	kernel	usb 2-1.5: device not accepting address 54, error -32
24/05/20 22.51	kernel	usb 2-1.5: reset full-speed USB device number 54 using ehci-pci
24/05/20 22.51	kernel	usb 2-1.5: device not accepting address 54, error -32
24/05/20 22.51	kernel	usb 2-1.5: USB disconnect, device number 54
24/05/20 22.51	kernel	usb 2-1.5: new full-speed USB device number 55 using ehci-pci
24/05/20 22.51	kernel	usb 2-1.5: device descriptor read/64, error -32
24/05/20 22.51	kernel	usb 2-1.5: device descriptor read/64, error -32
24/05/20 22.51	kernel	usb 2-1.5: new full-speed USB device number 56 using ehci-pci
24/05/20 22.51	kernel	usb 2-1.5: device descriptor read/64, error -32
24/05/20 22.51	kernel	usb 2-1.5: device descriptor read/64, error -32
24/05/20 22.51	kernel	usb 2-1-port5: attempt power cycle
24/05/20 22.51	kernel	usb 2-1.5: new full-speed USB device number 57 using ehci-pci
24/05/20 22.51	kernel	usb 2-1.5: device not accepting address 57, error -32
24/05/20 22.51	kernel	usb 2-1.5: new full-speed USB device number 58 using ehci-pci
24/05/20 22.51	kernel	usb 2-1.5: device not accepting address 58, error -32
24/05/20 22.51	kernel	usb 2-1-port5: unable to enumerate USB device

Whatever is that supposed to mean? I did not know either. So I did lsusb, like this:

joshua@joshua-t530:~$ lsusb
Bus 002 Device 059: ID 1eaf:0003

So basically the computer detected the Maple/Leaf device. But wait, the Maple/Leaf device is supposedly only active momentarily, to accept new programming command. This is called the DFU mode. After that, Roger Clark’s bootloader are supposed to change the vendor and product ID to 0483:5740 so the board can receive/send serial communication. So I waited a minute, and issued lsusb again. The result: nothing changes. In other words: the board is stuck in DFU mode.

Once the board is stuck in DFU mode, it will:

  1. Not able to be programmed using DFU upload protocol from PlatformIO again, even after powering the board off, or after pressing the reset button.
  2. Not able to send/receive serial communication using the STMicroelectronics Virtual COM Port. The Virtual COM Port is not even listed by lsusb.

To return it to normal, I had to reprogram the board by using Arduino IDE. Any program is fine. I used Blink. I also had to press the on-board reset button while Arduino IDE was sending the program to the board. Becase it can be returned to normal by Arduino IDE, the problem must be specific to PlatformIO. Time to see the PlatformIO Community again.

After searching, I found a thread with similar problem. User maxgerhardt offered a solution: reinstall the ststm32 platform in PlatformIO. Let’s try that, shall we:

joshua@joshua-t530:~/Projects/pio/STM32Test$ pio platform uninstall ststm32
Uninstalling ststm32 @ 6.1.0:   [OK]
Uninstalling framework-arduinoststm32 @ 4.10800.200207:         [OK]
Uninstalling framework-arduinoststm32-maple @ 2.10000.200103:   [OK]
Uninstalling framework-stm32cube @ 2.0.181130:  [OK]
Uninstalling tool-dfuutil @ 1.9.200310:         [OK]
Uninstalling tool-openocd @ 2.1000.190707:      [OK]
Uninstalling tool-stm32duino @ 1.0.1:   [OK]
Uninstalling toolchain-gccarmnoneeabi @ 1.90201.191206:         [OK]
The platform 'ststm32' has been successfully uninstalled!
joshua@joshua-t530:~/Projects/pio/STM32Test$ pio platform install ststm32
PlatformManager: Installing ststm32
Downloading [####################################] 100%
Unpacking [####################################] 100%
ststm32 @ 6.1.0 has been successfully installed!
PackageManager: Installing toolchain-gccarmnoneeabi @ >=1.60301.0,<1.80000.0
toolchain-gccarmnoneeabi @ 1.70201.0 is already installed
The platform 'ststm32' has been successfully installed!
The rest of packages will be installed automatically depending on your build environment.

Alright, reinstalled. Next, I clicked the upload button on PlatformIO: oh no! The upload-reset executable was acting up again. But of course, we had just reinstalled the entire platform. That means we need to recompile this utility again:

joshua@joshua-t530:~/.platformio/packages/tool-stm32duino$ file upload-reset
upload-reset: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=dc8dc5ad6de94179a9d534b1a34aeb6d906640b1, not stripped
joshua@joshua-t530:~/.platformio/packages/tool-stm32duino$ mv upload-reset upload-reset-32
joshua@joshua-t530:~/.platformio/packages/tool-stm32duino$ cd src/
dfu-util/          maple_loader/      stm32flash_serial/ upload-reset/
joshua@joshua-t530:~/.platformio/packages/tool-stm32duino$ cd src/upload-reset
joshua@joshua-t530:~/.platformio/packages/tool-stm32duino/src/upload-reset$ ls
upload-reset.c
joshua@joshua-t530:~/.platformio/packages/tool-stm32duino/src/upload-reset$ gcc -o ../../upload-reset upload-reset.c
upload-reset.c:121:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
 121 | main(int argc, char *argv[])
     | ^~~~
upload-reset.c: In function ‘main’:
upload-reset.c:127:3: warning: ‘return’ with no value, in function returning non-void
 127 | return;
     | ^~~~~~
upload-reset.c:121:1: note: declared here
 121 | main(int argc, char *argv[])
     | ^~~~
joshua@joshua-t530:~/.platformio/packages/tool-stm32duino/src/upload-reset$ cd ../..
joshua@joshua-t530:~/.platformio/packages/tool-stm32duino$ file ./upload-reset
./upload-reset: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=e5e26198184684180439e9ec8ef804d70a460caf, for GNU/Linux 3.2.0, not stripped
joshua@joshua-t530:~/.platformio/packages/tool-stm32duino$ ./upload-reset
Usage upload-reset <serial_device> <Optional_delay_in_milliseconds>

Okay, now the ststm32 had been reinstalled and the upload-reset utility had been compiled as 64-bit executable. I clicked the upload button in PlatformIO again. The result: the DFU upload succeeded and the errors are not occurring in the computer logs anymore. When I run lsusb, the result shows STMicroelectronics Virtual COM Port. I am also able to send/receive serial communication from that port in PlatformIO. Problem solved!

On that note, I am now realizing why Arduino boards and Arduino IDE are so popular. They are truly plug and play. In comparison, this STM32 boards (and clones) and PlatformIO IDE requires more tought 🤔 (and time ⏲, and effort 💪, you know what I mean).

Also, I had just figured that my OS has emoji picker 😋.

Laters!