3. 开发环境搭建:Zephyr SDK安装、West工具使用、目标板配置

好,咱们正式开始动手了。这一章我带你把开发环境搭起来。说实话,Zephyr的环境搭建比很多RTOS要复杂一些,但别怕,捋顺了其实就那么几步。我在项目里见过太多人卡在环境上,结果一天下来代码一行没写,全在折腾工具链。咱们争取半小时搞定。

3.1 Zephyr SDK安装——别选错版本

Zephyr SDK不是普通的编译器,它包含了针对不同架构的交叉编译工具链、调试器、QEMU模拟器等等。说白了,你电脑上装的GCC是给x86用的,而Zephyr SDK里的是给ARM、RISC-V这些嵌入式芯片用的。

下载与安装步骤:

  1. 去Zephyr官网下载对应你操作系统的SDK包。我建议用Linux,Windows虽然也能用但坑多。
  2. 解压到某个目录,比如 /opt/zephyr-sdk-0.16.8
  3. 运行安装脚本:./setup.sh
  4. 设置环境变量:export ZEPHYR_SDK_INSTALL_DIR=/opt/zephyr-sdk-0.16.8
注意:SDK版本必须和Zephyr主版本匹配。比如你用Zephyr 3.5,就别装0.15.x的SDK。我曾经因为版本不匹配,编译出来的固件跑起来就死机,查了两天才发现是工具链的问题。

安装完成后,验证一下:

# 查看SDK版本
$ $ZEPHYR_SDK_INSTALL_DIR/sysroots/x86_64-pokysdk-linux/usr/bin/arm-zephyr-eabi/arm-zephyr-eabi-gcc --version
arm-zephyr-eabi-gcc (Zephyr SDK 0.16.8) 12.2.0

看到版本号就说明SDK装好了。嗯,这里要注意,不同架构的编译器名字不一样,ARM的是arm-zephyr-eabi-gcc,RISC-V的是riscv64-zephyr-elf-gcc

3.2 West工具——Zephyr的瑞士军刀

West是Zephyr的元工具,它不只是个构建系统,还能管理多个仓库、拉取依赖、刷写固件。我个人习惯把它比作「Zephyr的包管理器+构建系统+刷写工具」三合一。

安装West:

# 用pip安装
pip3 install west

# 验证安装
west --version
West version: 1.2.0

安装完West后,下一步是获取Zephyr源码。这里有个坑——不要直接git clone,要用West来拉:

# 初始化工作区
west init ~/zephyrproject
cd ~/zephyrproject

# 拉取所有依赖模块
west update

为什么不用git clone?因为Zephyr依赖几十个外部模块,比如hal_stm32hal_nordiccmsis等等。West会自动帮你把这些都拉下来,并且版本对齐。你想想看,要是手动一个个git clone,光版本匹配就能让你崩溃。

小技巧:如果你网络不好,可以加--depth=1参数只拉最新版本:west init --depth=1 ~/zephyrproject。我刚开始学的时候没加这个,拉了一下午还没完...

拉完代码后,别忘了导出Zephyr的环境变量:

# 每次打开新终端都要执行
source ~/zephyrproject/zephyr/zephyr-env.sh

我建议把这行加到你的.bashrc.zshrc里,省得每次手动敲。

3.3 目标板配置——让Zephyr认识你的硬件

Zephyr支持几百种开发板,但你需要告诉它你用的是哪一块。配置分两步:选择板子、配置设备树。

第一步:选择板子

Zephyr里每个板子都有一个唯一的标识符,比如nrf52840dk_nrf52840stm32f429i_disc1。查看支持的板子:

# 列出所有支持的板子
west boards | grep nrf
nrf52840dk_nrf52840
nrf5340dk_nrf5340_cpuapp
nrf9160dk_nrf9160
...

第二步:配置设备树

设备树(Device Tree)是Zephyr描述硬件的方式。说白了,就是告诉Zephyr你的芯片有哪些外设、引脚怎么连、时钟跑多快。比如你要用USB,设备树里就得有USB控制器的节点。

一个典型的USB设备树片段长这样:

/ {
    usbd: &usb {
        compatible = "zephyr,usb-device";
        status = "okay";
    };
};

&usb {
    pinctrl-0 = <&usb_dp_pull_enable>;
    pinctrl-names = "default";
};

这里status = "okay"就是启用USB外设。很多新手忘了加这一行,结果USB怎么都枚举不上。我踩过这个坑,排查了半天才发现是设备树里USB被禁用了。

第三步:配置项目文件

在你的项目根目录下,创建prj.conf文件,里面放Kconfig配置:

# 启用USB设备栈
CONFIG_USB_DEVICE_STACK=y
CONFIG_USB_DEVICE_VID=0x2FE3
CONFIG_USB_DEVICE_PID=0x0001

# 启用日志输出(调试用)
CONFIG_LOG=y
CONFIG_USB_DEVICE_LOG_LEVEL=4

VID和PID是USB供应商ID和产品ID。0x2FE3是Zephyr的测试用VID,正式产品你得去USB-IF申请自己的VID。

3.4 编译与烧录——验证环境是否正常

环境搭没搭好,跑个Hello World就知道了:

# 创建一个示例项目
west build -b nrf52840dk_nrf52840 samples/basic/blinky

# 烧录到板子
west flash

如果LED开始闪烁,恭喜你,环境搭好了!如果报错,别慌,先检查:

  • SDK路径是否正确?echo $ZEPHYR_SDK_INSTALL_DIR
  • 板子名称是否拼写正确?west boards | grep 你的板子
  • USB驱动是否安装?Windows需要装JLink驱动,Linux需要udev规则。
避坑指南:我曾经在Windows上折腾了一整天,West编译没问题,但烧录时总是提示找不到设备。后来发现是JLink驱动没装对。如果你也用Windows,记得去SEGGER官网下载JLink驱动,别用系统自动安装的。

3.5 多板管理——同时开发多个目标

实际项目中,你很可能同时维护多个板子。比如我手头有个项目,既要跑在nRF52840上,也要跑在STM32F4上。West支持多板构建:

# 为不同板子创建独立的构建目录
west build -b nrf52840dk_nrf52840 -d build_nrf
west build -b stm32f429i_disc1 -d build_stm

-d参数指定构建目录,这样互不干扰。切换板子时只需要改-b参数和prj.conf里的配置就行。

好了,环境搭建就这些。下一章咱们开始写真正的USB设备代码,到时候你会回来感谢现在认真搭环境的自己。