Skip to content

⚠️ 产品声明 / Product Disclaimer

非量产产品,仅供工程验证,不承诺符合 RoHS。 Non-mass-production product; for engineering verification only. RoHS compliance is not guaranteed.

Overview

This chapter builds on the environment prepared in Software Setup: use VSCode connected to WSL, confirm the toolchain works, pull the official base project and complete your first build.


🎯Page GoalBuild the base project to produce the `9Mod_MCPBorad.bin` firmware, then flash it to the development board with ST-Link.
🧰Prerequisites① [Software Setup](./software-setup) done (WSL, VSCode and the toolchain all ready) ② [STM32 CMake Project Creation](./cmake-project) done.
🔗RelatedOnce the project is configured, continue with [emMCP Porting](./emmcp-porting) to hook up the AI communication framework.
Your First Build

Inside the base project directory DOCS_TEST1, do one configuration step first, then build (either method works).

💡 Tip (required, one time only): by default the official base project only produces 9Mod_MCPBorad.elf, but flashing needs a .bin. Append the following to the top-level file ~/DOCS_TEST1/CMakeLists.txt in the project root directory (the same directory as 9Mod_MCPBorad.ioc) — CubeMX will not regenerate this file, so it is safe to edit:

# Generate .bin and .hex files after build
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
    COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:${CMAKE_PROJECT_NAME}> ${CMAKE_PROJECT_NAME}.bin
    COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:${CMAKE_PROJECT_NAME}> ${CMAKE_PROJECT_NAME}.hex
    COMMENT "Generating .bin and .hex files"
)

Append POST_BUILD at the end of CMakeLists.txt

Save the file and every build from then on will automatically generate 9Mod_MCPBorad.bin.

Inside the base project directory DOCS_TEST1 there are two ways to build:

Method 1: build from the VSCode CMake extension GUI (recommended)

  1. Click the CMake icon in the VSCode Activity Bar on the left (the CMake Tools extension).

    CMake extension icon

  2. In the CMake panel in the sidebar, set the build preset to Debug (you can also switch it by clicking the CMake area on the bottom status bar).

    CMake build preset Debug

  3. Click the Build button and wait for the build to finish; the output panel reports success.

    Build finished output

Method 2: build from the command line

# 1. Configure: read CMakePresets.json and generate the Ninja build scripts
cmake --preset Debug

# 2. Build: compile and link several hundred source files into the final firmware
cmake --build build/Debug

Example of a successful build output (the number of lines varies by environment):

[xx/xx] Linking C executable 9Mod_MCPBorad.elf
Memory region         Used Size  Region Size  %age Used
         RAM:       16xxx B        20 KB     xx%
       FLASH:       98xxx B       128 KB     xx%

Check the artifacts:

ls -la build/Debug/

Build artifact files

Check the artifacts: build/Debug/ should contain three files — 9Mod_MCPBorad.elf, 9Mod_MCPBorad.bin and 9Mod_MCPBorad.hex (.bin/.hex are generated automatically by POST_BUILD).

The artifact names come from set(CMAKE_PROJECT_NAME 9Mod_MCPBorad) in CMakeLists.txt; every command in this tutorial is written for that artifact name.

Flash the Firmware to the Development Board

Wiring: the ST-Link connects to the development board over SWD, as follows:

ST-Link Development Board Description
SWDIO PA13 Data line
SWCLK PA14 Clock line
GND GND Common ground
3.3V 3.3V (optional) Can be left unconnected when the board is self-powered

ST-Link wiring diagram

Open Seahi-Serial and set up the WSL mapping (required before flashing)

By default WSL2 cannot see USB devices on Windows, so the ST-Link has to be mapped into WSL first:

  1. Open the Seahi-Serial app (installed in step ⑤ of Software Setup).
  2. Find the USB device (or COM port) for the ST-Link in the device list.
  3. Click Map to WSL (mounts it into WSL); once the status shows it is mapped, you are done.

The ST-Link is only visible inside WSL after mapping; if flashing reports that it cannot connect, check this step first.

Seahi-Serial mapping the ST-Link into WSL

Flash (VSCode Cortex-Debug GUI — the extension is already installed)

  1. Create .vscode/launch.json in the project root directory (contents below):

    {
        "version": "0.2.0",
        "configurations": [
            {
                "name": "烧录并调试 STM32F103 (OpenOCD)",
                "cwd": "${workspaceFolder}",
                "executable": "${workspaceFolder}/build/Debug/9Mod_MCPBorad.elf",
                "request": "launch",
                "type": "cortex-debug",
                "servertype": "openocd",
                "configFiles": ["interface/stlink.cfg", "target/stm32f1x.cfg"],
                "device": "STM32F103CB",
                "gdbPath": "arm-none-eabi-gdb",
                "toolchainPrefix": "arm-none-eabi",
                "runToEntryPoint": "main"
            }
        ]
    }
    

    Flashing and debugging with F5

  2. In the VSCode bottom bar (status bar), click the “烧录并调试 STM32F103 (OpenOCD)” button (“Flash & Debug STM32F103 (OpenOCD)”) → OpenOCD starts automatically, connects to the ST-Link and writes the firmware into the chip.

    Flash button on the VSCode status bar

  3. When flashing finishes the program stops at main(); click Continue in the debug toolbar to run it. You can also set breakpoints in the code before starting, to debug live.

