STM32 Serial Boot loader

September 20, 2016

I am working with a generic STM32F103 board.

This board has a serial bootloader on board, that runs on serial port 1. (There are 3 serial ports, numbered 1, 2, and 3). This port is on pins PA9 (tx1) and PA10 (rx1). Naturally the signals are at 3.3 volt levels.

It is not yet clear to me if this loader is in flash or is some permanent part of the chip. It may be possible to install some kind of USB boot loader. This would be more convenient, but would use more of the 64K flash.

To get the bootloader running, you must set the BOOT0 jumper to 1 and the BOOT1 jumper to 0. On my "blue pill" board, the jumper away to the reset buton is "BOOT0". After setting the jumpers the board must be power cycled or reset.

Then you need some USB to serial gadget that uses 3.3 volt levels.

On linux, you need the python loader script:

To run this and flash some new code you do something like:
./ stm32loader.py -p /dev/ttyUSB2 -evw mycode.bin
However, on my Fedora system, I need to first install the python serial module:
dnf install pyserial
After this, we have some success. I make a symbolic link since I am lazy.
ln -s stm32loader.py loader
./loader -p /dev/ttyUSB1 
Bootloader version 0x22
Chip id 0x410, STM32F1, performance, medium-density
It turns out that the python version has now been replaced by a compiled C loader for one reason or other and that is what you are advised to use: After fixing 3 or 4 silly bugs it compiles.
./stm32ld /dev/ttyUSB1 115200 0 0
Found bootloader version: 2.2
Chip ID: 0410
Skipping flashing ... 
Note also that in reading the documents from ST about the boot loader, two things are clear. One is that the boot loader resides in "system memory" which does not consume any of flash (and is apparently immutable, so it will be hard to brick one of these units). The other thing is that a USB DFU mode is supported as part of the boot loader in system memory, so making this useful would be a nice step as it would obviate the need for a USB to serial gadget.

Ruby and serial ports

These programs and scripts are so lame, I may try my hand at the serial protocol myself. My scripting language of choice is ruby, and this will be my first chance to try using the serial port module:
dnf install rubygem-serialport
What I want to do in particular is to read out the present contents of flash (as well as other areas). The C program seems to be tailored just for flashing images. The Python script is more versatile, but still has refused to do the following and read out flash contents. The base address is from the C "stm32ld" program.
tom@trona STM32]$ ./loader -p /dev/ttyUSB1 -a 0x08000000 -l 2048 -r
Bootloader version 0x22
Chip id 0x410, STM32F1, performance, medium-density
Read 256 bytes at 0x8000000
Traceback (most recent call last):
   ... blah blah blah
__main__.CmdException: Chip replied with a NACK during 0x11
Giving all the traceback is lame. If you know there is an error, then report it and exit (traceback is for developers, not end users). Besides that, why does the read from flash fail?

FTDI serial

I dug around and found my FTDI basic from Sparkfun. It needed a bit of surgery to convert it from the "factory" supplied 5 volt configuration to 3.3 volts. Then I started to wonder about using the 3.3 volt output provided by it to power the STM32. The FTDI chip provides a 3.3 volt output, but the specification limits it to 50 mA, which is by no means surprising. Is this really adequate to power the STM32 while flashing firmware? Apparently so. Looking at the datasheet, 50 mA is pretty much the most current it can be expected to draw, with 40 mA being typical, and if the clock rate is dropped from the full 72 Mhz this can be significantly reduced.

So, I connected this up as follows:

FTDI ground --- ground on edge of STM
FTDI 3.3 --- 3.3 on edge of STM
FTDI Rx ---- A9 on STM (Tx)
FTDI Tx ---- A10 on STM (Rx)
Then I plug it in and start playing with the python script.

Resources and links


Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org