Zephyr 核心功能:Kconfig、设备树与子系统能力
核心功能:Kconfig、设备树与子系统能力
Zephyr 的能力边界由 Kconfig 决定,硬件形态由设备树决定,两者在编译期就固定下来,运行期几乎没有动态查找开销。这也是它体积可控的根本原因:没打开的代码根本不进固件。
配置入口有好几层,优先级从低到高大致是:SoC 默认配置、板级 _defconfig、应用 prj.conf、命令行 -DCONFIG_*。调试时不要靠猜,直接用交互式配置界面看当前值:
# 基于当前工程打开配置界面,改完保存会写回 prj.conf 或 overlay 配置
west build -t menuconfig
west build -t guiconfig
# 体积与内存报告的必备手段
west build -t rom_report
west build -t ram_report
west build -t puncover
一份典型的 prj.conf 长这样,注释掉的项就是裁剪时最先考虑关掉的目标:
# 基础内核与主线程
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=1024
CONFIG_HEAP_MEM_POOL_SIZE=8192
# 日志子系统:延迟模式对实时性更友好,但占更多 RAM
CONFIG_LOG=y
CONFIG_LOG_MODE_DEFERRED=y
CONFIG_LOG_DEFAULT_LEVEL=3
CONFIG_PRINTK=y
# 交互 shell,调试期开,量产可关
CONFIG_SHELL=y
CONFIG_SHELL_BACKEND_SERIAL=y
# 蓝牙:按需开启,每开一个角色都会显著增加体积
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="sensor-node"
# 设备驱动
CONFIG_GPIO=y
CONFIG_I2C=y
CONFIG_SENSOR=y
设备树 overlay 的写法是 Zephyr 上手最难的一步,但规则其实简单:板级 .dts 已经描述了板子上的全部硬件,应用只需要用 &label 语法引用节点并改属性。约定放在 boards/<board>.overlay 或通过 -DEXTRA_DTC_OVERLAY_FILE 指定。
/* boards/nrf52840dk_nrf52840.overlay */
&uart0 {
status = "okay";
current-speed = <115200>;
};
&i2c0 {
status = "okay";
clock-frequency = <I2C_BITRATE_FAST>;
bme280@76 {
compatible = "bosch,bme280";
reg = <0x76>;
status = "okay";
};
};
/ {
aliases {
sensor0 = &bme280;
};
};
写完 overlay 后一定要验证它真的生效了——很多人卡在这里。构建产物里有一份展开后的完整设备树,直接看它:
west build -b nrf52840dk/nrf52840 .
# 查看合并后的设备树
less build/zephyr/zephyr.dts
# 查看编译期生成的设备树宏
less build/zephyr/include/generated/zephyr/devicetree_generated.h
子系统能力的取舍可以直接对照下表,裁剪时按「用不到就关」处理:
| Kconfig 开关 | 作用 | 端侧建议 |
|---|---|---|
CONFIG_SIZE_OPTIMIZATIONS | 以体积优先的编译优化 | Flash 紧张时开启 |
CONFIG_LOG | 日志子系统 | 调试开,量产可整体关闭 |
CONFIG_LOG_MODE_DEFERRED | 日志改为延迟处理 | 中断上下文日志多时开 |
CONFIG_ASSERT | 运行期断言 | 调试开,量产关可省代码 |
CONFIG_THREAD_NAME | 线程名字符串 | 关掉可省 RAM |
CONFIG_SHELL | 串口交互 shell | 调试开,量产关 |
CONFIG_BT | 蓝牙协议栈 | 按需,注意 RAM 占用 |
CONFIG_NETWORKING | 网络协议栈 | 按需,可只选 IPv4 或仅 L2 |
CONFIG_MINIMAL_LIBC | 精简 C 库 | 体积敏感时替代 newlib |
CONFIG_PM / CONFIG_PM_DEVICE | 电源管理与设备低功耗 | 电池设备必开 |
设备驱动模型统一在 DEVICE_DT_* 接口下,GPIO、I2C、SPI、ADC、传感器、显示、闪存等都有稳定的 API,并且大量驱动直接来自厂商 HAL 的 Zephyr 移植,不必自己写寄存器序列。CONFIG_ASSERT、CONFIG_THREAD_ANALYZER、CONFIG_STACK_SENTINEL 这类调试选项,配合 west build -t ram_report 能比较快定位栈溢出与内存吃紧的问题。

