設備樹


什么是設備樹

  • 設備樹(Device Tree)是用來描述板卡上的硬件資源信息的,包括外設控制器和各種外設所使用的硬件資源信息

  • 設備樹的源文件名后綴是.dts/.dtsi, dtsi文件一般用來描述一些通用的硬件信息資源,然后會被dts文件引入,這樣dts文件中就會包含dtsi文件中的內容

  • 設備樹源文件在內核中的位置:/arch/arm(64)/boot/dts

  • dts源文件不能直接被內核驅動所使用,必須被編譯成二進制文件才能被內核驅動使用,設備樹二進制文件后綴名是dtb,使用dtc工具把dts文件編譯成dtb文件

    graph LR dts ----dtc---> dtb

設備樹語法

dts文件布局

/dts-v1/;                // 表示版本
[memory reservations]    // 格式為: /memreserve/ <address> <length>;
/ {
    [property definitions]
    [child nodes]
};

以上各項的含義:

名稱 含義
/dts-v1/ 設備樹文件的版本
memory reservations 指定保留內存,內核不會使用保留內存
/ 根節點(使用花括號表示屬於根節點的內容)
property definitions 根節點的屬性,用來描述硬件
child nodes 子節點(使用花括號表示屬於孩子節點的內容)

設備節點

設備樹中的基本單元被稱為節點(node),格式為:

[label:] node-name[@unit-address] {
    [properties definitions]
    [child nodes]
};

label是標號,可以省略,label的作用是為了方便地引用node,比如:

/dts-v1/;
/ {
	uart0: uart@fe001000 {
        compatible="ns16550";
        reg=<0xfe001000 0x100>;
	};
};

可以使用下面2種方法來修改uart@fe001000這個node:
// 在根節點之外使用label引用node:

&uart0 {
    status = “disabled”;
};

或在根節點之外使用全路徑:

&{/uart@fe001000}  {
    status = “disabled”;
};

屬性(properties)

每個節點都有不同的屬性,不同的屬性又有不同的內容,屬性都是鍵值對,值可以為空或任意的字節流

屬性格式

  • 屬性有值
    [label:] property-name = value;
    
  • 屬性沒有值
    [label:] property-name;
    

屬性取值可以有四種

  1. arrays of cells(1個或多個32位數據, 64位數據使用2個32位數據表示)
    cell 就是一個32位的數據,一個或多個cell用尖括號括起來,並以空格隔開就可以作為一種合法的屬性值
interrupts = <17 0xc>

64bit數據使用2個cell來表示,一個或多個cell用尖括號包圍起來:

clock-frequency = <0x00000001 0x00000000>
  1. string(字符串),用雙引號包圍起來
compatible = "simple-bus";
  1. bytestring(1個或多個字節),用中括號包圍起來
local-mac-address = [00 00 12 34 56 78];  // 每個byte使用2個16進制數來表示
local-mac-address = [000012345678];       // 每個byte使用2個16進制數來表示
  1. 以上三種值的混合,以逗號隔開
compatible = "ns16550", "ns8250";
example = <0xf00f0000 19>, "a strange property format";

一些常用的屬性

compatible

compatible 屬性也叫做“兼容性”屬性,這是非常重要的一個屬性!compatible 屬性的值是一個字符串列表,compatible 屬性用於將設備和驅動綁定起來。

“compatible”表示“兼容”,對於某個LED,內核中可能有A、B、C三個驅動都支持它,那可以這樣寫:

led {
    compatible = “A”, “B”, “C”;
};

內核啟動時,就會為這個LED按這樣的優先順序為它找到驅動程序:A、B、C。

當該屬性位於根節點時,用於指定內核中哪個machine_desc可以支持本設備,即當前設備與哪些平台兼容。其值的格式一般是"manufacturer,model",其中manufacturer表示廠家,model表示型號(廠家的哪型產品)。

當該屬性的值有多個字符串時,從左往右,從最特殊到最一般。舉例來說,compatible = "samsung,smdk2416", "samsung,s3c2416";作為根節點的屬性時,第一個字符串指示了一個具體的開發板型號,而第二個字符串要更一般,只指示了SoC的型號。在linux初始化時,會優先找支持"samsung,smdk2416"的machine_desc用以初始化硬件,找不到時才退而求其次"samsung,s3c2416"。

model

model屬性與compatible屬性有些類似,但是有差別。
compatible屬性是一個字符串列表,表示你的硬件可以兼容A、B、C等驅動;
model用來准確地定義這個硬件是什么。
比如根節點中可以這樣寫:

/ {
    compatible = "samsung,smdk2440", "samsung,mini2440";
    model = "jz2440_v3";
};

它表示這個單板,可以兼容內核中的“smdk2440”,也兼容“mini2440”。
從compatible屬性中可以知道它兼容哪些板,但是它到底是什么板?用model屬性來明確。

#address-cells、#size-cells

cell指一個32位的數值
address-cells:address要用多少個32位數來表示
size-cells:size要用多少個32位數來表示

比如一段內存,怎么描述它的起始地址和大小?
下例中,address-cells為1,所以reg中用1個數來表示地址,即用0x80000000來表示地址;size-cells為1,所以reg中用1個數來表示大小,即用0x20000000表示大小:

/ {
#address-cells = <1>;
#size-cells = <1>;
memory {
    reg = <0x80000000 0x20000000>;
    };
};

status

status 屬性是和設備狀態有關的,status 屬性值是字符串

&uart1 {
    status = "disabled";
};

status 可選的狀態如下:

