设备树学习总结:

设备树学习总结:

 

1、https://blog.csdn.net/qq_41782149/article/details/101149210

2、https://blog.csdn.net/Klaus_Wei/article/details/42915545

3、https://blog.csdn.net/stoic163/article/details/56489195

4、https://www.cnblogs.com/liuwanpeng/p/7421661.html

5、设备树:中断

https://www.cnblogs.com/god-of-death/p/10270667.html

6、设备树:中断

https://blog.csdn.net/qq_17270067/article/details/105056348

 

一、标签 :节点(名称@设备地址)

标签(label)

可以为节点创建标签,别的地方引用时可以用标签。标签为可选项。

节点(node)
每个节点必须有一个 “<名称>[@<设备地址>]” /"<name>[@<unit-address>]"形式的名字, [ ]为可选项,unit-address一般是内存地址。

      名称(name):一个字节大小

      就是一个不超过31位的简单 ascii 字符串,节点的命名应该根据它所体现的是什么样的设备。比如一个 3 com 以太网适配器的节点应该命名为 ethernet,而不应该是 3com509。

      设备地址(unit-address)

      挂到内存空间的设备,unit-address一般是内存地址。

      用来访问该设备的主地址,并且该地址也在节点的reg属性中列出,同级节点命名必须是唯一的,但只要地址不同,多个节点也可以使用一样的通用名称,当然设备地址也是可选的,可以有也可以没有

二、自定义属性的设置与获取?

参考:https://blog.csdn.net/stoic163/article/details/56489195

三、常见属性——compatible(兼容性)属性:<制造商>,<型号>

指定了系统的名称,是一个字符串的列表,实际在代码中可以用于进行匹配,当前你选择的是哪个机器,它包含了一个"<制造商>,<型号>"形式的字符串。重要的是要指定一个确切的设备 ,并且包括制造商的名字,以避免命名空间冲突。不要使用带通配符的compatible值,比如"fsl,mpc83xx-uart" 或类似情况

如果一个节点是设备节点,那么它一定要有compatible(兼容性),因为这将作为驱动和设备(设备节点)的匹配依据。

compatible(兼容性)的值可以有不止一个字符串以满足不同的需求,详见下一节。

而根节点的compatible也是非常重要的,因为系统启动后,将根据根节点的compatible来判断cpu信息,并由此进行初始化

属性设置的套路:

  • 一般来说,每一种设备的节点属性设置都会有一些套路,比如可以设置哪些属性?属性值怎么设置?那怎么知道这些套路呢,有两种思路 :
    • 第一种是抄类似的dts,比如我们自己项目的平台是4412,那么就可以抄exynos4412-tiny4412.dts、exynos4412-smdk4412.dts这类相近的dts
    • 第二种是查询内核中的文档,比如Documentation/devicetree/bindings/i2c/i2c-imx.txt就描述了imx平台的i2c属性设置方法;Documentation/devicetree/bindings/fb就描述了lcd、lvds这类属性设置方法

四、 常见属性——地址编码 属性:#address-cells和#size-cells 

父节点的address-cells和size-cells决定子节点的reg的address和lenth字段的长度,cell的单位为32bit
#address-cells=<1>  // 子节点reg的address为几个32bit的整型数据
#size-cells=<1>     // 长度为几个32bit整型数据,如果为0,则没有lenth字段

举例:

node{
      reg = <address1 lenth1 [address2 lenth2] [address3 lenth3]...>;
}

    ps7_axi_interconnect_0: amba@0 {
        #address-cells = <1>;  // 下一级节点reg的address字段长度为1个32bit,下一级节点为ps7-i2c@e0005000
        #size-cells = <1>
;         // 下一级节点reg的len字段长度为1个32bit

        ...
        ps7_i2c_1: ps7-i2c@e0005000 {
            clock-frequency = <400000>;
            clocks = <&clkc 39>;
            compatible = "cdns,i2c-r1p10";
            interrupt-parent = <&ps7_scugic_0>;
            interrupts = <0 48 4>;
            reg = <0xe0005000 0x1000>;  // 地址为0xe0005000,长度为0x1000
            xlnx,has-interrupt = <0x0>;
            #address-cells = <1>;  // 下一级eeprom的reg属性
            #size-cells = <0>;     // 没有len字段
            eeprom@52 {
                compatible = "at,24c512";
                reg = <0x52>;    // 地址为0x52,没有长度字段
            };
        } ;
        ...
    }

