HOWTO: USB Upload + USB Serial for STM32F103C8T6, Generic "Bluepill" (Macs welcome)

I bought a STM32F103C8T6 “Bluepill” board from Amazon.
I am using a 2017 Intel Mac, running Ventura 13.2.1.

I would like to do the following:

  • Upload “sketches” (firmware) via USB
  • Do serial send and receive via USB

I assume both things are possible.

Please see my question at the end of the post.

Board image

Background

I do understand that there may be obstacles:

  • R10 on the board may be of wrong value — R10 has 1.5 kiloohms :white_check_mark:
  • STM processor may be a forgery — has official STM markings :white_check_mark:
  • USB cable may be power only :crazy_face: — my cable also has data lines :white_check_mark:

I understand these points to be necessary

  • I uploaded proper version of the stm32duino-bootloader to the board
    • The on-board LED is attached to pin PC13, so I downloaded generic_boot20_pc13.bin from the stm32duino binaries (Github)
    • I attached a cloned ST-Link USB adapter to GND, 3.3V, SWDIO, SWCLK of the board
    • I uploaded the bootloader to the board. I used st-flash v1.7.0 for this
    • the command was st-flash write generic_boot20_pc13.bin 0x8000000. It finished with INFO common.c: Flash written and verified! jolly good! :white_check_mark:
  • I disconnected the ST-Link USB adapter, and connected a USB cable to the board
  • the board greets me with a few fast, then a few slower blinks:
  • In platform.ini, I set the environment to:
    [env:genericSTM32F103C8]
    platform = ststm32
    framework = arduino
    board = genericSTM32F103C8
    board_build.core = maple
    upload_protocol = dfu
    
  • I wrote a quick thing that blinks the LEDs. I built the source. All good. :white_check_mark:
  • In system profiler, the board is visible as Maple 003:, product ID 0x0003, vendor 0x1eaf, version 2.01, serial number LLM 003. :white_check_mark:

What is not working:

  • when I press upload, the upload seemingly begins, then fails. The PC13 LED starts to blink quickly and never stops.
Configuring upload protocol...
AVAILABLE: blackmagic, cmsis-dap, dfu, jlink, serial, stlink
CURRENT: upload_protocol = dfu
Looking for upload port...
Auto-detected: /dev/cu.usbmodem14301
Uploading .pio/build/genericSTM32F103C8/firmware.bin
*** [upload] Error 1
  • I even temporarily connected PC14 to GND to enter “perpetual bootloader” mode (source missing). This did not help to upload, though.
  • I should say that uploading “sketches” via ST-Link works, but is not practical in the expected use scenario.
  • Regarding suuitable [env]s, I am wondering which one is the best one (bluepill_f103c8, genericSTM32F103C8, bluepill_f103c8_128k). Looked them up via pio boards |grep STM32F103C8T6 .

Question

What can I do? I searched the interwebs for many hours, to no avail. I am happy to hear from you. Thank you so much.

I’m away from my kit etc, but there are lots of Bluepill docs here: Search — PlatformIO latest documentation

Cheers,
Norm.

I think it does a reset here which puts your already in bootloader mode board into “run application” mode. You might want to try and set

board_upload.require_upload_port = no
board_upload.use_1200bps_touch = no

for the very first upload.

1 Like

Thank you for the quick reply. For now, this did not work.

I was wondering if I should look more in the “do I have the right bootloader” side, or on the USB configuration side

Maybe it fails at something else completely. Execute the project task Advanced → Verbose Upload. What are the logs?

Can I post the logs here? Or is that bad form and I should pastebin or similar?

Well the last few lines where it tries to invoke the uploader command (mape_upload.bat I think in this case) suffice.

NB: I am on a Mac, so no batch files, but that should be OK :wink:
I ran verbose upload:

CURRENT: upload_protocol = dfu
MethodWrapper(["upload"], [".pio/build/genericSTM32F103C8/firmware.bin"])
Auto-detected: /dev/cu.usbmodem14301
maple_upload cu.usbmodem14301 2 1EAF:0003 "[snip]/230310-bluepill-general-test/.pio/build/genericSTM32F103C8/firmware.bin"
*** [upload] Error 1
=== [FAILED] Took 3.11 seconds 

Environment         Status    Duration
------------------  --------  ------------
bluepill_f103c8     IGNORED
genericSTM32F103C8  FAILED    00:00:03.106
=== 1 failed, 0 succeeded in 00:00:03.106 =====

Okay, getting closer. Can you modify the upload script at

/User/<user>/.platformio/packages/tool-stm32duino/maple_upload

so that the second line is

set -o xtrace

then upload again and post new logs.

Here you go

Auto-detected: /dev/cu.usbmodem14301
maple_upload cu.usbmodem14301 2 1EAF:0003 "/Users/<user>/Documents/PlatformIO/Projects/xxx-tests/230310-bluepill-general-test/.pio/build/genericSTM32F103C8/firmware.bin"
+ set -e
+ '[' 4 -lt 4 ']'
+ dummy_port=cu.usbmodem14301
+ altID=2
+ usbID=1EAF:0003
+ binfile=/Users/<user>/Documents/PlatformIO/Projects/xxx-tests/230310-bluepill-general-test/.pio/build/genericSTM32F103C8/firmware.bin
+ dummy_port_fullpath=/dev/cu.usbmodem14301
+++ dirname /Users/<user>/.platformio/packages/tool-stm32duino/maple_upload
++ cd /Users/<user>/.platformio/packages/tool-stm32duino
++ pwd
+ DIR=/Users/<user>/.platformio/packages/tool-stm32duino
+ /Users/<user>/.platformio/packages/tool-stm32duino/upload-reset /dev/cu.usbmodem14301 750
*** [upload] Error 1
==== [FAILED] Took 13.39 seconds ====

