One of the more attractive features or the STM32 processors, at least in their more recent revisions, is the presence of a built-in serial bootloader. JTAG is all very well but you need extra hardware and then software to drive it. If you want to do in-circuit debugging, it is ideal. However, for my use, I don’t much want a 20 pin header and I find the debugging feature for a micromouse to be a little redundant. Debugging can be done on a static test rig. But then, if I want to update the mouse software, a serial bootloader is perfect and I can use the same serial connection to communicate with my code when it is running
The STM32 has two pins which can be used to determine where the processor looks for code when it starts up. These are BOOT0 and BOOT1. The following table gives their function: [Corrected 16 May 2009 – PH]
BOOT1 | BOOT0 | Boot Mode |
X | 0 | Boot from user flash |
0 | 1 | Boot from System Memory |
1 | 1 | Boot from embedded RAM |
If we forego the option to boot from RAM, we can hold BOOT1 low and add a switch or jumper to BOOT0. If BOOT0 is high after a reset, the processor boots from system memory which, as delivered, means the bootloader. Holding the pin low boots from the on-board user flash and executes our code.
You can find a full description of the bootloader in the ST document AN2606
http://www.st.com/stonline/products/literature/an/13801.pdf
ST provide a flash loader application both as a Windows GUI application and as a command line program. Both versions are really just too much like hard work and you won’t use them much before looking for a better way. And there is one. It is a Python script originally written by Ivan A-R and available from here:
http://tuxotronic.org/wiki/projects/stm32loader
The page is in Russian but the comments and help are in English. The version there seems to have a small bug relating to writing a file containing the contents of the chip. I found a fix for that but can’t remember the location of that page so here is a revised version that I have used to successfully write and read the STM32F103RBT6 devices on my test boards.
My development platform at present is a Mac. That means I get Python already present on the system. If you have a Linux box, it may well have Python installed or it will be easy to do so. It can also be readily installed on Windows. Be sure to get Python 2.6.x as there are syntax differences that will stop the script from running in Python 3. Have a look here:
http://www.python.org/download/
Before you can use the script, you will also need to get the PySerial library from here:
http://pyserial.wiki.sourceforge.net/pySerial
This is needed so that Python can talk to the serial ports. Once you have the script, run it with the –h switch to get some help:
stm32loader.py [-hqVewvr] [-l length] [-p port] [-b baud] [-a addr] [file.bin] -h This help -q Quiet -V Verbose -e Erase -w Write -v Verify -r Read -l length Length of read -p port Serial port (default: /dev/tty.usbserial-ftCYPMYJ) -b baud Baud speed (default: 115200) -a addr Target address ./stm32loader.py -e -w -v example/main.bin
My script defaults to the normal location of my serial port. You will need to change that to suit your circumstances or use the appropriate switches. Note that the loader only understands binary files, not hex files. If you are using another toolchain you will need to get it to create binary files. If you have a hex file, it can be converted to a binary file with the following command:
arm-eabi-objcopy -I ihex -O binary data.hex data.bin
It is also necessary to erase the chip on each write so your typical write command looks like this:
stm32loader -evw data.bin
The script will know how much data to transfer and will default to writing it to location 0x08000000. Reading data requires that you tell the script how much you want and the name of the file you want it stored in.
stm32loader –r –l 0x1000 data.bin
To use the loader
- set your switch/jumper to make BOOT0 high
- press the reset button on the board
- run the script
- wait until it is done
- set the switch/jumper to make BOOT0 low
- reset the board to run your code
Once in loader mode, the chip waits for data from the computer and does an autobaud detection to determine transfer speed. Sometimes I seem to need to do this a couple of times before it works. That may be because I would be better off with a lower speed. Next we need to write something worth putting in the chip. Stay tuned.
looks like you are mistaking boot0 and boot1 in the last part of your article
apart from that, thanx alot
Oops.
Thanks for pointing that out.
The error is actually in the earlier part of the item. The instructions at the end are correct.
I have updated it all to be consistent.
[…] The Python based stm32loader […]
Does the built-in serial bootloader work like TSR? Or we should press reset to call it back?
It is always there. Look in the text to see how to use it. You need only to set a pin level on the processor and it starts up on reset, listening to the serial pins.
Hi,
Just thought I would drop a link here to a C based GPL 2.0 licensed flash program I have been developing, I did find your flash program first, but it relies on perl which I prefer not to use on my system.
http://stm32flash.googlecode.com/
If someone wants to write a serial_windows.c driver for it, it will also be cross platform. Supports a few things your perl script doesn’t such as device model detection, Intel HEX parsing, and resume already initialized connection support.
Still to come are the protection functions, but it is already usable in its current state.
Just realized its Python, not Perl, but still, a scripted language which I would prefer to avoid.
This is a handy looking utility. Thanks for sharing.
Hi, I have downloaded your stm32Loader.py but it doesn’t seem to work in my Ubuntu machine. I am getting this errors:
andrei@Tux:~/Desktop$ ./stm32loader.py -evw ET-STM32F103.bin
Bootloader version 22 Chip id `[‘0x4’, ‘0x14′]’
Write 256 bytes at 0x8000000
Write 256 bytes at 0x8000100
Write 256 bytes at 0x8000200
Write 256 bytes at 0x8000300
Write 256 bytes at 0x8000400
Write 256 bytes at 0x8000500
Write 256 bytes at 0x8000600
Write 256 bytes at 0x8000700
Write 256 bytes at 0x8000800
Write 256 bytes at 0x8000900
Write 256 bytes at 0x8000A00
Traceback (most recent call last): cmd.writeMemory(conf[‘address’], data)
File "./stm32loader.py", line 414, in
File "./stm32loader.py", line 289, in writeMemory self.cmdWriteMemory(addr, data[offs:offs+256])
File "./stm32loader.py", line 175, in cmdWriteMemory self._wait_for_ask("0x31 address failed")
File "./stm32loader.py", line 73, in _wait_for_ask raise CmdException("NACK "+info)
__main__.CmdException:
NACK 0x31 address failed
I am afraid I do not use this script any longer as I have changed my toolset. However, the error you see comes from the script itself rather than the system. It seems to be a communication error with the bootloader code in the target chip. You might try a lower speed and/or a smaller binary image first.
I found an error in the stm32loader.py script. In fact it reads the file in text mode instead of binary mode so, when it reaches a EOF character (0x1a), it ends. To solve this problem the line 408 must be modified as follows:
data = map(lambda c: ord(c), file(args[0], 'rb').read())
I don’t have the means to test this fix but it appears to be correct so thank you very much.
I have updated the download file with the change you suggested.
Thnk you for your kindnees~~lovly man~!thnnnnnnnnk you!
thank you
i was wondering did any one got STM32loader working on pyton 2.6 or 2.7. if so please help me i am trying to program a bootloader of my own. any help would be appreciated
thank you
i have tried running the file but it is not working for me. again any help would be appreciated