资讯动态

Zephyr RTOS 开发环境搭建实战:从零到 Blinky 的完整指南

发布时间:2026/10/14 1:03:09 来源:尧图企业网站定制
0. 写在最前面为什么我要从零写这个系列搞嵌入式的人多少都听过 Zephyr 这个名字。它不像 FreeRTOS 那样“小而美、拿来就用”也不像 Linux 那样“什么都有、但重得离谱”。Zephyr 卡在一个很有意思的位置它有一套完整的构建系统、设备树、Kconfig、驱动模型甚至还有自己的包管理器和测试框架但最终跑起来的内核可以小到几十 KB塞进一颗只有 64KB Flash 的 Cortex-M0 里。我第一次接触 Zephyr 是在一个多协议无线网关的项目上。当时的需求很明确一颗 nRF52840要同时跑 BLE 广播、Thread 边界路由器的部分逻辑还要留出足够的空间做 OTA。FreeRTOS 能跑但协议栈的移植和内存管理要自己搭一大套轮子Linux 根本放不下。Zephyr 恰好把 802.15.4、BLE、TCP/IP、CoAP 这些中间件都做成了可裁剪的模块用 Kconfig 一勾就能进固件。从那时候起我就决定把这个内核吃透。这个系列我打算从开发环境开始写一路写到内核调度、内存管理、设备驱动模型、电源管理。第 0 篇不讲内核代码只讲一件事怎么把 Zephyr 的开发环境搭起来并且搭得干净、可复现、不踩坑。很多人卡在第一步——west build报一堆错Python 版本不对工具链找不到CMake 版本太低——然后就放弃了。其实这些问题都有明确的解法只是官方文档写得太“正确”缺少一线开发者踩坑后的经验。这篇文章适合谁如果你已经会 C 语言、用过至少一种 RTOSFreeRTOS、RT-Thread、uC/OS 都行想试试 Zephyr那这篇就是为你写的。如果你完全没接触过嵌入式 RTOS建议先找个简单的点灯项目练练手再回来。全文我会用“从业者聊天”的方式写不堆砌官方术语每个操作都告诉你为什么这么做以及我实际踩过什么坑。1. 开发环境整体设计与工具链选型1.1 为什么 Zephyr 的环境比 FreeRTOS 复杂这么多先把这个“为什么”说清楚不然后面装工具的时候你会觉得莫名其妙。FreeRTOS 的典型用法是把几个.c文件拖进你的工程配一个FreeRTOSConfig.h搞定。它本质上是一个库你用什么编译器、什么构建系统、什么目录结构它不管。Zephyr 不是库它是一个完整的构建框架。它自己管构建CMake Ninja、自己管配置Kconfig、自己管硬件描述Devicetree、自己管依赖west Python venv、自己管工具链Zephyr SDK。这套东西的好处是你换一块板子改几行配置就能跑不用手动改一堆宏坏处是入门门槛被抬高了你得先理解这套框架怎么协作才能开始写业务代码。我个人的判断是如果你的项目只用一颗 MCU、外设简单、不涉及多协议栈FreeRTOS 更省事但如果你要做多协议、多板型、长期维护的产品Zephyr 这套框架的投入是值得的。它的可复现性极强——同一份代码换台电脑、换个操作系统west build出来的固件二进制是一致的。1.2 核心组件拆解west、CMake、Ninja、SDK、Python venv 各干什么很多人装环境装到一半就晕了因为一下子冒出五六个工具。我用一张表把它们的分工说清楚组件角色类比是否必须west元工具管理仓库、构建入口、flash、debug项目经理必须CMake构建系统生成器读取 CMakeLists.txt图纸翻译员必须Ninja实际执行编译链接的构建后端施工队必须也可用 MakeZephyr SDK交叉编译工具链 调试器 模拟器工具箱必须也可用系统 gccPython venv隔离 west 及其依赖的虚拟环境独立工作间强烈建议Devicetree compiler (dtc)编译 .dts 硬件描述硬件翻译SDK 自带关键理解west 不是构建系统它只是调用 CMakeCMake 再调用 Ninja。west 的价值在于它知道 Zephyr 的目录结构能自动找到zephyr/仓库、自动处理west.yml里的多仓库依赖。你完全可以直接用 CMake 构建但那样你就得自己设一堆环境变量得不偿失。提示Zephyr 从 2.x 开始强依赖 west 做多仓库管理。如果你看到老教程里用cmake -B build直接构建那是 1.x 时代的做法现在不推荐。1.3 版本选择的取舍LTS 还是主线Zephyr 的版本节奏是每 3-4 个月一个主线版本每 2-3 个主线版本出一个 LTS。截至我写这篇的时候LTS 是 3.7主线已经到 4.x。我的建议很直接产品开发用 LTS。API 稳定bug fix 有 backport社区支持周期长。学习内核用 LTS。代码结构清晰文档齐全不会遇到主线里刚改了一半的 API。追新特性比如某个刚合入的驱动用主线但做好 API 随时变的心理准备。我自己的机器上同时装了 LTS 和主线两套 SDK 和源码用west的 workspace 隔离。这个后面会讲怎么操作。2. 手把手搭建从裸机到第一个 Blinky2.1 系统准备与依赖安装的实操细节我以 Ubuntu 22.04 为例其他 Linux 发行版和 macOS 大同小异Windows 建议用 WSL2原生 Windows 也能跑但路径和权限问题多不推荐新手。第一步装系统级依赖。官方文档给了一长串apt install我精简成真正必要的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这里有几个点值得说--no-install-recommends避免拉一堆用不上的图形库容器环境里尤其重要。device-tree-compiler系统自带的 dtc 版本可能太老但 Zephyr SDK 里也带了一个实际构建时优先用 SDK 的。系统这个主要是给一些脚本用。libsdl2-dev只有你要跑native_sim把 Zephyr 当普通程序跑在 PC 上才需要做产品可以省。ccache强烈建议装。Zephyr 全量编译一次要几分钟ccache 能把重复编译降到几秒。装完检查版本cmake --version # 要求 3.20.0 python3 --version # 要求 3.8 dtc --versionCMake 版本是重灾区。Ubuntu 20.04 自带的 CMake 是 3.16直接不满足要求。要么升级系统要么用 Kitware 的 apt 源装新版要么用 pip 装pip install cmake。我推荐用 Kitware 源稳定。2.2 Python 虚拟环境的正确姿势Zephyr 的 west 和一堆脚本都是 Python 写的依赖包不少pyelftools、pykwalify、west 本身等。千万不要用系统 Python 直接 pip install会污染系统环境而且不同项目可能要不同版本的 west。正确做法是建一个专用 venvpython3 -m venv ~/zephyr-venv source ~/zephyr-venv/bin/activate pip install --upgrade pip pip install west激活后你的 shell 提示符前面会有(zephyr-venv)。每次开新终端做 Zephyr 开发第一件事就是source这个激活脚本。我把它写进了~/.bashrc的一个 aliasalias zephyr-envsource ~/zephyr-venv/bin/activate source ~/zephyrproject/zephyr/zephyr-env.sh这样一条命令搞定环境激活。注意zephyr-env.sh会设置ZEPHYR_BASE等环境变量west 靠它找源码。如果你不 source 它west 会报 “ZEPHYR_BASE not set”。2.3 获取源码west init 与 update 的门道初始化 workspace 的标准命令cd ~ west init ~/zephyrproject cd ~/zephyrproject west updatewest init做两件事克隆 Zephyr 主仓库到~/zephyrproject/zephyr并根据west.yml记录下所有依赖仓库的版本。west update才真正去克隆那些依赖仓库hal 层、mcuboot、各种模块。这里有个大坑west update会克隆几十个仓库网络不好时经常中断。中断后不要删掉重来直接再跑一次west update它会跳过已完成的。如果某个仓库卡死可以单独更新west update hal_nordic另一个坑默认west init拉的是主线。要指定 LTS 版本west init -m https://github.com/zephyrproject-rtos/zephyr --mr v3.7.0 ~/zephyrproject--mr后面跟分支名或 tag。这个参数在团队协作时特别重要——所有人必须用同一个 tag否则构建结果可能不一致。2.4 Zephyr SDK 安装与版本管理SDK 是预编译的交叉工具链包含 arm-zephyr-eabi、riscv64-zephyr-elf、x86_64-zephyr-elf 等多套。下载地址在官方 GitHub releases选zephyr-sdk-0.16.x_linux-x86_64.tar.xz这种。cd ~ wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.5/zephyr-sdk-0.16.5_linux-x86_64.tar.xz tar xf zephyr-sdk-0.16.5_linux-x86_64.tar.xz cd zephyr-sdk-0.16.5 ./setup.shsetup.sh会问你装哪些工具链默认全装。如果你只做 ARM 开发可以只选 arm-zephyr-eabi省几个 GB 空间。装完后 SDK 会注册到~/.cmake/packages/Zephyr-sdkCMake 构建时自动找到。版本管理的关键点SDK 版本和 Zephyr 版本有对应关系。比如 Zephyr 3.7 推荐 SDK 0.16.5用太老的 SDK 可能缺某些头文件。这个对应关系在 Zephyr 的SDK_VERSION文件里写着west update后可以查。提示如果你机器上有多套 SDK可以用-DZEPHYR_SDK_INSTALL_DIR/path/to/sdk在构建时指定不用改全局配置。2.5 环境变量与 shell 配置的收尾到这一步环境基本齐了。验证一下west --version west topdir # 应该输出 ~/zephyrproject echo $ZEPHYR_BASE # 应该输出 ~/zephyrproject/zephyr如果ZEPHYR_BASE为空说明你没 sourcezephyr-env.sh。这是新手最常见的报错来源。3. 第一个工程从 Blinky 到自定义板型3.1 构建 Blinky 的完整命令与参数解读Zephyr 自带大量 sample最经典的是samples/basic/blinky。构建命令cd ~/zephyrproject west build -b nrf52840dk_nrf52840 zephyr/samples/basic/blinky拆解这条命令west buildwest 的构建子命令内部调用 CMake Ninja。-b nrf52840dk_nrf52840指定 board。这个字符串不是随便起的它对应zephyr/boards/arm/nrf52840dk_nrf52840/目录。board 名字写错是最常见的错误报错信息通常是 “board not found”。最后的路径应用源码目录里面必须有CMakeLists.txt。第一次构建会创建build/目录全量编译。之后改代码再west build会增量编译很快。烧录west flashwest flash会自动找对应的烧录工具nRF52 用 nrfjprog 或 pyocdSTM32 用 openocd等等。如果报找不到烧录器检查 udev 规则或者用--runner手动指定。调试west debug会启动 gdb server 并连上 gdb。这个在排查 HardFault 时非常有用。3.2 构建产物的目录结构每个文件是什么构建完成后build/目录里东西很多我挑几个关键的文件/目录作用zephyr/zephyr.elf带调试信息的可执行文件zephyr/zephyr.hexIntel HEX 格式烧录用zephyr/zephyr.bin纯二进制OTA 用zephyr/zephyr.map链接映射查符号地址和内存占用zephyr/.config最终生效的 Kconfig 配置zephyr/include/generated/自动生成的头文件devicetree、syscall 等build.ninjaNinja 构建脚本CMakeCache.txtCMake 缓存改配置时可能要看zephyr.map是我最常看的文件。想知道某个函数占了多少 Flash、某个数组放在哪个 RAM 段直接在里面搜。zephyr/.config是排查“为什么某个驱动没编进去”的关键——Kconfig 的最终结果都在这里。3.3 用 menuconfig 和 guiconfig 调配置Zephyr 的配置系统基于 Kconfig和 Linux 内核同源。调配置有两种方式west build -t menuconfig # 终端界面 west build -t guiconfig # 图形界面需要 Python tkmenuconfig 里可以搜索配置项按/看依赖关系按?。比如你想开某个驱动的 debug 日志搜LOG_LEVEL找到对应模块改成 Debug。改完保存配置会写进build/zephyr/.config。但注意这个改动只对当前 build 目录有效。要永久保存得用prj.conf或者-DEXTRA_CONF_FILE。我个人的习惯是临时调试用 menuconfig确定要保留的配置写进prj.conf用 git 管理。3.4 自定义板型与 devicetree overlay 入门实际项目里你很少直接用官方开发板多半是自己画的板子。Zephyr 支持两种方式方式一基于现有 board 做 overlay。比如你的板子和 nRF52840 DK 差不多只是 LED 接的引脚不同/* boards/nrf52840dk_nrf52840.overlay */ / { leds { compatible gpio-leds; my_led: led_0 { gpios gpio0 13 GPIO_ACTIVE_HIGH; label My LED; }; }; };构建时用-DEXTRA_DTC_OVERLAY_FILEboards/nrf52840dk_nrf52840.overlay指定。方式二创建自定义 board。在zephyr/boards/下建目录写board.cmake、Kconfig.board、xxx.dts、xxx_defconfig。这个工作量大但适合量产项目。新手建议先用 overlay等熟悉了 devicetree 语法再考虑自定义 board。4. 常见问题与排查技巧实录4.1 构建报错速查表我把这些年遇到的报错整理成一张表按报错关键词查报错关键词原因解决ZEPHYR_BASE not set没 source zephyr-env.shsource zephyr/zephyr-env.shboard not foundboard 名字拼错west boards列出所有可用 boardCMake 3.20 or higher requiredCMake 太老升级 CMakePython interpreter not foundvenv 没激活source ~/zephyr-venv/bin/activateNo such file: zephyr-sdkSDK 没装或路径不对重跑 SDK 的 setup.shundefined reference to __device_dts_orddevicetree 配置和驱动不匹配检查 overlay 里的 compatibleregion FLASH overflowed固件超出 Flash关掉不用的模块或换更大 Flash 的芯片west: command not foundvenv 没激活或 west 没装pip install west4.2 我踩过的三个真实坑坑一Python 版本冲突。我一开始图省事用系统 Python 装了 west结果系统里还有别的项目依赖老版本的 pyelftools两边打架。后来老老实实建 venv再没出过问题。教训永远用 venv。坑二SDK 版本和 Zephyr 版本不匹配。有次我拉了最新的主线代码但 SDK 还是半年前的编译时报某个头文件找不到。查了半天才发现是 SDK 太老。教训升级 Zephyr 源码后先看SDK_VERSION文件必要时同步升级 SDK。坑三ccache 缓存污染。有次我改了工具链路径但 ccache 里还缓存着旧工具链的编译结果导致链接时符号对不上。清一下ccache -C就好了。教训换工具链或大改配置后清 ccache。4.3 构建速度优化ccache 与并行编译Zephyr 全量编译一次nRF52 这种规模大概 2-3 分钟。优化手段ccache装好后 CMake 自动检测并使用。第二次编译同样的文件命中缓存后几秒完成。并行编译Ninja 默认用满 CPU 核心。如果内存不够比如 4GB 的虚拟机可以限制west build -- -j 4。增量编译只改应用代码时west build只重编改动的文件很快。但如果改了prj.conf或 devicetree会触发大范围重编。我实测下来配好 ccache 后日常开发改代码到烧录平均 10 秒以内。4.4 多版本共存与 workspace 隔离如果你同时维护 LTS 和主线两个项目建议建两个 workspacewest init -m https://github.com/zephyrproject-rtos/zephyr --mr v3.7.0 ~/zephyr-lts west init -m https://github.com/zephyrproject-rtos/zephyr --mr main ~/zephyr-main每个 workspace 独立west update独立构建。切换时改ZEPHYR_BASE指向对应目录即可。SDK 可以共用一套只要版本满足两个 workspace 的要求。这种隔离方式比在一个 workspace 里切分支干净得多不会出现依赖仓库版本错乱的问题。5. 环境搭好之后下一步该看什么环境跑通、Blinky 点亮之后很多人会迷茫接下来学什么我的建议是按这个顺序先读samples/下的代码。Zephyr 的 sample 质量很高从basic/blinky到net/sockets到subsys/logging每个都覆盖一个子系统。挑你项目里会用到的读。理解 devicetree 和 Kconfig 的协作。这是 Zephyr 区别于其他 RTOS 的核心。花一天时间把zephyr/boards/下某个 board 的.dts和_defconfig读一遍比看十篇教程有用。再进内核。线程调度、内存管理、同步原语这些等你能熟练构建和调试之后再深入否则容易陷入“看得懂代码但不知道怎么用”的困境。这个系列的第 1 篇我会从 Zephyr 的线程模型和调度器开始拆。环境是地基地基打好了上面的楼才稳。最后分享一个我自己的小习惯每次搭新环境我都会把整个流程写成一个 shell 脚本从装依赖到构建 Blinky 全自动跑一遍。这样换电脑、带新人、搭 CI都是几分钟的事。脚本里我会加set -e任何一步失败就停避免错误累积。这个脚本我用了三年改过十几版现在基本能做到“一条命令从裸机到点灯”。你也可以试试搭环境这件事一次投入长期受益。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