Flashing CircuitPython to STM32F4 using SWD Programmers and OpenOCD on Windows

<rawat.s>
5 min readOct 29, 2021

.

This article describes how to flash CircuitPython firmware (.bin) to a STM32F4 microcontroller board (such as the WeAct Studio STM32F411CEU6 board) by using the OpenOCD (for Windows) open source software on a Windows computer. An SWD (Serial Debug Wire) compatible debug probe or hardware programmer, such as J-Link OB Debug Probe, ST-Link/v2 USB Dongle and CMSIS-DAP/DAPLink Probe, can be used for this purpose.

Preparation Steps

  1. Download the latest CircuitPython firmware file from https://circuitpython.org/board/stm32f411ce_blackpill/. As of the writing of this article, the latest version of CircuitPython is 7.0.0.
  2. Install OpenOCD for Windows which is maintained by the xPack project (https://github.com/xpack-dev-tools/openocd-xpack/releases).
  3. Install Git for Windows which can be downloaded from https://git-scm.com/downloads.
  4. Install USB Driver Tool v2.1 for Windows (https://sysprogs.com/getfile/1372/UsbDriverTool-2.1.exe).
  5. Connect the STM32 board to the device programmer via SWD. Four pins are used: VCC=+3.3V , SWDIO, SWDCLK, and GND.
  6. Connect the A9 and A10 pins on the STM32F4 board together and pulled up to 3.3V with a 4.7k or 10k Ohm resistor.
  7. Connect the SWD programmer to the USB port of the host computer.
CircuitPython firmware (.bin) for STM32F11CE Black Pill, provided by Adafruit

Using J-Link Debug Probe (SWD) with OpenOCD

.

In this section, we will use a J-Link OB device to flash the CircuitPython firmware.

  1. Open the USB Driver Tool, select the Device Name “J-Link” and change the USB driver for this device, from J-Link driver to WinUSB driver. This step is necessary because OpenOCD will work with the WinUSB driver.
USB Driver List on Windows shown by USB Driver Tool
Select “J-Link Driver (Segger)” and Click the “Install” button
Select “WinUSB (universal driver)” and click the “Install” button
The WinUSB driver is now selected for the J-Link OB device.

2. Open the Git Bash and run the following commands:
— note that the symbol ‘$’ represents the Bash shell prompt.

# show the location of the openocd.exe program 
$ where openocd.exe
# set the path to the CircuitPython firmware file
$ FIRMWARE_BIN="adafruit-circuitpython-stm32f411ce_blackpill-en_US-7.0.0.bin"
# Erase the on-chip flash and program the firmware
$ openocd.exe -f interface/jlink.cfg \
-c "transport select swd" -f target/stm32f4x.cfg \
-c "reset_config none separate; adapter speed 480;" \
-c "telnet_port disabled" \
-c "init" -c "reset init" \
-c "stm32f4x unlock 0; reset halt" \
-c "flash erase_sector 0 0 last" \
-c "sleep 100" \
-c "init" -c "reset init" \
-c "program $FIRMWARE_BIN verify 0x8000000" \
-c "reset" -c "exit"
Screenshots: Executing command lines under Git Bash Shell
STM32F411CEU6 + J-Link OB (STM32F103-based)

After flashing the microcontroller board with CircuitPython, it mounts automatically and appears as a USB storage drive as “CIRCUITPY” in Windows Explorer.

Using CMSIS-DAP Programmer / Debugger with OpenOCD

.

We can also use a CMSIS-DAP / DAPLink compatible device for flashing the firmware via the SWD interface.

Examples of CMSIS-DAP / DAPLink devices tested with OpenOCD:

NanoDAP-HS by MuseLab (two different versions and sizes, but with the same MCU chip)
nanoDAP-HS (top view)
nanoDAP-HS (bottom view)
nanoDAP-HS and Seeeduino XIAO (both with a USB Type-C port)
STM32F4 BlackPiil board interfaced with nanoDAP-HS via the SWD interface
STM32F4 BlackPill interfaced with Seeeduino (CMSIS-DAP v2)

Note: When using the Seeeduino XIAO board as a CMSIS-DAP V2 debug probe (VID=2886,PID=802F), please choose the WinUSB driver.

SWD pin configuration for Seeeduino (Default)

PIN_SWDIO  = A9
PIN_SWCLK = A10
PIN_TDO = A2
PIN_TDI = A3
PIN_nRESET = A8
Seeedduino XIAO pinout (top view)

Steps to flash the firmware:

  1. Press and hold the BOOT button on the board, and then press the RESET button — this MCU will enter the bootloader mode.
  2. Run the following commands:
# set the path to the CircuitPython firmware file
$ FIRMWARE_BIN="adafruit-circuitpython-stm32f411ce_blackpill-en_US-7.0.0.bin"
$ openocd.exe -f interface/cmsis-dap.cfg \
-c "transport select swd" -f target/stm32f4x.cfg \
-c "telnet_port disabled" \
-c "reset_config srst_nogate" \
-c "adapter speed 480" \
-c "init" -c "reset init" \
-c "stm32f4x unlock 0; reset halt" \
-c "flash erase_sector 0 0 last" \
-c "sleep 100" \
-c "init" -c "reset init" \
-c "program $FIRMWARE_BIN verify 0x8000000" \
-c "reset" -c "exit"

Here are some screenshots of the command execution in the Git bash shell and the output messages:

Using the ST-Link/V2 USB Dongle with OpenOCD

.

When using a ST-Link/V2 USB dongle, run the following commands:

# set the path to the CircuitPython firmware file
$ FIRMWARE_BIN="adafruit-circuitpython-stm32f411ce_blackpill-en_US-7.0.0.bin"
$ openocd -f interface/stlink.cfg \
-c "transport select hla_swd" \
-f target/stm32f4x.cfg \
-c "reset_config none separate" \
-c "init" -c "reset halt" \
-c "adapter speed 480" \
-c "flash erase_sector 0 0 last" \
-c "flash write_bank 0 $FIRMWARE_BIN 0" \
-c "reset" -c "exit"

--

--