Zephyr为何成为嵌入式开发者的“第二个Linux”?与FreeRTOS深度对比
Zephyr - 特别篇|Higgsfield 原创系列(2026):为什么它正在成为嵌入式开发者的“第二个 Linux”
2026 年再讨论嵌入式 RTOS,很多人会默认“选 FreeRTOS 准没错”。这个判断放在五年前基本成立,但放在今天已经不够准确了。原因很简单:当你的产品开始需要联网、需要 OTA、需要复杂的电源管理、需要多协议栈共存时,FreeRTOS 能做的和你真正想做的事情之间,会拉开一条巨大的鸿沟。
Zephyr 在这条鸿沟上搭了一座桥。它不是一个传统的、以最小资源占用为唯一目标的 RTOS,而是一整套面向连接设备和物联网场景的操作系统级解决方案。这篇文章不是帮你“再认识一个 RTOS”,而是用实际开发链路告诉你:Zephyr 到底解决了什么问题,它在 2026 年嵌入式项目选型中应该摆在什么位置,以及你从零开始搭建 Zephyr 环境、配置 Kconfig、写一个能跑起来的工程,要经过哪些步骤。
无论你是做 MCU 应用开发、物联网网关、可穿戴设备,还是正在考虑把现有 FreeRTOS 项目迁移到 Zephyr,读完这篇文章后,你对“该不该用 Zephyr”这个问题会有一个清晰的技术判断。
1. 这篇文章真正要解决的问题
很多工程师第一次接触 Zephyr 时,第一个反应是:这个系统怎么这么“重”?又是 Kconfig、又是 Devicetree、又是 west 工具链,一个 Hello World 都要配置半天。相比之下,FreeRTOS 只需要加两个 C 文件就能跑起来。
但如果你正在做的事情超出了“点亮 LED”或“跑一个任务调度”的范畴,体验会完全不同。
举一个典型场景:你要做一个带有 BLE、Wi-Fi、FOTA 升级和低功耗管理的智能家居设备。用传统 FreeRTOS 方案,你需要自己选协议栈(是 NimBLE 还是 Zephyr 自带的)、自己对接 OTA 分区表、自己处理不同硬件版本的板级差异、自己设计功耗控制框架。这些工作不是不能做,而是大量时间会花在“搭框架”而不是“做产品”上。
Zephyr 换了一种思路:把内核、驱动、协议栈、电源管理、构建系统全部纳入一个统一框架。你不再需要反复拼装不同开源项目,而是通过配置系统按需裁剪。这正是它和 FreeRTOS 在 2026 年最本质的区别:FreeRTOS 是“一个调度器”,Zephyr 是“一个系统”。
所以这篇文章的核心目标有三个:
第一,帮你建立 Zephyr 的正确心智模型。它不是“复杂版的 FreeRTOS”,而是“面向 MCU 的类 Linux 工程体系”。
第二,给你一份可落地的环境搭建和工程运行指南,包括 west 工具链、Kconfig 配置、Devicetree 基本用法。
第三,用表格和场景对比 Zephyr 和 FreeRTOS 的差异,让选型这件事有依据,而不仅仅是凭感觉。
2. Zephyr 基础概念:Kconfig、Devicetree 与 west 工具链
在动手之前,先把 Zephyr 的三个核心概念说清楚。这三个概念理解了,后面所有配置和编译过程都不会觉得别扭。
2.1 Kconfig:不再靠宏定义开关功能
Kconfig 最早来自 Linux 内核配置体系,Zephyr 把它完整带到了 MCU 领域。它的作用是在编译之前,决定“这个固件包含哪些功能模块”。
传统 RTOS 的做法是在代码里写一堆
#ifdef XXX_ENABLE
。功能少的时候没问题,功能上百个之后,宏管理的复杂度会非常高。Kconfig 把这个过程集中到统一的配置入口,所有可选项都有清晰的依赖关系。
比如你想启用某种传感器驱动,只需要在配置文件中加上:
CONFIG_BOARD_GPIO_SENSOR=y
CONFIG_SENSOR_LOG_LEVEL_INF=y
系统会自动检查这个驱动依赖哪些硬件资源、是否和当前板卡兼容、是否需要连带开启其他配置项。
2.2 Devicetree:硬件描述与代码逻辑分离
Devicetree(设备树)也是从 Linux 引入的概念。它的作用,是用一套统一的数据格式描述硬件拓扑:CPU 内核、内存地址、外设寄存器、中断号、引脚复用。
这样做的好处在于:当你的产品换了同系列但引脚不同的 MCU 时,不需要改 C 代码,只要改设备树文件里的引脚描述即可。这在传统 STM32 裸机开发中几乎不敢想象。
// 文件路径:boards/board_name/board_name.dts
/ {
model = "Example Board";
compatible = "example,board";
leds {
compatible = "gpio-leds";
red_led: led_0 {
gpios = <&gpioa 5 GPIO_ACTIVE_HIGH>;
label = "Red LED";
};
};
};
2.3 west:一切命令的统一入口
west 是 Zephyr 的项目管理工具,类似 Linux 下的 repo,但它做的事情更多:拉取代码、管理多仓库版本、编译、烧录、调试,全部通过 west 完成。
初次接触 Zephyr 的人最容易被 west 绕晕。其实只需要记住两件事:
第一,west 的所有子命令都与项目构建流程相关,比如
west build
、
west flash
、
west debug
。
第二,west 管理的是一个 workspace,也就是以 zephyr 主仓库为中心的一组相关仓库。整个 Zephyr 生态不是单一代码库,而是由 zephyr、hal_stm32、hal_nordic、mcuboot 等多个仓库组成的集合。
3. Zephyr 与 FreeRTOS 深度对比:2026 年嵌入式项目选型参考
这一章节直接给结论:Zephyr 和 FreeRTOS 在 2026 年并不是完全对立的替代关系,而是两种不同项目需求下的不同答案。下面从六个维度做对比。
| 对比维度 | Zephyr | FreeRTOS |
|---|---|---|
| 本质定位 | 面向物联网和连接设备的操作系统 | 轻量级实时调度内核 |
| 内核最小体积 | 几十 KB 级,可以裁剪 | 几 KB 级,极致轻量 |
| 硬件抽象层 | Devicetree + 驱动框架,统一接口 | 无标准硬件抽象,驱动由厂商提供 |
| 协议栈支持 | BLE、Wi-Fi、Thread、Zigbee、802.15.4 等原生集成 | 需自行集成第三方协议栈 |
| 构建系统 | CMake + west,支持 Kconfig 配置 | Makefile / CMake,无统一配置体系 |
| 许可证 | Apache 2.0 | MIT(内核部分) |
| 主要适用场景 | 智能家居、可穿戴、工业物联网、车联网 | 简单任务调度、资源受限 MCU、教学 |
| 社区生态 | Linux 基金会主导,厂商参与度高 | 生态成熟,资料海量 |
从这张表可以提炼出三个关键判断。
第一,如果项目只有一个传感器采集任务和一个上报任务,MCU 资源极度紧张,FreeRTOS 仍然是最好的选择。它轻、快、稳定,而且团队里几乎人人都会用。
第二,如果项目需要同时跑 BLE 和 Wi-Fi,还要考虑 OTA 和功耗管理,Zephyr 的集成度优势非常明显。你不会想把 NimBLE、LwIP、MCUboot 一个个手动拼起来。
第三,Zephyr 的学习曲线更陡,但学到的知识可迁移性强。因为它背后的 Devicetree、Kconfig、CMake 体系,和 Linux 开发经验是相通的。换句话说,学会 Zephyr,你掌握的其实是一套更接近现代嵌入式工程化的思维。
4. Zephyr 环境搭建与基础配置
明确一下环境假设:本文以 Ubuntu 22.04 或 Windows 10/11 + WSL2 为主要开发环境。如果你只装了 Windows 原生环境,建议优先装一个 WSL2,因为 Zephyr 的官方工具链脚本对类 Unix 环境支持最好。这不是说 Windows 完全不可行,而是从工程效率角度,WSL2 会让后续操作顺畅很多。
4.1 安装必要依赖
无论什么环境,先确保 Python 版本在 3.8 以上,并准备好 pip 和 cmake。下面以 Ubuntu 环境为例:
sudo apt update
sudo apt install --no-install-recommends git cmake ninja-build gperf \
ccache dfu-util device-tree-compiler wget \
python3-dev python3-pip python3-setuptools python3-tk python3-wheel xz-utils file \
make gcc gcc-multilib g++-multilib libsdl2-dev libmagic1
这里用到
dfu-util
是因为很多 Zephyr 支持的开发板通过 DFU 模式烧录;
device-tree-compiler
用来编译设备树;
ninja-build
是 Zephyr 默认的构建后端,比 Make 快很多。
4.2 安装 west 并初始化工作目录
Zephyr 不推荐直接把源码 clone 到任意文件夹,而是用 west 创建一个规范的 workspace。建议给代码单独建一个目录,例如
zephyrproject
。
pip install west
mkdir ~/zephyrproject && cd ~/zephyrproject
west init
west update
west init
会拉取默认的 manifest 文件,
west update
则会根据 manifest 把 zephyr、hal 库、第三方模块全部下载到本地。这个操作需要联网,首次拉取数据量在 1GB 以上,耐心等待即可。
4.3 安装编译工具链
Zephyr 官方推荐使用 Zephyr SDK。SDK 里包含了针对不同架构的交叉编译器、调试器和 QEMU 支持。
cd ~
wget https://github.com/zephyrproject-rtos/sdk-ng/releases/latest/download/zephyr-sdk-<VERSION>_linux-x86_64.tar.xz
tar xf zephyr-sdk-<VERSION>_linux-x86_64.tar.xz
cd zephyr-sdk-<VERSION>
./setup.sh
安装完成后,把工具链路径导出到环境变量中:
export ZEPHYR_SDK_INSTALL_DIR=~/zephyr-sdk-<VERSION>
export ZEPHYR_TOOLCHAIN_VARIANT=zephyr
注意:
<VERSION>
请替换为你实际下载的 SDK 版本号,不要照抄。如果你使用的开发板是 STM32 系列,也可以直接用 ARM GCC 工具链,但用 Zephyr SDK 能少踩很多版本匹配的坑。
4.4 环境变量验证
安装完成后,验证环境是否基本就绪。进入 zephyr 仓库目录并查看版本信息:
cd ~/zephyrproject/zephyr
source zephyr-env.sh
west --version
如果能看到 west 版本号和 Zephyr 版本提示,环境就基本搭建完成了。
5. 使用 Workbench for Zephyr 与 Kconfig 图形化配置
Zephyr 的 Kconfig 体系在命令行下确实能完成所有配置,但配置项太多时,记忆成本很高。这就是“Workbench for Zephyr”这类工具能发挥作用的地方。
5.1 什么是 Workbench for Zephyr
简单说,Workbench for Zephyr 是基于 VS Code 的图形化开发环境。它将工程管理、Kconfig 配置、编译、烧录、调试集成到一个界面中,降低纯命令行操作的认知负担。对于刚接触 Zephyr 的开发者,它可以让你先通过图形界面理解配置体系,再逐步过渡到命令行。
在 2026 年的实际开发中,团队里往往是懂内核的人用命令行,应用层开发者在 Workbench 中完成日常构建和调试。
5.2 Kconfig 图形化配置入口
即使不使用 Workbench 的完整 IDE,Zephyr 自身也提供了终端 UI 方案。进入任意一个 build 目录后运行:
west build -t guiconfig
系统会打开图形化配置界面。你也可以用:
west build -t menuconfig
menuconfig 是基于终端菜单方式的配置界面,操作逻辑与 Linux 内核配置完全一致。对于习惯键盘操作的人,这种方式的效率反而更高。
在实际项目里,我们更常采用的方式是直接维护
prj.conf
文件。下图是一个典型的 BLE 项目配置:
# 文件路径:prj.conf
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="Zephyr_BLE_Device"
CONFIG_BT_PRIVACY=y
CONFIG_LOG=y
Kconfig 的价值在于:它把所有功能开关收敛到可审查、可版本管理的配置文件中,而不是散落在代码各处。这一点在后期的工程维护中价值极大。
6. Zephyr 完整示例:最小工程编译与运行
现在进入真正的实操环节。我们从一个最基础的 Hello World 工程开始,再到一个带 GPIO 控制的 Blinky 工程,完整跑通编译、烧录、验证的整个流程。
6.1 Hello World 示例
Zephyr 官方自带大量示例,Hello World 位于
zephyr/samples/hello_world
。先查看目录结构:
cd ~/zephyrproject/zephyr/samples/hello_world
ls -l
核心文件有三个:
-
prj.conf:工程配置文件,本示例中保持为空即可。 -
src/main.c:程序入口。 -
CMakeLists.txt:构建脚本。
main.c
的内容如下:
// 文件路径:samples/hello_world/src/main.c
#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
void main(void)
{
printk("Hello World! %s\n", CONFIG_BOARD);
}
注意这里的头文件写法。
<zephyr/kernel.h>
是 Zephyr 2.6 以后推荐的标准头文件路径,老代码里常见的
<zephyr.h>
如今也会被兼容,但新项目建议统一使用带
zephyr/
前缀的路径。
6.2 编译命令
在 hello_world 目录下执行:
west build -b qemu_cortex_m3
这里
-b
指定目标板卡。
qemu_cortex_m3
是模拟的 Cortex-M3 开发板,不需要真实硬件就能验证编译和运行流程。如果你手上有具体的开发板,例如
nucleo_f103rb
或
nrf52840dk_nrf52840
,直接替换板卡名即可。
第一次编译会初始化构建目录并下载相关依赖,可能需要几分钟。
6.3 运行与验证
因为目标平台是 QEMU 模拟板,编译完成后可以直接用 QEMU 运行:
west build -t run
如果一切正常,终端会输出类似下面的结果:
*** Booting Zephyr OS build zephyr-v3.x-xxxx ***
Hello World! qemu_cortex_m3
看到这行输出,说明 Zephyr 的最小系统已经成功运行。
6.4 Blinky 示例:GPIO 与设备树结合
接下来做一个小而完整的硬件示例。以
nrf52840dk_nrf52840
开发板为例,演示如何通过设备树配置 LED 引脚。
官方 Blinky 示例路径是
samples/basic/blinky
,其
main.c
核心逻辑如下:
// 文件路径:samples/basic/blinky/src/main.c
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/devicetree.h>
#define LED0_NODE DT_ALIAS(led0)
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
int main(void)
{
if (!device_is_ready(led.port)) {
return -1;
}
gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
while (1) {
gpio_pin_toggle_dt(&led);
k_msleep(500);
}
return 0;
}
这段代码很短,但包含两个重要知识点:
第一,
DT_ALIAS(led0)
通过设备树别名获取 LED 节点的引用,实际引脚在
nrf52840dk_nrf52840.dts
中定义。
第二,
gpio_pin_configure_dt
和
gpio_pin_toggle_dt
是 Zephyr 的新版 GPIO API,它们自动适配设备树里的引脚配置,开发者不需要手写寄存器操作。
编译命令:
west build -b nrf52840dk_nrf52840 samples/basic/blinky
west flash
烧录成功后,开发板上的 LED 会以 0.5 秒间隔闪烁。
7. Devicetree 机制:Zephyr 硬件抽象的精髓
如果说 Kconfig 解决了“软件功能怎么选”,Devicetree 解决的就是“硬件资源怎么描述”。这一章用通俗的语言拆解 Devicetree,因为它是许多 Zephyr 初学者最不容易跨过的坎。
7.1 没有 Devicetree 时的开发方式
传统 MCU 开发中,开发者通常依赖厂商提供的 HAL 库。比如 STM32 项目里,要让某个引脚输出高电平,需要打开
.ioc
文件,在可视化界面里配置引脚模式,然后重新生成初始化代码。一旦换了引脚或 MCU 型号,需要重新生成工程。
这种方式的缺点在于:硬件配置过程和业务代码是强绑定的,板级资源变更会直接引发代码级修改。
7.2 Devicetree 的解决思路
Devicetree 将硬件描述固化成文本文件,与 C 代码分离。当硬件引脚变化时,只改 dts 文件,不需要改 main.c。
看一个实际的 LED 定义:
/ {
aliases {
led0 = &red_led;
};
leds {
compatible = "gpio-leds";
red_led: led_0 {
gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
label = "Red LED";
};
};
};
这段描述告诉系统两件事:LED 连接在 GPIO0 的第 13 号引脚,低电平有效。对应的 C 代码只需要通过
DT_ALIAS(led0)
获取引用,系统会自动完成寄存器映射。
7.3 使用 Overlay 文件做板级适配
实际项目更常见的情况是:开发板本身有默认的设备树,但你的产品硬件改了引脚。这时候不要直接修改厂商板级 dts 文件,而是使用 overlay 文件覆盖。
在工程根目录下创建
app.overlay
:
// 文件路径:app.overlay
/ {
aliases {
led0 = &custom_led;
};
};
&gpio1 {
status = "okay";
};
custom_led: led_custom {
compatible = "gpio-leds";
gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
label = "Custom LED";
};
然后在
CMakeLists.txt
中指定:
set(DTC_OVERLAY_FILE "${CMAKE_CURRENT_SOURCE_DIR}/app.overlay")
这样,同一套业务代码可以支持不同引脚定义的不同硬件版本。在产品线需要做到“一套固件多种硬件”时,这个能力非常有价值。
8. Zephyr 常见问题与排查方法
从环境搭建到实际编译,开发者最常遇到的坑集中在工具链匹配、依赖下载速度和设备树配置三个方面。下面整理成表格,方便日常检索。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
west init
拉取失败
| 网络不通或 manifest 仓库被墙 | 检查网络,重试 |
配置代理或镜像源,重试
west init
|
west update
中途报错
| 某个子仓库拉取失败 | 查看错误提示中的仓库名 |
单独进入对应仓库目录
git pull
后再执行
west update
|
| 编译时报找不到头文件 | SDK 环境变量未设置 |
运行
echo $ZEPHYR_SDK_INSTALL_DIR
|
source
zephyr-env.sh
,重新 export 环境变量
|
| 板卡名称拼写错误 | 对目标板不熟悉 |
west boards
查看支持的板卡
| 从列表中找到准确的板卡名 |
| 烧录提示无法连接设备 | 板卡未进入烧录模式或驱动问题 | 检查 USB 设备是否被识别 | 按开发板手册进入 DFU/Bootloader 模式 |
| 设备树中引脚配置无效 | overlay 文件未生效 |
确认
DTC_OVERLAY_FILE
设置
|
在
CMakeLists.txt
中显式指定 overlay 文件
|
| 编译很慢 | 首次构建拉取 HAL 库并全量编译 | 观察构建日志 |
使用 ccache,
sudo apt install ccache
|
这里单独强调一个高频问题:在 Windows 原生环境下,
west update
比较容易因为路径过长或软链接问题失败。使用 WSL2 后,这一系列问题基本消失。这也是为什么前文建议直接从 WSL2 开始。
9. 最佳实践与工程建议
Zephyr 的项目实践,有一些经验值得在工作开始前就固化到流程中。
9.1 使用版本管理锁定 Zephyr 版本
Zephyr 的迭代速度很快,不同版本之间的 API 变动不小。团队项目一定要把
west
的 manifest 文件纳入 Git 管理,并在文档中明确声明使用的 Zephyr 版本。否则“昨天还能编译,今天突然报错”的问题会频繁出现。
9.2 项目目录与源码目录分离
不要在 Zephyr 官方源码目录里直接改代码。更规范的做法是新建自己的 application 目录,把
src
、
prj.conf
、
CMakeLists.txt
、
boards
、
dts
等文件组织在项目仓库中。
my_app/
├── CMakeLists.txt
├── prj.conf
├── src/
│ └── main.c
└── boards/
└── my_board.overlay
这样不仅便于 Git 版本管理,也让多个产品复用同一套 Zephyr SDK 成为可能。
9.3 配置文件与环境变量脚本化
环境变量(
ZEPHYR_SDK_INSTALL_DIR
、
ZEPHYR_BASE
等)最好不要每次手动 export,而是写入
~/.zephyrrc
或项目入口脚本。这样换一台电脑、新同事入职时,只需要执行一条 source 命令就能完成环境初始化。
9.4 先跑官方 samples,再修改,最后造轮子
Zephyr 的官方 samples 覆盖了内核、驱动、BLE、传感器、显示等几乎全部模块。遇到新外设时,优先找对应 sample,在其基础上改动,远比从零开始研究 HAL 手册效率高。
9.5 理解安全启动和 OTA 的设计
如果你的产品需要 FOTA 升级,Zephyr 生态里默认使用 MCUboot 作为 bootloader。这意味着从产品设计初期就要考虑分区表、密钥管理、签名校验等问题。这部分内容不是简单的功能叠加,而是系统级设计,建议在项目规划阶段就纳入技术选型。
9.6 团队学习路线的建议
对于从 FreeRTOS 迁移而来的团队,不建议一上来就追求复杂的多协议栈工程。更务实的路径是:先跑通 Hello World,再用 Blinky 理解设备树,接着做 GPIO 按键中断,然后逐步引入传感器驱动、通信协议、日志系统。每一步都验证通过后,再进入整体产品集成。
10. 选型判断:你的下一个项目到底该用谁
最后回到最开始的问题:2026 年做嵌入式项目,到底选 Zephyr 还是 FreeRTOS?
如果是做一个简单的温湿度传感器节点,一颗 8 位或低端 Cortex-M0 就能完成,整机资源紧张、固件体积要求苛刻,FreeRTOS 依然合适。因为这种项目几乎不需要考虑复杂的协议栈、低功耗管理和 OTA 流程,轻量就是最大的优势。
如果产品需要长久维护、需要保持多硬件版本兼容、需要不断加入新的连接协议或云平台能力,Zephyr 是更符合“系统工程”思路的选择。它前期投入的学习成本,会换来后续开发中更少的“野生封装”和“重复造轮子”。
还有一类项目需要特别提醒:如果你正在为公司内部的多个产品线做统一软件平台,Zephyr 的价值会成倍放大。因为它统一的构建方式、设备树描述和驱动接口,让不同产品线之间复用固件工程成为可能,而不是每个产品都变成一座独立的“技术孤岛”。
Zephyr 不是“另一个 RTOS”,它代表的是嵌入式开发向系统化、工程化演进的方向。选型没有绝对的对错,只有是否匹配你的项目阶段和团队能力。希望这篇 Zephyr 特别篇,能让你在 2026 年的技术选型中多一个清晰的选择项。
更多推荐



所有评论(0)