设备树

ZYNQ的Linux开发--使用SDK生成设备树

开发环境:
Windows下的Vivado套件
Linux ubuntu

Step1:首先从Xilinx GitHub上下载Device Tree Generator(设备树生成器)的BSP https://github.com/Xilinx/device-tree-xlnx/pulls 并将其复制到SDK的安装目录下

Step2:配置SDK开发环境,Xilinx Tools->Repositories,在Local Repositories 中点击New,将在github中下载的文件夹路径添加进去。


Step3:使用Device Tree Generator生成设备树
File->New->Board Support Package

petalinux如何用SD卡上的设备树

petalinux如何用SD卡上的设备树

cd petalinux-v2015.4/fszedboard_ad9361_wireless

petalinux-config



Zynq Zed Device Tree

device tree最开始的是skeleton.dtsi
/*
* Skeleton device tree; the bare minimum needed to boot; just include and
* add a compatible value. The bootloader will typically populate the memory
* node.
*/

/ {
#address-cells = <1>;
#size-cells = <1>;
chosen { };
aliases { };
memory { device_type = "memory"; reg = <0 0>; };
};

这是32位体系架构的设备树的skeleton,address-cells那行表示的是用32bit表示地址,寄存器也是用32bit来表示。接下来设备树里的东西是和zynq-7000这款芯片cpu息息相关的定义。将cpu以及外设都定义在此处。
《zynq-7000.dtsi》
1 /*
2 * Copyright (C) 2011 - 2014 Xilinx
3 *

Zynq设备树历史最详解

注:由于内核版本的演变,设备树成了任何使用较高版本linux系统的设备平台所必须文件,然国内相关技术文档严重不足,本文是国外技术专栏的翻译,原文链接: http://xillybus.com/tutorials/device-tree-zynq-1

本教程是针对Xilinx Zynq-7000设备写的,但其中的概念适用于所有使用了设备树的Linux内核。本文使用Xillinux发行版为例,该发行版运行于Zedboard硬件上。

设备树有什么好处
设想一下:bootloader刚刚将Linux内核复制到内存中,然后跳到内核的入口点开始执行。此时内核就像运行在处理器上的一个裸机程序。需要配置处理器,设置虚拟内存,向控制台打印一些信息。但是这些事情如何完成?所有的这些操作都要通过写寄存器来实现,但Linux内核如何知道这些寄存器的地址?如何知道当前有多少个CPU核可以使用?有多少内存可以访问?

最直接的办法就是在内核代码里为指定平台写好这些代码,由内核配置参数决定哪些平台代码将被启用。当一切都固定不变时这种方法还不错,比如在x86处理器上内部的寄存器,或是BIOS的访问。但对于变化量来说, 比如PCI/PCIe外设,就需要内核明确了解这些变化的细节。

九、编译设备树dts为dtb

前面的linux内核源码目录中已经包含了设备树编译器Device Tree Compiler(dtc),在目录arch/arm/boot/dts/目录下。

将前面生成的xilinx.dts文件拷贝到ubuntu下,使用如下命令进行编译
dtc -I dts -O dtb -o devicetree.dtb xilinx.dts

上面Dtc编译器有几个选项和参数:
-I是输入文件格式,在本文中是dts
-O是目标文件格式,在本文中是dtb
-o是目标文件路径

最后一个参数是输入文件路径
编译之后会在目标文件路径生成一个dtb文件,这个文件名必须按照前面uboot默认配置中的文件进行命名,本文中是devicetree.dtb。

至此,dtb文件生成完成。

十、制作根文件系统

设备树用于硬件和软件之间的信息交互,也就是将ZedBoard的硬件信息传递给linux内核,避免在linux内核中硬编码而影响在其他平台上的可移植性。设备树一般以两种文件格式存在,一个是dts文件,也就是文本文件,便于阅读,另外一种是dtb文件,是二进制格式,是dts使用dtc编译器编译而来,由uboot展开并传递给linux内核。设备树的文件格式可以参考 http://www.devicetree.org/Device_Tree_Usage
http://xillybus.com/tutorials/device-tree-zynq-1

如果你已经下载了最开始提到的linux-digilent内核源码,你可以在arch/arm/boot/dts/目录中找到digilent-zed.dts文件。这个dts文件包含比较丰富的硬件结构,但是不适合我们前面配置的最小系统。所以,我们需要自己来创建一个适合我们自己平台的dts文件。但这并不意味着我们需要使用文本编辑器从头按照繁琐的格式来编写。参考Xilinx Wiki上的一篇教程 http://www.wiki.xilinx.com/Build+Device+Tree+Blob ,我们可以轻松创建需要的设备树。

Zynq设备树教程(五)

应用程序相关的数据
之前提过,设备树中是一些特殊信息,这样一个驱动可以管理数片类似的硬件。例如,一个LCD显示驱动,分辨率信息和物理尺寸可能出现在设备树中。串口信息要告诉驱动当前的时钟频率。

最简单的,最常用的形式,这个信息由一条赋值语句组成:
xlnx,slv-awidth = <0x20>;

Zynq设备树教程(四)

获取资源信息

内核模块驱动加载之后,就开始把硬件资源管理起来,如读写寄存器、接收中断。

来看看设备树里的一条:
xillybus_0: xillybus@50000000 {
compatible = "xlnx,xillybus-1.00.a";
reg = < 0x50000000 0x1000 >;
interrupts = < 0 59 1 >;
interrupt-parent = <&gic>;

xlnx,max-burst-len = <0x10>;
xlnx,native-data-width = <0x20>;
xlnx,slv-awidth = <0x20>;
xlnx,slv-dwidth = <0x20>;
xlnx,use-wstrb = <0x1>;
} ;

驱动一般在探测函数里就取得了硬件内存段的所有权(探测函数就是probe指针指向的函数)。

来看看一个典型探测函数的框架:
static int __devinit xilly_drv_probe(struct platform_device *op)
{

Zynq设备树教程(三)

定义外设
可能你读本文是为了给你的设备写一个Linux驱动,在这方面要推荐著名的《Linux Device Driver》。但是在写一个设备驱动之前,允许我分享写Linux驱动的第一诫:永远不要为Linux写设备驱动。

更好的办法是找一个维护状态良好的类似功能的设备驱动,然后修改它。这不仅仅意味着更容易,更可能帮我们避免我们一些未意识到的问题。从其他驱动移植过来可以让这份驱动更容易被理解,可移植,更可能被内核树接受。

所以现在的重点变为理解其他驱动,然后做一点调整。有疑问的地方就照着别人的做法做。创新和个人风格在这里没什么用。

Zynq设备树教程(二)

设备树结构

Zynq的设备树如下:
/dts-v1/;
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "xlnx,zynq-zed";
interrupt-parent = <&gic>;
model = "Xillinux for Zedboard";
aliases {
serial0 = &ps7_uart_1;
} ;
chosen {
bootargs = "consoleblank=0 root=/dev/mmcblk0p2 rw rootwait earlyprintk";
linux,stdout-path = "/axi@0/uart@E0001000";
};

cpus {

[ ... CPU definitions ... ]

} ;
ps7_ddr_0: memory@0 {
device_type = "memory";
reg = < 0x0 0x20000000 >;
} ;
ps7_axi_interconnect_0: axi@0 {

同步内容