如果你玩过 STM32,大概率是从 Keil + 标准外设库或者 HAL 库起步的。点个灯、跑个串口、接个传感器,这套流程驾轻就熟。但当你开始接触稍微复杂一点的项目,比如要同时跑多个任务、要处理网络协议栈、要对接各种外部设备驱动,裸机或者简单前后台轮询的写法会越来越吃力。我自己是在做一个需要 WiFi + MQTT + 多传感器数据采集的小项目时,被中断优先级、内存管理、外设驱动这些琐碎细节反复折磨,才下决心试试 Zephyr RTOS。这篇文章就是记录我从零开始,给手头的 STM32 开发板搭好 Zephyr 环境、成功点亮板载 LED 的完整过程。
Zephyr 是 Linux 基金会旗下的开源实时操作系统,对 STM32 的支持非常完善。它最大的魅力在于,驱动模型、调度器、网络协议栈、低功耗管理这些都是现成的,你不用再从零造轮子。这篇“保姆级”博文会覆盖从硬件准备、主机环境配置、工具链安装、源码获取,到编译烧录验证的每一个步骤,还夹带了我踩过的坑和排查思路。不管你是刚从 Keil 转过来的老手,还是第一次接触 RTOS 的初学者,照着走一遍,基本能让你手头的开发板跑起 Zephyr。
1. 为什么是 Zephyr:先搞懂它给 STM32 带来了什么
1.1 从裸机到 RTOS,Zephyr 解决了什么
很多人在 STM32 上的第一款 RTOS 会选 FreeRTOS,因为资料多、上手快。但 Zephyr 的定位其实不太一样,它更像一个“面向物联网的迷你 Linux”。它有统一的设备驱动模型、基于设备树(Device Tree)的硬件描述、模块化内核、丰富的网络协议支持,还有一套非常强大的构建系统(west + CMake)。
直接用裸机开发遇到的最大问题,不是“能不能跑”,而是“跑了之后怎么维护”。比如你要在 STM32 上挂一个 OLED 屏,同时用 DMA 接收串口数据,还要定时采集传感器。裸机下你可能得自己维护一堆状态机,处理各种优先级关系,稍微一改逻辑就容易出 bug。Zephyr 里,每个功能都可以拆成一个独立的线程,通过信号量、消息队列来做线程间通信,系统的整体结构清晰很多。
再说外设驱动。裸机开发时,每换一块屏幕、每换一个传感器型号,都要去翻 datasheet、自己写初始化序列和读写时序。Zephyr 的驱动框架把这一层抽象掉了,大多数常见外设(GPIO、UART、I2C、SPI、PWM、ADC 等)都有现成驱动,你只需要在设备树里声明“我用的是哪个引脚、什么速率”,驱动框架会自动完成剩下的工作。我第一次在 Zephyr 里操作 I2C 传感器时,真的被这种“配置驱动”而不是“手写驱动”的开发方式惊艳到了。
1.2 Zephyr 在 STM32 上的优势与适用场景
STM32 家族庞大,从 F0 到 H7,内核从 Cortex-M0 到 Cortex-M7 都有。Zephyr 对 ST 系列的支持覆盖度很高,官方支持的开发板列表里能看到很多常见的 NUCLEO、Disco 系列板卡。即使你的板子不在官方列表里,只要芯片型号有支持,也可以自己通过设备树文件“移植”过去,并不复杂。
Zephyr 特别适合需要网络功能的场景。它的原生网络协议栈支持 TCP/IP、UDP、CoAP、MQTT、TLS,底层可以走以太网、WiFi(通过外部模块)、BLE 或者 6LoWPAN。这意味着你可以在 STM32 上直接跑 MQTT 客户端,而不需要像裸机方案那样自己移植 lwIP、mbedTLS,再把它们和业务代码粘在一起。我在后面那个项目里就是用 Zephyr 的 MQTT 库,只写了不到两百行业务代码,就把数据推送到了服务器。
如果你有低功耗需求,Zephyr 的电源管理框架也很有优势。它支持 tickless idle 模式,能在没有任务运行时让 CPU 进入低功耗状态,同时通过设备电源管理 API 去控制外设的休眠和唤醒。这在电池供电的物联网设备上非常关键。
1.3 用 Zephyr 搭环境的整体思路
Zephyr 的环境搭建有个特点:它不像 Keil 那样装一个 IDE 就完事,而是依赖命令行工具链。整个过程可以概括为“装 west、拿源码、装 SDK、编译烧录”四步。
听起来简单,但实际操作中容易卡在各种细节上:
- west 是 Zephyr 的元工具,负责管理多仓库代码、构建和刷写;
- Zephyr 源码仓库本身很庞大,而且通过 west 会拉取很多子模块;
- Zephyr SDK 是一套预编译好的交叉编译工具链,包含了针对各种架构的 GCC、binutils、调试器,不用自己手动折腾 arm-none-eabi-gcc 版本。
所以我强烈建议,第一次搭建环境时严格按照官方推荐的流程走,不要企图自己“精简步骤”。我在踩坑过程中发现,很多编译错误都源于版本不匹配,比如 Zephyr 主仓库版本太新但 SDK 版本太老,或者 west 版本跟 manifest 文件里声明的依赖冲突。
2. 环境搭建前的准备:硬件、主机与软件选型
2.1 开发板选型和硬件准备
理论上,只要是 Zephyr 官方支持列表里的 STM32 开发板,都能按这篇文章的流程跑通。我用的是常见的 NUCLEO-F411RE,板载 ST-LINK/V2 调试器,通过 USB 连电脑就能同时供电和烧录。这种板子小巧、带板载调试器,新手用起来最省心,不需要额外买 J-Link 或者 ST-Link。
如果你用的是 STM32F103C8T6 那种“蓝 pill”最小系统板,也没有问题。它板载的 USB 口只是 USB-to-TTL 串口,不能直接用来烧录调试,你需要外接一个 ST-Link V2 或者其他 SWD 调试器。准备硬件的时候,我建议先确认以下几点,可以避免不少麻烦:
- 确认开发板上有板载调试器,或者你手头有可用的 SWD/JTAG 调试器;
- 确认开发板供电正常。有些板子通过 USB 口供电时,如果 USB 线质量差或者接触不良,会出现调试器不稳定、烧录失败的问题;
- 确认板载 LED 接到了哪个 GPIO。Zephyr 的 blinky 示例会默认使用设备树里定义的“led0”节点,如果你的板子设备树里没有定义,需要自己改设备树或者选对 board target。
2.2 宿主机操作系统的选择
Zephyr 官方支持 Linux、macOS 和 Windows。但我个人强烈推荐在 Linux 环境下使用,尤其是 Ubuntu 20.04 或 22.04 这些 LTS 版本。原因很简单:Zephyr 的构建、烧录工具链在 Linux 下最“原生”,很多自动化脚本和依赖管理工具都优先保证 Linux 环境的兼容性。Windows 下虽然可以做,但往往要额外处理驱动、PATH 环境变量、串口权限等一堆琐碎问题。
如果你和我一样,主力电脑是 Windows,但又不想装双系统或者换电脑,有两个比较顺手的方案:
一是装虚拟机,用 VirtualBox 或 VMware 跑一个 Ubuntu 22.04。整个 Zephyr 开发环境都放在虚拟机里,好处是干净、不影响主系统,缺点是 USB 设备直通到虚拟机偶尔会有小问题,尤其是 ST-Link 这类调试器,需要在虚拟机的 USB 设置里单独添加设备过滤规则。
二是用 WSL2(Windows Subsystem for Linux)。Zephyr 官方对 WSL2 的支持比较友好,USB 设备可以通过 usbipd-win 项目转发到 WSL2 里,实现烧录。不过这个方案需要多配置一步 USB 串口转发,如果没接触过 WSL2,第一次配置容易卡住。我自己现在的习惯是:日常在 Ubuntu 物理机或虚拟机上跑 Zephyr,Windows 只用来开文档和查资料,分工明确,减少折腾。
2.3 必备软件安装:Python、CMake、Ninja 等
Zephyr 的构建系统依赖 CMake、Ninja、Python3、pip、dtc(设备树编译器)等工具。在 Ubuntu 下,这些大多可以通过 apt 直接安装。建议在开始之前先把系统软件源更新一遍,避免装到一半因为老软件源导致依赖安装失败。
sudo apt update sudo apt upgrade -y sudo apt install -y cmake ninja-build gcc g++ python3 python3-pip \ dfu-util device-tree-compiler git wget curl这里有几个小提醒:
- CMake 版本不能太老。Zephyr 官方对 CMake 有最低版本要求(通常是 3.20 以上),如果 apt 源里默认的 CMake 版本偏低,建议通过 pip 安装最新版本,或者从 CMake 官网下载预编译包。
- Python 建议用 3.8 以上的版本。Zephyr 的脚本和 west 工具对 Python 版本有依赖,老版本容易出现语法兼容问题。
- dfu-util 是 DFU 模式烧录工具,如果你用支持 DFU 的板子(比如某些 STM32 板卡可以通过 bootloader 进入 DFU),这个工具很有用。对于 ST-Link 调试器来说,虽然不一定直接用到,但属于“装了不亏”的项。
装完这些基础包之后,最好再验证一下版本,确认它们都可用。我遇到过一种情况:系统里同时装了多个 CMake 版本,终端里默认调用的结果跟预期不一致,导致编译时出现奇怪的“找不到 CMake”错误。
3. 一步步搭好 Zephyr 开发环境
3.1 安装 west 与 Python 依赖
west 是 Zephyr 的元工具,负责仓库管理、构建和烧录。它本身是一个 Python 包,通过 pip 安装。为了避免污染系统全局 Python 环境,我强烈建议用 Python 虚拟环境(venv)来安装 west,尤其是你平时还会在系统里装其他 Python 项目的时候。
创建并激活虚拟环境:
python3 -m venv ~/zephyr-venv source ~/zephyr-venv/bin/activate pip install --upgrade pip pip install west激活虚拟环境后,你的终端提示符前面会出现一个(zephyr-venv)前缀,这说明你已经在虚拟环境里了。之后每次开新终端,都要先执行source ~/zephyr-venv/bin/activate才能使用 west 命令,否则系统会提示找不到命令。
有两点要特别注意:
- 别在这时候急着装 Zephyr SDK。Zephyr SDK 和 west 是两套东西,SDK 是交叉编译工具链,west 负责拉取源码和构建。我一开始把这两个概念搞混,折腾了很久。
- 如果你之前安装过旧版 west,建议
pip uninstall west先卸载干净再装新版,避免命令路径冲突。
3.2 获取 Zephyr 源码并初始化 workspace
Zephyr 的源码不是单个 Git 仓库,而是由多个仓库组成的 manifest 项目。west 通过一个 manifest 文件来描述这些仓库的依赖关系,west init会根据这个 manifest 把项目骨架搭好。
在一个你希望存放代码的目录下执行:
cd ~ mkdir zephyr-project && cd zephyr-project west init zephyr cd zephyr west updatewest init zephyr会在zephyr-project/zephyr目录下创建一个 Zephyr 的主仓库,west update则会根据 manifest 把所有必要的仓库(比如 modules、hal、third_party 等)拉取到本地。这一步依赖网络,而且仓库数据量不小,可能需要几分钟到十几分钟,取决于你的网络状况。
我没有给这一步单独配加速方案,因为 Zephyr 仓库本身托管在 GitHub 上,如果你所在网络环境访问 GitHub 比较慢,可以考虑用代理镜像,但我不在这里展开这个话题。跑完west update后,可以检查一下zephyr-project目录下面是否多了一些bootloader、modules、tools之类的文件夹,这些就是 west 帮你拉下来的依赖仓库。
3.3 安装 Zephyr SDK 交叉编译工具链
Zephyr SDK 是预编译好的工具链集合,官方发布了针对 x86、ARM、RISC-V 等架构的版本。对 STM32 来说,我们主要用到的是 ARM 相关工具链。
SDK 安装包很大,建议直接去 Zephyr 官网或者 GitHub Releases 页面下载.run文件。我用的版本是 0.16.x,与 Zephyr 3.x 系列主版本搭配没有问题。下载后执行:
chmod +x zephyr-sdk-0.16.1_linux-x86_64.run ./zephyr-sdk-0.16.1_linux-x86_64.run -- -d ~/zephyr-sdk安装完成后,SDK 会被解压到~/zephyr-sdk目录。你需要设置环境变量ZEPHYR_TOOLCHAIN_VARIANT和ZEPHYR_SDK_INSTALL_DIR,或者简单地把 SDK 目录下的environment-setup脚本 source 进当前终端。我比较推荐后者:
source ~/zephyr-sdk/environment-setup把这个source命令加进~/.bashrc,以后每次打开新终端就自动生效,不用手动执行。这一点挺重要的,因为 Zephyr 的构建系统在找不到 SDK 环境变量时会直接报错退出,而且报错信息还比较隐晦。
一个容易踩的坑是:Zephyr SDK 自带了一个特定版本的 CMake 和 Python,它可能会影响你系统中原本的默认版本。我建议不要在 PATH 里把 SDK 的 bin 目录放到最前面,否则可能出现“新版系统 CMake 被 SDK 里的旧版覆盖”这种奇怪问题。
3.4 编译第一个示例:blinky
环境搭好之后,最激动的时刻来了:编译第一个示例。Zephyr 官方示例里,最“点灯”的就是zephyr/samples/basic/blinky。进入zephyr-project/zephyr目录,执行:
cd ~/zephyr-project/zephyr west build -b nucleo_f411re samples/basic/blinky-b参数指定板卡 target,也就是开发板型号。如果你的板子不在官方支持列表里,可能会出现“找不到 board”的报错。这时候可以先执行west boards | grep <关键字>查一下有没有相近型号,或者去boards/arm目录下看看有哪些板卡定义。
编译过程首次会比较慢,因为要生成一堆构建文件、编译内核和外设驱动。这时候不要急着中断,喝口水等一等。构建完成后,终端末尾会出现类似Firmware files的输出,告诉你生成的固件文件在哪。我当时的输出里提示固件位置在build/zephyr/zephyr.bin。
这一步算是环境搭建成功与否的“体检”。如果编译过程没有报错,说明 west、SDK、源码拉取都没有问题,接下来就差烧录验证了。
4. 烧录与验证:让 LED 真正闪起来
4.1 准备烧录工具:ST-Link / OpenOCD / STM32CubeProgrammer
在 Windows 上玩 STM32 的同学,对 ST-Link 驱动和 STM32CubeProgrammer 应该很熟。Zephyr 里烧录则通常走 west flash,它会自动调用底层烧录工具。当你指定-b nucleo_f411re这类板卡时,Zephyr 构建系统会根据设备树的 flash 配置,自动选择用 OpenOCD 或者 STM32CubeProgrammer 来烧录。
Zephyr 对 OpenOCD 的支持比较老牌,但 OpenOCD 对 ST-Link 的适配版本敏感。我建议在 Ubuntu 下先用 apt 安装 OpenOCD,同时保证版本不要太旧:
sudo apt install openocd如果你更习惯 ST 官方工具,可以去 ST 官网下载 STM32CubeProgrammer,然后在 Linux 下配置好路径。Zephyr 的 west flash 会优先在系统 PATH 里查找STM32_Programmer_CLI,所以安装后记得把它的路径加进环境变量。
4.2 用 west flash 烧录固件
把你手里的开发板用 USB 线连接到电脑。如果是 NUCLEO 板,通常是板子上那个 Mini-USB 或 Micro-USB 口,连接后电脑上应该会出现一个新的 USB 设备。在 Linux 下,可以先执行lsusb看看是否识别到 ST-Link 设备。如果啥都没看到,大概率是 USB 线质量不行只能供电不能传数据,或者驱动没装好。
确认硬件识别后,直接执行:
west flashwest 会自动探测当前构建目录(也就是之前 west build 生成的 build 目录),找到对应的烧录配置。终端里会打印出调用的烧录命令和进度。烧录完成后,如果一切顺利,你会看到板载 LED 开始以默认频率闪烁。
我当时遇到过一次烧录失败,报错的是Error: open failed In procedure: 'transport select',其实就是 OpenOCD 没有找到 ST-Link 调试器。检查之后发现,是虚拟机里的 USB 设备没有挂载到 Ubuntu。如果你也遇到类似报错,先别怀疑代码,先看看 USB 设备是不是真的在虚拟机里可见。
4.3 验证串口输出与系统运行
blinky 示例本身没有串口输出,但如果你的板子连接了 USB 转串口,或者板载了 ST-Link 的虚拟串口,你可以在烧录一个 hello_world 示例来看串口输出:
west build -b nucleo_f411re samples/hello_world west flash然后用串口调试工具(比如 minicom、putty 或 screen)打开对应的串口设备。Linux 下可以用screen /dev/ttyACM0 115200,如果权限不足,把当前用户加入 dialout 组:
sudo usermod -aG dialout $USER退出重新登录后,按下开发板复位键,串口终端里应该会打印出Hello World!以及uart:~$之类的 shell 提示符。Zephyr 默认还带了一个小 shell,可以用来查看内核线程、设备列表等等,还挺酷的。
验证串口这个步骤,在一次我接手一台没有显示器的 Linux 主机时,成了排查环境问题的救命稻草——至少在头灯亮之前,可以先确认系统有没有在跑。
5. 常见问题排查与避坑记录
5.1 STM32 开发板无法识别 USB 设备
这个现象很常见:插上开发板,电脑没反应,lsusb里也看不到任何新设备。优先排查 USB 线是不是“只有充电没有数据”的类型。嵌入式开发建议至少要备两三根支持数据传输的 USB 线。
其次,在虚拟机和 WSL2 环境下,要检查 USB 设备是否已经通到宿主机系统。VirtualBox 需要在虚拟机的设置里添加 USB 设备过滤器,WSL2 则需要用 usbipd 之类的工具绑定设备。这些细节很琐碎,但不搞定它们,后面的烧录和设备访问都无从谈起。
还有一点:开发板的 USB 口如果接了板载 ST-Link,插上后系统应该能识别到一个 USB 转串口设备和 ST-Link 调试器两个设备。如果只有一个出现,检查一下是不是板子上的跳线帽动了,某些板卡的调试器和串口是可以通过跳线独立控制的。
5.2 编译报错:找不到 board、toolchain 相关问题排查
编译时最常见的报错是error: invalid choice: 'nucleo_f411re',说明在当前的 boards 目录里没有找到对应的板卡定义。可能原因:一是板卡型号写错了,去boards/arm目录下查实际的文件夹名字;二是 Zephyr 源码拉取不完全,执行west update后再试一次。
另一种常见错误是Sdk not installed或Zephyr SDK can not be found。这是环境变量没设对。检查一下ZEPHYR_TOOLCHAIN_VARIANT和ZEPHYR_SDK_INSTALL_DIR是否正常,或者有没有执行过 SDK 的environment-setup。一个非常容易忽略的点是:你把 SDK 解压到了某个目录,但这个路径下有空格或中文,CMake 可能会解析失败。
有时候编译报错的“真相”并不在最后几行。Zephyr 构建系统是 CMake 驱动的,错误信息可能很长,建议把整段日志滚动上去看,寻找第一个Error开头的行,而不是只看结尾的 summary。
5.3 west update 网络超时与版本锁定问题
west update拉取仓库时因为网络原因经常中断,可以在命令前设置 git 的 http 和 https 代理环境变量来加速下载,但这里不展开,也可以通过多拉取几次的方式解决。还有一种更省事的做法:直接用west update -o=--depth=1,这样每个仓库都只拉取最近一次提交,能显著减少下载量。不过这会取消本地仓库的完整历史,如果之后要切换分支或者查历史,就会比较麻烦。
版本锁定的问题也很典型。Zephyr 主仓库会随着时间不断更新,某些第三方仓库可能跟不上主仓库的变更,导致west update之后出现编译错误。我自己在上半年就遇到过一次,主仓库更新后,某个传感器驱动模块的 API 变了,但 west 拉下来的第三方模块没有同步。这种情况最稳妥的解决方式是用固定的 manifest 版本。你可以通过west init --mr指定某个 release 分支,比如:
west init zephyr --mr v3.7.0这样你会得到一个相对稳定的源码树,适合“先跑通环境,再追新版本”的同学。
5.4 烧录失败或连接不上调试器
烧录失败一般分两类:一类是 OpenOCD 报错,另一类是 STM32CubeProgrammer 报错。OpenOCD 报错里比较常见的是无法连接调试器、SWD 通信超时。这时先检查调试器是否被其他程序占用,比如你同时开着 STM32CubeIDE 的调试窗口,它会占用 ST-Link,导致 west flash 连不上。
另一个容易踩的坑是开发板没有进入正确的 BOOT 模式。有些 STM32 板卡默认的 BOOT0 引脚电平会决定芯片是从 Flash 启动还是从系统 Bootloader 启动。如果你从 I2C 或者 UART 烧录时发现芯片总是烧完不执行,检查一下 BOOT0 跳线。
如果换了电脑或者第一次连接开发板,Linux 下 ST-Link 需要 udev 规则。Zephyr SDK 自带的 OpenOCD 在安装时会顺带安装 udev 规则,但如果你用的是系统 apt 装的 OpenOCD,可能需要手动把 Zephyr SDK 下的openocd/contrib/60-openocd.rules复制到/etc/udev/rules.d/,然后重新加载 udev。
5.5 一些实用小技巧:调试器和开发板之间的选择
刚开始接触 Zephyr 的时候,建议尽量选一块“官方支持度好、社区资料多”的板子,比如 NUCLEO 系列。这些板子的设备树、板级定义文件、文档都非常完善,照着跑不容易出幺蛾子。后期如果想把 Zephyr 移植到自己的自制 PCB 上,可以直接从官方的板卡目录里拷贝一份配置文件,修改设备树里的 flash 大小、引脚定义、时钟配置,工作量会小很多。
调试器的选择上,ST-Link 对 STM32 肯定是首选。J-Link 性能更强、功能更多,但对 Zephyr 的 OpenOCD 适配并不一定比 ST-Link 更省心。在 Zephyr 环境里,ST-Link 和 OpenOCD 的组合是我实测最稳的。
另外,我建议准备一个 USB 转 TTL 模块,哪怕板载了虚拟串口。在很多排查场景下——比如系统启动崩溃、看门狗复位、串口打印乱码——外接一个逻辑分析仪调试器或者独立串口,能帮你定位到驱动开始初始化之前的问题。
6. 跑通之后,Zephyr 还能怎么玩
6.1 设备树在 STM32 上的作用
很多从 Keil 转过来的同学,第一次看到 Zephyr 里的设备树文件(.dts/.dtsi)会觉得头大。实际上,设备树的作用就是“用文本描述硬件”。你的 STM32 芯片有哪些 UART、哪些 SPI、哪些 GPIO,每个外设挂在哪个地址、映射到哪个引脚,都写在设备树文件里。
对于 STM32 而言,设备树文件通常分为三级:SoC 级别的.dtsi(描述芯片内部外设),板卡级别的.dts(描述具体板子上的引脚连接、外部设备),以及 overlays(用户自定义扩展)。你在编译 Zephyr 时,如果要用到某个外设,只需要在 overlay 文件里把对应的节点状态从disabled改成okay,并设置好引脚,驱动框架会自动帮你初始化。
这个设计对于产品做板级适配非常高效。我在一个项目中需要把按键从 PA0 换到 PB1,改一行设备树重新编译就行,完全不用动驱动代码。
6.2 从 blinky 走向实际项目:多线程、外设和网络
跑通 blinky,只能算环境没问题。真正用 Zephyr 做项目,还需要掌握几个核心概念:
- 线程(Thread)和调度:Zephyr 的调度器支持优先级抢占、时间片轮转。
- 内核对象:信号量、互斥量、消息队列、事件标志,它们解决了线程间同步和通信。
- 设备驱动模型:通过
device_get_binding()获取设备实例,再用统一的 API 操作外设。 - 实时性保障:中断处理、线程优先级、内核 tick 的配置会影响系统的实时表现,这部分需要慢慢调。
我自己的体会是,把 blinky 换成“UART 接收命令行 + 按键控制 LED + 定时上报传感器数据”这样一个小项目,你就基本掌握了 Zephyr 的核心用法。再往后,如果想接入 WiFi 模块或者以太网,Zephyr 有专门的网络子系统,配合 DHCP、TCP/UDP、MQTT,可以非常快地搭出一个物联网设备的雏形。
6.3 少走弯路的两个学习建议
最后分享两条切身体会的学习建议。
第一,遇到问题优先看 Zephyr 官方文档。虽然它有些页面写得不够“亲民”,但对于环境搭建、设备树、驱动模型这些核心主题,官方文档还是最准确、最及时的。网上博客和社区讨论可以作为补充,但别盲目跟着抄,尤其要注意文档版本和你的代码版本是否匹配。
第二,多花点时间读示例代码。Zephyr 的samples/目录里都是宝藏,每个示例都对应一个具体的功能点,比如 GPIO、UART、I2C、蓝牙、网络。你可以在这些示例的基础上改改看,把几个示例拼到一起,比单纯看 API 手册高效得多。
我实际用下来,Zephyr 学习曲线比裸机陡不少,但只要把环境跑通、把第一个 LED 点起来,接下来就顺畅许多了。对我个人来说,Zephyr 最大的价值是让我在写 STM32 项目时,能把更多精力放在业务逻辑上,而不是反复折腾底层驱动细节。希望这篇文章能帮你少踩一些我踩过的坑,顺利把你手上的 STM32 开发板也带进 Zephyr 的世界。