U-Boot/Linux设备树简明使用手册

设备树(Device Tree)起源于IEEE1275 OpenFirmware和Power(PC) ePAPR标准,主要适用于Power(PC)架构,用于引导程序(Bootloader)向操作系统内核传递硬件配置和内核参数。目前,设备树已经扩展到U-Boot/Linux的Power(PC)/ARM/RISC-V/MIPS/x86等多个架构,从而大大简化了代码中的驱动的配置信息。

1. 简介

设备树的官网为devicetree.org,提供相关的FAQ和最新的标准等。对应的文档和库存放在github.com/devicetree-orgkernel.org/dtc

设备树包括如下文件类型:

  • DTS(Device Tree Source):文本形式的设备树源文件,后缀为dts,可以包含头文件和DTSI文件,于配置如下信息:
    • 硬件信息, 包括设备的驱动兼容信息字符串、寄存器地址、中断请求、时钟、管脚复用、引用关系,以及CPU、Cache(高速缓存)、总线、物理内存等;
    • 内核参数,包括用于匹配BSP(板级支持包)和驱动的兼容信息字符传,启动参数,调试串口,从核启动方式等。
  • DTSI(Device Tree Source Include):文本形式的设备树源包含文件,后缀为dtsi,用于将若干个DTS文件公用的配置信息抽离出来,从而被多个DTS文件包含,从而简化DTS文件的配置;注意,DTSI文件可以包含其他DTSI文件,形成多级嵌套;
  • DTB(Devic Tree Blob):设备树源文件编译而成的二进制文件,用于被U-Boot/Linux访问以获取配置信息;
  • DTSO:安卓引入的扩展,用于对DTS文件中已经存在硬件信息进行修改,需要包含/plugin/;标签;
  • DTBO:安卓引入的扩展,从DTSO编译而来。

2. 设备树配置

设备树本质是一个树形结构,如下所示:

/dts-v1/;

#include "xxx.dtsi"

/ {
    model = "board name";
    compatible = "vendor,BSP name";

    aliases {
        ts0 = &tempsensor0;
    };

    cpus {
        #address-cells = <1>;
        #size-cells = <0>;

        cpu0: cpu@0 {
                device_type = "cpu";
                compatible = "arm,cortex-a72";
                enable-method = "psci";
                reg = <0x0>;
                clocks = <&clockgen 1 0>;
                d-cache-size = <0x8000>;
                ...
            };
        ...
        };

    memory@0 {
        device_type = "memory";
        reg = < 0x00 0x80000000 0x00 0x40000000 0x00 0x00 0x00 0x00 >;
    };

    chosen {
        stdout-path = "/soc/serial@48020000";
        bootargs = "console=ttyS0,115200n8 root=xxx rw rootfstype=ext4 ...";
    };
    ...
    soc {
        #address-cells = <2>;
        #size-cells = <2>;
        ...
        i2c0: i2c@2000000 {
            compatible = "fsl,vf610-i2c";
            #address-cells = <1>;
            #size-cells = <0>;
            reg = <0x0 0x2000000 0x0 0x10000>;
            interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
            clock-names = "i2c";
            clocks = <&clockgen 4 15>;
            scl-gpios = <&gpio2 15 GPIO_ACTIVE_HIGH>;

            tempsensor0: i2c3dev0@62 {
                compatible = "nxp,sa56004";
                reg = <0x4c>;
                vcc-supply = <&sb_3v3>;
            };
        ...
        };
        ...
    };
    ...
};

其中:

  • 所有节点都从根节点/开始逐级包含,名称和路径都不得重复;
  • 每个节点的路径都是从根节点开始计算,例如/soc/i2c@2000000/i2c3dev0@62:为了方便使用,可以为每个节点加上1个标签,例如tempsensor0clockgen
  • 每个节点都包含若干个属性,用于配置设备驱动软件需要的各种信息;这些属性与软件紧密相关,没有统一的标准;其中的compatible属性包含若干个兼容字符,按照从高到低的优先级依次排列,用于匹配到最合适的驱动软件。

设备树的其他具体配置规范可以参考github.com/devicetree-org/devicetree-specification

3. 设备树访问

设备树源文件(DTS/DTSO)通过开源工具DTC(Devic Tree compiler)转换为为DTB文件或者包含DTB二进制数据的汇编文件,进而与U-Boot/Linux等编译在一起,并可以通过libfdt库从DTB文件和二进制数据中获取信息。

DTC工具源码托存在kernel.org/dtc,包含DTC工具和libfdt库,也可以使用操作系统自带的工具安装,例如:

sudo apt install device-tree-compiler

DTC工具除了可以从DTS生成DTB,还可以从DTB文件和文件系统(/sys/firmware/devicetree/base或者/proc/device-tree)生成DTS文件,例如:

