☰
Ubuntu下Zephyr RTOS开发环境搭建与实操指南
2026/9/25 1:40:01 网站建设 项目流程

前阵子客户丢给我一块开发板,让帮忙评估一下Zephyr RTOS的落地情况。Zephyr这个实时操作系统在物联网圈子里已经不算小众,Ubuntu作为嵌入式开发宿主系统也是最常见的组合之一,但真正动手从零搭一套可编译、可烧录的完整环境时,才发现踩坑点比想象中多得多。这篇文章就是我在Ubuntu下安装Zephyr并完成基础测试的完整记录,包括依赖安装、west工具链、SDK配置、hello_world编译运行和常见问题排查,给正准备入坑Zephyr的嵌入式开发放一个可以直接照抄的实操参考。

1. 安装前的整体思路:先搞清楚Zephyr到底需要什么

1.1 Zephyr开发环境到底由什么组成

Zephyr不是一个简单的文件夹,它是一整套相互关联的工具链和源码仓库。核心部分有五个:Zephyr源码树本身(kernel、drivers、samples、modules这些)、west工具、CMake和Ninja构建系统、Zephyr SDK交叉工具链,再加上Python环境及若干pip依赖。

很多人一上来就git clone官方仓库,以为把代码拉下来就能编译,实际上Zephyr采用多仓库管理模式,内核和各个SoC厂商的HAL、驱动模块都是独立仓库存放的。west工具就是专门干这个的,它会根据west.yml这个清单一次把需要的外部模块全部对齐。编译的时候,west build会调用CMake生成构建配置,再用Ninja去做增量编译,而编译器、链接器、QEMU模拟器这些则来自Zephyr SDK。打个不严谨的比方,Zephyr代码相当于毛坯房,SDK是瓷砖水泥,west是施工监理,CMake就是施工图纸,少了哪一环都盖不起来。

我第一次在Ubuntu上装Zephyr时,照着官方文档一步步来,结果在SDK环境变量上卡了一整天。后来把整个工具链的工作原理过了一遍,再遇到报错就从容多了:先想清楚是哪个环节出的问题,而不是盲目百度报错信息。

1.2 为什么选择Ubuntu作为宿主系统

现在嵌入式开发的主流宿主系统基本就是Linux,而Ubuntu又是其中社区支持最好的发行版。Zephyr官方文档的快速上手章节,默认就是Ubuntu LTS环境的命令,这意味着网上大多数教程、issue回复、社区方案都基于这套环境,遇到问题更容易搜到答案。

在Windows上用WSL也可以跑Zephyr,但USB设备透传给开发板这个环节会额外增加不少麻烦,尤其是CMSIS-DAP、ST-Link这类调试器,WSL的usbip配置对新手不太友好。macOS整体可以,只是某些驱动和下载工具的支持会滞后。我自己长期用Ubuntu 22.04.5 LTS做主力开发机,除了Zephyr,其他嵌入式工具链如OpenOCD、pyOCD、JLink也都跑得很稳,一份环境通吃所有项目。

1.3 版本选择和系统准备

Ubuntu 22.04和24.04都可以,我建议直接用LTS版本,别在非LTS上跟自己较劲。开始之前先确认两件事:系统架构和磁盘剩余空间。终端执行uname -a,看到x86_64就是标准64位平台,绝大多数情况下都不会有问题。

磁盘剩余空间至少要有20GB的余量,因为west update会把Zephyr主仓库、hal、bootloader、工具模块全部拉下来,整体占用经常超过1GB,再加上SDK解压和构建中间文件,空间不够会非常被动。虚拟机用户记得给Ubuntu分配不低于4GB内存,编译器跑满时内存太小会出现莫名其妙的OOM问题。

另外,安装过程会大量调用apt和pip,务必保证网络状态良好,软件源可用。如果用的是虚拟机,建议拍摄一个初始快照,装坏了好随时回滚,这个习惯帮我省了很多重装系统的功夫。

2. 系统依赖安装与环境准备:先把地基打牢

2.1 Ubuntu下需要预装的软件包清单

Zephyr官方文档列出了完整的依赖清单,我合并成一条apt命令:

sudo apt update sudo apt install --yes \ cmake \ ninja-build \ gperf \ ccache \ dfu-util \ device-tree-compiler \ python3-dev \ python3-pip \ python3-setuptools \ python3-tk \ python3-wheel \ xz-utils \ file \ make \ gcc \ gcc-multilib \ libsdl2-dev