Environment           Status    Duration
--------------------  --------  ------------
bluepill_f103c8       IGNORED
genericSTM32F103C8    FAILED    00:00:13.386
bluepill_f103c8_128k  IGNORED

Note: Regarding the [env]s, I am wondering which one is the best one (bluepill_f103c8, genericSTM32F103C8, bluepill_f103c8_128k). Looked them up via pio boards |grep STM32F103C8T6.

This is a native compiled binary. Perhaps it fails on an M1 Mac because Rosetta 2 is not installed. But let me not judge prematurely.

Open a new PlatformIO CLI and execute the same command.

/Users/<user>/.platformio/packages/tool-stm32duino/upload-reset /dev/cu.usbmodem14301 750

what is the output?

If there is none, execute echo $? after the command.

FYI I am still on Intel :spider: :spider_web:

Linefeed for convenience:

> /Users/<user>/.platformio/packages/tool-stm32duino/
upload-reset /dev/cu.usbmodem14301 750; echo $?
> 1

(LED jumps into quick blink loop)

The src/upload-reset.c code looks weird. The main() function has no declared return value type and on success there is no explicit return 0;.

Let’s do a very simple test and ignore the return value of upload-reset. In maple_upload, find the

${DIR}/upload-reset ${dummy_port_fullpath} 750

line and change it to

${DIR}/upload-reset ${dummy_port_fullpath} 750 || true

What does uploading output now?

1 Like

This is amazing. :man_dancing: :mirror_ball: Thank you so much. How do you do it? How is it possible? (I really mean it).

I also would like to add that incidentally, the serial comm via USB now also works. :white_check_mark:

maple_upload cu.usbmodem14301 2 1EAF:0003 "/Users/<user>/Documents/PlatformIO/Projects/xxx-tests/230310-bluepill-general-test/.pio/build/genericSTM32F103C8/firmware.bin"
+ set -e
+ '[' 4 -lt 4 ']'
+ dummy_port=cu.usbmodem14301
+ altID=2
+ usbID=1EAF:0003
+ binfile=/Users/<user>/Documents/PlatformIO/Projects/xxx-tests/230310-bluepill-general-test/.pio/build/genericSTM32F103C8/firmware.bin
+ dummy_port_fullpath=/dev/cu.usbmodem14301
+++ dirname /Users/<user>/.platformio/packages/tool-stm32duino/maple_upload
++ cd /Users/<user>/.platformio/packages/tool-stm32duino
++ pwd
+ DIR=/Users/<user>/.platformio/packages/tool-stm32duino
+ /Users/<user>/.platformio/packages/tool-stm32duino/upload-reset /dev/cu.usbmodem14301 750
+ true
+ '[' 4 -eq 5 ']'
+ dfuse_addr=
+ DFU_UTIL=/Users/<user>/.platformio/packages/tool-stm32duino/dfu-util/dfu-util
+ '[' '!' -x /Users/<user>/.platformio/packages/tool-stm32duino/dfu-util/dfu-util ']'
+ '[' '!' -x /Users/<user>/.platformio/packages/tool-stm32duino/dfu-util/dfu-util ']'
+ /Users/<user>/.platformio/packages/tool-stm32duino/dfu-util/dfu-util -d 1EAF:0003 -a 2 -D /Users/<user>/Documents/PlatformIO/Projects/xxx-tests/230310-bluepill-general-test/.pio/build/genericSTM32F103C8/firmware.bin -R -R
dfu-util 0.8

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2014 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/

dfu-util: Invalid DFU suffix signature
dfu-util: A valid DFU suffix will be required in a future dfu-util release!!!
Opening DFU capable USB device...
ID 1eaf:0003
Run-time device DFU version 0110
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
Copying data from PC to DFU device

[DOWNLOADING]

Download done.
state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present
Done!
Resetting USB to switch back to runtime mode
+ echo -n Waiting for /dev/cu.usbmodem14301 serial...
+ COUNTER=0
+ '[' '!' -c /dev/cu.usbmodem14301 ']'
+ echo Done
Waiting for /dev/cu.usbmodem14301 serial...Done
=====
[SUCCESS] Took 6.12 seconds =====

Environment           Status    Duration
--------------------  --------  ------------
bluepill_f103c8       IGNORED
genericSTM32F103C8    SUCCESS   00:00:06.123
bluepill_f103c8_128k  IGNORED
=============================================```

Okay so it was just the return value of 1 from upload-reset keeping it from working.

Yeah the error (and I firmly believe not declaring int main and doing return 0; is a bug) was also already visible in Upload-reset: No such file or directory - #5 by pfeerick.

Maybe this only occurs on some systems or maybe it doesn’t even persist accross reboots when the memory layout is different.

Could you do one final test: Backup the original upload-reset binary somewhere.

Download the new source code at upload-reset.c · GitHub and save it somewhere.

Recompile the binary using clang or gcc or whatever native compiler you have on your system

gcc -o  /Users/<user>/.platformio/packages/tool-stm32duino/upload-reset -Os <path to new source code>

Then revert the || true quickfix. Does it still work?

I reverted the quickfix and compiled the updated binary you posted (I had to download Command Line Tools for Xcode 14.2 (YMMV) from developer.apple.com (Free account required).

It still works! :white_check_mark:

1 Like

:beetle: :gun::laughing:

1 Like