PlatformIO-Newbie hitting wall after wall

Hi there.

I have been coding for Arduinos and STM32 for quite some time now using the Arduino IDE and it worked well. After it started hanging I found a reference to PlatformIO on Reddit which I didn’t know before. Putting my Microsoft aversion aside, I first installed “code”, which is the open source package of VSCODE that comes in Arch Linux.

Wall 1: The Platform IO extension wasn’t found there at all. sigh deinstalled that “code” package

Next step, downloading the open source version vscode for Linux (*.tar.gz) starting that, and voila Platform.IO is there.

Tested the blink with an Arduino - works. No wall there - yay!

Created a “Blink STM32” folder to test the blink with a - well, hard to say - “blue pill” or “black pill” STM32F103C8T6 with 128K of flash. I mean it is probably a blue pill, but it’s pretty black:
http s://robotdyn.com/stm32-arm-arduino-mini-system-dev-board-with-arduino-bootloader-stm32f103c8t6-64kb-not-soldered.html

Be it as it may, selected blue pill F103C8 with 128k, dfu as upload protocol and /dev/ttyACM0 as port as nothing was autodetected.

After a whole Friday and Saturday no juice. Would you believe, that a SPACE in a folder name could lead to some error? In 2021? I wouldn’t:

Wall 2: Folder “STM32 Blink” and no error message, but failure to upload.

    Waiting for /dev/ttyACM0 serial...Done
    =================================== [SUCCESS] Took 5.85 seconds ===================================

Yeah, success. Right. So after a hunt for the cheesy cheese, I saw somewhere a lonely “File not found” /yadda/Documents/Projects/STM32 in the log. Renamed to STM32_Blink and yay! something happened! Shell escaping snafu I guess.

Wall 3: First Blue Pill bricked

You see,

...
Opening DFU capable USB device... ID 1eaf:0003
Run-time device DFU version 0110
Found DFU: [1eaf:0003] devnum=0, cfg=1, intf=0, alt=2, name="STM32duino bootloader v1.0  Upload to Flash 0x8002000"
Claiming USB DFU Interface...
...

I thought the name was nice and informative, but after the first “successful” STM32 upload in 48 hours, the device was … if not dead, then certainly with a blow:

Opening DFU capable USB device... ID 1eaf:0003
Run-time device DFU version 0110
Found DFU: [1eaf:0003] devnum=0, cfg=1, intf=0, alt=2, name="UNDEFINED"
Claiming USB DFU Interface...

I do suspect, the bootloader got overwritten. At least that’s what I read from:
http s://community.platformio.org/t/upload-firmware-to-specific-address/12088
and elsewhere because the default seems to be 0x8000000 and not 0x8002000.

Wall 4: Second Blue Pill bricked

platformio.ini:

[env:bluepill_f103c8_128k]
platform = ststm32
board = bluepill_f103c8_128k
framework = arduino
upload_protocol = dfu
upload_port = /dev/ttyACM0
board_upload.offset_address = 0x8002000

So I thought this should prevent some overwriting, but wrong. Again name=“UNKNOWN”

At which point I registered in this forum, because 48hours without a successful STM32 upload is tough for an IDE… :wink:

I have one blue/black pill left and do not feel lucky.

PlatformIO is only available in the Microsoft marketplace, as per discussed per PlatformIO IDE not in marketplace and related.

Reported issue with missing shelll-escape: Upload protocol can't identify space char " " for dfu-util · Issue #422 · platformio/platform-ststm32 · GitHub. The bug stems from the original STM32Duino developer.

Hope the PlatformIO devs can workaround / fix it soon.

I repeated this experiment with my Bluepill. In the beginning, it did not have a bootloader on it. So, I grabed the 2.0 bootloader from the github and flashed it on my bluepill using an STLink. Then I only plugged in the bluepill via USB, and got the expected USB device / virtual COM port.

I then went ahead and created a new project with the platformio.ini

[env:bluepill_f103c8_128k]
platform = ststm32
board = bluepill_f103c8_128k
framework = arduino
upload_protocol = dfu