这条命令里的软件包各有各的用途,挑几个容易忽略的说。cmake是构建系统生成器,Ninja是快速的构建工具,这俩是编译Zephyr的核心;gperf用于生成哈希表,在设备树处理时会用到;dfu-util是做DFU升级固件的工具,烧录时要靠它;libsdl2-dev作用在QEMU图形模拟输出上,少了它跑图形化的sample可能报SDL相关错误;gcc-multilib则是为了让编译链能够生成32位目标代码,很多Zephyr平台需要这个功能。

如果个别包安装失败,不要慌,最常见的原因是软件源没有刷新或者源列表有问题,先重新执行sudo apt update,再单独装一下报错的包试试。

2.2 Python虚拟环境的创建与west的安装

我强烈建议在安装west之前先创建一个Python虚拟环境。不要图省事直接在系统Python里装west,否则后期不同项目对west版本要求不一致时,包冲突会让你怀疑人生。

创建虚拟环境的步骤很简单:

mkdir -p ~/zephyrproject cd ~/zephyrproject python3 -m venv .venv source .venv/bin/activate pip install --upgrade pip pip install west

激活虚拟环境后,命令行的提示符前面会多出一个(.venv)前缀,这就是环境生效的标志。之后的west命令都要在这个虚拟环境里执行,所以我一般会在~/.bashrc里加一行自动激活:

echo "source ~/zephyrproject/.venv/bin/activate" >> ~/.bashrc

这样每次打开终端都自动进入虚拟环境,省得忘记激活导致west命令找不到。

安装完成后验证一下:

west --version

能输出版本号,说明west已经就绪。

2.3 确认工具链版本:CMake与Python的版本要求

Zephyr对基础工具的版本有硬性要求,比较关键的是CMake需要3.20以上,Python需要3.8以上,Ninja需要1.10以上。Ubuntu 22.04自带的CMake是3.22.x,Python是3.10.x,直接满足要求;Ubuntu 24.04版本更高,更没问题。

可以通过下面这组命令快速核对版貌:

cmake --version python3 --version ninja --version gperf --version

如果CMake版本不够,不建议自己从源码编译,直接用apt安装系统自带的版本最省心。Zephyr对版本的要求其实比较宽容,并不是非最新不可,官方支持测试版本范围内能跑就行。

3. 工作区初始化与Zephyr源码同步

3.1 使用west init创建workspace

在虚拟环境激活的状态下,开始初始化workspace。

cd ~/zephyrproject west init -m https://github.com/zephyrproject-rtos/zephyr .

这条命令会在当前目录初始化一个manifest管理的工作区。特别注意,最后的那个.表示以当前目录作为workspace根目录,所以执行前一定要先进入目标目录。如果省略路径参数,west会默认使用当前目录。

初始化完成之后,目录下会多出一个.west文件夹和一个west.yml清单文件。这时候源码树还没有完全拉全,只能算搭好了骨架。

3.2 west update拉取全部组件

接着执行最关键的一步:

west update

west会读取west.yml清单文件,把Zephyr主仓库、hal、CMSIS、各种bootloader、SoC厂商支持包全部拉取到本地。这一步下载量比较大,实际运行过程中可能会卡住,这属于正常现象,保持网络通畅,耐心等待即可。如果中途断了,直接重新执行west update,git具备断点续传能力,已拉取的部分不会重复下载。

拉取完成之后,目录结构大致是这样的:

  • zephyr/:主仓库,包含kernel、drivers、samples、doc等
  • modules/:HAL、加密库、文件系统等外部模块
  • bootloader/:MCUboot等启动代码
  • .west/:west配置和manifest信息

3.3 为什么必须用west而不是直接git clone

很多新手会问:我单独把Zephyr克隆下来不行吗?真不行。Zephyr的构建系统在编译时会根据manifest找外部module的头文件和库文件,如果这些模块缺失,编译到一半就会报各种“cannot find hal_stm32”“cannot find cmsis”之类的错误。

west相当于Zephyr世界里的包管理工具,它和git的关系,大概类似于apt和dpkg的关系:git只是最底层的版本管理工具,west在git之上做了多仓库协调。它知道每个组件应该放在哪个位置,还负责处理仓库之间的依赖关系。更妙的是,切换不同Zephyr版本时,west能把所有关联仓库对齐到对应版本,避免库和内核版本不匹配导致的诡异问题。

所以我的建议是:所有涉及Zephyr源码的操作都通过west来做,包括查看分支、切换版本、更新代码。手动git pull很容易把workspace搞乱。

4. Zephyr SDK安装与工具链对接

4.1 SDK下载与解压

Zephyr SDK是交叉编译工具链的集合,里面包含了针对不同CPU架构的GCC编译器、GDB调试器、QEMU模拟器和各种主机工具。

