STM32 MCU: PlatformIO Setup
Use this page with AI
Set up with your favorite AI
Gemini & other AI
Copy the setup prompt into your AI. Work through each step together, from checking your kit to getting it running.
Copy the prompt, then paste it into Gemini’s message box.
View prompt
Table of contents
Introduction
This guide follows the Japanese STM32 PlatformIO guide and uses VS Code with PlatformIO to build a program that prints Hello World once per second. STM32CubeProgrammer uploads it through a USB leaf. You do not need Arduino IDE or its board package for this workflow.
Install the latest stable software from the official distribution sites. The STM32CubeProgrammer version pins in older instructions are no longer required for this workflow.
Required items
- STM32 MCU leaf (AP03 / STM32L452REI6) and a USB leaf
- A data-capable USB cable
- A Windows, macOS or Linux computer with an internet connection
For Basic Kit 2, replace the assembled AVR MCU with the STM32 MCU leaf before programming.
Install the tools
- Install Visual Studio Code for your OS and CPU.
- Open Extensions in VS Code, find PlatformIO IDE published by PlatformIO, and install it. Wait for its initial setup to finish and restart VS Code if requested.
- Install STM32CubeProgrammer from ST. Locate its command-line executable; you will use its actual path in
upload_command.
PlatformIO Core and its serial monitor are included in the IDE extension. If prompted for Python, follow PlatformIO’s Python installation instructions; Linux also requires python3-venv. See the PlatformIO IDE documentation for setup details.
Python is prepared automatically on supported operating systems. Add Japanese Language Pack for Visual Studio Code if you want a Japanese interface, or Teleplot for graphs.
| OS | STM32CubeProgrammer command-line tool |
|---|---|
| Windows | bin/STM32_Programmer_CLI.exe under the installation folder |
| macOS | Contents/Resources/bin/STM32_Programmer_CLI inside STM32CubeProgrammer.app |
| Linux | bin/STM32_Programmer.sh under the installation folder |
Use a local project path with simple ASCII characters, such as C:/PlatformIO/Projects on Windows. Open the command terminal through PlatformIO → Quick Access → Miscellaneous → PlatformIO Core CLI. To change the default folder for new projects, run the following with your actual path and restart VS Code:
pio settings set projects_dir "C:/PlatformIO/Projects"
This does not move existing projects. See the projects_dir documentation.
Simple paths help avoid path-handling problems. User folders and OneDrive locations differ between computers, so check the actual destination before copying an example. On macOS and Linux, replace the quoted path with the absolute path to your chosen folder.
Install the latest ST STM32 platform
Install PlatformIO’s ST STM32 (ststm32) development platform. For AP03, use its built-in Leafony Systems AP03 board definition.
Run this command in PlatformIO Core CLI. Omitting the version installs the latest stable release from PlatformIO Registry.
pio pkg install --global --platform "platformio/ststm32"
If ST STM32 is already installed, update it to the latest release with:
pio pkg update --global --platform "platformio/ststm32"
Packages required by the project, including the Arduino framework, are installed automatically during the first build. See pio pkg install, pio pkg update, and the ST STM32 releases for details.
Quick start
Uploading replaces the program currently on the MCU. To run the kit demo again later, follow Restore the demo.
1. Create the project
- Create an empty folder named
STM32_Hello_World_Pjtand open it with File → Open Folder in VS Code. - Create
platformio.iniand asrcfolder in the project root, then createmain.cppinsidesrc. Their contents are provided in the steps below.
STM32_Hello_World_Pjt/
├── platformio.ini
└── src/
└── main.cpp
2. Identify the serial port
With USB disconnected, assemble the STM32 MCU and USB leaves as shown in the connection example. Connect the USB leaf to your computer, then run:
pio device list
The connected port disappears and reappears when you unplug and reconnect the cable.
| OS | Example port |
|---|---|
| Windows | COM3 |
| macOS | /dev/cu.usbserial-XXXXXXXX |
| Linux | /dev/ttyUSB0 |
If no port appears, check the cable, leaf connections and USB driver. Refer to the FAQ. On Linux, also follow PlatformIO’s serial port permissions instructions.
3. Configure platformio.ini
The following example is for Windows on COM3. Replace the port and executable path with those on your computer.
[env:leafony_ap03]
platform = ststm32
board = leafony_ap03
framework = arduino
upload_protocol = custom
upload_port = COM3
upload_command = "C:/Program Files/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin/STM32_Programmer_CLI.exe" -c port=$UPLOAD_PORT br=115200 -w "$SOURCE" 0x08000000 -v
monitor_port = ${this.upload_port}
monitor_speed = 115200
On macOS, replace upload_port and upload_command with the following, using the actual port name:
upload_port = /dev/cu.usbserial-XXXXXXXX
upload_command = "/Applications/STMicroelectronics/STM32Cube/STM32CubeProgrammer/STM32CubeProgrammer.app/Contents/Resources/bin/STM32_Programmer_CLI" -c port=$UPLOAD_PORT br=115200 -w "$SOURCE" 0x08000000 -v
On Linux, use the absolute installation path and actual serial port. This example uses the account name user:
upload_port = /dev/ttyUSB0
upload_command = "/home/user/STMicroelectronics/STM32Cube/STM32CubeProgrammer/bin/STM32_Programmer.sh" -c port=$UPLOAD_PORT br=115200 -w "$SOURCE" 0x08000000 -v
| Setting | Purpose |
|---|---|
[env:leafony_ap03] | Names the build environment and output folder |
platform = ststm32 | Uses ST STM32 without a version pin |
board = leafony_ap03 | Selects the built-in Leafony Systems AP03 board definition; use lowercase |
framework = arduino | Uses the Arduino framework supported by ST STM32 |
upload_protocol = custom | Runs upload_command for uploads |
$UPLOAD_PORT, $SOURCE | Substituted by PlatformIO with the port and firmware path |
0x08000000 | Flash start address |
-v | Verifies the uploaded data |
monitor_port | Serial monitor port; the upload port in this example |
monitor_speed | Serial baud rate; must match Serial.begin() |
Leave $UPLOAD_PORT and $SOURCE unchanged. See the PlatformIO upload command reference and STM32CubeProgrammer CLI manual.
4. Write the program
Save the following as src/main.cpp:
#include <Arduino.h>
void setup() {
Serial.begin(115200);
}
void loop() {
Serial.println("Hello World");
delay(1000);
}
5. Build
Run PlatformIO → PROJECT TASKS → leafony_ap03 → General → Build, or run this command in the project folder:
pio run -e leafony_ap03
The first build downloads the compiler and framework and can take several minutes. Check for SUCCESS at the end of the log and the generated file .pio/build/leafony_ap03/firmware.bin. If the project is not recognized, reopen the folder containing platformio.ini.
If several projects or build environments are open, check that the selected target is leafony_ap03 in STM32_Hello_World_Pjt.
6. Upload to the STM32 MCU
- Close any application using the serial port, including the serial monitor and Teleplot. Press
Ctrl+Cin PlatformIO’s monitor terminal to stop it. - Set the STM32 MCU switch to Program and check that its LED is on.
- Press Reset to enter programming mode.
- Run PROJECT TASKS → leafony_ap03 → General → Upload, or:
pio run -e leafony_ap03 -t upload

