基于Zynq平台的设备树指南 --第一部分

来源:互联网 发布:淘宝女装店宣传语 编辑:程序博客网 时间:2024/05/14 00:44

这个指南的目标读者:

这个指南是基于赛灵思的 Zynq-7000 EPP 设备编写的,但是关于设备树的通用知识也适用于使用设备树的任何Linux内核。这里的例子运行环境是:在Zedboard上运行的Xillinux

设备树的优势是什么?

设想一下:bootloader已经把Linux 内核复制到了处理器的SDRAM。然后调转到了内核的入口处,此时的内核就像其他任何裸金属程序一样,运行在处理器上。它需要去配置处理器,需要去设置虚拟内存,需要向控制台输出一些东西,。但是怎么才能做到这些呢?上面的操作都是通过写寄存器实现的,但是Linux内核怎么知道这些寄存器的地址?内核如何怎么知道它将运行在几核的处理器上?内核又如何知道有多少内存可以访问?

最直接的解决方法就是在内核代码中设置平台相关的启动规则。这些启动规则是通过内核的配置参数启用的。这种方法对于内核访问比较固定的设备(如x86处理器上的内部寄存器,及在PC上访问BIOS等)比较有用,但是,当内核需要面对可能变化的设备(如:PC 计算机上的PCI/PCIe 总线)时,这种方法就不能在运行时让内核知道可能变化的设备信息。

ARM架构已经成为Linux社区非常麻烦的问题:即使这些处理器共享同样的编译器和许多功能,每一个实例(如芯片)都有它自己的寄存器地址,及完全不同的配置信息。除开这个,每个开发板都有自己的外部元件组合。结果就是头文件,补丁和特别的配置参数在内核树上疯狂增加,每一个头文件,补丁及配置参数的组合都对应一个开发板,这些开发板都包含一个基于ARM架构的芯片。简单来说,内核树上的ARM部分的源码已经变的非常讨厌和不可维护,也没有人真的喜欢这些东西。

除开这个,每个内核二进制文件都是针对特定板子上特定的芯片而编译的,这中方法差不多就像为市场上的每一款PC母版编译内核。因此,就有了为所有的ARM处理器编译内核的愿望,让内核以某种方法去探测它的硬件设备并添加必要的适当的设备驱动,就像PC上运行的那样。

但是如何做到呢?在PC上,初始的寄存器都是硬编码的,并且剩下的信息由BIOS提供。当有其他软件告诉内核拥有什么时,内核自动探测到这些硬件设备就非常容易。ARM处理器没有BIOS, Linux内核只相信它自己。

最终选择的解决方法就是设备树,也被称作开放固件(缩写为OF)或者扁平的设备树。它的本质是字节码形式(不可读的)组成的数据机构, 当内核启动时,这些数据结构包含信息是非常有用的。boot loader 在跳转到内核的入口处之前,会拷贝这些数据块到RAM中的一个已知的地址。

我定义的设备树有些模糊,但是上面的内容准确地说明了设备树是怎么来的:即使这里有严格的规范(虽然大家并没有严格遵守这些规范),也没有精确的规则说明哪些设备可以加入到设备树及它应该被放在设备树的什么位置。内核中的任何程序都可能去查询设备树中如何路径下任何参数。由程序员选择哪些可以用参数表示,并且应该把这些参数放在设备树的说明地方。

采用标准的树结构,可以使用标准的API去获取特定的数据。例如:对于如何定义总线上的外围设备, 一个API为驱动获取必要的地址,中断和自定义的变量等必要信息都有清楚明确的约定。稍后介绍更多的内容。

对于我们中的大部分人而言,设备树是我们通知内核我们已经添加的或者移除的一系列特定硬件(如:PL逻辑),然后内核可以启动适合的驱动并操作硬件(如果硬件被移除,内核就不加载对应的驱动等)。设备树也是定义硬件要传送给内核特定信息的地方。

 

编译设备树

设备树有三种形式:

  文本文件形式(*.dts——

  二进制形式(*.dtb——目标代码

  存在运行的linux上的一个文件系统‘/proc/device-tree’目录——调试和逆向工程的相关信息

通常,DTS 文件是可以编辑的并且使用特定的编译器被编译成DTB文件, 特定的编译器可以从Linux内核源码中获取。在Xillinux 中,编译器位于/usr/src/kernels/3.3.0-xillinux-1.0+/scripts/dtc/(或者相近的地方)

设备树编译器可以通过下面的方式下载并单独编译。

$ git clone git://www.jdl.com/software/dtc.git dtc
$ cd dtc
$ make

但是,下面的内容,我假定使用的内核源码中dtc

这里描述了设备树语言的语法。注意:这种语言并不会执行,但是类似XML,它只是组织数据的语法。一些架构(如Microblaze)可以通过XPS工程 中自动化的工具生成设备树,但是目前在Zynq EPP的平台,还没有类似的工具可用。(译者注:Zynq已经有类似的工具,参见这里:http://www.wiki.xilinx.com/Build+Device+Tree+Blob)
在Zedboard 上运行Xillinux1.0,进入下面的目录:
$ cd /usr/src/kernels/3.3.0-xillinux-1.0+/
接着执行:
$ scripts/dtc/dtc -I dts -O dtb -o /path/to/my-tree.dtb /path/to/my-tree.dts
就可以把DTS 文件编译成DTB 文件,上面的命令生成my-tree.dtb文件, DTC 编译器是一个二进制的应用程序,它运行在主机的平台上(不是交叉编译的)。如果内核没有在主机上被编译过,就需要至少编译下DTS编译器:首先,设置好内核的配置信息,不管使用什么方法。可以拷贝一个相关的配置文件到内核树的根目录下 的.config文件。 如果下面的命令能够工作:
$ make ARCH=arm digilent_zed_defconfig

接着生成DTS编译器

$ make ARCH=arm scripts
如果指向交叉编译工具的路径没有被设置,可能会报错。通常都是在错误之前,DTC编译器已经生成了,错误就无关紧要了,通常都是这样的。如何在make命令之后的某个地方出现 “HOSTLD scripts/dtc/dtc”, 这就可以了。或者去试着像上面演示的那样运行dtc命令。
无论从DTB文件还是文件系统的/proc/device-tree,反编译出DTS都是可行的。从DTB二进制文件使用下面的命令可以得到文本文件。
$ scripts/dtc/dtc -I dtb -O dts -o /path/to/fromdtb.dts /path/to/booted_with_this.dtb
DTS 文件再编译成DTB文件也是可行的,但是最好使用原来的DTS文件。

实际上,在运行中的内核上,设备树也是可以以DTS的格式获取的。

# cd /usr/src/kernels/3.3.0-xillinux-1.0+/
# scripts/dtc/dtc -I fs -O dts -o ~/effective.dts /proc/device-tree/

上面的命令运行Zedboard板子上运行的Xillinux系统中(或者其他提供了内核代码的发布版),生成的文件就在home目录。


原文链接:http://xillybus.com/tutorials/device-tree-zynq-1

0 0
原创粉丝点击