含義
“okay” 表明設備是可操作的。
“disabled” 表明設備當前是不可操作的,但是在未來可以變為可操作的
“fail” 發生了嚴重錯誤,需修復
“fail-sss” 發生了嚴重錯誤,需修復;sss表示錯誤信息

phandle

該屬性可以為節點指定一個全局唯一的數字標識符。這個標識符可以被需要引用該節點的另一個節點使用。舉例來說,現有一個中斷控制器:

pic@10000000 {
    phandle = <1>;
    interrupt-controller;
};

還有一個可以產生中斷的設備,且這個設備的中斷信號線連接到了上述中斷控制器,為了描述清楚這種關系,該設備的設備節點就需要引用中斷控制器的節點:

another-device-node {
    interrupt-parent = <1>; /* 數字1就唯一標識了節點pic@10000000 */
};

interrupt-controller

這是一個沒有值的屬性,用在中斷控制器的設備節點中,以表明這個節點描述的是一個中斷控制器。

interrupt-parent

該屬性用於可以產生中斷,且中斷信號連接到某中斷控制器的設備的設備節點,用於表示該設備的中斷信號連接到了哪個中斷控制器。該屬性的值通常是中斷控制器設備節點的數字標識(phandle),具體示例在上文已經出現過了。

reg

reg屬性描述了設備資源在其父總線定義的地址空間內的地址。reg 屬性的值一般是(address,length)對,該屬性使用一對或多對(地址,長度)來描述設備所占的地址空間。至於地址和長度使用多少個cell來表示呢?這取決於父節點的#address-cells、#size-cells屬性的值。

舉個例子,當:

#address-cells = <1>;
#size-cells = <1>;

那么reg = <0x3000 0x20 0xFE00 0x100>,表示該屬性所屬的設備占據了兩塊內存空間,第一塊是以0x3000為起始的32字節內存塊;第二塊是以0xFE00為起始的256字節內存塊。

/aliases

/aliases節點應當作為根節點的孩子節點,用於定義一個或多個別名屬性,每條別名屬性會為一個設備節點的路徑名設置一個別名,別名即為別名屬性的屬性名,屬性值則是設備節點的路徑名。如下面這個例子所示:
aliases { serial0 = "/simple-bus@fe000000/serial@llc500"; ethernet0 = "/simple-bus@fe000000/ethernet@31c000"; };

/chosen

/chosen節點應當用作根節點的孩子節點,有以下可選屬性:

  • bootargs
  • stdout-path
  • stdin-path

顧名思義,該節點可以指定啟動參數、標准輸出和標准輸入,一個例子如下:

/ {
	......
	chosen {
		bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200";
	};
	......
};

向節點追加或修改內容

要向節點中追加或修改節點中的屬性,可以對節點使用引用的方式來處理。
比如原始的i2c1節點是:

i2c1: i2c@021a0000 {
    #address-cells = <1>;
    #size-cells = <0>;
    compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
    reg = <0x021a0000 0x4000>;
    interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&clks IMX6UL_CLK_I2C1>;
    status = "disabled";
};

要對i2c1節點做屬性的追加和修改,使用如下方式:

&i2c1 {
    /* 要追加或修改的內容 */
};

&i2c1 表示使用引用的方式訪問 i2c1 這個 label 所對應的節點

修改后的設備樹代碼如下:

&i2c1 {
    clock-frequency = <100000>;
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_i2c1>;
    status = "okay";

    mag3110@0e {
        compatible = "fsl,mag3110";
        reg = <0x0e>;
        position = <2>;
    };

    fxls8471@1e {
        compatible = "fsl,fxls8471";
        reg = <0x1e>;
        position = <0>;
        interrupt-parent = <&gpio5>;
        interrupts = <0 8>;
    };
};

其中:
clock-frequency 就是新添加的屬性。
status 屬性的值由原來的 disabled 改為 okay
mag3110 和 fxls8471 是新增加的2個子節點

編寫設備樹

在DTS文件中包含其他文件

編寫設備樹文件時,我們通常會把多種設備的共性抽出來,寫在DTSI文件(后綴為.dtsi)中,其語法與DTS文件一樣。比如,多款使用了am335x的板子,因為使用了同一款SoC,描述設備時肯定會有一些相同的部分,可以把這部分抽出來,寫到am335x.dtsi中,然后在具體的某型板子的設備樹中包含相應的DTSI文件,包含的方式有:

/include/ “xxx.dtsi”
#include “xxx.dtsi”

設備樹編譯器還支持c語言的頭文件,因此,如果有需要可以定義一些宏並在設備樹文件中使用。

如何在設備樹文件中描述設備

設備樹寫出來是給驅動程序看的,也就是說驅動程序怎么寫的,相應的設備樹就該怎么寫;或者反過來,先約定好設備樹怎么寫,在相應的設計驅動。驅動和設備樹有着對應的關系,這種對應關系也被稱為bindings。具體的:

對於上游芯片廠商,應當按照devicetree-specification推薦的設備樹寫法,遵守各種約定,確定好如何規范的描述設備,並提供相應的驅動程序。devicetree-specification-v0.3的第四章給出了一些推薦的做法。

對於下游產品廠商,當使用芯片廠商的芯片做產品時,芯片廠商通常會提供驅動程序和設備樹文件編寫的參考文檔,這些文檔位於linux內核源碼樹的Documentation/devicetree/bindings目錄下。如果芯片廠商沒提供相應文檔的話,就要讀驅動的源碼,知道驅動怎么寫的,自然也就知道如何寫設備樹了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM