正点原子----Linux设备树详解
linux設(shè)備樹
- 1、什么是設(shè)備樹
- 2、DTS、DTB、DTC的關(guān)系
- 3、如何編譯設(shè)備樹
- 4、DTS基本結(jié)構(gòu)
- 4.1、語(yǔ)法
- 4.2、設(shè)備樹在系統(tǒng)中的體現(xiàn)
- 4.3、嘗試自己添加節(jié)點(diǎn)
- 4.4、嘗試對(duì)根節(jié)點(diǎn)追加信息
- 5、設(shè)備樹特殊節(jié)點(diǎn)
- 5.1、chosen子節(jié)點(diǎn)
- 5.2、aliases子節(jié)點(diǎn)
- 6、設(shè)備樹中標(biāo)準(zhǔn)屬性
- 6.1、compatilbe屬性
- 6.2、model屬性
- 6.3、status屬性
- 6.4、reg屬性
- 6.5、#address-cells和#size-cells
- 7、OF操作函數(shù)
- 7.1、OF函數(shù)查找節(jié)點(diǎn)
- ① of_find_node_by_name
- ② of_find_compatible_node
- ③ of_find_node_by_path
- 7.2、查找父子節(jié)點(diǎn)的OF函數(shù)
- ① of_get_parent
- ② of_get_next_child
- 7.3、提取屬性值的OF函數(shù)
- ① of_find_property
- ② of_property_read_u32_index
- ③ of_property_read_u8_array
- ④ of_property_read_u8
1、什么是設(shè)備樹
????????
????????設(shè)備樹DTS(Device Tree Source),DTS文件用樹形結(jié)構(gòu)描述板級(jí)設(shè)備,也就是開發(fā)板上的設(shè)備信息,比如CPU數(shù)量,內(nèi)存基地址,IIC接口上接了哪些設(shè)備等等,如下圖:
2、DTS、DTB、DTC的關(guān)系
????????1、DTS是設(shè)備樹的源文件
????????2、DTB是DTS編譯后得到的二進(jìn)制文件
????????3、DTC是DTS的編譯工具,源碼在內(nèi)核的scripts/dtc目錄下面,如下:
3、如何編譯設(shè)備樹
????????1、make dtbs:編譯所有的dts文件;
????????2、make xxx.dts:編譯指定的dts文件按;
4、DTS基本結(jié)構(gòu)
????????設(shè)備樹也有頭文件,擴(kuò)展名為.dtsi
4.1、語(yǔ)法
????????1、根節(jié)點(diǎn):/
????????2、從/根節(jié)點(diǎn)開始描述設(shè)備信息
????????3、在/根節(jié)點(diǎn)外有一些&cpu0這樣的語(yǔ)句是“追加”
????????這里以imx6ull-alientek-emmc.dts為例,下圖chosen,memor為子節(jié)點(diǎn)
????????4、節(jié)點(diǎn)名字完整的要求:node-name@unit-address,例如:
i2c4: i2c@021f8000 {#address-cells = <1>;#size-cells = <0>;compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";reg = <0x021f8000 0x4000>;interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;clocks = <&clks IMX6UL_CLK_I2C4>;status = "disabled";};????????后面0x021f8000為i2c4的起始地址。
????????5、還可以為節(jié)點(diǎn)加標(biāo)簽,在設(shè)備樹也是很常見的,例如:
????????lable:node-name@unit-address
????????lable為標(biāo)簽,后面node-name是名字。加lable的目的是為了后面訪問追加時(shí)方便。
4.2、設(shè)備樹在系統(tǒng)中的體現(xiàn)
????????1、系統(tǒng)啟動(dòng)以后可以在根文件系統(tǒng)里面可以看到設(shè)備樹節(jié)點(diǎn)信息,在/proc/device-tree/目錄下存放著設(shè)備樹信息,一級(jí)子節(jié)點(diǎn)。一級(jí)子節(jié)點(diǎn)內(nèi)還有二級(jí)子節(jié)點(diǎn)。
4.3、嘗試自己添加節(jié)點(diǎn)
????????1、在imx6ull-alientek-emmc.dts根節(jié)點(diǎn)下添加如下內(nèi)容
????????2、make dtbs編譯,拷貝到tftp目錄下,重啟開發(fā)板,進(jìn)入到/proc/device-tree目錄下即可看到添加的節(jié)點(diǎn)
4.4、嘗試對(duì)根節(jié)點(diǎn)追加信息
????????1、添加之前intc節(jié)點(diǎn)目錄內(nèi)容如下:
????????2、在imx6ull-alientek-emmc.dts下加入如下內(nèi)容
????????3、編譯、拷貝、重啟開發(fā)板,追加節(jié)點(diǎn)信息如下:
5、設(shè)備樹特殊節(jié)點(diǎn)
5.1、chosen子節(jié)點(diǎn)
????????1、chosen并不是一個(gè)真實(shí)的節(jié)點(diǎn),主要目的是將uboot里面的bootargs環(huán)境變量傳遞給linux內(nèi)核,作為命令行參數(shù)。
????????uboot里面的bootargs為:
????????kernel中bootargs為:
????????2、經(jīng)過查看chosen節(jié)點(diǎn)中包含bootargs屬性,但是我們?cè)谠O(shè)備樹里面并沒有設(shè)置bootargs。
????????3、這是因?yàn)樵趗boot過程中fdt_chosen函數(shù)會(huì)將bootargs傳給內(nèi)核,在uboot源碼中common/fdt_support.c文件內(nèi),如下:
5.2、aliases子節(jié)點(diǎn)
????????aliaese的意思是 “別名” ,給節(jié)點(diǎn)起另一個(gè)名字。
6、設(shè)備樹中標(biāo)準(zhǔn)屬性
6.1、compatilbe屬性
????????1、copatible屬性叫做兼容性,值是一個(gè)字符串列表,compatible屬性用來將設(shè)備和驅(qū)動(dòng)綁定起來,其格式一般為“manufacturer,model”。
????????2、在驅(qū)動(dòng)中of_device_id機(jī)構(gòu)提匹配表,保存著一些compatible值,如果設(shè)備節(jié)點(diǎn)的compatible屬性值和of匹配表中的任何一個(gè)值相等,就會(huì)調(diào)用probe函數(shù)。
6.2、model屬性
????????model屬性值也是一個(gè)字符串,描述設(shè)備模塊信息,比如名字:
model = "wm8960-audio";6.3、status屬性
狀態(tài)
????????okay:表示設(shè)備可操作
????????disable:表示設(shè)備不可操作
6.4、reg屬性
????????reg屬性值一般是(address,length),描述設(shè)備地址空間資源,一般都是某個(gè)外設(shè)的寄存器地址范圍信息,如:
uart1: serial@02020000 {compatible = "fsl,imx6ul-uart","fsl,imx6q-uart", "fsl,imx21-uart";reg = <0x02020000 0x4000>;interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;clocks = <&clks IMX6UL_CLK_UART1_IPG>,<&clks IMX6UL_CLK_UART1_SERIAL>;clock-names = "ipg", "per";status = "disabled"; };6.5、#address-cells和#size-cells
????????1、這兩個(gè)屬性值都是無符號(hào)32位整形。address-cells屬性絕對(duì)了子節(jié)點(diǎn)reg屬性中地址信息所占用的字長(zhǎng),size-cells屬性值決定了子節(jié)點(diǎn)reg屬性中長(zhǎng)度信息所占用的字長(zhǎng)。如:
spi4 {compatible = "spi-gpio";#address-cells = <1>;#size-cells = <0>;gpio_spi: gpio_spi@0 {compatible = "fairchild,74hc595";reg = <0>;}; };aips3: aips-bus@02200000 {compatible = "fsl,aips-bus", "simple-bus";#address-cells = <1>;#size-cells = <1>;dcp: dcp@02280000 {compatible = "fsl,imx6sl-dcp";reg = <0x02280000 0x4000>;}; };????????2、spi4的address=1,size=1,說明spi4的子節(jié)點(diǎn)reg屬性中起始地址所占用字長(zhǎng)為1,地址長(zhǎng)度所占用字長(zhǎng)位0
????????3、gpio_spi: gpio_spi@0節(jié)點(diǎn)中的reg屬性:reg = <0>,是因?yàn)楦腹?jié)點(diǎn)設(shè)置了address=1,size=0。
????????aips3也同樣理解。
7、OF操作函數(shù)
????????1、在驅(qū)動(dòng)中使用OF函數(shù)獲取設(shè)備屬性內(nèi)容。設(shè)備都是以節(jié)點(diǎn)的形式掛到設(shè)備樹上,因此要想獲取這個(gè)設(shè)備的其他屬性信息,必須先獲取節(jié)點(diǎn)。
????????2、Linux內(nèi)核使用device_node結(jié)構(gòu)體來描述一個(gè)節(jié)點(diǎn),此結(jié)構(gòu)體定義在include/linux/of.h中。
7.1、OF函數(shù)查找節(jié)點(diǎn)
① of_find_node_by_name
struct device_node *of_find_node_by_name(struct device_node *from,const char *name);參數(shù):
????????1、form:開始查找的節(jié)點(diǎn),如果為NULL表示從根節(jié)點(diǎn)開始查找整個(gè)設(shè)備樹name:要查找的節(jié)點(diǎn)名字
????????2、返回值:找到的節(jié)點(diǎn),如果為NULL表示查找失敗
② of_find_compatible_node
參數(shù):
????????1、from:開始查找的節(jié)點(diǎn),如果為 NULL 表示從根節(jié)點(diǎn)開始查找整個(gè)設(shè)備樹。
????????2、type:要查找的節(jié)點(diǎn)對(duì)應(yīng)的 type 字符串,也就是 device_type 屬性值,可以為 NULL,表示忽略掉 device_type 屬性。
????????3、compatible: 要查找的節(jié)點(diǎn)所對(duì)應(yīng)的 compatible 屬性列表。
????????4、返回值: 找到的節(jié)點(diǎn),如果為 NULL 表示查找失敗
③ of_find_node_by_path
參數(shù):
????????1、path:帶有全路徑的節(jié)點(diǎn)名,可以使用節(jié)點(diǎn)的別名,比如“/backlight”就是 backlight 這個(gè)節(jié)點(diǎn)的全路徑。
????????2、返回值: 找到的節(jié)點(diǎn),如果為 NULL 表示查找失敗
7.2、查找父子節(jié)點(diǎn)的OF函數(shù)
????????參數(shù)就不介紹了,使用較少。
① of_get_parent
② of_get_next_child
7.3、提取屬性值的OF函數(shù)
????????節(jié)點(diǎn)的屬性信息里面保存了驅(qū)動(dòng)所需要的內(nèi)容,Linux內(nèi)核中使用結(jié)構(gòu)體property表示屬性,此結(jié)構(gòu)體定義在of.h文件中,如下:
struct property {char *name; /* 屬性名字 */int length; /* 屬性長(zhǎng)度 */void *value; /* 屬性值 */struct property *next; /* 下一個(gè)屬性 */unsigned long _flags;unsigned int unique_id;struct bin_attribute attr; };① of_find_property
????????該函數(shù)用于查找指定的屬性,函數(shù)原型:
property *of_find_property(const struct device_node *np,const char *name,int *lenp)參數(shù)介紹:
????????1、np:設(shè)備節(jié)點(diǎn)
????????2、name:屬性名字
????????3、lenp:屬性值的字節(jié)數(shù)
????????4、返回值:找到的屬性
② of_property_read_u32_index
????????從屬性中獲取指定標(biāo)號(hào)的u32類型數(shù)據(jù)值,函數(shù)原型如下:
int of_property_read_u32_index(const struct device_node *np,const char *propname,u32 index,u32 *out_value)③ of_property_read_u8_array
????????讀取屬性中u8類型的數(shù)組數(shù)據(jù),也可以讀u16、u32、u64類型的,函數(shù)原型如下:
int of_property_read_u8_array(const struct device_node *np,const char *propname,u8 *out_values,size_t sz)④ of_property_read_u8
????????讀取之后一個(gè)整形值的屬性,函數(shù)原型如下:
int of_property_read_u8(const struct device_node *np,const char *propname,u8 *out_value)下篇使用OF函數(shù)獲取設(shè)備樹節(jié)點(diǎn)信息。
總結(jié)
以上是生活随笔為你收集整理的正点原子----Linux设备树详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于S2SH+ExtJS4+Oracle
- 下一篇: 一文速学数模-分类模型(一)SVM(Su