Android&Linux關於DTS設備樹源碼的介紹
Device tree是一種簡單的節點和屬性的樹形結構。屬性是鍵值對,而節點可能包括屬性和子節點。畫一顆電路板上CPU、總線、設備組成的樹,內核根據這棵樹展開出platform_device、i2c_client、spi_device等設備,並根據節點內容為這些設備分配必要的內存、中斷等資源。
節點語法
節點名稱
無reg屬性 node-name
有reg屬性 node-name[@unit-address]
compatible屬性
指定與driver的對應關系
reg屬性
reg = <address1 [[length1] [address2[length2]]] … >
#address-cells 說明address的字節長度
#size-cells 說明length的字節長度
ranges屬性
用於非內存映射設備(總線設備?),指定如何從一個域名將局部地址轉換到CPU地址域。
external-bus {
#address-cells = <2>
#size-cells = <1>;
ranges = <0 0 0x10100000 0x10000 // Chipselect 1, Ethernet
1 0 0x10160000 0x10000 // Chipselect 2, i2c controller
2 0 0x30000000 0x1000000>; //Chipselect 3, NOR Flash
ethernet@0,0 {
compatible = "smc,smc91c111";
reg = <0 0 0x1000>;
};
i2c@1,0 {
compatible = "acme,a1234-i2c-bus";
#address-cells = <1>;
#size-cells = <0>;
reg = <1 0 0x1000>;
rtc@58 {
compatible = "maxim,ds1338";
reg = <58>;
};
};
flash@2,0 {
compatible = "samsung,k8f1315ebm", "cfi-flash";
reg = <2 0 0x4000000>;
};
};
空ranges屬性的出現表示位於子地址空間的地址被1:1的映射到母地址空間。你也許要問為什么當地址可以被1:1映射的時候還要使用地址轉換。一些總線(如PCI)擁有完全不同的地址空間,而這些地址空間細節需要出現在操作系統。其它則擁有DMA驅動程序,這些程序需要在總線了解真正的地址。有時設備需要被集合,因為他們都分享相同的軟件可編程物理地址映射。
中斷
Interrupt-controller
一個空屬性表明一個節點作為一個接收中斷信號的設備
#interrupt-cell
這是中斷控制器節點的一個屬性。它代表此中斷控制器的interrupt specifier有多少cells
Interrupts
包括interrupt specifier列表設備的一個屬性,設備上每個中斷輸出信號都有一個
DTS關聯關系
linux設備驅動模型三要素:device,driver,bus。Device和driver分別注冊到bus上,然后通過name匹配,最終走到driver的probe函數中。
傳統的ARM Linux定義platform_device和注冊過程都是通過靜態寫在arch/mach下面的文件中,為每一個外設都初始化好一個platform_device,然后在kernel初始化的時候把這些device注冊到platform_bus_type中,然后在后續的driver初始化中再把相應的platform_driver結構體注冊到platform_bus_type中,然后通過name匹配。
現在有了device tree,platform_device不需要靜態定義在c文件中了,而是利用device tree的方法實現了動態生成platform_device。這樣同一個內核就可以在不需要修改內核代碼的情況下根據不同的DTS文件,動態生成針對不同硬件平台的platform_device。
DTS使用
編譯命令 dtc -Idts -O dtb -@ BB-UART1-00A0.dts > BB-UART1-00A0.dtbo
反編譯命令 dtc -I dtb-O dts BB-UART1-00A0.dtbo > BB-UART1-00A0.dts
加載之前,一定記住要把編譯好的dtbo文件放到/lib/firmare/目錄中,否則程序是找不到你的dtbo文件的。