五、常见属性——reg属性,实例见以上

reg的组织形式为 reg = <address1 lenth1 [address2 lenth2] [address3 lenth3]...>;

其中的每一组address1 lenth1表明了设备使用的一个地址范围

六、常见属性——GPIO、时钟、pinmux连接

 1. GPIO属性的设置与获取

  • dts的GPIO描述

  gpio-controller表示“我是GPIO控制器”;

  #gpio-cells,设置GPIO属性的大小

举例1:

ps7_gpio_0: ps7-gpio@e000a000 {
            #gpio-cells = <2>;    // 2个cell,一般第一个表示用哪个GPIO,第二个数0表示高电平有效、1表示低电平有效
            clocks = <&clkc 42>;
            compatible = "xlnx,zynq-gpio-1.0";
            emio-gpio-width = <64>;
            gpio-controller ;
            gpio-mask-high = <0x0>;
            gpio-mask-low = <0x5600>;
            interrupt-parent = <&ps7_scugic_0>;
            interrupts = <0 20 4>;
            reg = <0xe000a000 0x1000>;
        } ;

        ps7_ethernet_0: ps7-ethernet@e000b000 {          ...         enet-reset = <&ps7_gpio_0 11 0>;
        ...
        } ;

举例2:

/*imx6dl.dtsi中gpio1控制器的定义节点*/
gpio1: gpio@0209c000 {
    compatible = "fsl,imx6q-gpio", "fsl,imx35-gpio";
    reg = <0x0209c000 0x4000>;
    interrupts = <0 66 IRQ_TYPE_LEVEL_HIGH>,
             <0 67 IRQ_TYPE_LEVEL_HIGH>;
    gpio-controller;
    #gpio-cells = <2>;
    interrupt-controller;
    #interrupt-cells = <2>;
};
 
/*imx6qdl-sabreauto.dtsi中某个设备节点*/
max7310_reset: max7310-reset {
    compatible = "gpio-reset";
    reset-gpios = <&gpio1 15 1>;
    reset-delay-us = <1>;
    #reset-cells = <0>;
};

1、一般来说,我们把gpio属性的名字起为 xxx-gpios(xxx我们可以随便起),这样驱动才能通过特定API从识别该属性,并转换成具体的gpio号

2、该设备节点中设置了reset-gpios = <&gpio1 15 1>;这格式是什么意思呢?&gpio1 15引用了gpio1节点,故此处含义为gpio1_15这个引脚;最后一个参数1则代表低电平有效,0则为高电平有效。至于gpio1_15具体对应哪个引脚,在imx6的手册上都有详细描述

3、其实最后一个参数(高低电平有效)不是必须的,因为gpio1节点中设置了#gpio-cells = <2>;,所以才有两个参数;某些soc的gpio节点中会设置为#gpio-cells = <1>;,那么可以不写最后一个参数

参考:

https://www.cnblogs.com/liuwanpeng/p/7421661.html

https://blog.csdn.net/stoic163/article/details/56489195

七、常见属性——中断属性:interrupts 和 interrupts
描述中断连接需要四个属性:

中断控制器节点属性:这类节点可能是中断父节点

        interrupt-controller -一个空的属性定义该节点作为一个接收中断信号的设备

        #interrupt-cells -这是一个中断控制器节点的属性。它声明了该中断控制器的中断指示符中cell的个数(类似于#address-cells 和#size-cells )


