訂閱
糾錯(cuò)
加入自媒體

Linux設(shè)備驅(qū)動(dòng)統(tǒng)一模型解析

1. 設(shè)備樹概念

 1.1.設(shè)備樹感性認(rèn)識(shí)

設(shè)備樹(Device Tree),將這個(gè)詞分開就是“設(shè)備”和“樹”,描述設(shè)備樹的文件叫做DTS(Device Tree Source),這個(gè)DTS 文件采用樹形結(jié)構(gòu)描述板級(jí)設(shè)備,比如CPU 數(shù)量、 內(nèi)存基地址、IIC 接口上接了哪些設(shè)備、SPI 接口上接了哪些設(shè)備等等。設(shè)備樹是樹形數(shù)據(jù)結(jié)構(gòu),具有描述系統(tǒng)中設(shè)備的節(jié)點(diǎn)。每個(gè)節(jié)點(diǎn)都有描述所代表設(shè)備特征的鍵值對(duì)。每個(gè)節(jié)點(diǎn)只有一個(gè)父節(jié)點(diǎn),而根節(jié)點(diǎn)則沒有父節(jié)點(diǎn)。

1.2.DTS、DTB、DTC

DTS:設(shè)備樹源碼文件;DTB:將DTS編譯后得到的二進(jìn)制文件;DTC:DTS的編譯工具,其源碼在內(nèi)核的scriptsdtc目錄下;谕瑯觓rm架構(gòu)的CPU有很多,同一個(gè)CPU會(huì)制作很多配置不一的板子,如何正確的編譯所選的板子的DTS文件呢?在內(nèi)核的arch/arm/boot/dts/Makefile中:

dtb-$(CONFIG_ARCH_XXX) += xxx.dtb
dtb-$(CONFIG_ARCH_XXX) += xxx-sip.dtb
dtb-$(CONFIG_ARCH_XXX) += xxx.dtb
dtb-$(CONFIG_ARCH_XXX) += xxx.dtb

例如xxxx的開發(fā)板,只要設(shè)置CONFIG_ARCH_xxx=y(tǒng),所有用到這顆SOC的DTS都會(huì)編譯成DTB。如果后續(xù)還用到了這顆SOC設(shè)計(jì)的開發(fā)板,只要新建一個(gè)DTS文件,并將對(duì)應(yīng)名稱的DTB文件名加到dtb-$(CONFIG_ARCH_xxx)中,在編譯設(shè)備樹時(shí)就會(huì)將DTS編譯為二進(jìn)制的DTB文件。

1.3.Device Tree語法

以下語法分析均以xxx.dts為例。

1.3.1. dtsi頭文件

設(shè)備樹的頭文件擴(kuò)展名為 .dtsi。以xxx.dts為例,其包含以下頭文件。

#include "skeleton.dtsi"
#include xxx.h"
#include "xxx-clocks.dtsi"
#include "xxx-pinctrl.dtsi"
#include "xxx-camera.dtsi"

需要注意的是.dts文件不但可以引用.dtsi文件,還可以引用.h文件和其他的.dts文件。Q1:每一個(gè).dtsi和.dts都有自己的根節(jié)點(diǎn),但是一個(gè)設(shè)備樹文件只允許有一個(gè)根節(jié)點(diǎn),DTC如何處理?將根節(jié)點(diǎn)合并,保留最后一級(jí)的根節(jié)點(diǎn)。包含的頭文件內(nèi)容會(huì)被展開,展開的位置在/memory和/cpus之間。(存疑,只用xxx.dts編譯過)Q2:如果包含過程中有重復(fù)的compatible,DTC怎么處理?編譯時(shí)不會(huì)報(bào)錯(cuò),會(huì)生成兩個(gè)compatible屬性一樣的節(jié)點(diǎn)。

1.3.2. 設(shè)備節(jié)點(diǎn)

設(shè)備樹中的每一個(gè)節(jié)點(diǎn)都按照以下格式命名:

