U-Boot/Linux設(shè)備樹簡明使用手冊

設(shè)備樹(Device Tree)起源于IEEE1275 OpenFirmware和Power(PC) ePAPR標準,主要適用于Power(PC)架構(gòu),用于引導(dǎo)程序(Bootloader)向操作系統(tǒng)內(nèi)核傳遞硬件配置和內(nèi)核參數(shù)。目前,設(shè)備樹已經(jīng)擴展到U-Boot/Linux的Power(PC)/ARM/RISC-V/MIPS/x86等多個架構(gòu),從而大大簡化了代碼中的驅(qū)動的配置信息。

1. 簡介

設(shè)備樹的官網(wǎng)為devicetree.org,提供相關(guān)的FAQ和最新的標準等。對應(yīng)的文檔和庫存放在github.com/devicetree-orgkernel.org/dtc

設(shè)備樹包括如下文件類型:

  • DTS(Device Tree Source):文本形式的設(shè)備樹源文件,后綴為dts,可以包含頭文件和DTSI文件,于配置如下信息:
    • 硬件信息, 包括設(shè)備的驅(qū)動兼容信息字符串、寄存器地址、中斷請求、時鐘、管腳復(fù)用、引用關(guān)系,以及CPU、Cache(高速緩存)、總線、物理內(nèi)存等;
    • 內(nèi)核參數(shù),包括用于匹配BSP(板級支持包)和驅(qū)動的兼容信息字符傳,啟動參數(shù),調(diào)試串口,從核啟動方式等。
  • DTSI(Device Tree Source Include):文本形式的設(shè)備樹源包含文件,后綴為dtsi,用于將若干個DTS文件公用的配置信息抽離出來,從而被多個DTS文件包含,從而簡化DTS文件的配置;注意,DTSI文件可以包含其他DTSI文件,形成多級嵌套;
  • DTB(Devic Tree Blob):設(shè)備樹源文件編譯而成的二進制文件,用于被U-Boot/Linux訪問以獲取配置信息;
  • DTSO:安卓引入的擴展,用于對DTS文件中已經(jīng)存在硬件信息進行修改,需要包含/plugin/;標簽;
  • DTBO:安卓引入的擴展,從DTSO編譯而來。

2. 設(shè)備樹配置

設(shè)備樹本質(zhì)是一個樹形結(jié)構(gòu),如下所示:

/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>;
            };
        ...
        };
        ...
    };
    ...
};

其中:

  • 所有節(jié)點都從根節(jié)點/開始逐級包含,名稱和路徑都不得重復(fù);
  • 每個節(jié)點的路徑都是從根節(jié)點開始計算,例如/soc/i2c@2000000/i2c3dev0@62:為了方便使用,可以為每個節(jié)點加上1個標簽,例如tempsensor0clockgen
  • 每個節(jié)點都包含若干個屬性,用于配置設(shè)備驅(qū)動軟件需要的各種信息;這些屬性與軟件緊密相關(guān),沒有統(tǒng)一的標準;其中的compatible屬性包含若干個兼容字符,按照從高到低的優(yōu)先級依次排列,用于匹配到最合適的驅(qū)動軟件。

設(shè)備樹的其他具體配置規(guī)范可以參考github.com/devicetree-org/devicetree-specification

3. 設(shè)備樹訪問

設(shè)備樹源文件(DTS/DTSO)通過開源工具DTC(Devic Tree compiler)轉(zhuǎn)換為為DTB文件或者包含DTB二進制數(shù)據(jù)的匯編文件,進而與U-Boot/Linux等編譯在一起,并可以通過libfdt庫從DTB文件和二進制數(shù)據(jù)中獲取信息。

DTC工具源碼托存在kernel.org/dtc,包含DTC工具和libfdt庫,也可以使用操作系統(tǒng)自帶的工具安裝,例如:

sudo apt install device-tree-compiler

DTC工具除了可以從DTS生成DTB,還可以從DTB文件和文件系統(tǒng)(/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 # 從文件系統(tǒng)生成DTS

DTC工具包含的libfdt庫用于訪問通過DTB文件或者包含DTB二進制數(shù)據(jù)的匯編文件形式加載到內(nèi)存或者其他存儲介質(zhì)中的設(shè)備樹信息中,其接口定義在libfdt/libfdt.h

4. U-Boot/Linux設(shè)備樹獲取

有源碼的情況下,設(shè)備樹文件通常可以通過搜索后綴為dtsdtsidtso的文件來獲取。其中:

  • 對于U-Boot,設(shè)備樹文件通常可以defconfig配置文件中CONFIG_DEFAULT_DEVICE_TREE對應(yīng)的設(shè)備樹名字或來尋找者根據(jù)defconfig配置文件的名字來猜測;

  • 對于Linux,設(shè)備樹文件的名字通常可以從內(nèi)核加載信息里面根據(jù)Machine model即DTS中的根節(jié)點下的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的設(shè)備樹暫時沒有辦法獲取,但是Linux的設(shè)備樹卻可以通過U-Boot來獲取:

  • 獲取設(shè)備樹地址:

    • 對于Legacy加載模式,Linux內(nèi)核和DTB文件通常使用bootm <內(nèi)核地址> <initrd文件系統(tǒng)地址> <DTB地址>,其中initrd文件系統(tǒng)地址可能用-代替;因此可以先執(zhí)行bootm之前的命令,使得DTB文件被加載到內(nèi)存中去;

    • 對于FIT加載模式,Linux內(nèi)核和DTB文件被編譯在一個鏡像中,加載信息中fdt鏡像對應(yīng)的Data Start地址即FIT鏡像加載后設(shè)備樹的地址,因此可以先執(zhí)行bootm之前的命令,使得FIT鏡像被加載到內(nèi)存中去,進而將設(shè)備樹拷貝到最終的內(nèi)存位置即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 ...
      
  • 使用如下命令設(shè)置設(shè)備樹基地址到上一步發(fā)現(xiàn)的設(shè)備樹地址并dump:

    => fdt addr 90000000; fdt print
    
  • 如果U-Boot支持U盤、SD卡等,還可以直接將設(shè)備樹文件轉(zhuǎn)存上去,以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
    

    其中,用于轉(zhuǎn)存的USB分區(qū)為IDE device 0上的分區(qū)1,因此使用usb 0:1來寫入;對于SD卡來說,不需要執(zhí)行usb start命令,只需要確認設(shè)備和分區(qū)即可。

此外,如果Linux文件系統(tǒng)中包含/sys/firmware/devicetree/base或者/proc/device-tree目錄,則設(shè)備樹還可以直接通過文件系統(tǒng)來獲取:

$ dtc -I fs -O dts -o xxx.dts /sys/firmware/devicetree/base
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,345評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,494評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,283評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,953評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,714評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,410評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,940評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,776評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,210評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,654評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內(nèi)容