查看: 621|回复: 0
打印 上一主题 下一主题

【Seeed开发板试用体验】技巧篇(2)设备树之我见

[复制链接] qrcode

33

主题

36

帖子

110

积分

注册会员

Rank: 2

积分
110
楼主
跳转到指定楼层
发表于 2015-12-5 08:10 PM | 只看该作者 回帖奖励 |倒序浏览 |阅读模式


一、设备树的引入(以下来自网络)

     Device Tree起源于OpenFirmware (OF),在过去的Linux中,arch/arm/plat-xxxarch/arm/mach-xxx中充斥着大量的垃圾代码,相当多数的代码只是在描述板级细节,而这些板级细节对于内核来讲,不过是垃圾,如板上的platform设备、resourcei2c_board_infospi_board_info以及各种硬件的platform_data。为了改变这种局面,Linux社区的大牛们参考了PowerPC等体系架构中使用的Flattened Device TreeFDT),也采用了Device Tree结构,许多硬件的细节可以直接透过它传递给Linux,而不再需要在kernel中进行大量的冗余编码。

    Device Tree是一种描述硬件的数据结构,由一系列被命名的结点(node)和属性(property)组成,而结点本身可包含子结点。所谓属性,其实就是成对出现的namevalue。在Device Tree中,可描述的信息包括(原先这些信息大多被hard codekernel中):CPU的数量和类别,内存基地址和大小,总线和桥,外设连接,中断控制器和中断使用情况,GPIO控制器和GPIO使用情况,Clock控制器和Clock使用情况。

    通常由.dts文件以文本方式对系统设备树进行描述,经过Device Tree Compiler(dtc)dts文件转换成二进制文件binary device tree blob(dtb).dtb文件可由Linux内核解析,有了device tree就可以在不改动Linux内核的情况下,对不同的平台实现无差异的支持,只需更换相应的dts文件,即可满足。

    device treelinux 3.x开始使用的加载硬件资源的方式,这里说的硬件资源既包括片上的诸如GPIOPWMI2CADC等资源,也包括外部拓展的如FLASHLCD等。device tree主要作用是将某个硬件外设与相应的驱动程序进行绑定,使用时首先需要编写一个.dts文件(device tree source),在文件中说明要设置的硬件和它的各种属性,然后编译这个.dts文件生成对应的二进制文件.dtb,系统启动时就会加载这个device tree并配置各种硬件资源。系统启动时,从/boot目录自动加载。

    如果想要自己修改某些功能,可以使用device tree overlay来动态重定义某些功能。device tree overlaydevice tree类似,同样是编写一个.dts文件,但编译成.dtbo文件(末尾的o应该代表overlay)。不同的是不必把它放到/boot目录中去,它也不必在启动时加载,而可以在需要时随时进行动态加载。另外device tree overlay.dts文件跟device tree.dts文件格式还是有一点区别的

 

二、认识设备树

       设备树有4种文件格式,分别为dtsidevice tree source include),dtsdevice tree source),dtbdevice tree blob),dtbodevice tree blob overlay), 其中前两者是作者编写的,可以查看其内容的,后两者是编译后形成的二进制文件,是linux加载使用的。前三者主要位于内核目录的/arch/arm/boot/dts下,在编译内核时,由dtsdtsi生成dtb,在加载内核时使用dtb。而由具体的capedts,编译生成dtbo,用来加载某一cape模块。而需要关注的也就是可以生成dtbodts,它主要位于/lib/firmware目录下,下面是改写的一个关于PRU模块的设备树文件。


 /dts-v1/;  
/plugin/;  
  
/ {  
compatible = "ti,beaglebone", "ti,beaglebone-black";  
  
/* identification */  
part-number = "BB-BONE-PRU";  
version = "00A0";  
  
exclusive-use =  
"P8.12","P8.46";  
  
fragment@0 {  
    target = <&am33xx_pinmux>;  
    __overlay__ {  
        mygpio: pinmux_mygpio{  
        pinctrl-single,pins = <  
            0x30 0x06 0x0A4 0x05 
            >;  
    };  
    };  
};  
  
fragment@1 {  
    target = <&ocp>;  
    __overlay__ {  
        test_helper: helper {  
        compatible = "bone-pinmux-helper";  
        pinctrl-names = "default";  
        pinctrl-0 = <&mygpio>;  
        status = "okay";  
    };  
    };  
};  
  
fragment@2{  
    target = <&pruss>;  
    __overlay__ {  
        status = "okay";  
    };  
    };  
}; 


    从上面的代码中,可以看出,dts文件是一个树形结构:第一行的/代表根,下面的fragment@0fragment@1是其两个分支节点。每个fragment节点下面又各有一个__overlay__节点(这些节点的名字都是固定的)。每个fragment节点下面相邻的target说明这个节点要修改的对象,在__overlay__节点下面的内容阐明了要修改的属性。

其中:

1)

compatible = "ti,beaglebone", "ti,beaglebone-black";


一般都这么写,它与具体的驱动相关

2)


part-number = "BB-BONE-PRU";  
version = "00A0"; 
 


代表该dts的名字和版本号,加载时需要这两个参数,可以自定义名字,如上的BB-BONE-PRU,如果有多个版本,则还要指定不同的版本如00A0。

 3)

exclusive-use =  
"P8.12","P8.46"; 


说明了该cape使用的引脚硬件资源,这里指定了P8.12和P8.46引脚。


__overlay__ {  
        mygpio: pinmux_mygpio{  
        pinctrl-single,pins = <  
            0x30 0x06 0x0A4 0x05 
            >;  
    };  
    };    


指定了具体引脚的偏移地址和要设置的功能,这里0x30和0x0A4分别表示引脚P8.12和P8.46的偏移地址,0x06和0x05表示将这两个引脚设置为输出。

 

三、使用设备树

1 编译


dtc -I dts -O dtb -@BB-BONE-PRU-00A0.dts > BB-BONE-PRU-00A0.dtbo
dtc -O dtb -o BB-BONE-PRU-00A0.dtbo -b 0 -@ BB-BONE-PRU-00A0.dts


 ps 反编译


dtc -I dtb -O dts BB-BONE-PRU-00A0.dtbo > BB-BONE-PRU-00A0.dts


2 加载

1)手动加载

# echo BB-BONE-PRU  > /sys/devices/bone_capemgr.*/slots 

ps 所有已经加载的overlay列表都在/sys/devices/bone_capemgr.*/slots这个文件中

2)自动加载

uExt文件中,使用enable表示自动加载,使用disable表示禁止加载,具体如下所示


optargs=quiet capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN,BB-BONE-EMMC-2G capemgr.enable_partno=
BB-BONE-PRU




回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表