(no upload_port, PlatformIO will detect it just fine…) and wrote the src\main.cpp file as a blinky on PC13.

#include <Arduino.h>

void setup() { pinMode(PC13, OUTPUT);}
void loop() { digitalWrite(PC13, digitalRead(PC13) ^ 1); delay(200); }

Before uploading, I also had to install the necessary Windows drivers.

And then a “upload” gave me…

Auto-detected: COM23
Uploading .pio\build\bluepill_f103c8_128k\firmware.bin
maple_loader v0.1
Resetting to bootloader via DTR pulse
Searching for DFU device [1EAF:0003]...
Reset via USB Serial Failed! Did you select the right serial port?
Assuming the board is in perpetual bootloader mode and continuing to attempt dfu programming...

Found it!

Opening USB Device 0x1eaf:0x0003...
Found Runtime: [0x1eaf:0x0003] devnum=1, cfg=0, intf=0, alt=2, name="STM32duino bootloader v1.0  Upload to Flash 0x8002000"
Setting Configuration 1...
Claiming USB DFU Interface...
Setting Alternate Setting ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
Transfer Size = 0x0400
bytes_per_hash=205
Starting download: [##################################################] finished!
state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present
error resetting after download: usb_reset: could not reset device, win error: Ein nicht vorhandenes Gerät wurde angegeben.
Done!


Resetting USB to switch back to runtime mode

And the LED started flashing as I wanted. After plugging the device in- and out of the USB port, I still have my Maple DFU device though.

grafik

But, the serial port was gone with which the reset-into-bootloader mode is triggered (by opening the virtual COM port and sending a magic sequence of DTR/RTS/bytes). This is because I just uploaded a firmware wich uses the STM32 core (GitHub - stm32duino/Arduino_Core_STM32: STM32 core support for Arduino) and not the Maple core (GitHub - rogerclarkmelbourne/Arduino_STM32: Arduino STM32. Hardware files to support STM32 boards, on Arduino IDE 1.8.x including LeafLabs Maple and other generic STM32F103 boards) with which this DFU bootloader is supposed to be used continuously. I will show how to do it properly in a minute, but to prove a point:

A new firmware is still flashable to the device. The bootlaoder is still on there and executes on boot – so the technique here to unplug the device first, then start the upload process until it says Searching for DFU device [1EAF:0003], and then plug the device in again. Another caveat though is that the Maple upload program still requires a COM port on which it wants to do the reset dance. So I write upload_port = COM1 in my platformio.ini which is my motherboard’s UART port that’s not connecting to anything, but makes the program happy. I upload again and…

Looking for upload port...
Use manually specified: COM1
Uploading .pio\build\bluepill_f103c8_128k\firmware.bin
maple_loader v0.1
Resetting to bootloader via DTR pulse
Searching for DFU device [1EAF:0003]...
Found it!

Opening USB Device 0x1eaf:0x0003...
Found Runtime: [0x1eaf:0x0003] devnum=1, cfg=0, intf=0, alt=2, name="STM32duino bootloader v1.0  Upload to Flash 0x8002000"
Setting Configuration 1...
Claiming USB DFU Interface...
Setting Alternate Setting ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
Transfer Size = 0x0400
bytes_per_hash=205
Starting download: [##################################################] finished!
error resetting after download: usb_reset: could not reset device, win error: Ein nicht vorhandenes Gerät wurde angegeben.
state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present

Done!

Resetting USB to switch back to runtime mode
==================== [SUCCESS] Took 11.61 seconds ====================

The firmware is uploaded successfully and the device string

Found Runtime: [0x1eaf:0x0003] devnum=1, cfg=0, intf=0, alt=2, name=“STM32duino bootloader v1.0 Upload to Flash 0x8002000”

Is still present. The LED is now blinking at the rate of the newly compiled firmware. So, all is well and I can reflash arbitrary firmwares however many times I like by unplugging the USB device first, then uploading, waiting until it looks for the device, and replugging the device.

This also does not need a board_upload.offset_address directive. This is not used / needed in the Maple DFU upload, but in the STM32 USB DFU bootloader for other STM32 chips (refer code).

So, how to do it correctly? Use the Maple core with the Maple USB bootloader. The documentation states how to switch the used core. So, we write the platformio.ini as

[env:bluepill_f103c8_128k]
platform = ststm32
board = bluepill_f103c8_128k
framework = arduino
upload_protocol = dfu
board_build.core = maple

and we let the src\main.cpp be the same.

For my first upload, I also had to write upload_port = COM1 again and do the unplug-plug trick to upload the new firmware initially.

Looking for upload port...
Use manually specified: COM1
Uploading .pio\build\bluepill_f103c8_128k\firmware.bin
maple_loader v0.1
Resetting to bootloader via DTR pulse
Searching for DFU device [1EAF:0003]...
Found it!

Opening USB Device 0x1eaf:0x0003...
Found Runtime: [0x1eaf:0x0003] devnum=1, cfg=0, intf=0, alt=2, name="STM32duino bootloader v1.0  Upload to Flash 0x8002000"
Setting Configuration 1...
Claiming USB DFU Interface...
Setting Alternate Setting ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
Transfer Size = 0x0400
bytes_per_hash=389
Starting download: [##################################################] finished!
state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present
Done!
error resetting after download: usb_reset: could not reset device, win error: Ein nicht vorhandenes Gerät wurde angegeben.
Resetting USB to switch back to runtime mode


==================== [SUCCESS] Took 10.53 seconds ====================

After the new firmware was uploaded, the device was reset and now I have a new USB device: The virtual COM port.

Notice how the firwmare code (src\main.cpp) that I’ve uploaded does not do anything with a Serial or the USB serial – the USB serial device simply appears as it’s baked into the Maple core that we’ve switched to.

Now that a firmware with the Maple core is uploaded to the device, I can remove my uplaod_port = COM1 line again and upload new firmwares absolutely normally, without plugging or unplugging the device. A new firmware upload with changed LED interval and no USB re-plugging gives:

Looking for upload port...
Auto-detected: COM23
Uploading .pio\build\bluepill_f103c8_128k\firmware.bin
maple_loader v0.1
Resetting to bootloader via DTR pulse
Searching for DFU device [1EAF:0003]...
Reset via USB Serial Failed! Did you select the right serial port?
Assuming the board is in perpetual bootloader mode and continuing to attempt dfu programming...

Found it!

Opening USB Device 0x1eaf:0x0003...
Found Runtime: [0x1eaf:0x0003] devnum=1, cfg=0, intf=0, alt=2, name="STM32duino bootloader v1.0  Upload to Flash 0x8002000"
Setting Configuration 1...
Claiming USB DFU Interface...
Setting Alternate Setting ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
Transfer Size = 0x0400
bytes_per_hash=389
Starting download: [##################################################] finished!
error resetting after download: usb_reset: could not reset device, win error: Ein nicht vorhandenes Gerät wurde angegeben.

state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present

Done!
Resetting USB to switch back to runtime mode
==================== [SUCCESS] Took 10.57 seconds ====================

An auto-detected upload port and a good upload to the device with the new firmware running. After the upload, the virtual USB COM port of course still exists and I can directly do it another time…

Auto-detected: COM23
Uploading .pio\build\bluepill_f103c8_128k\firmware.bin
maple_loader v0.1
Resetting to bootloader via DTR pulse
Searching for DFU device [1EAF:0003]...
Reset via USB Serial Failed! Did you select the right serial port?
Assuming the board is in perpetual bootloader mode and continuing to attempt dfu programming...

Found it!

Opening USB Device 0x1eaf:0x0003...
Found Runtime: [0x1eaf:0x0003] devnum=1, cfg=0, intf=0, alt=2, name="STM32duino bootloader v1.0  Upload to Flash 0x8002000"
Setting Configuration 1...
Claiming USB DFU Interface...
Setting Alternate Setting ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
Transfer Size = 0x0400
bytes_per_hash=389
Starting download: [##################################################] finished!
error resetting after download: usb_reset: could not reset device, win error: Ein nicht vorhandenes Gerät wurde angegeben.

state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present

Done!
Resetting USB to switch back to runtime mode
==================== [SUCCESS] Took 9.53 seconds ====================

And the device string is also still there.

So, regarding your situation now: The bootloader on your device is probably still fine and your device is not bricked. The first thing you should do is use a platformio.ini like

[env:bluepill_f103c8_128k]
platform = ststm32
board = bluepill_f103c8_128k
framework = arduino
upload_protocol = dfu
board_build.core = maple
upload_port = /dev/arbitrary_serial_device_here

and upload any firmware (e.g. blinky from above) to the device with the discussed procedure.

Also, your device is never truly bricked until the chip fails. You can program the board over the SWD interface with a cheap ST-Link V2 programming probe (which also enables you to debug firmwares instead of just uploading them), and you can reboot your chip into bootloader mode by connecting the BOOT0 pin to GND and resetting it. The BOOT0 and BOOT1 pins are accessible through the two jumpers to the left of the reset button, which can be connected to GND or VCC (0/1). The embedded bootloader in the STM32F103 chip will then make the chip flashable via a serial UART interface, which PlatformIO also supports per upload_protocol = serial. If you have any cheap USB-UART adapter, you can reflash the chip. So, it’s never truly bricked.

Should the bootloader be damaged by some kind of miracle (that shouldn’t have happened), use one of the two methods listed above. Otherwise, you’ll be able to recover it just fine.

So as a TL;DR:

  • double check which Arduino core you want to use with the device
  • double check the PlatformIO STSTM32 documentation
  • use the Maple USB DFU bootloader with the Maple Arduino core for maximum comfort
  • the Maple USB DFU bootloader can still be used to flash STM32-core firmwares, but needs a USB replug for every firmware upload
  • if you want debugging and comfortable uploading to the STM32 chip in every situtation / core, invest the 5€ in an ST-Link clone
  • STM32 chips can be reflashed via SWD, the embedded UART bootloader or the Maple bootloader
  • you cannot override the bootloader when uploading via the Maple DFU USB bootloader – it takes care of that itself. (not so with the other upload methods)
1 Like

Thank you @maxgerhardt for your extensive answer/follow-up.

I changed the platform.ini accordingly, but it seems under Linux the USB handling is different and I am not able to reproduce your workflow. The logs in the terminal are completely different.

If I just reset the STM32 (because the USB device is still there and seen by Linux);

Configuring upload protocol...
AVAILABLE: blackmagic, cmsis-dap, dfu, jlink, stlink
CURRENT: upload_protocol = dfu
Looking for upload port...
Use manually specified: /dev/ttyACM0
Uploading .pio/build/bluepill_f103c8_128k/firmware.bin
Failed to open serial device.

dfu-util 0.7
Cannot set alternate interface

Copyright 2005-2008 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2012 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to dfu-util@lists.gnumonks.org

Filter on vendor = 0x1eaf product = 0x0003
Opening DFU capable USB device... ID 1eaf:0003
Run-time device DFU version 0110
Found DFU: [1eaf:0003] devnum=0, cfg=1, intf=0, alt=2, name="UNDEFINED"
Claiming USB DFU Interface...
Setting Alternate Setting #2 ...
Waiting for /dev/ttyACM0 serial...Done

If I unplug it, start the upload and replug it while upload:

Configuring upload protocol...
AVAILABLE: blackmagic, cmsis-dap, dfu, jlink, stlink
CURRENT: upload_protocol = dfu
Looking for upload port...
Use manually specified: /dev/ttyACM0
Uploading .pio/build/bluepill_f103c8_128k/firmware.bin
Failed to open serial device.
No DFU capable USB device found

dfu-util 0.7

Copyright 2005-2008 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2012 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to dfu-util@lists.gnumonks.org

Filter on vendor = 0x1eaf product = 0x0003
Waiting for /dev/ttyACM0 serial...Done

So no luck…
I have ordered one stlink (actually two, one USB V2 and one being part of a Nucleo-64) - it was long overdue to have these.

Hm in my case I specify a serial port that exists in the system but is not connected to anything. Maybe the error here is that that serial doesn’t exist at all? Can you use another port like /dev/ttyS0 or plug in another Arduino board which is seen as serial and reference that?

It is indeed strange that the name is still “undefined”, but maybe that’s a Linux specific thing.

The weirdest thing just happened. I take my last blue pill (because it’s still 2-3 days until the STlink arrives) and connect it via USB, /dev/ttyACM0 appears.

I try an upload and it fails:

CURRENT: upload_protocol = dfu
Looking for upload port...
Use manually specified: /dev/ttyACM0
Uploading .pio/build/bluepill_f103c8_128k/firmware.bin
setDTR: TIOCMSET: Connection timed out
setDTR: TIOCMSET: Protocol error
setRTS(): TIOCMSET: Protocol error
setDTR: TIOCMSET: Protocol error
setDTR: TIOCMSET: Protocol error
No valid DFU suffix signature
Warning: File has no DFU suffix

With anxiety I watch the PC13 LED having its strange PWM-like up/down dimming (which was precursor to “soft-bricking(?)” the other pills) and then I give the blue pill the reset. As soon as I do that, DFU resumes like this:

Filter on vendor = 0x1eaf product = 0x0003
Opening DFU capable USB device... ID 1eaf:0003
Run-time device DFU version 0110
Found DFU: [1eaf:0003] devnum=0, cfg=1, intf=0, alt=2, name="STM32duino bootloader v1.0  Upload to Flash 0x8002000"
Claiming USB DFU Interface...
Setting Alternate Setting #2 ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 0110
Device returned transfer size 1024
bytes_per_hash=387
Copying data from PC to DFU device
Starting download: [##################################################] finished!
state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present
Done!
Resetting USB to switch back to runtime mode
Waiting for /dev/ttyACM0 serial...Done

And I have my first successful successful download - the blinky now evidently has 0.5secs and not 1sec as it had before (from Arduino IDE still). Maybe I’m lucky and now in the situation you described with maple core and maple bootloader. Fingers crossed.

edit:

Nope. Just nope.
After one upload, the USB device is visible, but /dev/ttyACM0 does not appear anymore.

dmesg:

[191479.497124] usb 1-1: USB disconnect, device number 105
[191479.785842] usb 1-1: new full-speed USB device number 106 using xhci_hcd
[191479.927587] usb 1-1: New USB device found, idVendor=1eaf, idProduct=0003, bcdDevice= 2.01
[191479.927599] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[191479.927606] usb 1-1: Product: Maple 003
[191479.927610] usb 1-1: Manufacturer: LeafLabs
[191479.927614] usb 1-1: SerialNumber: LLM 003

while I would like to see

[114950.275017] usb 1-6: new full-speed USB device number 82 using xhci_hcd
[114950.420350] usb 1-6: New USB device found, idVendor=1eaf, idProduct=0004, bcdDevice= 2.00
[114950.420363] usb 1-6: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[114950.420369] usb 1-6: Product: Maple
[114950.420372] usb 1-6: Manufacturer: LeafLabs
[114950.424210] cdc_acm 1-6:1.0: ttyACM0: USB ACM device

Well, I restarted udev in the hope it might do something, I also stumbled across this

and tried it, but to no avail.

Hm as said I couldn’t reproduce that on Windows :confused:. Maybe there was initially a different bootloader on there (different or older than from the official repo that I’ve linked to) or using it on Linux really makes a difference.

Got my STlink V2 - uploads are smooth as butter now, platformio.ini is just

[env:bluepill_f103c8_128k]
platform = ststm32
board = bluepill_f103c8_128k
framework = arduino
upload_protocol = stlink

So certainly my 2-3days of woes with the Arduino/Maple bootloader was not worth these 3-4€ cost for the STlink. As of now, I would not recommend STM32+arduino bootloader+dfu under Linux.

STlink: piece of cake.