zephyr设备树节点获取

Node identifiers 节点标识符

以下是获得节点标识符的主要方法:

  • By path 路径
    从根节点开始,在设备树中使用 DT_PATH() 和节点的完整路径。如果您恰好知道正在寻找的确切节点,这将非常有用。

  • By node label 按节点标签
    使用 DT_NODELABEL() 从节点标签获取节点标识符。节点标签通常由SoC .dtsi提供,以提供与SoC数据表匹配的节点名称,如i2c1, spi2等。

  • By alias 化名
    使用 DT_ALIAS() 获取特定的 /aliases 节点的属性的节点标识符。有些应用程序(比如 blinky,它使用 led0 别名)需要引用某种特定类型的设备(“主板的用户 LED”) ,但是不在乎使用哪种设备。

  • By instance number 按实例编号
    这主要由设备驱动程序完成,因为实例号是基于匹配兼容性引用单个节点的一种方式。使用 DT_INST() 获得这些,但是这样做要小心。见下文。

  • By chosen node 按选择的节点
    使用 DT_CHOSEN() 获取 /chosen 的节点属性的节点标识符。

  • By parent/child 按父母/子女划分
    使用 DT_PARENT()DT_CHILD() 获取父节点或子节点的节点标识符,从已有的节点标识符开始。

/dts-v1/;

/ {

	aliases {
		sensor-controller = &i2c1;
	};

	soc {
		i2c1: i2c@40002000 {
			compatible = "vnd,soc-i2c";
			label = "I2C_1";
			reg = <0x40002000 0x1000>;
			status = "okay";
			clock-frequency = < 100000 >;
		};
	};
};

以下是获取 i2c@40002000 节点的节点标识符的几种方法:

  • DT_PATH(soc, i2c_40002000)
  • DT_NODELABEL(i2c1)
  • DT_ALIAS(sensor_controller)
  • DT_INST(x,vnd_soc_i2c) 表示某个未知数 x. 详细信息请参阅 DT_INST()文档。

非字母数字字符,如 dash (-)和 devicetree 名称中的 at 符号 (@)转换为下划线(_)。DTS 中的名称也将转换为小写。

Property access

用于读取属性值的正确 API 取决于节点和属性。

  • Checking properties and values
    检查属性和值
  • Simple properties
    简单的属性
  • reg properties
    寄存器属性
  • interrupts properties
    中断属性
  • phandle properties
    Phandle 属性

使用 DT_PROP(node_id,property)读取基本的整数、布尔值、字符串、数值数组和字符串数组属性。
例如,要读取上面示例中的时钟频率属性值:

DT_PROP(DT_PATH(soc, i2c_40002000), clock_frequency)  /* This is 100000, */
DT_PROP(DT_NODELABEL(i2c1), clock_frequency)          /* and so is this, */
DT_PROP(DT_ALIAS(sensor_controller), clock_frequency) /* and this. */

类型 array、 uint8-array 和 string-array 的属性的工作方式类似,只不过在这些情况下 DT_PROP()扩展为数组初始值设定项。下面是一个设备树片段的例子:(2)

foo: foo@1234 {
        a = <1000 2000 3000>; /* array */
        b = [aa bb cc dd];    /* uint8-array */
        c = "bar", "baz";     /* string-array */
};

它的属性可以这样访问:

#define FOO DT_NODELABEL(foo)

int a[] = DT_PROP(FOO, a);           /* {1000, 2000, 3000} */
unsigned char b[] = DT_PROP(FOO, b); /* {0xaa, 0xbb, 0xcc, 0xdd} */
char* c[] = DT_PROP(FOO, c);         /* {"foo", "bar"} */

您可以使用 DT_PROP_LEN()以元素个数获取逻辑数组长度。

size_t a_len = DT_PROP_LEN(FOO, a); /* 3 */
size_t b_len = DT_PROP_LEN(FOO, b); /* 4 */
size_t c_len = DT_PROP_LEN(FOO, c); /* 2 */

DT_PROP_LEN()不能与特殊的 reg 或中断属性一起使用。

reg properties 寄存器属性

有关 reg 的介绍,请参见重要属性

给定一个节点标识符 node_idDT_NUM_REGS(node_id) 是该节点的 reg 属性中寄存器块的总数。

使用 DT_PROP(node,reg) 无法读取寄存器块地址和长度。相反,如果一个节点只有一个寄存器块,使用 DT_REG_ADDR()DT_REG_SIZE() :

  • DT_REG_ADDR (node_id) : 给定节点的寄存器块地址
  • DT_REG_SIZE (node_id) : 其大小

如果节点有多个寄存器块,则使用 DT_REG_ADDR_BY_IDX()DT_REG_SIZE_BY_IDX() :

  • DT_REG_ADDR_BY_IDX (node_id,idx) : 索引 idx 处寄存器块的地址
  • DT_reg_size_by_idx (node_id,idx) : 索引 idx 处块的大小

从设备树节点获取 struct device

在编写 Zephyr 应用程序时,您通常希望获得与设备树节点对应的驱动程序级struct device。

例如,对于这个 devicetree 片段,您可能需要用于 Series@40002000的 struct device:

/ {
        soc {
                serial0: serial@40002000 {
                        status = "okay";
                        current-speed = <115200>;
                        /* ... */
                };
        };

        aliases {
                my-serial = &serial0;
        };

        chosen {
                zephyr,console = &serial0;
        };
};

有不同的方法可以做到这一点; 选择最适合您的需求的方法。下面是一些例子:

/* Option 1: by node label */
#define MY_SERIAL DT_NODELABEL(serial0)

/* Option 2: by alias */
#define MY_SERIAL DT_ALIAS(my_serial)

/* Option 3: by chosen node */
#define MY_SERIAL DT_CHOSEN(zephyr_console)

/* Option 4: by path */
#define MY_SERIAL DT_PATH(soc, serial_40002000)

有了节点标识符之后,有两种方法可以继续。获得设备的一种方法是使用 DEVICE_DT_GET() :

const struct device *uart_dev = DEVICE_DT_GET(MY_SERIAL);

if (!device_is_ready(uart_dev)) {
        /* Not ready, do not use */
        return -ENODEV;
}

DEVICE_DT_GET()有多种变体,例如 DEVICE_DT_GET_OR_NULL()DEVICE_DT_GET_ONE()DEVICE_DT_GET_ANY()。这个习惯用法在构建时获取设备指针,这意味着没有运行时损失。如果要将设备指针存储为配置数据,则此方法非常有用。但是,由于设备可能没有被初始化,或者可能未能初始化,因此在将设备传递给任何 API 函数之前,必须验证设备是否已准备好可以使用。

在某些情况下,在构建时无法知道设备,例如,如果它依赖于用户输入,比如在 shell 应用程序中。在这种情况下,您可以通过将 DT_LABEL()device_get_binding()组合起来获得 struct 设备:

const struct device *uart_dev = device_get_binding(DT_LABEL(MY_SERIAL));
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盗版摩羯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值