devicetree.h常用宏定义使用说明

本篇为devicetree.h部分常用的宏定义功能及用法。
文件路径为:ncs\zephyr\include\devicetree.h

关于gpio的PIN及Flag说明:
 * gpio1: gpio@... {
 *             compatible = "vnd,gpio";
 *             #gpio-cells = <2>;
 *     };
 *
 *     gpio2: gpio@... {
 *             compatible = "vnd,gpio";
 *             #gpio-cells = <2>;
 *     };
 *
 *     n: node {
 *             gpios = <&gpio1 10 GPIO_ACTIVE_LOW>,
 *                     <&gpio2 30 GPIO_ACTIVE_HIGH>;
 *     };

这里用到了#gpio-cells,介绍下#gpio-cells的概念
gpio可以有两个参数,分别是PIN和Flag,PIN脚说明了该gpio的引脚位置,flag则描述该引脚是高电平还是低电平有效。#gpio-cells的值决定了gpio的参数的个数,以上面的dts文件为例,这里面#gpio-cells的值为2,所以后面<&gpio1 10 GPIO_ACTIVE_LOW>会有PIN和flag两个参数,也就是<&gpio1 10 GPIO_ACTIVE_LOW>里面的pin脚是10,GPIO_ACTIVE_LOW这两个参数,如果#gpio-cells的值为1,那么这里只需要写成<&gpio1 10>即可。

0,DT_PATH(…)

根据传入路径获取node id。

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

dts文件如上图时,调用 DT_PATH(soc,serial_40001000)可以获取serial1对应的node id。

1,DT_NODELABEL(label)

根据devicetree 的 node label获取node id,注意,node label和label属性不是一种概念。

 *     serial1: serial@40001000 {
 *             label = "UART_0";
 *             status = "okay";
 *             current-speed = <115200>;
 *             ...
 *     };

如上图所示,node label 为 serial1,而不是 “UART_0”,可以通过 DT_NODELABEL(serial1)来获取serial@40001000 node的node id.

2,DT_ALIAS(alias)

根据devicetree的别名获取node id,参数是节点的别名

 *
 *     / {
 *             aliases {
 *                     my-serial = &serial1;
 *             };
 *
 *             soc {
 *                     serial1: serial@40001000 {
 *                             status = "okay";
 *                             current-speed = <115200>;
 *                             ...
 *                     };
 *             };
 *     };

如图所示:可以通过 DT_ALIAS(my_serial) 来获取到serial@40001000 node的nodeid

3,DT_INST(inst, compat)

通过一个兼容性Instance number来获取node id。参数分别是instance number和兼容性组件名字。
具有相同兼容性的属性值会被分配一个从0开始的Instance number,通过 DT_INST()可以根据Instance number来获取到对应的node id。

Instance number 具有如下属性:

  • 对于任意的兼容性组件,Instance number从0开始并持续增长
  • 每一个兼容性组件节点,只分配一个Instance number,包括disabled状态的节点
  • 状态为 “okay”或者未定义状态的节点,从0开始分配Instance number,状态为disabled的节点的Instance number比其他的要大
 *     serial1: serial@40001000 {
 *             compatible = "vnd,soc-serial";
 *             status = "disabled";
 *             current-speed = <9600>;
 *             ...
 *     };
 *
 *     serial2: serial@40002000 {
 *             compatible = "vnd,soc-serial";
 *             status = "okay";
 *             current-speed = <57600>;
 *             ...
 *     };
 *
 *     serial3: serial@40003000 {
 *             compatible = "vnd,soc-serial";
 *             current-speed = <115200>;
 *             ...
 *     };

如上图所示,假设没有其他"vnd,soc-serial"节点,那么instance numbers 被分配为0,1,2

由于serial2和serial3的状态是“okay”和缺省,所以他们两个的instance number被分配为0和1,但是这两个哪个是0哪个是1是没有规则限制的。
由于serial1的状态时disable,所以他的instance number被分配为2

所以如果使用 DT_INST(0,vnd_soc_serial),则获取到的可能是serial2或者serial3
DT_INST(1,vnd_soc_serial),则获取到的可能是serial2或者serial3

DT_INST(2,vnd_soc_serial),则获取到的一定是serial1

备注:在dts文件中,存在,或者-等符号,如上文的vnd,soc-serialcurrent-speed = <115200>,这些符号,在作为参数调用的时候,需要变成下划线,也就是_,如上面的vnd,soc-serialcurrent-speed = <115200>变成vnd_soc_serialcurrent_speed.

