Flashing BluePill STM32duino Bootloader & QMK on Linux (For M-Star Model M Keyboard Kit)

Hello!
I’m writing this little info article to help anyone who was on the struggle bus like me. It took a lot of trying to flash QMK on our BluePills for the M-Star Classic Kit (specifically Linux). When I tried to recreate our QMK setup on a linux PC, oml. I ran into a surprising amount of trouble!

The great thing about this guide is that (hopefully) it is universal enough to where you have the foundation to download whichever Arduino IDE bootloader package you need, then make/flash your own QMK for other projects!

For more info about the classic kits check out my
All About Level1Techs M-Star DIY Keyboard Controller Kits
guide.

Prerequisites

Just some things you need to do/have/buy before you’re able to flash anything. Universal things you need are right below, then seperatd into Windows and Linux.

Adafruit ST-Link v2 USB Adapter

Buy here → ST-Link STM8/STM32 v2 Compatible Programmer & Emulator : ID 2548 : $14.95 : Adafruit Industries, Unique & fun DIY electronics and kits

Make sure the pins are connected to the correct ends! The BluePill will be labeled as are the link usb. Once you’re done with that, electrical tape is pretty good at holding the 4-pins together.

BluePill

You can order your own, or you can buy the replacement kit from Level1Techs that comes with a pre-flashed BluePill and a PCB with surface mounts ready a for model M.

.bin Bootloader File

Whether or not you use Windows or Linux, you will need the .bin file that has the stm32duino bootloader configuration. You will still probably use linux for QMK, but the bootloader is much easier on Windows.
STM32duino-bootloader-PB2.zip (5.0 KB)

For the guide I put the .bin file in ~/ for easy access.

Linux

For this setup I was using Pop!OS. Commands/setup may vary depending on your distro. Ubuntu and similar flavors should be the same as what I’m doing.

Install Git & Python

QMK Setup page says they’re necessary.

sudo apt install -y git python3-pip

Clone QMK Repository

I put mine in ~/ but if you want it somewhere else, just remember for future commands where you put it.

cd ~
git clone https://github.com/qmk/qmk_firmware.git

Add User To Dialout Group

Even if you do all the steps correctly, without being in the dialout group you will not have the correct permissions.

sudo adduser <user> dialout

Windows

Install the ST-Link Utility Drivers

Download here → https://www.st.com/en/development-tools/stsw-link009.html

Install the ST-Link Utility Programmer

Download here → https://www.st.com/en/development-tools/stsw-link004.html

Bootloader Flash (Windows)

  1. Start ST-Link Utility and open the .bin file.

  2. In Target → Settings, Make sure “Hardware reset” and “Connect under reset” are set from the drop down manus. Also, toggle on “low power debug mode.”

  3. Press and hold the “reset” button on the blue pill.

  4. Go to Target → Click on “Connect”

  5. Let go of the reset button. (It should be connected now).

  6. Go to Target → Click on “Program” make sure “reset after programming” is toggled on and click “Start”

  7. Ctrl + D will safely disconnect the BluePill.

Missing .DLL Files Error
I had an issue where the ST-Link Utility would not open, turns out this was due to not having the “Microsoft Visual C++ 2015 Redistributable Update 3 RC” installed. Also, according to the website (linked below) you need the 32bit version. I installed and sure enough, that worked.
Download here → https://www.microsoft.com/en-us/download/details.aspx?id=52685

Bootloader Flash (Linux)

First off, the ST-Link Utility is a Windows-based program. To do this in Linux we could (and I did) try to use a virtual machine, but I decided there must be a better way. (There was!)

STM32dunio Package For Arduino IDE

The .arduino15 folder we’re going to create is how we will flash the BluePill without needing the Windows ST-Link Utility.
The arduino section will install the foundation, specifically ~/.arduino15/packages/

Arduino IDE v2
Download here → https://www.arduino.cc/en/software

  1. Once installed, navigate to File → Preferences
    In the “Additional Boards Managers URL” box copy an paste:

    http://dan.drown.org/stm32duino/package_STM32duino_index.json

    Click ok to get out of the window.

  2. Next, go to Tools → Boards → Boards Manager
    In the window that pops up, search for “STM32”

    You’ll want to install the “STM32F1xx” by stm32dunio. It has “Maple Mini” in the description.
    → Click Install.

Clicking install adds the stm32duino folder in ~/.arduino15/packages/

STM32dunio .sh File

The Arduino IDE so rudely assumes we are using Windows, so you need to manually navigate to the linux directory and install the linux version of the package. Depending on the version of things you might have a different folder date than me.

cd ~/.arduino15/packages/stm32duino/tools/stm32tools/2022.9.26/linux
./install.sh

Bootloader Commands

Before we start flashing, make sure the BOOT0 pin in high and the BOOT1 pin is low. It won’t work otherwise!


