Note: let’s use “F103” as shorthand to avoid typing “STM32F103C8T6” all the time
The F103 has a built-in ROM-based boot loader, so there’s no risk of ever damaging it, but it’s quite limited since it can only deal with a serial connection on the USART1 pins (PA9 for TX and PA10 for RX). There is no way to reflash an empty or messed-up F103 from USB.
In addition, every ARM chip has either JTAG hardware built-in, or its low-pincount variant, called SWD. This is a very powerful mechanism which is separate from the µC core itself, to access memory, peripherals, and even the chip’s pins with a “JTAG programmer”.
But the implication of all this is that an F103 requires additional hardware to be programmed: either a USB-serial (a.k.a. FTDI or USB-TTL) converter, or a JTAG/SWD programmer. Since SWD programming is fully supported on the F103, you could use either an ST-Link (many clones available from eBay) or a Black Magic Probe (which uses an F103 itself, by the way).
You can search this weblog for several older articles about ST-Link and the BMP. One benefit of the BMP is that it can also act as USB serial port via a separate header.
For very powerful debugging of firmware written in C or C++, JTAG/SWD offers advanced feaures such as hardware “breakpoints” and “watchpoints”. This requires “gdb” - the GNU Debugger - or one of the many front-ends made for it.
But there is more to embedded development than uploading and debugging. We need a way to communicate with our program during actual use, and we need to supply power to the board. With JTAG/SWD, before you know it, you’ll have to attach three cables to make it all usable.
Luckily, there’s a way out: a USB-serial adapter can be used to perform all three tasks through one cable: uploads, serial comms, and a 5V power feed. It won’t do hardware debugging, but you can always attach an extra BMP when you really have to dig that deep to solve problems.
Here’s one way to work fully through a single USB connection:
Four wires in total: 2 for power, 2 for RX/TX (note that RX and TX need to be crossed-over!).
If you’re feeling adventurous, you could also hook up a permanent FTDI header:
It’s not the most convenient setup, as will become clear below, but it’s the simplest possible setup that will work, and it should work with just about every USB-serial / FTDI / BUB / FRIEND / BOB / eBay clone out there. Perhaps most importantly: this hookup can restore every F103 to a working condition. As long as it hasn’t been electrically damaged, of course.
Note that regardless of which USB serial interface you use, you’ll need to get
it working with your host computer - be it running Windows, MacOS, or Linux.
This may require a driver installation - the USB interface vendor should be able
to tell you. All we need is a working serial connection, i.e. the USB interface
showing up as a “Virtual Comm Port” - COM<N>:
on Windows, /dev/tty/cu.*
on
MacOS, and /dev/ttyUSB<N>
or /dev/ttyACM<n>
on Linux.
Two more hurdles remain: 1) putting the F103 in ROM boot mode, and 2) sending the proper commands to it to erase and re-flash its firmware.
Entering boot mode is easy. Change the yellow jumpers to look as follows, then press reset:
Boot mode is entered when BOOT0 is “1” and BOOT1 is “0” (normal run mode is both “0”).
The F103 will now be running its ROM boot loader, waiting for an autobaud sequence on the PA9/PA10 pins. To get out of boot mode: restore the original jumpers and press reset again.
The last step is to use the proper utility for sending uploads. This uses a special protocol (described in this PDF). The protocol requires the connection to be set to even parity 8-bit.
One option is to use stm32loader, which is a Python script and uses the PySerial package:
TTY=/dev/cu.usbmodem14123
APP=/path/to/your/compiled/app.bin
stm32loader.py -e -w -v -p $TTY -a 0x8000000 $APP
Where TTY
and APP
need to be adjusted to match your own requirements. Note
that you can enter this command to get a brief command-line summary:
“stm32loader.py --help
”.
Another utility which works in a very similar fashion is stm32flash, a compiled C program.
Lastly, there is Folie v2. It’s written in Go and has pre-compiled binaries for all the common platforms on GitHub. To use Folie just for uploading of a .bin or .hex file, proceed as follows:
- download the proper build for your platform from the releases page
- or if you have Go installed, build from source:
go get github.com/jeelabs/folie
- launch as “
folie -r
” from the command line (or “/path/to/folie -r” if needed) - select the serial port to connect to from the list
- enter “
!upload /path/to/your/compiled/app.bin-or-hex
” and press return - once the upload completes, enter CTRL-D to exit Folie
Note that all these approaches require the F103 to already be in boot mode.
Once you have succesfully uploaded your application to the F103, you need to restore the jumpers to the normal state (i.e. all on the left in the above images). Then press reset and the newly uploaded code will start running.
There is some inconvenience with all this, because you have to repeat these same steps for every single upload: change jumpers, reset, upload, restore jumpers, reset. An alternative which greatly streamlines this process will be presented in a future article. Stay tuned!