目錄
1.什麼是設備樹?
2.設備樹的結構
3.節點結構
4.節點標準屬性
4.1 compatible
4.2 status
4.3 #address-cells #size-cells
4.4 reg
4.5 name
4.6 device_type
4.7 phandle
4.8 virtul-reg
4.9 range
4.10 dma-range
5.特殊節點
5.1 /aliases node
5.2 /chosen node
6."of_"相關函數
6.1 查找節點
6.1.1 of_find_node_by_name
6.1.2 of_find_node_by_type
6.1.3 of_find_compatible_node
6.1.4 of_find_node_by_path
6.2 提取屬性值
6.2.1 of_find_property
6.2.2 of_property_read_u32_index
6.2.3 of_property_read_u*_array
6.2.4 of_property_read_u*
設備樹被引入的背景就不説了。直接來看設備樹。
1.什麼是設備樹?
設備樹是用一種樹狀的結構和節點,來描述系統中的硬件。每個節點都具有描述被表示的設備的特性的屬性/值等。那麼有幾個概念。
|
DTS
|
設備樹的代碼源文件,可以理解為各開發板,對DTSI各節點的引用定製。
|
|
DTSI
|
同平台更通用的設備樹代碼,可以作為頭文件定義在DTS文件中。
|
|
DTC
|
DTS編譯文件,可以編譯DTS為DTB,也可以將DTB反編譯為DTS
|
|
DTB
|
DTC編譯出來的二進制文件
|
2.設備樹的結構
/dts-v1/;
[memory reservations]
/{
[property defintions]
[child node]
};
|
/dts-v1/;
|
設備樹的版本信息
|
|
[memory reservations]
|
預留的內存空間不被內存使用/分配:/memreserve/<address><lenth>;
|
|
[property defintions]
|
屬性的name和屬性的value:property-name = value;
|
property-name有兩種,一種是用户定義的名字如“led-pins”,一種是固定的名字如“compatible”。
value的取值如下:
|
empty
|
可以為空如:enable-active-high;
|
|
<u32> |
32位數據:tx_delay = <0x30>;
|
|
<u64> |
兩個32位數據:<0x11223344 0x55667788>.
|
|
<string> |
字符串:compatible = "silergy,syr827";
|
|
<prop-encoded-array> |
規定值:status = "okay";
|
|
<phandle> |
phandle值:基本不推薦使用了
|
|
<stringlist> |
多個字符串:“hello”,”world”
|
|
十六進制數
|
local-mac-address = [00 00 12 34 56 78];
or:local-mac-address = [000012345678]; |
|
節點的引用
|
interrupt-parent = < &mpic >;
or:interrupt-parent = < &{/soc/interrupt-controller@40000} >; |
|
沒有<>的節點引用
|
ethernet0 = &EMAC0; 這裏&EMAC0會被展開為節點的全路徑 |
3.節點結構
設備樹只有一個根節點'/',和若干個節點node1,node2....如果這些節點下還有節點如node1下有節點node-a,那麼node-a稱之為子節點,node1為它的父節點。
[label:] node-name[@unit-address] {
[properties definitions]
[child nodes]
};
|
[label:]
|
節點的標識,方便引用
|
|
node-name
|
節點的名字
|
|
[@unit-address]
|
節點內存的起始地址(如果沒有相同名字節點需要區分,可省略)
|
4.節點標準屬性
4.1 compatible
該節點用於匹配platform Driver,當該屬性的名字和platform_drvier中的of_match_table匹配時,則驅動匹配上,會執行probe函數。
例: compatible = "active-semi,act8846";
4.2 status
節點的狀態,可用、禁用等,有錯誤等。
|
value
|
Description
|
|
"okay"
|
設備可用
|
|
"disabled"
|
設備禁用
|
|
"fail"
|
設備出現了錯誤,不可用
|
|
"fail-sss"
|
設備出現了錯誤,錯誤內容為"sss"
|
|
例:
|
status = "okay";
|
4.3 #address-cells #size-cells
|
#address-cells
|
指定子節點中"reg"屬性的地址是由幾個32位數表示
|
|
#size-cells
|
指定子節點中"reg"屬性的地址長度是由幾個32位數表示
|
bus_intmem@ff700000 {
compatible = "mmio-sram";
reg = <0x0 0xff700000 0x0 0x18000>;
#address-cells = <1>; //用1個32位數表示地址
#size-cells = <1>; //用1個32位數表示長度
ranges = <0 0x0 0xff700000 0x18000>;
smp-sram@0 {
compatible = "rockchip,rk3066-smp-sram";
reg = <0x00 0x10>; //這裏就是體現
};
4.4 reg
用來定義地址/寄存器的起始地址和長度,裏面的值由#address-cells #size-cells來指定。
格式:reg = <addr1 lenth1 addr2 lenth2 ...>
4.5 name
不建議使用
4.6 device_type
不建議使用,應該只包含在"cpu"和"memeroy"節點上,但是有些設備也會用該屬性去描述,不知道為什麼
serial@4600 {
device_type = "serial";
compatible = "ns16550";
reg = <0x4600 0x100>;
clock-frequency = <0>;
interrupts = <0xA 0x8>;
interrupt-parent = <&ipic>;
}
4.7 phandle
用來指定該節點是設備樹中唯一的節點,可以被其他節點來使用,進而關聯該節點,現在一般不用了。
pic@10000000 {
phandle = <1>;
interrupt-controller;
};
another-device-node {
interrupt-parent = <1>;
};
4.8 virtul-reg
沒研究
4.9 range
沒研究
4.10 dma-range
沒研究
5.特殊節點
5.1 /aliases node
官方的解釋為該節點在根節點下,可以為其他節點定義一個別名。先來看個例子。
/ {
compatible = "rockchip,rk3288";
interrupt-parent = <&gic>;
aliases {
ethernet0 = &gmac;
i2c0 = &i2c0;
i2c1 = &i2c1;
i2c2 = &i2c2;
...
...
};
};
上面有講過 property-name = value,當value沒有<>時,會被展開為完整路徑,上面可以通過反編譯看到如"&i2c0"的全路徑,下面是個例子。
aliases {
serial0 = "/simple-bus@fe000000/serial@llc500";
ethernet0 = "/simple-bus@fe000000/ethernet@31c000";
};
在網上看了一些文章,內核會解析該節點,通過展開的node path找到該節點,並將別名的id(也就是I2C0,I2C1後面的數字'0','1')解釋出來,用來註冊驅動和設備。
5.2 /chosen node
系統啓動時所選擇的參數,如nfs掛載點等等。
chosen {
bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200";
};
6."of_"相關函數
6.1 查找節點
6.1.1 of_find_node_by_name
struct device_node *of_find_node_by_name(struct device_node *from, const char *name);
|
功能
|
通過節點名字查找節點
|
|
*from
|
開始查找的節點名字,如果'NULL'則從從根節點查找整個設備樹
|
|
*name
|
要查找的節點名字
|
|
返回值
|
查找到的節點指針
|
6.1.2 of_find_node_by_type
struct device_node *of_find_node_by_type(struct device_node *from, const char *type);
|
功能
|
通過 'device_type' 的值查找節點
|
|
*from
|
開始查找的節點名字,如果'NULL'則從從根節點查找整個設備樹
|
|
*name
|
要查找的 ‘device_type’屬性的value(字符串)
|
|
返回值
|
查找到的節點指針
|
6.1.3 of_find_compatible_node
struct device_node *of_find_compatible_node(struct device_node *from, const char *type, const char *compatible)
|
功能
|
通過 'device_type' 和 'compatible' 兩個屬性的值查找節點,如果device_type為NULL,則忽略這個屬性的從compatible的值查找
|
|
*from
|
開始查找的節點,如果為 NULL表示從根節點開始查找整個設備樹
|
|
*type
|
要查找的節點對應的device_type屬性值,'NULL'代表忽略這個屬性
|
|
*compatible
|
要查找的節點所對應的 compatible屬性值
|
|
返回值
|
查找到的節點指針
|
6.1.4 of_find_node_by_path
struct device_node *of_find_node_by_path(const char *path)
|
功能
|
通過節點的全路徑來查找節點
|
|
*path
|
節點的全路徑
|
|
返回值
|
查找到的節點指針
|
6.2 提取屬性值
6.2.1 of_find_property
property *of_find_property(const struct device_node *np, const char *name, int *lenp)
|
功能
|
查找屬性
|
|
*np
|
節點指針
|
|
*name
|
屬性的名字
|
|
*lenp
|
屬性的value長度
|
|
返回值
|
查找到的節點指針
|
6.2.2 of_property_read_u32_index
int of_property_read_u32_index(const struct device_node *np, const char *propname,
u32 index, u32 *out_value);
|
功能
|
讀取屬性的32位無符號的值
|
|
*np
|
節點指針
|
|
*propname
|
屬性的名字
|
|
index
|
屬性值的index
|
|
*out_value
|
讀取到的值
|
|
返回值
|
0讀取成功,非0讀取失敗
|
opp-microvolt = <1111 2222 3333>; //該屬性的value是3個32位無符號的整形值
如果這時候函數的index為0,那麼讀到的值為'1111'
6.2.3 of_property_read_u*_array
int of_property_read_u8_array(const struct device_node *np,
const char *propname, u8 *out_values, size_t sz);
int of_property_read_u16_array(const struct device_node *np,
const char *propname, u16 *out_values, size_t sz);
int of_property_read_u32_array(const struct device_node *np,
const char *propname,u32 *out_values, size_t sz);
int of_property_read_u64_array(const struct device_node *np,
const char *propname,u32 *out_values, size_t sz);
|
功能
|
屬性值是多個u8(u16,u32,u64)數,可以一次性讀出來
|
|
*np
|
節點指針
|
|
*propname
|
屬性的名字
|
|
*out_values
|
讀取到的數組指針
|
|
sz
|
要讀取的數組成員的數量
|
|
返回值
|
0讀取成功,非0讀取失敗
|
6.2.4 of_property_read_u*
int of_property_read_u8(const struct device_node *np, const char *propname,
u8 *out_value)
int of_property_read_u16(const struct device_node *np, const char *propname,
u16 *out_value)
int of_property_read_u32(const struct device_node *np, const char *propname,
u32 *out_value)
int of_property_read_u64(const struct device_node *np, const char *propname,
u64 *out_value)
|
功能
|
屬性的值只有一個u8(u16,u32,u64)的值,讀取該值
|
|
*np
|
節點指針
|
|
*propname
|
屬性的名字
|
|
*out_values
|
讀取到的值的指針
|
|
返回值
|
0讀取成功,非0讀取失敗
|
|
備註:
|
這些函數完全可以用_array的函數替代,只不過sz變量設置為1就行
|