Linux設備樹學習


1.概念

設備樹用於實現驅動代碼與設備信息相分離。驅動代碼只負責處理驅動的邏輯而關於設備的具體信息存放到設備樹文件中。(dts文件,編譯后為dtb文件)。一個dts文件對應一個ARM的machine,位置:/arch/arm/boot/dts

 

一般dtb文件的開頭會#include<xxxx.dtsi>。(eg.#include "zynq-7000.dtsi")在同樣的目錄下能夠找到該dtsi文件。這個文件是一個SOC公用的部分或者多個machine共同的部分。dts文件只需要改寫差異部分即可。由於編譯設備樹的時候,相同節點的不同屬性信息會被合並,相同節點的相同屬性會被重寫。所以,比如我要做的是iic的設備樹,那么把dtsi里面的I2C的設備樹整個節點copy出來到dts文件當中再進行改寫即可(引用)

 

2.設備數框架

設備樹用樹狀結構描述設備信息,它有以下幾種特性

  1. 每個設備樹文件都有一個根節點,每個設備都是一個節點。
  2. 節點間可以嵌套,形成父子關系,這樣就可以方便的描述設備間的關系。
  3. 每個設備的屬性都用一組key-value對(鍵值對)來描述。
  4. 每個屬性的描述用;結束

所以,一個設備樹的基本框架可以寫成下面這個樣子,一般來說,/表示板子,它的子節點node1表示SoC上的某個控制器,控制器中的子節點node2表示掛接在這個控制器上的設備(們)

/{                                  //根節點
    node1{                          //node1是節點名,是/的子節點
        key=value;                  //node1的屬性
        ...
        node2{                      //node2是node1的子節點
            key=value;              //node2的屬性
            ...
        }
    }                               //node1的描述到此為止
    node3{
        key=value;
        ...
    }
}

  

節點名

格式:<name>[@<unit_address>]

axi_hdmi@70e00000 {
			compatible = "adi,axi-hdmi-tx-1.00.a";
			reg = <0x70e00000 0x10000>;
			dmas = <&axi_vdma_0 0>;
			dma-names = "video";
			clocks = <&hdmi_clock>;

			port {
				axi_hdmi_out: endpoint {
					remote-endpoint = <&adv7511_in>;
				};
			};

  比如這個,節點名是hdmi,設備地址為70e00000。這個設備地址一般是在處理器的用戶手冊,或者hdf文件里面有的。一些可更改的設備地址同樣可以在block designd的address editor里面配置(VIVADO)。reg<address offset>中的地址要和節點名那里的地址對應上哦~~

KEY

在設備樹中,鍵值對是描述屬性的方式,比如,Linux驅動中可以通過設備節點中的"compatible"這個屬性查找設備節點。
Linux設備樹語法中定義了一些具有規范意義的屬性,包括:compatibleaddressinterrupt等,這些信息能夠在內核初始化找到節點的時候,自動解析生成相應的設備信息。此外,還有一些Linux內核定義好的,一類設備通用的有默認意義的屬性,這些屬性一般不能被內核自動解析生成相應的設備信息,但是內核已經編寫的相應的解析提取函數,常見的有 "mac_addr""gpio""clock""power""regulator" 等等。

 

compatible

設備節點中對應的節點信息已經被內核構造成struct platform_device。驅動可以通過相應的函數從中提取信息。compatible屬性是用來查找節點的方法之一,另外還可以通過節點名或節點路徑查找指定節點。dm9000驅動中就是使用下面這個函數通過設備節點中的"compatible"屬性提取相應的信息,所以二者的字符串需要嚴格匹配。
在下面的這個dm9000的例子中,我們在相應的板級dts中找到了這樣的代碼塊:

然后我們取內核源碼中找到dm9000的網卡驅動,從中可以發現這個驅動是使用的設備樹描述的設備信息(這不廢話么,顯然用設備樹好處多多)。我們可以找到它用來描述設備信息的結構體,可以看出,驅動中用於匹配的結構使用的compatible和設備樹中一模一樣,否則就可能無法匹配,這里另外的一點是struct of_device_id數組的最后一個成員一定是空,因為相關的操作API會讀取這個數組直到遇到一個

address

 

  • #address-cells,用來描述子節點"reg"屬性的地址表中用來描述首地址的cell的數量
  • #size-cells,用來描述子節點"reg"屬性的地址表中用來描述地址長度的cell的數量

有了這兩個屬性,子節點中的"reg"就可以描述一塊連續的地址區域。下例中,父節點中指定了#address-cells = <2>;#size-cells = <1>,則子節點dev-bootscs0中的reg中的前兩個數表示一個地址,即MBUS_ID(0xf0, 0x01)0x1045C,最后一個數的表示地址跨度,即是0x4

 

interrupts

  • interrupt-controller 一個空屬性用來聲明這個node接收中斷信號,即這個node是一個中斷控制器。
  • #interrupt-cells,是中斷控制器節點的屬性,用來標識這個控制器需要幾個單位做中斷描述符,用來描述子節點中"interrupts"屬性使用了父節點中的interrupts屬性的具體的哪個值。一般,如果父節點的該屬性的值是3,則子節點的interrupts一個cell的三個32bits整數值分別為:<中斷域 中斷 觸發方式>,如果父節點的該屬性是2,則是<中斷 觸發方式>
  • interrupt-parent,標識此設備節點屬於哪一個中斷控制器,如果沒有設置這個屬性,會自動依附父節點的
  • interrupts,一個中斷標識符列表,表示每一個中斷輸出信號

 


免責聲明!

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



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