After flashing, the board runs the firmware: the OLED shows the welcome page and the LED strip plays a gradient animation (features are added step by step in later chapters).

The board running after flashing

Verify the Download Succeeded
  1. Check the screen: the OLED should display two lines, “欢迎使用” (“Welcome”) and “九章开发板” (“Jiuzhang Development Board”) — the welcome page of the official base project.

    OLED welcome page

  2. Check the serial log: connect the Seahi-Serial serial assistant to USART1 (PA9) at 1500000 baud; you should see temperature and humidity logs refreshed once per second:

    [INFO] sht3x_read_task:234: sht30: 29 C,52 %
    

    The temperature and humidity values change with the environment. Seeing this log means the firmware is running normally and the SHT30 sensor is communicating correctly.

    Serial temperature and humidity log

  3. You will also see initialization logs on the serial port: [INFO] emMCP init done, [INFO] sht3x init OK!, [INFO] ch224 init OK! and so on.

If all of the above looks right, the download succeeded and the development board is running the base firmware.


Build Error Troubleshooting

ErrorCauseSolution
arm-none-eabi-gcc: not foundCross-compiler not installedsudo apt install -y gcc-arm-none-eabi
CMake Error: Could not find ninjaNinja not installedsudo apt install -y ninja-build
No CMAKE_C_COMPILER could be foundToolchain file not taking effectMake sure you run cmake in the project root directory and that CMakePresets.json exists
cannot find -lc and similar link errorsnewlib linking problemMake sure newlib_lock_glue.c is in the project root directory
Stubborn build cache issuesCorrupted cacherm -rf build && cmake --preset Debug && cmake --build build/Debug

FAQ & Troubleshooting

🔧 sudo apt update is slow or fails
Cause: the default software sources are overseas
Fix: switch to a mirror closer to you (Tsinghua / Aliyun) and every command in this tutorial becomes fast

🔧 arm-none-eabi-gcc --version shows 9.x
Cause: older systems such as Ubuntu 20.04 ship an outdated default version
Fix: this tutorial uses Ubuntu 22.04 (default 10.3+); on older systems you can install the xpack toolchain

🔧 cmake: command not found
Cause: CMake is not installed
Fix: sudo apt install -y cmake ninja-build

🔧 Cloning the official repository is slow / fails
Cause: unstable network
Fix: retry; or git clone --depth 1 https://github.com/Ai-Thinker-Open/emMCP.git (fetches only the latest revision)

🔧 Running cmake --preset Debug outside the project directory errors out
Cause: the preset file lives in the project root directory
Fix: run cd ~/DOCS_TEST1 first

🔧 Build error No CMAKE_C_COMPILER
Cause: the cross-compiler is not installed or not on PATH
Fix: sudo apt install -y gcc-arm-none-eabi, then reopen the terminal

🔧 The first build takes a long time
Cause: a full build of several hundred files
Fix: this is normal; later incremental builds take only a few seconds

🔧 Rebuilding after changing the code
Cause: —
Fix: just run cmake --build build/Debug (no need to configure again)

🔧 The artifact name is not your own project name
Cause: CMAKE_PROJECT_NAME is not what you expect
Fix: the base project artifact is named 9Mod_MCPBorad.bin; to rename it, change set(CMAKE_PROJECT_NAME ...) in CMakeLists.txt and run cmake --preset Debug again

🔧 Antivirus deletes the build artifacts
Cause: a false positive from Windows Defender
Fix: add the project directory to the allow list, or trust builds done inside WSL

🔧 The serial port / USB device cannot be mapped into WSL (the serial assistant cannot open the COM port)
Cause: by default WSL2 cannot access Windows serial devices directly
Fix: use the community tool Seahi-Serial to do the mapping: https://github.com/SeaHi-Mo/Seahi-Serial (mounts the COM port into WSL; works for serial debugging and the ST-Link)

Can't flash inside WSL?

By default WSL2 cannot see USB devices on Windows (the ST-Link is plugged into Windows). Map the ST-Link into WSL with Seahi-Serial (installed in step ⑤ of Software Setup), then flash using Method 1 (Cortex-Debug GUI) or Method 2 (OpenOCD command line) from step ②.

Released under the MIT License. Build Time 2026-09-11 14:52:23