zephyr设备树的硬件描述转换为c语言
正是 Zephyr 的自动化关键机制:把 设备树(.dts) 里的硬件描述,自动转换成 C 代码里能直接用的宏和结构体。
设备树 → 代码 的全过程拆开:
1. 写设备树(.dts / .dtsi)
你在 boards/.../xxx.dts
或 SoC 的 .dtsi
文件里写:
anx7451: anx7451@39 {compatible = "analogix,anx7451";reg = <0x39>;reset-gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;init-delay-ms = <50>;
};
这只是硬件的声明,告诉内核:有个设备在 I²C 地址 0x39
,带一个 reset 引脚,还有个上电延时参数。
2. 设备树编译器 (DTC) 解析
Zephyr 在构建时会调用 DTC(Device Tree Compiler),把 .dts/.dtsi
转换成一个中间形式(*.dts → .dtb → header files)。
这里会生成一个 .dts
的二进制版本(.dtb
),并且 Zephyr 的 Python 脚本会再把它转换成 C 宏头文件。
3. Zephyr 生成设备树头文件
在 build/zephyr/include/generated/
目录里,你会看到类似:
devicetree_unfixed.h
device_extern.h
里面会有一堆自动生成的宏,比如:
/* 节点路径对应的 node id 宏 */
#define DT_N_S_soc_S_i2c_40003000_S_anx7451_39 1/* reg 属性 */
#define DT_PROP(DT_NODELABEL(anx7451), reg) 0x39/* reset-gpios 属性 → 自动包装成 gpio_dt_spec 结构体 */
#define DT_PROP(DT_NODELABEL(anx7451), reset_gpios) { .port = ..., .pin = 5, .flags = GPIO_ACTIVE_LOW }/* init-delay-ms 属性 */
#define DT_PROP(DT_NODELABEL(anx7451), init_delay_ms) 50
这些宏就是你在 C 代码里能用的“桥梁”。
4. 驱动里使用
驱动在 DEVICE_DT_DEFINE()
里就能直接用这些宏初始化 config:
static const struct anx7451_config anx7451_cfg = {.bus = I2C_DT_SPEC_GET(DT_NODELABEL(anx7451)),.reset_gpio = GPIO_DT_SPEC_GET(DT_NODELABEL(anx7451), reset_gpios),.init_delay_ms = DT_PROP(DT_NODELABEL(anx7451), init_delay_ms),
};
这样,.dts 里的属性值就自动变成了 C 代码里的常量。
5. 运行时
当 Zephyr 启动时,驱动就能用这些配置:
static int anx7451_init(const struct device *dev)
{const struct anx7451_config *cfg = dev->config;i2c_write_dt(&cfg->bus, ...);gpio_pin_set_dt(&cfg->reset_gpio, 1);k_msleep(cfg->init_delay_ms);return 0;
}
总结流程
.dts (硬件描述)│▼
DTC + Zephyr 脚本│▼
生成 C 宏头文件 (devicetree_unfixed.h)│▼
DEVICE_DT_DEFINE() 用宏填充 config 结构体│▼
运行时驱动通过 dev->config 访问这些值