Zephyr 的设备驱动模型强调三件事:
DEVICE_DT_INST_DEFINE() 等宏注册设备config:只读配置,通常来自设备树data:运行时状态api:提供给上层的函数表init:启动阶段初始化DEVICE_DT_DEFINE()DEVICE_DT_INST_DEFINE()DT_INST_FOREACH_STATUS_OKAY()驱动开发时,设备树通常提供:
如果你写自定义驱动,第一步往往不是写寄存器读写,而是先把 binding、overlay 和 DT_* 宏链路跑通。
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/kernel.h>
如果是 I2C / SPI / 传感器类,还会加:
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/spi.h>
#include <zephyr/drivers/sensor.h>
struct my_dev_config {
struct i2c_dt_spec bus;
};
struct my_dev_data {
uint16_t cached_value;
};
static int my_dev_init(const struct device *dev)
{
const struct my_dev_config *cfg = dev->config;
if (!device_is_ready(cfg->bus.bus)) {
return -ENODEV;
}
return 0;
}
典型例子:
重点在:
i2c_dt_specspi_dt_spec典型例子:
sensorgpiopwmcounter重点在:
这类更靠近底层,通常会涉及:
zephyr/samples/drivers例如:
zephyr/drivers/sensorzephyr/drivers/gpiozephyr/drivers/spizephyr/drivers/i2c如果一开始就跳到自定义 binding,往往会把问题混在一起,不容易定位。
label 当作新设备树写法的核心入口device_is_ready()zephyr/samples/driverszephyr/driverszephyr/include/zephyr/device.hzephyr/include/zephyr/devicetree.h