$ dtc -h                                                    # 查看帮助信息
$ dtc -I dts -O dtb -o xxx.dtb xxx.dts                      # 从DTS生成DTB
$ dtc -I dtb -O dts -o xxx.dts xxx.dtb                      # 从DTB生成DTS
$ dtc -I fs -O dts -o xxx.dts /sys/firmware/devicetree/base # 从文件系统生成DTS

DTC工具包含的libfdt库用于访问通过DTB文件或者包含DTB二进制数据的汇编文件形式加载到内存或者其他存储介质中的设备树信息中,其接口定义在libfdt/libfdt.h

4. U-Boot/Linux设备树获取

有源码的情况下,设备树文件通常可以通过搜索后缀为dtsdtsidtso的文件来获取。其中:

  • 对于U-Boot,设备树文件通常可以defconfig配置文件中CONFIG_DEFAULT_DEVICE_TREE对应的设备树名字或来寻找者根据defconfig配置文件的名字来猜测;

  • 对于Linux,设备树文件的名字通常可以从内核加载信息里面根据Machine model即DTS中的根节点下的model属性来定位DTS文件:

    [    0.000000] Booting Linux on physical CPU 0x0
    ...
    [    0.000000] CPU: ARMv7 Processor [412fc0f2] revision 2 (ARMv7), cr=30c5387d
    [    0.000000] CPU: div instructions available: patching division code
    [    0.000000] CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction cache
    [    0.000000] OF: fdt:Machine model: TL570x-EVM
    

没有源码的情况下,U-Boot的设备树暂时没有办法获取,但是Linux的设备树却可以通过U-Boot来获取:

  • 获取设备树地址:

    • 对于Legacy加载模式,Linux内核和DTB文件通常使用bootm <内核地址> <initrd文件系统地址> <DTB地址>,其中initrd文件系统地址可能用-代替;因此可以先执行bootm之前的命令,使得DTB文件被加载到内存中去;

    • 对于FIT加载模式,Linux内核和DTB文件被编译在一个镜像中,加载信息中fdt镜像对应的Data Start地址即FIT镜像加载后设备树的地址,因此可以先执行bootm之前的命令,使得FIT镜像被加载到内存中去,进而将设备树拷贝到最终的内存位置即Booting using the fdt blob at 0xXXXXXXXX包含的地址:

      ## Loading kernel from FIT Image at a0000000 ...
        Using 'ls1046afrwy' configuration
        Trying 'kernel' kernel subimage
          ...
      ## Loading ramdisk from FIT Image at a0000000 ...
        Using 'ls1046afrwy' configuration
        Trying 'initrd' ramdisk subimage
          ...
      ## Loading fdt from FIT Image at a0000000 ...
        Using 'ls1046afrwy' configuration
        Trying 'ls1046afrwy-dtb' fdt subimage
          Description:  ls1046afrwy-dtb
          Type:         Flat Device Tree
          Compression:  uncompressed
          Data Start:   0xa19d41b8
          Data Size:    31569 Bytes = 30.8 KiB
          Architecture: AArch64
          Load Address: 0x90000000
          Hash algo:    crc32
          Hash value:   d30014cb
        Verifying Hash Integrity ... crc32+ OK
        Loading fdt from 0xa19d41b8 to 0x90000000
        Booting using the fdt blob at 0x90000000
        ...
      Starting kernel ...
      
  • 使用如下命令设置设备树基地址到上一步发现的设备树地址并dump:

    => fdt addr 90000000; fdt print
    
  • 如果U-Boot支持U盘、SD卡等,还可以直接将设备树文件转存上去,以USB为例(SD卡类似):

    => usb start
    starting USB...
    USB0:   Register 2000140 NbrPorts 2
    Starting the controller
    USB XHCI 1.00
    scanning bus 0 for devices... 2 USB Device(s) found
        scanning usb for storage devices... 1 Storage Device(s) found
    => usb dev
    
    IDE device 0: Vendor: SanDisk  Rev: 0    Prod: Extreme Pro
                Type: Removable Hard Disk
                Capacity: 122112.0 MB = 119.2 GB (250085376 x 512)
    => usb part
    
    Partition Map for USB device 0  --   Partition Type: DOS
    
    Part    Start Sector    Num Sectors     UUID            Type
    1     2048            195309568       000930ef-01     0b Boot
    2     195313662       54769666        000930ef-02     05 Extd
    5     195313664       54769664        000930ef-05     83
    => fatwrite usb 0:1 ${fdtaddr} am5708_uboot.dtb 16F67
        writing am5708_uboot.dtb
        94055 bytes written
    

    其中,用于转存的USB分区为IDE device 0上的分区1,因此使用usb 0:1来写入;对于SD卡来说,不需要执行usb start命令,只需要确认设备和分区即可。

此外,如果Linux文件系统中包含/sys/firmware/devicetree/base或者/proc/device-tree目录,则设备树还可以直接通过文件系统来获取:

$ dtc -I fs -O dts -o xxx.dts /sys/firmware/devicetree/base
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354

推荐阅读更多精彩内容