Blink an STM32F103C8 "blue pill" development board (LED on PC13) using various methods:
- cubemx: using STMicroelectronics' STM32CubeMX platform
- opencm: using libopencm3 library function calls
- opencm-registers: using libopencm3, but only for register definitions
- bare-metal: using no libraries
Size of each binary for comparison:
pill_blink $ find . -name '*.bin' -exec ls -l {} \;
-rwxr-xr-x 1 admin staff 3496 Dec 22 20:58 ./cubemx/build/pill_blink.bin
-rwxr-xr-x 1 admin staff 1088 Dec 22 22:43 ./opencm/pill_blink.bin
-rwxr-xr-x 1 admin staff 608 Dec 22 23:00 ./opencm-registers/pill_blink.bin
-rwxr-xr-x 1 admin staff 440 Dec 23 00:10 ./bare-metal/pill_blink.bin
How to build these examples? First, install an ARM compiler, I use the GNU ARM Embedded Toolchain
installed via Homebrew as follows: brew cask install gcc-arm-embedded
. See each individual project directory for
additional instructions; all are using the make
tool for building.
Where to acquire a blue pill? Search on Aliexpress or eBay for "stm32", look for the cheapest. I use these:
- STM32F103C8T6 ARM STM32 Minimum System Development Board Module, ~$1.70
- Free Shipping STM32F103C8T6 ARM STM32 Minimum System Development Board Module Forarduino, $1.85
How to flash the firmwares? You can use any USB-to-serial adapter, but for development I prefer to flash another blue pill as a Black Magic Probe since it can be used both for uploading via serial and debugging via SWD, see: Converting an STM32F103 board to a Black Magic Probe. Assuming you want to do this too, connect the Black Magic Probe blue pill to the target blue pill as follows:
Black Magic Probe blue pill | target blue pill |
---|---|
A2 (TX) | A10 |
A3 (RX) | A9 |
A5 (SWCLK) | SWD header CK |
B14 (SWDIO) | SWD header O |
GND | GND |
5V | 5V |
If using a regular USB-to-serial adapter, connect only A10 and A9 and ground. For flashing the firmware I use stm32loader, example:
python stm32loader.py -p /dev/cu.usbmodemE3C896E3 -e -w -v bare-metal/pill_blink.bin
How to debug? Use a dongle capable of the Serial Wire Debug protocol, connect to the right-angle header on the blue pill board, assuming you're using a BMP (see above), connect using GDB:
arm-none-eabi-gdb -ex "target extended-remote /dev/cu.usbmodemE3C896E1" -ex "monitor swdp_scan"
then attach with att 1
and you should be able to continue, examine registers and memory, and step through as usual. To load symbols, build
with make CFLAGS+=-g
and load the elf with file
.
+ arm-none-eabi-gdb -ex 'target extended-remote /dev/cu.usbmodemE3C896E1' -ex 'monitor swdp_scan'
Available Targets:
No. Att Driver
1 STM32F1 medium density
(gdb) att 1
Attaching to Remote target
warning: No executable has been specified and target does not support
determining executable automatically. Try using the "file" command.
0x08000194 in ?? ()
(gdb) file pill_blink/bare-metal/pill_blink.elf
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Reading symbols from pill_blink/bare-metal/pill_blink.elf...done.
(gdb) c
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x0800017e in reset_handler () at pill_blink.c:9
9 for (int i = 0; i < 1000000; ++i) __asm__("nop");
(gdb)
Any simpler? Yes, see also Arduino for STM32 at stm32duino.com, for a friendlier
Arduino-compatible STM32 platform where digitalWrite()
can toggle the LED, but these
examples are primarily intended as experiments in lower-level embedded programming without Arduino, for background see also:
STM32 Blue Pill ARM development board first look: from Arduino to bare metal programming.
See also accompanying blog post: JTAG/SWD debugging via Black Magic Probe on an STM32 blue pill and blinking a LED using STM32CubeMX, libopencm3, and bare metal C
--