node-name@unit-address

node-name表示節(jié)點(diǎn)名稱,它的長(zhǎng)度范圍應(yīng)該是1~31個(gè)字符,可以由以下的字符組成:

字符說明0~9數(shù)字a-z小寫字母A-Z大寫字母,逗號(hào)(英文).句號(hào)(英文)_下劃線(英文)+加號(hào)-減號(hào)

表 2-1節(jié)點(diǎn)名稱的有效字符

節(jié)點(diǎn)名稱應(yīng)以較低或大寫字符開頭,并應(yīng)描述設(shè)備的一般類別。節(jié)點(diǎn)的單位地址特定于節(jié)點(diǎn)所在的總線類型。它由表2-1中字符集中的一個(gè)或多個(gè)ASCII字符組成。單位地址必須與節(jié)點(diǎn)的reg屬性中指定的第一個(gè)地址匹配。如果節(jié)點(diǎn)沒有reg屬性,則必須省略@unit-address,并且單獨(dú)使用節(jié)點(diǎn)名稱將節(jié)點(diǎn)與樹中相同級(jí)別的其他節(jié)點(diǎn)區(qū)分開來。對(duì)于reg格式和單位地址,特定總線的綁定可能會(huì)指定附加更具體的要求。根節(jié)點(diǎn)沒有節(jié)點(diǎn)名稱或單位地址。它由正斜杠(/)標(biāo)識(shí)。

圖 2-1節(jié)點(diǎn)名稱示例

在圖2-1中,節(jié)點(diǎn)名稱為cpu的兩個(gè)節(jié)點(diǎn)通過uint-address 0和1區(qū)分;節(jié)點(diǎn)名稱為ethernet的兩個(gè)節(jié)點(diǎn)通過uint-address fe002000和fe003000區(qū)分。在設(shè)備樹中經(jīng)常會(huì)看到以下設(shè)備名稱:

watchdog: watchdog@04009800

冒號(hào)前的是節(jié)點(diǎn)標(biāo)簽(label),冒號(hào)后是節(jié)點(diǎn)名稱。引入label的目的是方便訪問節(jié)點(diǎn),可以直接通過&label來訪問這個(gè)節(jié)點(diǎn)。比如上述節(jié)點(diǎn)就可以使用&watchdog來訪問。

1.3.2.1. 通用名稱建議

節(jié)點(diǎn)的名稱應(yīng)該有些通用,反映設(shè)備的功能,而不是其精確的編程模型。如適用,名稱應(yīng)為以下選擇之一:

? adc    ? accelerometer
? atm    ? audio-codec
? audio-controller ? backlight:
? bluetooth   ? bus
? cache-controller ? camera
? can    ? charger
? clock:   ? clock-controller
? compact-flash  ? cpu
? cpus    ? crypto
? disk    ? display
? dma-controller ? dsp
? eeprom   ? efuse:
? mdio    ? memory
? memory-controller ? mmc
? mmc-slot   ? mouse
? nand-controller ? nvram
? oscillator  ? parallel
? pc-card   ? pci
? pcie    ? phy
? pinctrl   ? pmic
? pmu    ? port
? ports    ? pwm
1.3.2.2. 路徑名稱

通過指定從根節(jié)點(diǎn)到所需節(jié)點(diǎn)的完整路徑(通過所有子節(jié)點(diǎn)),可以唯一識(shí)別devicetree中的節(jié)點(diǎn)。指定設(shè)備路徑的約定是:

/node-name-1/node-name-2/.../node-name-N

例如,在圖2-1中,到cpu#1的設(shè)備路徑為:

/cpus/cpu@1

/為根節(jié)點(diǎn),在保證完整路徑明確的前提下,可以省略u(píng)int-address。

1.3.3. 屬性

設(shè)備樹中的每個(gè)節(jié)點(diǎn)都有描述節(jié)點(diǎn)特性的屬性。屬性由名稱和值組成。