picture from Getting Started with STM32F103C8T6 Blue Pill | Program with Arduino IDE

Once you go 1 folder down to /stlink
→ Here, you can also run a probe command to make sure it’s working correctly.

cd ~/.arduino15/packages/stm32duino/tools/stm32tools/2022.9.26/linux/stlink
st-info --probe

Result

Found 1 stlink programmers
  version:    V2J29S7
  serial:     52FF78067287514823160467
  flash:      65536 (pagesize: 1024)
  sram:       20480
  chipid:     0x0410
  descr:      F1xx Medium-density

If something weird pops up like “unknown” you probably have it not plugged in, wires placed incorrectly, or maybe you just need to unplug & plug it back in. Sometimes things decide to just work or not work after a bit of use lol

Still in the /stlink folder, we can now flash the bluepill with the bootloader and .bin file you downloaded at the beginning! Yay!

st-flash --reset write ~/STM32duino-bootloader-PB2.bin 0x8000000

Result — Success!!

st-flash 1.7.0
2023-05-25T16:58:12 INFO common.c: F1xx Medium-density: 20 KiB SRAM, 64 KiB flash in at least 1 KiB pages.
file /home/w/STM32duino-bootloader-PB2.bin md5 checksum: c6e9f747f7812876fde1ed22d3ac913, stlink checksum: 0x0009036f
2023-05-25T16:58:12 INFO common.c: Attempting to write 7108 (0x1bc4) bytes to stm32 address: 134217728 (0x8000000)
2023-05-25T16:58:12 INFO common.c: Flash page at addr: 0x08000000 erased
2023-05-25T16:58:12 INFO common.c: Flash page at addr: 0x08000400 erased
2023-05-25T16:58:12 INFO common.c: Flash page at addr: 0x08000800 erased
2023-05-25T16:58:12 INFO common.c: Flash page at addr: 0x08000c00 erased
2023-05-25T16:58:12 INFO common.c: Flash page at addr: 0x08001000 erased
2023-05-25T16:58:12 INFO common.c: Flash page at addr: 0x08001400 erased
2023-05-25T16:58:12 INFO common.c: Flash page at addr: 0x08001800 erased
2023-05-25T16:58:12 INFO common.c: Finished erasing 7 pages of 1024 (0x400) bytes
2023-05-25T16:58:12 INFO common.c: Starting Flash write for VL/F0/F3/F1_XL
2023-05-25T16:58:12 INFO flash_loader.c: Successfully loaded flash loader in sram
2023-05-25T16:58:12 INFO flash_loader.c: Clear DFSR
  7/  7 pages written
2023-05-25T16:58:12 INFO common.c: Starting verification of write complete
2023-05-25T16:58:12 INFO common.c: Flash written and verified! jolly good!

QMK Flash (Linux)

Remember to set your BOOT0 and BOOT1 pins back down to LOW. Also, connect the BluePill to your PC with a micro USB on the opposite end instead of the link usb!

I downloaded the m_star_classic folder from the M-Star Gitlab repository and moved it into the “~/qmk_firmware/keyboards/” folder.

With the proper .rules file set & bootloader flashed, you should be able to run this:

cd ~/qmk_firmware/keyboards/m_star_classic
qmk flash --keymap default

Depending on what QMK you want to flash, just change the word “default” to whatever you’re wanting. e.g. “wendell” for his custom preset.

Result – Success!!

Ψ Compiling keymap with gmake --jobs=1 m_star_classic:default:flash


QMK Firmware 0.20.8
☒ Invalid LAYOUT macro in keyboards/m_star_classic/m_star_classic.h: Key k4J in macro LAYOUT_at122 has no matrix position!
☒ Invalid LAYOUT macro in keyboards/m_star_classic/m_star_classic.h: Key k5I in macro LAYOUT_at122 has no matrix position!
☒ Invalid LAYOUT macro in keyboards/m_star_classic/m_star_classic.h: Key K64 in macro LAYOUT_at122 has no matrix position!
☒ Invalid LAYOUT macro in keyboards/m_star_classic/m_star_classic.h: Key k76 in macro LAYOUT_at122 has no matrix position!
☒ Invalid LAYOUT macro in keyboards/m_star_classic/m_star_classic.h: Key K6B in macro LAYOUT_at122 has no matrix position!
☒ Invalid LAYOUT macro in keyboards/m_star_classic/m_star_classic.h: Key k7C in macro LAYOUT_at122 has no matrix position!
☒ Invalid LAYOUT macro in keyboards/m_star_classic/m_star_classic.h: Key k7D in macro LAYOUT_at122 has no matrix position!
☒ Invalid LAYOUT macro in keyboards/m_star_classic/m_star_classic.h: Key k0I in macro LAYOUT_at122 has no matrix position!
⚠ m_star_classic: UNUSED_PINS in config.h is deprecated and will be removed at a later date
⚠ m_star_classic: PRODUCT_ID in config.h is deprecated in favor of `usb.pid` in info.json and will be removed at a later date
⚠ m_star_classic: VENDOR_ID in config.h is deprecated in favor of `usb.vid` in info.json and will be removed at a later date
⚠ m_star_classic: PRODUCT in config.h is deprecated in favor of `keyboard_name` in info.json and will be removed at a later date
⚠ m_star_classic: MANUFACTURER in config.h is deprecated in favor of `manufacturer` in info.json and will be removed at a later date
⚠ m_star_classic: DEVICE_VER in config.h is deprecated in favor of `usb.device_version` in info.json and will be removed at a later date
Making m_star_classic with keymap default and target flash

