Zephyr RTOS在STM32F103C8T6上的VSCode开发环境搭建与实战
最近在尝试将 Zephyr RTOS 移植到 STM32F103C8T6 这款经典的“蓝色药丸”最小系统板上时,发现虽然 Zephyr 官方支持强大,但结合 VSCode 进行一站式开发、编译、调试和烧录的完整中文教程却比较零散。很多开发者卡在环境配置、项目构建或烧录环节,反复折腾。本文将整合一套从零开始的闭环实操方案,手把手带你搭建 VSCode + Zephyr 开发环境,完成一个基础示例项目的编译,并通过 ST-Link 成功烧录到 STM32F103C8T6 最小系统板运行。无论你是刚接触嵌入式 RTOS 的新手,还是想将现有项目迁移到 Zephyr 的开发者,都能从中获得可直接复用的代码和配置。
1. 背景与核心概念:为什么选择 Zephyr + VSCode + STM32F103?
在开始动手之前,我们先理清几个核心概念和选择这套技术栈的理由。
Zephyr RTOS是一个由 Linux 基金会托管的、开源、可扩展的实时操作系统(RTOS),专为资源受限的嵌入式设备设计。它支持超过 450 款开发板和 SoC,提供了高度模块化的架构、丰富的驱动和组件(如文件系统、网络协议栈、蓝牙等),并且拥有活跃的社区和严格的代码质量要求。对于 STM32F103C8T6 这类 Cortex-M3 内核的 MCU,Zephyr 能提供比裸机编程更清晰的任务管理、同步机制和设备驱动抽象。
Visual Studio Code (VSCode)是微软推出的轻量级但功能强大的源代码编辑器。通过安装 C/C++、CMake、Zephyr IDE 等插件,它可以变身为一款优秀的嵌入式集成开发环境(IDE),提供代码补全、语法高亮、智能感知、图形化配置界面(Kconfig)、一键编译和调试等功能,极大地提升了开发效率,尤其适合不喜欢庞大传统 IDE(如 Keil、IAR)的开发者。
STM32F103C8T6 最小系统板,常被称为“Blue Pill”,因其低廉的价格和完整的 ARM Cortex-M3 内核功能,成为嵌入式入门和原型开发的热门选择。它拥有 64KB Flash、20KB RAM,足以运行 Zephyr 内核及多个基础任务。
将三者结合,你得到的是一个:免费、开源、功能现代、体验流畅的嵌入式开发工作流。你不再需要为 IDE 支付许可费用,可以利用 Zephyr 强大的生态快速构建应用,并通过 VSCode 享受高效的编码和调试体验。
2. 环境准备与版本说明
工欲善其事,必先利其器。以下环境配置是后续所有步骤的基础,请务必逐步完成。本文示例基于Windows 11操作系统,但主要步骤在 Linux 和 macOS 上同样适用,命令会有细微差别。
2.1 基础软件安装
- Visual Studio Code: 从官网下载并安装最新稳定版。
- Git: 用于克隆 Zephyr 源代码和项目管理。安装时记得勾选“Git from the command line and also from 3rd-party software”选项,以便在任意命令行中使用 Git。
- Python 3.8 或更高版本: Zephyr 的构建工具链依赖 Python。安装时务必勾选 “Add Python to PATH”。安装完成后,在命令行输入
python --version确认。 - CMake 3.20.0 或更高版本: Zephyr 使用 CMake 作为构建系统。下载 Windows 安装包并安装。
- Ninja: 一个更快的构建工具。下载后将其可执行文件(
ninja.exe)所在目录添加到系统的 PATH 环境变量中。
2.2 安装 Zephyr SDK 和依赖
Zephyr SDK 是一个集成的工具链,包含了编译器(GCC)、调试器(GDB)以及用于构建和测试 Zephyr 应用程序的其他工具。
打开一个管理员权限的 PowerShell 或 CMD 窗口,执行以下步骤:
# 1. 安装 chocolatey (Windows 包管理器,如果未安装) # 在管理员 PowerShell 中运行: Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) # 2. 使用 chocolatey 安装 west (Zephyr 项目元工具) choco install west # 3. 克隆 Zephyr 主仓库(建议在用户目录下操作,如 C:\Users\YourName\zephyrproject) cd ~ west init zephyrproject cd zephyrproject west update # 4. 导出 Zephyr CMake 包 west zephyr-export # 5. 安装 Python 依赖 pip install -r zephyr/scripts/requirements.txt # 6. 安装 Zephyr SDK # 访问 https://github.com/zephyrproject-rtos/sdk-ng/releases 下载最新版 Windows 安装包,例如 `zephyr-sdk-0.16.5_windows-x86_64.exe` # 运行安装程序,记住安装路径(例如 `C:\zephyr-sdk-0.16.5`)。安装程序会自动将工具链添加到系统环境变量。安装完成后,重启命令行窗口,运行west --version和cmake --version确认工具安装成功。
2.3 安装 VSCode 必要插件
打开 VSCode,进入扩展市场(Ctrl+Shift+X),搜索并安装以下插件:
- C/C++(Microsoft): 提供 C/C++ 语言支持。
- CMake Tools(Microsoft): 提供 CMake 项目的构建、调试和配置支持。
- Zephyr IDE(Zephyr Project):关键插件!提供 Zephyr 项目的 Kconfig 图形化配置、项目创建、构建和烧录等功能。
- (可选)Cortex-Debug: 用于 ARM Cortex-M 芯片的调试。
- (可选)GitLens: 增强 Git 功能。
安装完 Zephyr IDE 插件后,需要配置 Zephyr 根目录和 SDK 路径。
- 按下
Ctrl+Shift+P,输入Preferences: Open Settings (JSON)。 - 在
settings.json文件中添加以下配置(路径请替换为你自己的实际路径):
{ "zephyr-ide.zephyr-base": "C:\\Users\\YourName\\zephyrproject\\zephyr", "zephyr-ide.toolchain-path": "C:\\zephyr-sdk-0.16.5", "cmake.configureOnOpen": false // 避免打开项目时自动配置,手动控制更稳定 }2.4 硬件准备:STM32F103C8T6 与 ST-Link
- STM32F103C8T6 最小系统板一块。
- ST-Link/V2 调试编程器一个。
- 杜邦线若干(通常需要4根:SWDIO, SWCLK, GND, 3.3V)。
连接方式如下:
| ST-Link 引脚 | STM32F103C8T6 引脚 | 说明 |
|---|---|---|
| SWDIO | PA13(JTMS/SWDIO) | 数据输入输出 |
| SWCLK | PA14(JTCK/SWCLK) | 时钟信号 |
| GND | GND | 共地 |
| 3.3V | 3.3V | 为目标板供电(如果板子已有独立供电,可不接) |
重要提示:确保 ST-Link 的固件是最新的。可以使用 ST 官方的STM32 ST-LINK Utility软件中的“ST-LINK Upgrade”功能进行升级。
3. 创建并配置你的第一个 Zephyr 项目
环境就绪后,我们开始创建项目。Zephyr 项目通常位于zephyrproject目录之外。
3.1 使用 west 创建项目
打开命令行,切换到一个你希望存放项目的目录(例如D:\MyZephyrApps),然后执行:
west init my_first_zephyr_app cd my_first_zephyr_app west update这会在my_first_zephyr_app目录下创建一个标准的 Zephyr 应用程序骨架,并链接到之前初始化的zephyrproject仓库。
3.2 在 VSCode 中打开并配置项目
- 用 VSCode 打开
my_first_zephyr_app文件夹。 - 按下
Ctrl+Shift+P,输入Zephyr IDE: Create a new application。插件会引导你,但因为我们已用 west 创建,可以直接使用现有目录。 - 我们需要告诉 CMake Tools 我们的目标开发板。在 VSCode 底部状态栏,点击当前工具链(可能是“No Kit selected”),选择“Unspecified”或类似选项,这会触发 CMake 配置。
- 在弹出的“选择工具包”列表中,你应该能看到 Zephyr SDK 相关的选项,选择它。
- 接着,状态栏会显示“No Active Project”。点击它,VSCode 会扫描项目根目录下的
CMakeLists.txt。选择它。 - 最关键的一步:选择构建目标(Board)。再次点击状态栏,现在应该会出现一个“Build Target”或类似选项。点击后,输入
stm32f103c8t6并选择。VSCode 和 CMake 会开始为这个目标板配置项目。
3.3 编写示例代码:闪烁 LED
STM32F103C8T6 最小系统板上通常有一个连接在 PC13 引脚的用户 LED(对于某些板子可能是 PA1 或其他,请根据你的板子原理图确认。这里以最常见的 PC13 为例)。
在项目根目录下,找到src文件夹,在里面创建或修改main.c文件:
/* * 文件路径:my_first_zephyr_app/src/main.c * 功能:使 STM32F103C8T6 的 PC13 引脚 LED 以 1 秒间隔闪烁 */ #include <zephyr/kernel.h> #include <zephyr/drivers/gpio.h> /* 1000 msec = 1 sec */ #define SLEEP_TIME_MS 1000 /* 根据你的板子定义 LED0,对于 Blue Pill,通常是 PC13 */ #define LED0_NODE DT_ALIAS(led0) /* 获取 LED 的设备树节点指针 */ static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios); void main(void) { int ret; /* 检查设备是否就绪 */ if (!device_is_ready(led.port)) { return; } /* 配置 LED 引脚为输出模式,并初始化为高电平(LED 灭) */ ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE); if (ret < 0) { return; } while (1) { /* 设置引脚电平为低,点亮 LED */ ret = gpio_pin_set_dt(&led, 1); if (ret < 0) { return; } k_msleep(SLEEP_TIME_MS); /* 设置引脚电平为高,熄灭 LED */ ret = gpio_pin_set_dt(&led, 0); if (ret < 0) { return; } k_msleep(SLEEP_TIME_MS); } }3.4 配置设备树 (Device Tree)
Zephyr 使用设备树(DTS)来描述硬件。我们需要为 STM32F103C8T6 指定 LED 引脚。在项目根目录下创建或修改boards文件夹下的 overlay 文件,但更简单的方式是在项目根目录创建一个app.overlay文件:
// 文件路径:my_first_zephyr_app/app.overlay / { aliases { led0 = &myled; }; leds { compatible = "gpio-leds"; myled: led_0 { gpios = <&gpioc 13 GPIO_ACTIVE_LOW>; // PC13, 低电平有效 label = "User LED"; }; }; };这段设备树覆盖(Overlay)文件定义了一个名为led0的别名,指向我们自定义的 LED 节点myled,并将其硬件引脚指定为 GPIOC 的第 13 引脚,且为低电平点亮。
3.5 配置项目文件
确保项目根目录下的CMakeLists.txt和prj.conf文件内容正确。
CMakeLists.txt:
# 文件路径:my_first_zephyr_app/CMakeLists.txt cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(my_first_zephyr_app) target_sources(app PRIVATE src/main.c)prj.conf:
# 文件路径:my_first_zephyr_app/prj.conf # 启用 GPIO 驱动 CONFIG_GPIO=y4. 构建、烧录与运行
一切配置就绪,现在进入编译和烧录环节。
4.1 使用 VSCode 构建项目
- 在 VSCode 中,确保底部状态栏显示的目标板是
stm32f103c8t6。 - 按下
Ctrl+Shift+P,输入CMake: Build并执行,或者直接点击状态栏的“Build”按钮(一个齿轮或播放图标)。 - 构建过程会在终端输出大量信息。如果一切顺利,最后会显示
[100%] Built target zephyr_final,并在build/zephyr目录下生成zephyr.bin、zephyr.hex和zephyr.elf等文件。
4.2 使用 west 命令烧录
VSCode Zephyr IDE 插件也支持烧录,但使用west命令行更为直接和通用。确保你的 ST-Link 已正确连接到电脑和开发板。
在项目根目录(my_first_zephyr_app)下,打开终端(可以在 VSCode 内置终端中操作),执行以下命令:
# 使用 west flash 命令烧录程序,并自动复位运行 west flashwest flash命令会自动调用正确的烧录工具(对于 STM32 和 ST-Link,通常是openocd或pyocd),找到生成的zephyr.elf或zephyr.hex文件,并将其烧录到开发板的 Flash 中,然后复位芯片。
执行此命令后,你应该能看到板载的 LED(PC13)开始以 1 秒的间隔闪烁!
4.3 使用 VSCode 插件烧录(可选)
如果你更喜欢图形化操作:
- 按下
Ctrl+Shift+P,输入Zephyr IDE: Flash Project。 - 插件会列出可用的烧录方式,选择
west flash或openocd等。 这种方式本质上是调用了背后的west flash命令。
5. 进阶:调试配置与串口打印
让 LED 闪烁只是第一步。调试和获取运行信息同样重要。
5.1 配置串口输出
STM32F103C8T6 的 USART1 (PA9-TX, PA10-RX) 常用来连接 USB 转 TTL 模块进行串口通信。修改prj.conf启用串口和打印功能:
# 文件路径:my_first_zephyr_app/prj.conf CONFIG_GPIO=y # 启用串口控制台 CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y # 启用打印输出 CONFIG_PRINTK=y CONFIG_STDOUT_CONSOLE=y修改main.c,添加串口打印:
#include <zephyr/kernel.h> #include <zephyr/drivers/gpio.h> #include <stdio.h> // 添加标准输入输出头文件 #define SLEEP_TIME_MS 1000 #define LED0_NODE DT_ALIAS(led0) static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios); void main(void) { int ret; int count = 0; if (!device_is_ready(led.port)) { printf("Error: LED device is not ready\n"); return; } ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE); if (ret < 0) { printf("Error: Failed to configure LED pin\n"); return; } printf("Zephyr Blinky Sample started on STM32F103C8T6!\n"); while (1) { gpio_pin_set_dt(&led, 1); // LED 亮 printf("LED ON, count: %d\n", count++); k_msleep(SLEEP_TIME_MS); gpio_pin_set_dt(&led, 0); // LED 灭 printf("LED OFF, count: %d\n", count++); k_msleep(SLEEP_TIME_MS); } }重新构建 (west build) 并烧录 (west flash)。使用串口调试助手(如 Putty、MobaXterm 或 VSCode 的 Serial Monitor 插件)连接 USB 转 TTL 模块(波特率通常为 115200),即可看到打印信息。
5.2 配置 VSCode 进行调试
调试需要Cortex-Debug插件和正确的启动配置。
- 在项目根目录创建
.vscode/launch.json文件:
{ "version": "0.2.0", "configurations": [ { "name": "Cortex Debug (ST-Link)", "cwd": "${workspaceRoot}", "executable": "${workspaceRoot}/build/zephyr/zephyr.elf", "request": "launch", "type": "cortex-debug", "servertype": "openocd", "serverpath": "C:/zephyr-sdk-0.16.5/sysroots/x86_64-pokysdk-mingw32/usr/bin/openocd.exe", // 根据你的SDK路径修改 "interface": "swd", "device": "STM32F103C8", "configFiles": [ "interface/stlink.cfg", "target/stm32f1x.cfg" ], "runToEntryPoint": "main", "svdFile": "${env:ZEPHYR_BASE}/../modules/hal/stm32/svd/stm32f103.svd" // 用于查看外设寄存器 } ] }- 按
F5或点击 VSCode 的“运行和调试”视图,选择“Cortex Debug (ST-Link)”即可开始调试,可以设置断点、单步执行、查看变量和寄存器。
6. 常见问题与排查思路
在实践过程中,你可能会遇到以下问题:
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
west flash失败,提示找不到设备或连接失败 | 1. ST-Link 驱动未安装或异常。 2. 硬件连接错误(线序、接触不良)。 3. 目标板未供电或供电不足。 4. ST-Link 固件过旧。 | 1. 使用设备管理器检查 ST-Link 是否被识别为“STMicroelectronics STLink dongle”等。可尝试重新安装驱动(STM32CubeProgrammer 自带驱动)。 2. 仔细检查 SWDIO、SWCLK、GND、3.3V 四根线是否连接正确且牢固。 3. 尝试通过 USB 口或外部电源为开发板独立供电。 4. 使用 ST-Link Utility 升级 ST-Link 固件。 |
构建失败,提示board not found或DTS error | 1. 未正确指定或选择目标板。 2. Zephyr 源码或 SDK 路径配置错误。 3. 设备树文件 ( app.overlay) 语法错误。 | 1. 确认在 VSCode 状态栏或west build命令中正确指定了-b stm32f103c8t6。2. 检查 ZEPHYR_BASE环境变量和 VSCode 的zephyr-ide.zephyr-base设置。3. 检查 app.overlay文件,确保语法正确,引脚定义与芯片数据手册一致。可先注释掉自定义 overlay 测试。 |
| 程序烧录成功,但 LED 不闪烁 | 1. LED 引脚定义错误(不是 PC13)。 2. 设备树中 GPIO 极性 ( GPIO_ACTIVE_LOW/HIGH) 设置错误。3. 代码中 gpio_pin_set_dt的参数逻辑反了。 | 1. 查阅你的最小系统板原理图,确认用户 LED 的实际连接引脚。修改app.overlay中的gpios属性(如<&gpioa 1 ...>)。2. 尝试将 GPIO_ACTIVE_LOW改为GPIO_ACTIVE_HIGH,或反之。3. 交换代码中 gpio_pin_set_dt(&led, 1)和gpio_pin_set_dt(&led, 0)的参数。 |
| 串口无输出 | 1. 串口引脚连接错误(PA9-TX 接 USB-TTL 的 RX)。 2. 波特率不匹配(Zephyr 默认通常是 115200)。 3. prj.conf中串口配置未启用或冲突。 | 1. 确认 PA9 接 USB-TTL 的 RX,PA10 接 TX,GND 互连。 2. 在串口调试助手中尝试不同的波特率。 3. 确保 prj.conf包含了CONFIG_SERIAL=y和CONFIG_UART_CONSOLE=y。检查是否有其他配置覆盖了控制台设备。 |
| VSCode 插件不工作或选项灰色 | 1. 插件依赖(Python, west, CMake)未正确安装或不在 PATH。 2. 未在正确的文件夹(包含 CMakeLists.txt)中打开项目。3. 插件设置中的 Zephyr 路径错误。 | 1. 在系统终端中测试west --version和cmake --version是否能运行。2. 确保在项目根目录(与 CMakeLists.txt同级)打开 VSCode。3. 仔细核对 settings.json中的zephyr-ide.zephyr-base路径。 |
7. 最佳实践与工程建议
掌握了基础流程后,遵循一些最佳实践能让你的 Zephyr 项目更健壮、更易维护。
- 项目结构清晰:将应用代码放在
src/下,设备树覆盖放在boards/或根目录的.overlay文件,配置文件(prj.conf,Kconfig)放在根目录。复杂的项目可以创建include/目录存放头文件。 - 善用 Kconfig 图形化配置:在 VSCode 中,按下
Ctrl+Shift+P输入Zephyr IDE: Open Configuration,可以打开一个图形界面来勾选和配置内核功能、驱动、组件等,这比手动编辑prj.conf更直观,且能避免配置冲突。 - 版本控制:使用 Git 管理你的应用代码。但注意,
build/目录应该被添加到.gitignore中。通常只需要提交src/,CMakeLists.txt,prj.conf,app.overlay等核心文件。 - 模块化与设备树:对于自定义外设(如传感器、显示屏),尽量为其编写专用的设备树绑定(Bindings)和驱动(Driver),并通过设备树来配置,而不是在代码中写死硬件信息。这提高了代码的硬件抽象层和可移植性。
- 资源监控:STM32F103C8T6 资源有限(64KB Flash, 20KB RAM)。在
prj.conf中启用CONFIG_SIZE_OPTIMIZATIONS=y可以进行尺寸优化。使用west build -t rom_report和west build -t ram_report命令来查看 Flash 和 RAM 的占用详情,优化不必要的模块。 - 调试与日志:除了串口,可以启用
CONFIG_LOG=y和CONFIG_LOG_MODE_IMMEDIATE=y以获得更灵活的日志系统。对于复杂问题,使用调试器(GDB)单步跟踪是最高效的手段。 - 电源管理:对于电池供电设备,务必研究 Zephyr 的电源管理(PM)子系统,合理使用
k_sleep()、k_msleep()以及各种低功耗模式,以延长设备续航。 - 生产烧录:开发阶段使用
west flash很方便。但对于量产,应考虑使用更专业的烧录工具(如 STM32CubeProgrammer 的 CLI 模式)或生成.bin/.hex文件交给产线。确保你的prj.conf中包含了正确的启动和链接器配置。
从点亮一个 LED 开始,你已经成功搭建了基于 Zephyr RTOS 和 VSCode 的现代化 STM32 开发环境。这套工作流的核心优势在于其开源、可定制和高效性。接下来,你可以探索 Zephyr 提供的更多强大功能,如线程管理、信号量、消息队列、文件系统(LittleFS)、网络协议栈(如 LwIP 用于 Ethernet,或 Zephyr 自带的 BSD Socket API)以及蓝牙 Mesh 等,将它们应用到你的实际项目中。遇到问题时,多查阅 Zephyr 官方文档 和 GitHub 上的议题(Issues),社区通常能提供有效的帮助。