下载地址在Zephyr官方GitHub的sdk-ng仓库Releases页面,选择文件名包含linux-x86_64的.tar.xz压缩包。以0.16版本的包为例,下载命令大致是:

wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/zephyr-sdk-0.16.8/zephyr-sdk-0.16.8_linux-x86_64.tar.xz

解压到一个固定目录,我习惯放在主目录下:

tar xf zephyr-sdk-0.16.8_linux-x86_64.tar.xz mv zephyr-sdk-0.16.8 ~/zephyr-sdk

强烈建议解压后先校验下载完整性。在下载页面找到对应的SHA256校验值,然后执行:

sha256sum zephyr-sdk-0.16.8_linux-x86_64.tar.xz

如果校验结果和页面一致再解压。我吃过一次亏,下载中断后文件损坏,解压勉强成功但编译器不可用,折腾了两个小时才发现是SDK包的问题。

4.2 setup.sh脚本做了什么

SDK目录下有一个setup.sh,运行它会把SDK的host工具安装到系统可执行路径中:

cd ~/zephyr-sdk ./setup.sh

执行过程中可能会提示输入用户密码,这是因为它需要把一些elf工具软链接到系统目录。setup.sh会把sysroots/x86_64-pokysdk-linux/usr/bin下的工具复制或链接到/usr/local/bin等位置,让west和cmake能直接找到这些工具。

如果你不想安装到系统路径,也可以跳过setup.sh,仅通过环境变量指定SDK位置。不过我还是建议正常执行这个脚本,因为很多构建流程会依赖系统路径中的arm-zephyr-eabi-gdb、qemu-system-*等程序,用系统装好的最方便。首次执行记得记录输出的最后几行,它会提示你是否需要安装额外的工具链。

4.3 环境变量配置与常见错误

SDK装好后,还需要让Zephyr构建系统知道编译器在哪里。编辑~/.bashrc,加入这两行:

export ZEPHYR_TOOLCHAIN_VARIANT=zephyr export ZEPHYR_SDK_INSTALL_DIR="$HOME/zephyr-sdk"

然后执行:

source ~/.bashrc

ZEPHYR_TOOLCHAIN_VARIANT=zephyr告诉构建系统使用Zephyr官方SDK作为交叉编译工具链,而不是系统自带的gcc。这一点特别关键,如果不设置,cmake会尝试用宿主机的gcc编译Zephyr的内核,那是完全跑不通的。

ZEPHYR_SDK_INSTALL_DIR指定SDK的安装目录。注意这个变量指向SDK根目录,不需要在末尾加上具体的版本号路径,west会自动扫描该目录下的工具链子目录。

如果这两个变量没配置好,最常见的报错是:

CMake Error at cmake/modules/dts.cmake... Could not find a suitable Zephyr toolchain

看到这类错误,优先检查环境变量是否正确设置。

5. 编译并运行第一个例程:hello_world

5.1 编译qemu_x86平台示例

环境和SDK都就绪后,进入workspace目录,开始编译Zephyr自带的hello_world示例。

cd ~/zephyrproject west build -b qemu_x86 -p samples/basic/hello_world

参数说明:-b qemu_x86指定目标平台为QEMU模拟的x86 Borad;-p是--pristine的简写,表示执行一次干净构建,清空可能存在的旧构建缓存。首次编译时,Zephyr会先生成设备树相关文件和配置文件,再编译内核和示例代码。

第一次编译耗时比较长,三到五分钟都很正常。编译成功后,终端末尾会显示构建产物路径:

Memory: 2626 bytes ... Flashing files...

生成的固件在build/zephyr/目录下,包括zephyr.elf、zephyr.bin、zephyr.hex三种格式。zephyr.elf包含调试符号,是调试器用的;zephyr.bin是纯二进制,直接烧录用;zephyr.hex是Intel HEX格式,很多下载工具要求这个格式。

5.2 使用QEMU运行与验证

编译qemu_x86平台的其中一个优势,就是不需要真实硬件就能运行验证。在同一个终端里执行:

west build -t run

这个命令会启动QEMU模拟器,然后你会在终端里看到类似下面这样的输出:

Welcome to the Zephyr Real Time Kernel Hello World! x86

看到这行就说明Zephyr内核已经成功跑起来了。退出QEMU的方式是Ctrl+A X(先按Ctrl+A,再按X键),不要随手按Ctrl+C,否则可能无法正常退出虚拟机进程。

QEMU模式的优势是方便快捷,它适合验证内核基本功能,但无法模拟真实板卡的IO和外设时序,所以跑完QEMU之后,强烈建议在真实开发板上再烧一次固件。