☒ Invalid LAYOUT macro in keyboards/m_star_classic/m_star_classic.h: Key k4J in macro LAYOUT_at122 has no matrix position!
☒ Invalid LAYOUT macro in keyboards/m_star_classic/m_star_classic.h: Key k5I in macro LAYOUT_at122 has no matrix position!
☒ Invalid LAYOUT macro in keyboards/m_star_classic/m_star_classic.h: Key K64 in macro LAYOUT_at122 has no matrix position!
☒ Invalid LAYOUT macro in keyboards/m_star_classic/m_star_classic.h: Key k76 in macro LAYOUT_at122 has no matrix position!
☒ Invalid LAYOUT macro in keyboards/m_star_classic/m_star_classic.h: Key K6B in macro LAYOUT_at122 has no matrix position!
☒ Invalid LAYOUT macro in keyboards/m_star_classic/m_star_classic.h: Key k7C in macro LAYOUT_at122 has no matrix position!
☒ Invalid LAYOUT macro in keyboards/m_star_classic/m_star_classic.h: Key k7D in macro LAYOUT_at122 has no matrix position!
☒ Invalid LAYOUT macro in keyboards/m_star_classic/m_star_classic.h: Key k0I in macro LAYOUT_at122 has no matrix position!
⚠ m_star_classic: UNUSED_PINS in config.h is deprecated and will be removed at a later date
⚠ m_star_classic: PRODUCT_ID in config.h is deprecated in favor of `usb.pid` in info.json and will be removed at a later date
⚠ m_star_classic: VENDOR_ID in config.h is deprecated in favor of `usb.vid` in info.json and will be removed at a later date
⚠ m_star_classic: PRODUCT in config.h is deprecated in favor of `keyboard_name` in info.json and will be removed at a later date
⚠ m_star_classic: MANUFACTURER in config.h is deprecated in favor of `manufacturer` in info.json and will be removed at a later date
⚠ m_star_classic: DEVICE_VER in config.h is deprecated in favor of `usb.device_version` in info.json and will be removed at a later date
arm-none-eabi-gcc (15:10.3-2021.07-4) 10.3.1 20210621 (release)
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Size before:
   text	   data	    bss	    dec	    hex	filename
      0	  31614	      0	  31614	   7b7e	m_star_classic_default.bin

Compiling: quantum/command.c                                                                        [OK]
Linking: .build/m_star_classic_default.elf                                                          [OK]
Creating binary load file for flashing: .build/m_star_classic_default.bin                           [OK]
Creating load file for flashing: .build/m_star_classic_default.hex                                  [OK]

Size after:
   text	   data	    bss	    dec	    hex	filename
      0	  31614	      0	  31614	   7b7e	m_star_classic_default.bin

Copying m_star_classic_default.bin to qmk_firmware folder                                           [OK]
Flashing for bootloader: stm32duino
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/

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%        31616 bytes
Download done.
state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present
Done!
Resetting USB to switch back to runtime mode

.Rules Files Fix

This was my big hangup! Before I finally got QMK to flash, I kept getting the error:

Couldnt find the DFU device: [1eaf:0003]

I figured out this was an issue with a .rules file based on some other people’s posts. Apparently the .50-qmk.rules file was in the wrong spot…? Cloning the repository puts it in /util, but I randomly saw an article (linked below) that said to move it to /etc. Boom! Working. Let me know if you have more info on why moving to another folder fixed the issue. Also, why wasn’t it there to begin with…? Lol.

curl https://raw.githubusercontent.com/qmk/qmk_firmware/master/util/udev/50-qmk.rules -s -o 50-qmk.rules
sudo mv 50-qmk.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules
sudo udevadm trigger

Result

Opening DFU capable USB device...
ID 1eaf:0003
Run-time device DFU version 0110

Example

Quick and easy! The reason mine looks so short is because I put the bootloader into a .sh file, and QMK into a .sh file. Even without the bash files, it’s still pretty quick!

Resources

If it wasn’t for these sources, I wouldn’t have figured it out.

5 Likes