enricorossi.org

Enrico Rossi


Flash programming STM32 maple mini

I had a little confusion regarding how to flash a firmware into the maple mini board and, more in general, on the STM32 family microcontroller.

Normally I have always used an st-link V2 usb pen for both upload a new firmware and debugging purpose, but a friend ask me “why we can’t use the USB connector directly without any other adaptor?”

Digging a little bit I have found that STM32 micro do have an in-ROM bootloader to update the firmware, but it is not the same software on every stm32 device ( STMicroelectronics AN2606 which describe the stm32-microcontroller-system-memory-boot-mode).

Also, to complicate the scenario, some board do have a custom bootloader already installed which provide a more customizable way to upload a new firmware (arduino, maple mini, platformio boot etc…).

The maple mini should come with it’s own DFU bootloader pre-installed, but as an STM32 F103xxx family microcontroller it has a SERIAL only bootloader written in ROM (see the AN2606).

Serial Only stm32 flash bootloader (ROM)

One linux software to interact with that kind of bootloader is the stm32flash flash utility present in Debian main distribution (currently Debian 10).

Install with:

apt install stm32flash

Connect the serial port 1 of the maple to you PC using a serial port (if available) or an usb->serial adaptor, then connect the TX/RX of the serial port to the TX/RX (pin PA9/PA10, see maple boot on how to connect). In order to boot the maple mini into this bootloader mode the two pin boot 0 and boot 1 need to be Boot0(pin) = 1 and Boot1(pin) = 0 (described in Table 2: Bootloader activation patterns of the AN2606), where the boot1 pin need to be manually grounded (PB2 on the maple mini) and the Boot1 is the but=32 button present on the board.

To enter in the flashing mode, reset the board keeping the but=32 button pressed and the released, from the command line use:

> stm32flash /dev/ttyUSB2

stm32flash 0.5

http://stm32flash.sourceforge.net/

Interface serial_posix: 57600 8E1
Version      : 0x22
Option 1     : 0x00
Option 2     : 0x00
Device ID    : 0x0410 (STM32F10xxx Medium-density)
- RAM        : 20KiB  (512b reserved by bootloader)
- Flash      : 128KiB (size first sector: 4x1024)
- Option RAM : 16b
- System RAM : 2KiB

where /dev/ttyUSB2 is the serial port I’m currently using, but it can be something different.

Now it is time to download the maple mini bootloader (DFU) and flash it. I have choosen the STM32duino-bootloader which is already compiled and available under the bootloader_only_binaries directory.

> stm32flash -w maple_mini_boot20.bin -v -g 0x0 /dev/ttyUSB2

stm32flash 0.5

http://stm32flash.sourceforge.net/

Using Parser : Raw BINARY
Interface serial_posix: 57600 8E1
Version      : 0x22
Option 1     : 0x00
Option 2     : 0x00
Device ID    : 0x0410 (STM32F10xxx Medium-density)
- RAM        : 20KiB  (512b reserved by bootloader)
- Flash      : 128KiB (size first sector: 4x1024)
- Option RAM : 16b
- System RAM : 2KiB
Write to memory
Erasing memory
Wrote and verified address 0x08001bbc (100.00%) Done.

Starting execution at address 0x08000000... done.

and the blinking led should demonstrate that the DFU bootloader is now active.

DFU bootloader using the USB

Let’s check if the DFU bootloader is there using the dfu-util software:

Install and run it

> apt install dfu-util
> dfu-util --list

dfu-util 0.9

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

Deducing device DFU version from functional descriptor length
Found Runtime: [0a5c:2110] ver=0100, devnum=2, cfg=1, intf=3, path="2-1", alt=0, name="UNKNOWN", serial="UNKNOWN"
Found DFU: [1eaf:0003] ver=0201, devnum=19, cfg=1, intf=0, path="1-4.3", alt=2, name="STM32duino bootloader v1.0  Upload to Flash 0x8002000", serial="LLM 003"
Found DFU: [1eaf:0003] ver=0201, devnum=19, cfg=1, intf=0, path="1-4.3", alt=1, name="STM32duino bootloader v1.0  Upload to Flash 0x8005000", serial="LLM 003"
Found DFU: [1eaf:0003] ver=0201, devnum=19, cfg=1, intf=0, path="1-4.3", alt=0, name="STM32duino bootloader v1.0  ERROR. Upload to RAM not supported.", serial="LLM 003"

Let try to upload a software using the DFU over USB starting at the 0x8002000 address, in the example here I have a main.elf to be converted into a binary and downloaded into the board.

Compiling note: Now at the 0x8000000 memory address, the beginning of the flash on the Maple mini, there is the DFU bootloader, therefor your linker must compile your software starting at 0x8002000 (see linker files at the end).

arm-none-eabi-objcopy --output-target binary main.elf main.bin
dfu-util --device 1eaf:0003 --alt 2 --download main.bin

note the “–alt 2” tells the DFU to Upload to Flash starting at 0x8002000 address.

dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 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!!!
Deducing device DFU version from functional descriptor length
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
Download	[=========================] 100%        41936 bytes
Download done.
state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present
Done!

and the program should run after a reset.

Finally the last method I use is by using the st-link adaptor and the openocd utility. There is a vast amount of information details regarding on how to use the openocd to program/debug a firmware, here I can only dump a working example. Again I’m going to flash the bootloader we have flashed in the beginning with the serial line.

Install the openocd as usual:

apt install openocd

Connect the USB st-link v2 adaptor to the maple mini board by connecting the 5 pin RST, SWCLK, SWDIO, GND and 3.3V (search internet for detailed images) and run the openocd as

> openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg --command "bindto 0.0.0.0" 

Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
none separate
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v21 API v2 SWIM v4 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 3.245940
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : accepting 'telnet' connection on tcp/4444

and on another terminal (or computer) using telnet or nc (netcat) connect to the openocd and command to write the firmware.

> nc localhost 4444

> reset halt
reset halt
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08002914 msp: 0x20005000

> flash write_image erase maple_mini_boot20.bin 0x08000000 bin
flash write_image erase maple_mini_boot20.bin 0x08000000 bin
auto erase enabled
target halted due to breakpoint, current mode: Thread 
xPSR: 0x61000000 pc: 0x2000003a msp: 0x20005000
wrote 7168 bytes from file maple_mini_boot20.bin in 0.775920s (9.022 KiB/s)

> reset
reset

> exit
exit

note that since the bootloader is in binary format I have to specify the flashing address and the format (0x08000000 bin) on the write command. If the file to program is in ELF format, then no need to specify nor the address neither the format.

To complete this quick look at the openocd, if it is still connected to the board and suppose your software has been compiled with the debug switch, I can attach the gdb to the device using:

gdb-multiarch -tui --eval-command="target extended-remote localhost:3333" main.elf

Linker files:

Typical linker part used for the standard non DFU firmware (this is used in the libopencm3 library, check your projects).

MEMORY {
	rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
	ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
}

INCLUDE cortex-m-generic.ld

Modified for the DFU bootloader presence at 0x08002000:

MEMORY {
	rom (rx) : ORIGIN = 0x08002000, LENGTH = 120K
	ram (rwx) : ORIGIN = 0x20000c00, LENGTH = 17K
}

INCLUDE cortex-m-generic.ld