1.3.3.1. 屬性名稱

屬性名稱的長(zhǎng)度范圍應(yīng)該是1~31個(gè)字符,可以由以下的字符組成:

字符說明0~9數(shù)字a-z小寫字母A-Z大寫字母,逗號(hào)(英文).句號(hào)(英文)_下劃線(英文)+加號(hào)?問號(hào)(英文)##號(hào)(hash)

非標(biāo)準(zhǔn)屬性名稱應(yīng)指定唯一的字符串前綴,例如股票代號(hào),用于標(biāo)識(shí)定義該屬性的公司或組織的名稱。示例:

xxx,pin-function = <6>;
fsl,channel-fifo-len
 linux,network-index
 ibm,ppc-interrupt-server#s
1.3.3.2. 屬性值

屬性值是包含與屬性關(guān)聯(lián)的信息的零或多個(gè)字節(jié)的數(shù)組。

數(shù)值描述、值為空,用于描述bool信息。個(gè)人理解類似于flag參數(shù)、32位整數(shù),采用big-endian格式。示例:32位值0x11223344將在內(nèi)存中表示為:地址    11  地址 + 1 22  地址 + 2 33   地址 + 3 44、表示采用big-endian格式的64位整數(shù)。包括兩個(gè)值,其中第一個(gè)值包含整數(shù)的最有效位,第二個(gè)值包含最小有效位。例如:64位值0x1122334455667788將表示為兩個(gè)單元格:<0x11223344 0x55667788>。、格式特定于屬性,參見屬性定義。、字符串可打印且以空值()結(jié)尾。、一個(gè)值。phandle值是引用設(shè)備樹中另一個(gè)節(jié)點(diǎn)的方法。可被引用的任何節(jié)點(diǎn)都用唯一的定義了phandle屬性數(shù)值。該數(shù)字用于帶有phandle值類型的屬性值。、串聯(lián)在一起的值列表。

big-endian和little-endian(大小端):big-endian:是指低地址端存放高位字節(jié);little-endian:是指高地址端存放低位字節(jié);

1.3.3.3. 標(biāo)準(zhǔn)屬性Compatible(兼容)屬性名稱兼容值值類型<stringlist>描述兼容屬性值由定義設(shè)備特定編程模型的一個(gè)或多個(gè)字符串組成。客戶端程序應(yīng)使用此字符串列表選擇設(shè)備驅(qū)動(dòng)程序。該屬性值包含一個(gè)從最特定到最通用的null終止字符串的串聯(lián)列表。它們?cè)试S設(shè)備表達(dá)其與一系列類似設(shè)備的兼容性,可能允許單個(gè)設(shè)備驅(qū)動(dòng)器與幾個(gè)設(shè)備匹配。推薦的格式是“制造商,型號(hào)”,其中制造商是描述制造商名稱的字符串(如股票代號(hào))。

示例:

compatible =“fsl,mpc8641”,“ns16550”;

在此示例中,操作系統(tǒng)將首先嘗試查找支持fsl,mpc8641-uartmpc8641的設(shè)備驅(qū)動(dòng)程序。如果找不到驅(qū)動(dòng)程序,然后,它將嘗試定位受支持的更通用的ns16550設(shè)備類型驅(qū)動(dòng)程序 。

一般驅(qū)動(dòng)程序文件都會(huì)有個(gè)OF匹配表,此匹配表保存著一些compatible值,如果設(shè)備節(jié)點(diǎn)的 compatible屬性值和OF匹配表中的任何一個(gè)值相等,那么就表示設(shè)備可以使用這驅(qū)動(dòng)。比如在文件drvier/misc/memctrl.c中:

static struct of_device_id_xxx_memctrl_of_match[] = {
    { .compatible = "xxxx,memctrl", },
    {},
};

對(duì)應(yīng)的,在arch/arm/boot/dts/xxx.dts中有:

memctrl: memctrl {
  compatible = "xxxx,memctrl";
  reg = <0x0121B000 0x1044>;
  clocks = <&sdram_bandw_clk>, <&mem_axi_clk>;
  clock-names = "sdram_bandwidth_clk", "mem_axi_clk";
  interrupts = <GIC_SPI INT_SDRAM IRQ_TYPE_LEVEL_HIGH>;
  interrupt-controller;
  #interrupt-cells = <1>;
};
Model(型號(hào))屬性名稱模型值值類型
描述指定設(shè)備的制造商型號(hào)。推薦的格式為:“制造商,型號(hào)”,其中制造商是描述制造商名稱的字符串(如股票代號(hào))。

示例:

model =“fsl,MPC8349EMITX”;
Phandle(pointer handle)屬性名稱pointer handle值值類型
描述phandle屬性指定設(shè)備樹中唯一節(jié)點(diǎn)的數(shù)字標(biāo)識(shí)符。phandle屬性值被需要引用與該屬性關(guān)聯(lián)的節(jié)點(diǎn)的其他節(jié)點(diǎn)使用。

示例:

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

定義了1的phandle值。另一個(gè)設(shè)備節(jié)點(diǎn)可以引用phandle值為1的pic節(jié)點(diǎn):

another-device-node {
interrupt-parent = <1>;
};
Status屬性名稱狀態(tài)值值類型<string>描述狀態(tài)屬性指示設(shè)備的操作狀態(tài),其有效值如下:"okay":指示設(shè)備可運(yùn)行。"disabled":表明設(shè)備目前尚未運(yùn)行,但未來可能會(huì)運(yùn)行(例如,未插入或關(guān)閉某物)。"fail":表示設(shè)備無法運(yùn)行,在設(shè)備中檢測(cè)到嚴(yán)重錯(cuò)誤,如果不進(jìn)行維修就不太可能運(yùn)行"fail-sss":表示設(shè)備無法運(yùn)行,在設(shè)備中檢測(cè)到嚴(yán)重錯(cuò)誤,如果不進(jìn)行維修就不太可能運(yùn)行,sss部分特定于設(shè)備,并指示檢測(cè)到的錯(cuò)誤情況。#address-cells and #size-cells屬性名稱#address-cells,#size-cells值類型<u32>描述#address-cells和#size-cells屬性可用于設(shè)備樹層次結(jié)構(gòu)中包含子節(jié)點(diǎn)并描述如何解決子設(shè)備節(jié)點(diǎn)的任何設(shè)備節(jié)點(diǎn)。#address-cells屬性定義用于編碼子節(jié)點(diǎn)的reg屬性中地址字段的個(gè)單元格的數(shù)量。#size-cells屬性定義用于編碼子節(jié)點(diǎn)的reg屬性中大小字段的個(gè)單元格的數(shù)量。#address-cells = <1>;
 #size-cells = <0>;

表示reg屬性中有一個(gè)u32表示address,沒有表示reg大小的數(shù)據(jù),所以:reg = <0x0>; 即reg的起始地址為0x0,不描述其大小

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

表示reg屬性中有一個(gè)u32表示address,有一個(gè)u32表示size,所以:reg = <0x00000000 0x00040000>; 即reg的起始地址為0x00000000,大小是0x00040000

Reg屬性名稱reg值類型<prop-encoded-array> 編碼為任意數(shù)量(地址、長(zhǎng)度)對(duì)描述reg屬性描述設(shè)備資源在其父總線定義的地址空間內(nèi)的地址。這通常意味著內(nèi)存映射IO寄存器塊的偏移和長(zhǎng)度,但在某些總線類型上可能有不同的含義。根節(jié)點(diǎn)定義的地址空間中的地址為cpu真實(shí)地址。該值是一個(gè),由任意數(shù)量的地址和長(zhǎng)度對(duì)組成,<地址長(zhǎng)度>。指定地址和長(zhǎng)度所需的單元格的數(shù)量是總線特定的,由設(shè)備節(jié)點(diǎn)父級(jí)中的#address-cells和#size-cells屬性指定。如果父節(jié)點(diǎn)為#size-cells單元格指定值0,則應(yīng)忽略reg值中的長(zhǎng)度字段。