Check the STM32CubeProgrammer log for successful connection, programming and verification. A verification success message may read Download verified successfully; wording depends on the tool version. If there is a timeout or verification error, close other port users, reset in Program mode and upload again, even if the overall log says SUCCESS.
7. Check Hello World
- Set the switch back to Run and check that the LED turns off.
- Press Reset to start the program.
- Run PROJECT TASKS → leafony_ap03 → General → Monitor, or:
pio device monitor -e leafony_ap03
The following output should appear once per second:
Hello World
Hello World
Hello World
Use an existing sample
Download a project from the Leafony STM32 PlatformIO samples. Open the individual folder containing its platformio.ini, rather than the entire repository.
Use the same platform, board and upload settings as in the quick start. For example, when using STM32_Hello_World_Pjt, set platform = ststm32, board = leafony_ap03 and framework = arduino in platformio.ini, then configure the upload tool and port as described above. Review and preserve sample-specific lib_deps and build_flags.
Replace old upload commands referencing Arduino15/.../STM32Tools/1.4.0/... with the path to your installed STM32CubeProgrammer.
To update an existing project’s ST STM32 platform to the latest release, replace a version constraint such as platform = ststm32@... with platform = ststm32. Review library compatibility and adjust library version constraints as needed, then run the following in the project folder:
pio pkg update
Dependencies are updated within the version constraints in platformio.ini; see the pio pkg update reference.
Libraries
Add libraries to lib_deps inside the [env:...] section you use. The Hello World example needs no additional libraries.
If lib_deps already exists, append to its list. Add only the libraries needed for the leaves and functions you use.
lib_deps =
adafruit/Adafruit Unified Sensor
adafruit/Adafruit BusIO
https://github.com/Leafony/TBGLib
Git URLs require Git. Restart VS Code after installing it and check that git --version works in the terminal.
See Libraries and board definitions for the source catalog. Check STM32 Core and library compatibility below.
Library versions in older samples
ST STM32 20.0.0 moved to STM32 Arduino Core 3.0.0. Follow the STM32RTC requirements and STM32LowPower requirements: use the 2.x library lines with Core 3.x, and 1.x with Core 2.x.
; For STM32 Arduino Core 3.x
lib_deps =
stm32duino/STM32duino RTC@^2.0.0
stm32duino/STM32duino Low Power@^2.0.0
Check the framework-arduinoststm32 entry under PACKAGES in the build log to identify your Core. Do not use the AVR MsTimer2 library on STM32; use HardwareTimer instead.
Even if an older sample specifies a version such as @1.2.0, check each library’s README against the Arduino Core used by your project.
Serial plotter
Install Teleplot for VSCode. Upload this example, return the switch to Run and reset:
#include <Arduino.h>
void setup() {
Serial.begin(115200);
}
void loop() {
Serial.print(">seconds:");
Serial.println(millis() / 1000.0f);
delay(100);
}
Close PlatformIO’s serial monitor. From the VS Code command palette run teleplot: Start teleplot session, choose the serial port and baud rate 115200, then click Open. Check that seconds appears in the graph.
Teleplot uses newline-terminated >name:value messages. Serial.println() supplies the newline. Close Teleplot’s port before uploading another program. See also the STM32 Teleplot example.
Port an Arduino IDE sketch
src/main.cpp follows normal C++ rules. Add #include <Arduino.h>, declare functions before use, and add required libraries to lib_deps.
#include <Arduino.h>
void printMessage();
void setup() {
Serial.begin(115200);
printMessage();
}
void loop() {
}
void printMessage() {
Serial.println("Hello World");
}
Upload with the STM32CubeProgrammer GUI
- Build and locate
.pio/build/leafony_ap03/firmware.bin. If you renamed the environment, use its folder name instead. - Close other serial port users, switch to Program and press Reset.
- Open STM32CubeProgrammer and connect using the following settings.
| Setting | Value |
|---|---|
| Connection | UART |
| Port | The STM32 MCU serial port |
| Baud rate | 115200 |
| Parity | Even |
| Data bits | 8 |
| Stop bits | 1 |
| Flow control | OFF |
- Open Erasing & Programming. Select
firmware.binand start address0x08000000. - Enable Verify programming, click Start Programming, and check that verification succeeds.
- Click Disconnect, return the switch to Run, press Reset, and check output in PlatformIO’s serial monitor.
Troubleshooting
| Symptom | Check |
|---|---|
UnknownBoard or missing variant files | Use lowercase board = leafony_ap03 and update ST STM32 to the latest release |
pio command not found | Reopen the PlatformIO Core CLI terminal |
| Upload tool not found | Actual installation path and quotes around paths containing spaces |
| Cannot open the port | Port name, other applications holding the port, and Linux permissions |
| Connection times out | Program switch, Reset before upload, USB cable and port name |
| No output after upload | Switch back to Run, Reset, and monitor_port |
| Garbled serial output | Match monitor_speed to Serial.begin(); this example uses 115200 |
