应用构建、Kconfig 与 Devicetree
本页依据 文档基线与后续更新 中记录的 Zephyr main 快照更新。
Zephyr 的应用配置由源码、CMake、Kconfig、Devicetree 和板级定义共同组成。 先把命令行构建跑通,再配置 IDE,能更容易定位构建或编辑器各自的问题。
独立应用与工作区布局
实际项目通常将应用放在 Zephyr 主仓库之外(Out-of-Tree Application),避免直接修改
zephyr/samples/,以便主仓库与模块升级时保持应用目录独立:
zephyrproject/ <-- West 工作区顶层(含 .west/)
├── zephyr/ <-- Zephyr 官方主仓库(只读)
├── modules/ <-- 第三方 HAL 与组件模块
└── app/ <-- 独立应用工程目录
├── CMakeLists.txt <-- 构建入口
├── Kconfig <-- (可选)应用自定义配置菜单
├── prj.conf <-- 应用 Kconfig 配置文件
├── app.overlay <-- (可选)设备树叠加层
├── include/ <-- (可选)应用私有头文件
└── src/
└── main.c <-- 应用主程序入口
最小应用
在工作区顶层创建 app,最小结构仅需 CMakeLists.txt、prj.conf 和 src/main.c:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.20.5)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(cn_demo)
target_sources(app PRIVATE src/main.c)
prj.conf:
CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=3
src/main.c:
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(cn_demo, LOG_LEVEL_INF);
int main(void)
{
LOG_INF("Zephyr CN application started on %s", CONFIG_BOARD);
return 0;
}
在工作区顶层构建并运行(可使用 qemu_cortex_m3 或 64 位 qemu_cortex_a53):
west build -p always -b qemu_cortex_a53 -d build app
west build -d build -t run
find_package(Zephyr ...) 必须位于 project() 之前,由 Zephyr 接管交叉编译工具链初始化;
app 是 Zephyr 提供的应用构建目标。当工程包含多个源文件与头文件目录时,可在
CMakeLists.txt 中使用 target_include_directories(app PRIVATE include) 和
target_sources(app PRIVATE src/main.c src/other.c)。
Kconfig 选择软件能力
prj.conf 配置软件功能、资源数量和参数。构建期间 Kconfig 的合并与生成链路如下:
[配置定义树: zephyr/Kconfig + app/Kconfig]
│
▼
[按优先级合并输入源]
① Kconfig 默认值 (default)
② 板级默认配置 (<board>_defconfig)
③ 应用配置 (prj.conf / EXTRA_CONF_FILE)
│
▼
[构建目录输出: build/zephyr/]
• .config (最终生效的完整配置快照)
• include/generated/zephyr/autoconf.h (自动转换为 #define CONFIG_xxx 宏)
Kconfig 符号存在依赖与选择关系,强行写 CONFIG_...=y 不能越过缺失的依赖。可通过交互界面检查依赖:
west build -d build -t menuconfig
最终生效值保存在 build/zephyr/.config 中,生成的 autoconf.h 会自动注入所有编译单元。
不要直接手工编辑 .config 或生成的头文件;menuconfig 中的临时修改需整理回
prj.conf,才能在重新配置或 -p always 干净构建后复现。
需要定义应用自己的配置项时,在应用目录添加 Kconfig,并包含 Kconfig.zephyr:
mainmenu "Custom Application Configuration"
source "Kconfig.zephyr"
config APP_SAMPLE_INTERVAL_MS
int "Sensor sampling interval in milliseconds"
default 1000
range 100 60000
在 Kconfig 中定义符号时不写 CONFIG_ 前缀;在 prj.conf、CMakeLists.txt 和 C
源码中引用时统一加上 CONFIG_ 前缀(如 CONFIG_APP_SAMPLE_INTERVAL_MS)。
Devicetree 描述硬件实例
设备树描述寄存器地址、引脚、中断、总线、时钟、设备状态和板级连接;dts/bindings/*.yaml
定义节点的属性规则。应用可通过 app.overlay``(或 ``-DDTC_OVERLAY_FILE=...)在不改动官方板级源码的前提下修改或扩展目标硬件描述:
[SoC .dtsi] + [板级 <board>.dts] + [应用 app.overlay] + [dts/bindings/*.yaml]
│
▼
[构建目录输出: build/zephyr/]
• zephyr.dts (最终合并展开的完整设备树)
• include/generated/zephyr/devicetree_generated.h (供 DT_* 与 DEVICE_DT_GET 宏使用)
编译生成的 devicetree_generated.h 供设备树宏使用,不能通过直接修改它替代 overlay。
DT_NODELABEL() 使用 DTS 节点标签,DT_ALIAS() 使用 /aliases 中的别名(DTS 中的连字符
- 在 C 宏中需替换为下划线 _),DT_CHOSEN() 用于获取 /chosen 约定的系统角色设备。
应用取得设备的常用模式:
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
const struct device *dev = DEVICE_DT_GET(DT_NODELABEL(my_device));
my_device 是示意标签,必须替换为目标设备树中实际存在且可用的节点。
调用驱动接口前必须检查 device_is_ready(dev)。
Kconfig 与 Devicetree 的配合与排错:
只有同时满足 ① 设备树中存在该节点且
status = "okay"、② Kconfig 中启用了对应驱动程序、③ 运行时驱动初始化成功,才构成可访问的设备。链接时若出现
undefined reference to `__device_dts_ord_XX'错误,打开build/zephyr/zephyr.dts搜索该数字序号XX定位对应节点,通常是节点已在设备树中启用但prj.conf未开启对应的驱动CONFIG_*选项,或节点status未设为"okay"。
开发板目标与硬件模型
Zephyr 3.7 引入的新硬件模型改变了许多板名与板级组织。
当前目标可包含板名、SoC、CPU cluster 和 variant,例如
nrf52840dk/nrf52840、nrf5340dk/nrf5340/cpuapp 或双核 SMP 模拟目标
qemu_cortex_a53/qemu_cortex_a53/smp。
旧 nrf52840dk_nrf52840 名称不能直接假定仍适用。
west boards 帮助查找板卡,完整目标与 qualifiers 应看对应板卡页面。
开发自定义板卡时按当前 Board Porting Guide 配置 board.yml、SoC 关系、DTS、
Kconfig 与 runner,避免复制旧硬件模型的目录后只改名称。
多镜像与 sysbuild
需要协调引导程序或多个镜像时,可采用 sysbuild:
west build --sysbuild -p always -b <board-target> -d build-sysbuild app
替换目标后再执行。sysbuild 自身配置使用 SB_CONFIG_*,与每个镜像的 CONFIG_*
属于不同配置域。根据镜像名和域定位最终 .config、DTS 与 ELF,
不要把单镜像的输出路径套用到所有 sysbuild 产物。
可重复构建
记录源码与模块提交、应用配置、overlay、板卡完整目标、SDK 和构建命令。
切换 Zephyr 版本、板卡或工具链后进行干净构建。
确认命令行构建输出后,再用 compile_commands.json 配置编辑器,见 使用 VS Code 开发 Zephyr。
若希望通过一个完整工程演练 Kconfig、Devicetree Overlay、日志、Shell、GPIO、多线程与 NVS 的综合协同,请继续阅读 综合应用实战(基于 qemu_cortex_a53)。