示例:假設(shè)系統(tǒng)芯片中的設(shè)備包含兩個(gè)寄存器塊,SOC中偏移0x3000的32字節(jié)塊和偏移0xFE00的256字節(jié)塊。reg屬性的編碼如下(假設(shè)#address-cells和#size-cells值為1):

reg=<0x3000 0x20 0xFE00 0x100>;
virtual-reg屬性名稱virtual-reg值類型<u32>描述virtual-reg屬性指定一個(gè)有效地址,該地址映射到設(shè)備節(jié)點(diǎn)的reg屬性中指定的第一個(gè)物理地址。此屬性使引導(dǎo)程序能夠?yàn)榭蛻舳顺绦蛱峁┮言O(shè)置的虛擬到物理映射。Ranges屬性名稱range值類型<empty>或編碼為任意數(shù)量的(子總線地址、父總線地址、長(zhǎng)度)三聯(lián)體描述range屬性提供了一種在總線地址空間(子地址空間)和總線節(jié)點(diǎn)父地址空間(父地址空間)之間定義映射或轉(zhuǎn)換的方法。range屬性值的格式是任意數(shù)量的三聯(lián)體(子總線地址、父總線地址、長(zhǎng)度):1.子總線地址是子總線地址空間內(nèi)的物理地址。表示地址的單元格數(shù)取決于總線,可以通過此節(jié)點(diǎn)(出現(xiàn)range屬性的節(jié)點(diǎn))的#address-cells確定。2. 父總線地址是父總線地址空間中的物理地址。表示父地址的單元格數(shù)取決于總線,可以通過定義父地址空間的節(jié)點(diǎn)的#address-cells屬性確定。3. 長(zhǎng)度指定子地址空間中范圍的大小。表示大小的單元格數(shù)可以根據(jù)該節(jié)點(diǎn)(出現(xiàn)range屬性的節(jié)點(diǎn))的#size-cells確定。如果屬性用值定義,則它指定父地址和子地址空間相同,并且不需要地址轉(zhuǎn)換。如果總線節(jié)點(diǎn)中不存在該屬性,則假設(shè)節(jié)點(diǎn)的子節(jié)點(diǎn)和父地址空間之間不存在映射。

示例:

soc {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0xe0000000 0x00100000>;
serial {
 device_type = "serial";
 compatible = "ns16550";
 reg = <0x4600 0x100>;
 clock-frequency = <0>;
 interrupts = <0xA 0x8>;
 interrupt-parent = <&ipic>;
};
};

1  2  3  下一頁>  
聲明: 本文由入駐維科號(hào)的作者撰寫,觀點(diǎn)僅代表作者本人,不代表OFweek立場(chǎng)。如有侵權(quán)或其他問題,請(qǐng)聯(lián)系舉報(bào)。

發(fā)表評(píng)論

0條評(píng)論,0人參與

請(qǐng)輸入評(píng)論內(nèi)容...

請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字

您提交的評(píng)論過于頻繁,請(qǐng)輸入驗(yàn)證碼繼續(xù)

  • 看不清,點(diǎn)擊換一張  刷新

暫無評(píng)論

暫無評(píng)論

人工智能 獵頭職位 更多
掃碼關(guān)注公眾號(hào)
OFweek人工智能網(wǎng)
獲取更多精彩內(nèi)容
文章糾錯(cuò)
x
*文字標(biāo)題:
*糾錯(cuò)內(nèi)容:
聯(lián)系郵箱:
*驗(yàn) 證 碼:

粵公網(wǎng)安備 44030502002758號(hào)