5.3 针对真实开发板的烧录准备

如果你手里有支持的开发板,比如常见的STM32系列、nRF系列,用west build指定实际板卡的board名称重新编译一次:

west build -b <board-name> -p samples/basic/hello_world

board名称可以通过west boards命令查看完整列表。比如我手头的nRF52840DK,对应的名称是nrf52840dk_nrf52840。

编译完成后烧录:

west flash

west会根据板卡的调试器类型自动调用OpenOCD、pyOCD或J-Link工具。烧录之前先把开发板通过USB连接到电脑,并确认系统能识别到调试器。

6. 常见问题与排查技巧实录

6.1 依赖安装失败的经典场景

最常遇到的就是apt install时报Unable to locate package。这个多半是软件源没刷新的问题,先执行sudo apt update再重新安装。如果还不行,检查软件源配置文件,看看是不是把不同发行版的源混在一起了。

另一个高频错误是You have held broken packages,这通常是因为软件包依赖关系已经损坏。先用sudo apt --fix-broken install修复,再继续装。我之前在Ubuntu 22.04上装gcc-multilib就碰到过卡在依赖上的情况,修复之后问题才解决。

安装gcc失败也比较常见,特别是同时手动装过其他版本的gcc之后。建议直接用apt安装系统版本的gcc,不要从源码编译安装,否则会把系统gcc覆盖掉,连带引发一堆编译链问题。

6.2 west命令找不到或pip权限问题

如果你是按照虚拟环境的方式安装west,基本不会遇到这个问题。但如果你之前用了sudo pip install west,然后打开新终端又执行west --version提示找不到命令,不要惊讶。

新终端没有激活虚拟环境,或者路径没有配置完整。先激活虚拟环境,或者检查west所在的路径:

which west

如果是装在用户目录,执行:

export PATH="$HOME/.local/bin:$PATH"

把该路径加到~/.bashrc即可。有一点要特别提醒:不要用sudo pip install,这会把west装到系统Python的site-packages里,一旦系统Python升级或出现权限冲突,整个环境的稳定性都会受影响。

6.3 SDK下载解压不完整导致编译失败

SDK的tar.xz压缩包体积动辄数百MB,网速不稳定时很容易下载失败。如果你的提示栏显示下载完成了,但解压时出现unexpected EOF或者gzip: invalid compressed data,先不要急于重新解压,很可能压缩包本身就是坏的。

用前面提到的sha256sum对照官方校验和,确认无误再解压。如果校验不匹配,删除压缩包重新下载。另外,解压SDK之后最好执行./setup.sh时多留意输出内容,有些版本会明确提示缺失的组件。

6.4 编译过程中CMake报错怎么定位

编译报错是家常便饭,重要的是掌握定位思路。如果报错指向CMakeCache.txt相关,基本可以判断构建缓存出了问题,最简单的办法就是把build目录整个删掉再重新编译:

rm -rf build west build -b qemu_x86 -p samples/basic/hello_world

如果报错提示host tools not found or too old,就去检查cmake和ninja的版本。如果报错信息里出现No board found,说明board名称写错了,用west boards查一下正确的名称。

另外,千万注意不要直接进入build目录执行cmake,Zephyr的构建必须通过west命令来驱动,这是很多新手容易踩的坑。直接cmake大概率会报出一堆看不懂的配置错误。

6.5 无法识别USB串口或烧录失败

开发板用USB连接电脑后,执行:

lsusb dmesg | tail -20

确认调试器的USB设备是否被识别。如果是串口工具访问/dev/ttyUSB0没有权限,说明用户不在dialout组里,执行:

sudo usermod -aG dialout $USER

然后注销重新登录,或者重启一下系统。烧录失败还有一个常见原因是开发板没有进入boot模式,很多板子需要按住复位键或者拨动boot跳线开关,具体要看板卡引导说明。

我踩过最典型的一个坑是:烧录工具能识别到调试器,但一直报Cannot connect to target。最后发现是调试器固件版本太旧,去厂商官网更新了调试器的固件才解决。

最后聊几句实在话

从零搭建Zephyr环境,说难也难,说简单也简单。难在你需要对它的工具链体系有一个整体认知,简单在于只要按本文顺序一步步操作,一般不会有什么意外。我个人实际操作中的体验是:不要在SDK环境变量和west这两个点上省时间,它们决定了后续所有项目开发的基础。另外,刚开始接触Zephyr不用急着追最新版本,选一个官方支持周期内的稳定版本就够了,把环境跑通之后再去探索多板卡和多模块的方案扩展,反而更从容。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询