4,DT_PARENT(node_id)

获取某个节点的父节点的node_id,参数是子节点的node id

 *     parent: parent-node {
 *             child: child-node {
 *                     ...
 *             };
 *     };

如上图所示,通过调用DT_PARENT(DT_NODELABEL(child))可以获取到parent节点的node_id。同理,根据宏定义1的用法,通过DT_NODELABEL(parent)通样可以获取到parent节点的node id,他们两个是等价的

5,DT_CHILD(node_id, child)

获取节点的子节点的node id,参数分别是父节点的node id和子节点的节点名字

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

如上图所示,可以通过:

 *     #define SOC_NODE DT_NODELABEL(soc_label)
 *     DT_CHILD(SOC_NODE, serial_40001000)

来获取serial1的node id,这里SOC_NODE是父节点的node id,serial_40001000是子节点的节点名字
这里不能用serial1作为“child”参数,因为它是一个node label,而不是node name

可以通过DT_FOREACH_CHILD()来遍历一个节点的所有子节点。

6,DT_PROP(node_id,prop)

获取节点的属性值,参数分别为节点的node id和要获取属性值的属性名字。

 *             soc {
 *                     serial1: serial@40001000 {
 *                             status = "okay";
 *                             current-speed = <115200>;
 *                             ...
 *                     };
 *             };
 *     };

如上图的dts文件,可以通过DT_PROP(DT_NODELABEL(serial1),status)来获取到"okay"这个属性值。

7,DT_PROP_HAS_IDX(node_id, prop, idx)

检查节点的属性是否有idx的索引,参数分别是node_id,要检查的属性以及索引值。当属性具有idx的索引是,宏返回 1,当没有这个索引是,返回0.

当prop是reg property时,用DT_REG_HAS_IDX(node_id, idx)
当prop是interrupts property时,用DT_IRQ_HAS_IDX(node_id, idx)代替,用法和上面描述一致。

test_phandles: phandle-holder-0 {
	compatible = "vnd,phandle-holder";
	gpios = <&test_gpio_1 10 20>, <&test_gpio_2 30 40>;
};

当dts文件如上图所示时,通过调用如下参数

#define TEST_PH DT_NODELABEL(test_phandles)

DT_PROP_HAS_IDX(TEST_PH, gpios, 0),由于gpios具有2个值,因此返回值为1
同理,DT_PROP_HAS_IDX(TEST_PH, gpios, 1)通用返回1
DT_PROP_HAS_IDX(TEST_PH, gpios,2)由于gpios不具有第三个值,因此返回0

8,DT_PROP_BY_IDX(node_id, prop, idx)

通过节点属性的索引获取属性的描述值,参数分别是节点的node id,属性名字和索引值。
当参数prop是reg property时,用DT_REG_ADDR_BY_IDX() 或 DT_REG_SIZE_BY_IDX()代替
当参数prop是interrupts property时,用DT_IRQ_BY_IDX()代替

test_arrays: array-holder {
	/* vnd,undefined-compat is for DT_NODE_HAS_COMPAT_STATUS(..,okay) */
	compatible = "vnd,array-holder", "vnd,undefined-compat";
	a = <1000 2000 3000>;
	b = [aa bb cc dd];
	c = "bar", "baz";
};

#define TEST_ARRAYS DT_NODELABEL(test_arrays)
当dts文件如上图所示时,调用DT_PROP_BY_IDX(TEST_ARRAYS, a, 0),返回值为0x1000,调用DT_PROP_BY_IDX(TEST_ARRAYS, a, 1)时,返回值是0x2000

9, DT_PROP_OR(node_id, prop, default_value)

获取节点的属性值,如果值不存在,则使用default_value作为属性值。用法类似于DT_PROP().

test_reg: reg-holder@9999aaaa {
	compatible = "vnd,reg-holder";
	reg = < 0x9999aaaa 0x1000 0xbbbbcccc 0x3f >;
	status = "okay";
	reg-names = "first", "second";
	misc-prop = <1234>;
};

#define TEST_REG DT_NODELABEL(test_reg)
dts文件如上图所示:
调用DT_PROP_OR(TEST_REG, misc_prop, X)返回misc-prop属性值“1234”
调用DT_PROP_OR(TEST_REG, not_a_property, -1),由于test_reg没有“not_a_propety”的属性,所以给这个属性赋值为-1的默认值。

