petaLinux-Build-Device-Tree-Blob笔记

设备树是什么?

设备树简称DT,是用来描述硬件的数据结构。它可以由操作系统(如,Linux)读取,这样可以将操作系统与机器硬件分离,而不必对机器硬件的细节进行硬编码。

Linux上使用DT的基本功能包括:平台识别、运行时配置(如bootargs)和设备节点填充。

设备树的基础知识

设备树中的每个驱动程序或模块都由节点定义,其所有属性都在该节点下定义。基于驱动程序,它可以有子节点或父节点。

例如,由SPI总线连接的设备将以SPI总线控制器作为其父节点,而该设备将是SPI节点的一个子节点。根节点是所有节点的父节点。

典型的根节点通常包括如下的数据信息:

  • cpu节点信息

  • 内存信息

  • 可以选择配置的数据,如内核参数字符串和initrd映像的位置

  • 别名

  • 定义总线信息的节点

设备树的语法示例

文件名:zynqmp-example.dtsi

/ {
    compatible = "xlnx,zynqmp";
    #address-cells = <2>;
    #size-cells = <2>;
  
    cpus {
       #address-cells = <1>;
       #size-cells = <0>;
  
       cpu0: cpu@0 {
                compatible = "arm,cortexa53", "arm,armv8";
                device-type = "cpu";
                enable-method = "psci";
                operating-points-v2 = <&cpu_opp_table>;
                reg = <0x0>;
                cpu-idle-states = <&CPU_SLEEP_0>;
        };
  
        cpu1: cpu@1 {
               compatible = "arm,cortexa53", "arm,armv8";
               device-type = "cpu";
               enable-method = "psci";
               operating-points-v2 = <&cpu_opp_table>;
               reg = <0x1>;
               cpu-idle-states = <&CPU_SLEEP_0>;
        };
  };
  
  chosen {
           bootargs = "earlycon clk_ignore_unused";
  };
  
  memory {
          device-type = "memory";
          reg = <0x0 0x0 0x0 0x80000000>, <0x00000008 0x0 0x0 0x80000000>;
  };
  
  amba_apu: amba_apu@0 {
              compatible = "simple-bus";
              #address-cells = <2>;
              #size-cells = <1>;
              ranges = <0 0 0 0 0xffffffff>;
              gic: interrupt-controller@f9010000 {
                        compatible = "arm,gic-400", "arm,cortex-a15-gic";
                        #interrupt-cells = <3>;
                        reg = <0x0 0xf9010000 0x10000>,
                               0x0 0xf9020000 0x20000>,
                               0x0 0xf9040000 0x20000>,
                               0x0 0xf9060000 0x20000>,
                        interrupt-controller;
                        interrupt-parent = <&gic>;
                        interrupts =<1 9 0xf04>;
              };
  };
  
  amba: amba {
          compatible = "simple-bus";
          #address-cells = <2>;
          #size-cells = <2>;
          ranges;
          can0: can@ff060000 {
                     compatible = "xlnx,zynq-can-1.0";
                     clock-names = "can_clk", "pclk";
                     reg =<0x0 0xff060000 0x0 0x1000>;
                     interrupts = <0 23 4>;
                     interrupt-parent = <&gic>;
                     tx-fifo-depth = <0x40>;
                     rx-fifo-depth = <0x40>;
                     power-domains = <&pd_can0>;
          };
  };

设备树的属性

  • compatible:顶层的compatible属性定义了兼容的板卡,然后定义了兼容的SOC。

  • #address-cells:该属性表示用多少字长的地址来表示设备寄存器的基地址。如#address-cells
    = <1>,表示该设备的基地址为32bit,即1个cell。

  • #size-cells:表示设备寄存器属性所占的大小(以地址单元来表示),如cpu也有地址,在4核的处理器中,它们可能被称为0、1、2和3。这可以看作是一个没有深度的一维数组,因此大小为0,即#
    size -cells = <0>。

  • interrupt-controller:该属性为一个布尔属性,用来表示该节点是不是一个中断控制器。

  • #interrupt-cells:它表示中断源的属性的数量。这里为1,中断源只用IRQ数来表示。有些中断控制器可能还需要定义中断源的触发方式:边沿触发或电平触发等。这时#interrupt-cells属性的值就不再是1了。

  • interrupt-parent:定义了设备连接到的中断控制器。phandle指向当前节点的中断控制器。通常有一个顶层的interrupt-parent定义,指向主中断控制器。

MSS文件

MSS文件,即Microprocessor software specification
file,包含了定制操作系统、库和驱动的操作指令。

MDD文件

MDD文件,即Microprocessor Driver Definition file,包含了定制软件驱动的指令。

每一个设备驱动都有一个MDD文件和一个TCL文件与之关联。TCL文件根据MSS文件中不同的配置选项,使用MDD文件定制驱动。

每个驱动的源文件和MDD文件必须放在特定的目录中,以便能够找到这些文件和驱动。

驱动定义文件

驱动的定义包括定义一个数据定义文件MDD,和一个数据生成文件TCL。

  • 数据定义文件:MDD文件(<driver_name>.mdd)包含了可配置的参数。

  • 数据生成文件:TCL文件(<driver_name>.tcl)具有与MDD相同的文件名,使用MSS文件中的驱动的配置参数生成数据。

如何添加一个新的驱动到DTG中?

  1. 同步源码库repo https://github.com/xilinx/device-tree-xlnx

  2. 创建一个驱动名的文件夹,如device-tree-xlnx/axi_iic/

  3. 在该文件夹中添加一个数据文件夹,如device-tree-xlnx/axi_iic/data/

  4. 在该数据文件夹中创建一个MDD文件和TCL文件,如,axi_iic.tcl和axi_iic.mdd。

  5. axi_iic.mdd文件的内容和语法如下:

device-tree-xlnx/axi_iic/data/axi_iic.mdd文件。

OPTION psf_version = 3.0;
 
BEGIN driver axi_iic
OPTION supported_peripherals = (axi_iic);--> the axi_iic is the IP_NAME which we get from the HDF file.
OPTION supported_os_types = (DTS);
OPTION driver_state = ACTIVE;
OPTION NAME = axi_iic;
END drive

  1. axi_iic.tcl文件的内容和语法如下,该文件包含了一个需要基于某些条件来设置的属性,而这些条件是我们使用HIS
    APIs来升级节点属性时定义的。如下所示,我们更新了axi_iic调用泛型函数的时钟属性。

device-tree-xlnx/axi_iic/data/axi_iic.tcl文件。

if {[string match -nocase $proctype "psu_cortexa53"] } {
    update_clk_node $drv_handle "s_axi_aclk"
}

在pl.dtsi中生成的节点如下:

pl.dtsi文件。

io_bd_iic_0: i2c@a1200000 {
    #address-cells = <1>;
    #size-cells = <0>;
    clock-names = "s_axi_aclk";
    clocks = <&misc_clk_0>;
    compatible = "xlnx,xps-iic-2.00.a";
    interrupt-names = "iic2intc_irpt";
    interrupt-parent = <&gic>;
    interrupts = <0 2 4>;
    reg = <0x0 0xa1200000 0x0 0x10000>;
};

DTG中支持的驱动列表和在Linux设备树中的绑定

参考:

https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842279/Build+Device+Tree+Blob

设备树的说明文档在:

https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/

设备树的生成

一般来说对于SOC这类芯片,都有一个静态的dts/dtsi文件,但是对于FPGA来说情况就复杂的多,因为FPGA的情况要复杂很多,PL的IP设备可能多种多样,并由许多不同的配置。

一旦我们生成设备树文件,将输出多个各种不同的DT文件,例如,dt/pl.dtsi pcw.dtsi
system-top.dts zynqmp.dtsi zynqmp-clk-ccf.dtsi。

  1. pl.dtsi:该文件中包含了所有可用的内存映射的PL IP节点。

  2. pcw.dtsi:包含PS外设所需的动态属性,包含我们在FPGA工程创建时,在原理框图设计中进行IO配置的外设接口。

  3. system-top.dts:该文件以include的方式包含了pcw.dtsi和zynq-7000.dtsi,包含内存信息和早期控制台和启动参数。

  4. zynqmp.dtsi:包含了所有的PS外设信息以及CPU信息。

  5. zynqmp-clk-ccf.dtsi:包含了所有外设IP的时钟信息。

此外对于特定的板卡将生成一个特定于该板卡的dtsi文件。如<skeleton>.dtsi。其包含了板卡特定的属性,如I2C,其可能连接了一些从设备。

如何使用上层的DT覆盖底层的DTG?

使用HIS命令

  1. 克隆设备树源码库repo。
    https://github.com/Xilinx/device-tree-xlnx

  2. 在SDK软件中选择菜单Xilinx Launch Shell,启动SDK
    Shell,输入his,进入HIS命令提示符。

  3. 打开硬件描述文件。his% open_hw_design design_1_wrapper.hdf。

  4. 运行his% set_repo_path <DTG repo的绝对路径>。

  5. 构建设备树文件,his% create_sw_design –proc psu_crotexa53_0 sd22 –os
    device_tree

  6. his% set_property CONFIG.dt_overlay true [get_os]

  7. 查看生成的文件
    hsi% ls dt/
    pcw.dtsi pl.dtsi sd22.mss system-top.dts zynqmp-clk-ccf.dtsi zynqmp.dtsi

  8. 可以看到生成了一个MSS文件。

使用XSCT命令提示符

开发XSCT命令提示符。

  1. hsi open_hw_design design_1_wrapper.xsa

  2. hsi set_repo_path <DTG repo path>

  3. hsi create_sw_design -proc psu_cortexa53_0 sd22 -os device_tree

  4. hsi generate_target -dir dt

编译pl.dtsi

dtc –O dtb –o pl.dtbo –b 0 -@ pl.dtsi

设备树二进制文件的比较

可以通过dtx_diff程序来比较两个设备树Blob(dtb)之前的差异。

依赖性/局限性

  • zynqmp-clk-ccf.dtsi具有静态时钟节点配置,如果用户需要更改任何时钟信息,请更新system-user.dtsi中的信息。

  • DTG不支持多concat中断模块。

  • 中断端口宽度不支持超过1。

  • 当为MAC IPs启用多核(如果MAC
    IPs大于1)时,DTG中的标签就会出现问题,并且会失败。但是,如果MAC
    IP是一个,并且启用了多核,就不会有问题。

  • DTG不支持生成私有外围中断(PPI)。

  • DTG支持基于内部TRD设计的视频管道生成,如wiki中所述
    https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/25329832/Zynq+UltraScale+MPSoC+VCU+TRD+2018.3

  • 如果有任何自定义的ip连接在视频管道IP之间,DTG不支持这些情况,用户可能需要添加输入和输出端口。

  • 对于广播IP,输出可以连接到多个输出端口,DTG无法知道哪个输出端口对于正确的管道是有效的。如果在设计中有多个类似的视频管道,用户需要在节点中添加输入和输出端口信息。下面的wiki给出了一些关于如何添加输入和输出端口的信息。

  • DTG对于多媒体IP的局限性

构建设备树

在开始构建设备树之前,需要做如下的准备:

  • 获取源码(Device Tree Generator源码和Linux源码)

  • 硬件工程

需要的工具有:

  • Xilinx Vivado

  • Xilinx SDK

输入的文件

  • 硬件工程目录

  • Linux源码目录

输出的文件

*.dts, *.dtsi, *.dtb

任务描述

创建设备树源文件(.dts/.dtsi)

  • 生成硬件描述HDF文件;

  • 打开SDK;

  • 克隆设备树Generator Git repo;
    https://github.com/Xilinx/device-tree-xlnx.git

  • 在SDK中添加BSP repo:点击Xilinx Repositories New… (<bsp repo>) OK。

  • 创建设备树板级支持包(BSP):SDK Menu: File > New > Board Support Package
    > Board Support Package OS: device-tree > Finish。

  • 设置BSP窗口打开(也可以通过system.mss文件打开),修改设置BSP配置,在bootargs和console
    device参数中填入合适的启动参数。

.dts /.dtsi文件现在位于<SDK工作空间>/device_tree_bsp_0/文件夹中。

***例如:console=<tty>, <baudrate> root=/dev/ram rw ip=::: eth0:dhcp
earlyprintk

*** <tty>的一些示例值是当使用Zynq时ttyPS0,当使用UART
Lite软ip时ttyUL0,或者当使用UART16550软ip时ttyS0。

从DTS中编译设备树Blob(.dtb)文件

一个称为设备树编译器(DTC)的实用程序用于将DTS文件编译成DTB文件。DTC是Linux源代码目录的一部分。linux-xlnx/scripts/dtc/包含dtc的源代码,需要编译才能使用。编译DTC的一种方法是构建Linux树。DTC也可以通过OS的包管理器获得。

一旦DTC可用,该工具将可能被调用用来生成DTB。

./scripts/dtc/dtc -I dts -O dtb -o <devicetree name>.dtb <devicetree
name>.dts

DTC也可以反过来将DTB转换为DTS。

./scripts/dtc/dtc -I dtb -O dts -o <devicetree name>.dts <devicetree
name>.dtb

可选的方法(只针对ARM)

在Linux源码目录中,make ARCH=arm
dtbs,这将从linux-xlnx/arch/arm/boot/dts编译所有的DTS文件将其转换为DTB文件。

编译好的DTB文件与DTS文件在相同的目录中。

自定义IP

对于自定义IP,DTG将生成带有兼容属性和中断(如果连接的话)的节点。

参考文献:

https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842279/Build+Device+Tree+Blob

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值