中断产生设备节点属性:
        interrupt-parent -这是一个设备节点的属性,包含一个指向该设备连接的中断控制器的phandle(指向或者可以引用&)那些没有interrupt-parent 的节点则从它们的父节点中继承该属性。

        interrupts - 一个设备节点属性,包含-一个中断指示符的列表,对应于该设备上的每个中断输出信号

1、某个设备要使用中断, 需要在设备树中如何描述中断?

想使用中断,节点中至少有有2个属性:

interrupt-parent // 中断产生设备节点属性:这个中断要接到哪一个设备去? 即父中断控制器是谁

interrupts // 中断产生设备节点属性:表示要使用哪一个中断, 中断的触发类型等等。

父中断控制器有两种指定方法:

1)只有一个中断父设备

 interrupt-parent = <&父设备标号>;

 interrupts = <... ...>, <... ...>;

ethernet@20000000 {
    compatible = "davicom,dm9000";
    reg = <0x20000000 0x2 0x20000004 0x2>;
    interrupt-parent = <&gpf>; //父中断控制器为gpf
    interrupts = <7 IRQ_TYPE_EDGE_RISING>; 
    local-mac-address = [00 00 de ad be ef];
    davicom,no-eeprom;
};

2)有多个中断父设备

 interrupts-extended = <&父设备标号 .....>, <... ... ...>;

buttons {
    compatible = "jz2440_button"; 
    eint-pins  = <&gpf 0 0>, <&gpf 2 0>, <&gpg 3 0>, <&gpg 11 0>; 
    interrupts-extended = <&intc 0 0 0 3>,  
                          <&intc 0 0 2 3>,
                          <&gpg 3 3>,
                          <&gpg 11 3>;
};

假设某设备节点需要一个gpio中断

/*先确定中断所在的组*/
interrupt-parent = <&gpio6>;
 
/*表示中断,GPIO6中的第8个IO,2为中断触发条件,下降沿触发*/
interrupts = <8 2>;

interrupts = <GIC_PPI 13 (IRQ_TYPE_EDGE_RISING | GIC_CPU_MASK_SIMPLE(2))>; 

可以参考GIC的规范,第一个u32表示中断类型,第二个是中断号,第三个是中断触发条件

而在驱动中使用 中断号 =irq_of_parse_and_map(node, index)函数返回值来得到中断号

举例:

/ {
    compatible = "acme,coyotes-revenge";
    #address-cells = <1>;
    #size-cells = <1>;
    interrupt-parent = <&intc>;
    
    serial@101f0000 {
        compatible = "arm,pl011";
        reg = <0x10170000,0x1000>;
        interrupts = <1 0>;
    };

    intc:interrupt-controller@10140000{
        compatible = "arm,pl190";
        reg = <0x10140000,0x1000>;
        interrupt-controller;
        #interrupt-cells = <2>;
    };
}

2、在设备树中,如何描述在父中断控制器? (上述的interrupts属性用多少个u32来表示?由它的父中断控制器来描述)

在父中断控制器中, 至少有2个属性:

interrupt-controller; // 表示自己是一个中断控制器

#interrupt-cells // 表示自己的子设备里应该用几个U32的数据来描述中断

例如:

gpf {
    gpio-controller;
    #gpio-cells = <0x2>;
    interrupt-controller;
    #interrupt-cells = <0x2>; //使用两个u32数据来描述中断
    phandle = <0x6>;
};

3、如何找到一个子中断节点的父中断控制器

一般在描述子中断节点中都会有一个属性interrupt-parent,由此属性描述。

如果子中断节点中没有此属性,需要查看此节点的父节点,一级一级往上直到父节点中出现interrupt-parent

4、interrupts属性的具体含义

参考:https://blog.csdn.net/qq_17270067/article/details/105056348

5、驱动中使用这些中断

参考:https://blog.csdn.net/qq_17270067/article/details/105056348

6、GPIO中断使用方法

参考:https://blog.csdn.net/qq_17270067/article/details/105056348

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

a1809032425

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

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

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

打赏作者

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

抵扣说明:

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

余额充值