10,DT_LABEL(node_id)

获取节点的label值,用法等同于DT_PROP_LABEL(node_id,label),需要注意,node label和label不是一个概念。

test_i2c_1: i2c@77778888 {
	label = "TEST_I2C_CTLR_1";
};

dts文件如上图所示时,node label是test_i2c_1,而test_i2c_1的label是"TEST_I2C_CTLR_1"
当调用DT_LABEL(DT_NODELABEL(test_i2c_1))时,返回"TEST_I2C_CTLR_1“

11,DT_PROP_BY_PHANDLE_IDX(node_id, phs, idx, prop)

获取某个节点的具有phandle类型的的属性的idx项属性值,等同于:DT_PROP(DT_PHANDLE_BY_IDX(node_id, phs, idx), prop)
这里prop是指获取一个node id具有phandle 类型的属性的属性的值,而不是一个node id的属性值。

 *     n1: node-1 {
 *             foo = <&n2 &n3>;
 *     };
 *
 *     n2: node-2 {
 *             bar = <42>;
 *     };
 *
 *     n3: node-3 {
 *             baz = <43>;
 *     };
 *     #define N1 DT_NODELABEL(n1)
 *
 *     DT_PROP_BY_PHANDLE_IDX(N1, foo, 0, bar) // 42
 *     DT_PROP_BY_PHANDLE_IDX(N1, foo, 1, baz) // 43

如上图dts文件,使用上面的指令,分别可以获取到n2bar值42 和n3baz值 53。这里的node id为n1的node id,n1里面的foo属性具有phandle属性,phandle属性可以简单理解为指针,将n2n3引用进来。
然后这里idx参数分别是0,1,对应的就是foo值的n2n3prop属性分别是barbaz对应的分别是n2bar属性和n3baz属性。

12,DT_PROP_BY_PHANDLE(node_id, ph, prop)

等同于DT_PROP_BY_PHANDLE_IDX(node_id, ph, 0, prop),用法参考第11条宏定义。

13,DT_PHA_BY_IDX(node_id, pha, idx, cell)

通过node id的具有phandle array属性的描述符的idx值获取对应的cell值。

 *     gpio0: gpio@... {
 *             #gpio-cells = <2>;
 *     };
 *
 *     gpio1: gpio@... {
 *             #gpio-cells = <2>;
 *     };
 *
 *     led: led_0 {
 *             gpios = <&gpio0 17 0x1>, <&gpio1 5 0x3>;
 *     };

当dts文件如上图所示时,通过下面指令:分别可以获取到ledgpios第0项也就是gpio0的pin项,也就是0x1,和gpio1flag项,也就是0x3.

 *     #define LED DT_NODELABEL(led)
 *
 *     DT_PHA_BY_IDX(LED, gpios, 0, pin)   // 17
 *     DT_PHA_BY_IDX(LED, gpios, 1, flags) // 0x3
14,DT_PHA_BY_IDX_OR(node_id, pha, idx, cell, default_value)

用法类似于第13条,区别是在如果要查询的项不存在的话,使用default_value代替。

15,DT_PHA(node_id, pha, cell)

等同于DT_PHA_BY_IDX(node_id, pha, 0, cell),用法介绍见第13条。

16,DT_PHA_OR(node_id, pha, cell, default_value)

等同于DT_PHA_BY_IDX_OR(node_id, pha, 0, cell, default_value),用法参考第14条。

17,DT_BUS(node_id)

根据node id获取它的总线控制器

 *     i2c@deadbeef {
 *             label = "I2C_CTLR";
 *             status = "okay";
 *             clock-frequency = < 100000 >;
 *
 *             i2c_device: accelerometer@12 {
 *                     ...
 *             };
 *     };

dts文件如上图所示:
#define TEST_LABEL DT_NODELABEL(i2c_device)获取到“i2c_device”的node id,然后
DT_BUS(TEST_LABEL )获取i2c_device的总线控制器 i2c@deadbeef.然后就可以通过
DT_PROP(DT_BUS(TEST_LABEL ),clock_frequency)来获取i2c@deadbeef的clock_frequency属性的值

18,DT_DRV_COMPAT

这个宏定义用于指定一个compatile的名字,可以用于DT_DRV_INST(inst),这里等同于DT_INST(inst, DT_DRV_COMPAT),compatible项默认以DT_DRV_COMPAT代替。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值