从Linus Torvalds一封发飙的电邮开始谈设备树究竟是棵什么树?
[導讀] 新版的U-Boot以及內核都引入了設備樹,那么這究竟是棵什么樣的樹呢?長啥樣?有啥用?為啥弄個這樣的樹?本文基于對設備樹標準的理解,來學習整理一下相關的要點,供大家參考。
Linux為啥要設備樹?
在Linux3.x之前的內核源碼中,存在大量對板級細節(jié)信息描述的代碼。這些代碼充斥在/arch/arm/plat-xxx和/arch/arm/mach-xxx目錄,而且更嚴重的問題是,由于ARM商業(yè)生態(tài)模式,基于ARM IP授權模式,產生越來越多ARM核芯片。如此一來這類辣雞代碼越來越多,維護變得愈加困難。于是在2011年3月17這天,Linux之父Linus Torvalds飆了,郵件中罵到:“this whole ARM thing is a f*cking pain in the ass”。
自此之后,Linux內核引入了設備樹機制以描述計算機板機底層硬件信息。
啥是設備樹?
設備樹(device tree)是一種描述特定計算機的硬件組件的數(shù)據(jù)結構,以便操作系統(tǒng)的內核或者引導程序可以使用和管理那些組件,包括一個或多個CPU,內存,總線和外圍設備 。為什么說這個數(shù)據(jù)結構是樹呢?
設備樹是通過Open Firmware項目從基于SPARC的工作站和服務器發(fā)展而來,由https://www.devicetree.org/組織維護,目前的發(fā)展至V0.3版。
來看看設備樹標準中的例子:該圖顯示了一個簡單的設備樹的示例表示,該樹幾乎完整到足以啟動一個簡單的操作系統(tǒng),描述了平臺類型,CPU,內存和1個UART。看這個圖,正是一種樹形數(shù)據(jù)結構。
節(jié)點
設備樹數(shù)據(jù)結構,本質上由一系列帶屬性的節(jié)點組成,節(jié)點由節(jié)點名、單元地址以及屬性組成。描述節(jié)點的語法為:
node-name@unit-addressnode-name 由1到31個ASCII字符描述,字符可取0-9,a-z,A-Z,逗號(,),點(.),加減號(+ -),以及下劃線(_)組成
unit-address:節(jié)點所在的總線類型。
/ :表示樹的根節(jié)點
那么上圖的節(jié)點是哪些呢?移除掉屬性簡化一下:
節(jié)點的單元地址特定于節(jié)點所在的總線類型。單元地址必須與節(jié)點的r一般與reg屬性中指定的第一個地址匹配。如果節(jié)點不具有reg屬性,則必須省略@ unit-address,并且節(jié)點名稱僅會將節(jié)點與樹中同一級別的其他節(jié)點區(qū)分開。特定總線的綁定可以為reg和unit-address的格式指定其他更具體的要求。
節(jié)點名稱,一般按照功能描述進行命令,以提升可讀性,比如:
adc
atm
audio-codec
audio-controller
backlight
bluetooth
bus
.......
路徑名path name
通過指定從根節(jié)點到所有后代節(jié)點到所需節(jié)點的完整路徑,可以唯一標識設備樹中的節(jié)點。按照下述約定進行描述:
/node-name-1/node-name-2/node-name-N比如上圖中CPU1的路徑為:
/cpus/cpu@1屬性語法
屬性用于描述節(jié)點的特征,由屬性名及值組成。
屬性名,可由下表中字符組成:
| 0-9 | 數(shù)字 |
| a-z A-Z | 大小寫字母 |
| , | 逗號 |
| . | 點 |
| _ | 下劃線 |
| + - | 加減號 |
| ? | 問號 |
| # | #字符 |
值
<empty> 空,無值
<u32> <u64> ,大端16進制數(shù),所謂大端模式就是高字節(jié)存在低地址
<string> 以'\0'字符串結尾的字符串
<phandle> 引用設備樹中另一個節(jié)點的方法。見標準屬性中舉例。
<stringlist> ?字符串表
標準屬性
compatible, 其值為<stringlist>,兼容的屬性值包含一個或多個字符串,這些字符串定義了設備的編程模型。使用此字符串列表選擇設備驅動程序。該屬性值由具有空終止字符串的串聯(lián)列表組成。它們使設備可以表達與一系列類似設備的兼容性,從而可能使單個設備驅動程序與多個設備匹配。比如
model, <string> 其值為字符串,用于指定設備制造商的型號。如上例中的mpc8641/ns16550
phandle,<u32>phandle屬性為設備樹內唯一的節(jié)點指定一個數(shù)字標識符。phandle屬性值由其他需要引用與該屬性關聯(lián)的節(jié)點的節(jié)點使用。比如:
定義的phandle值為1。另一個設備節(jié)點可以使用一個phandle值1引用pic節(jié)點:
another-device-node?{interrupt-parent?=?<1>; };status,<string> status屬性指示設備的運行狀態(tài)。取值范圍定義如下表:
| "okay" | 表示設備使能正運行 |
| "disabled" | 表示該設備目前禁用,但將來可能會使能 |
| "reserved" | 表示該設備正在運行,但不應使用。 |
| "fail" | 表示設備無法運行。發(fā)現(xiàn)了一個嚴重的錯誤,不進行修理就不可工作。 |
| "fail-sss" | 與fail的區(qū)別是sss字段表示檢測到的錯誤 |
#address-cells 及 #size-cells,可以在設備樹層次結構中具有子節(jié)點的任何設備節(jié)點中使用#address-cells和#size-cells屬性,它們描述如何尋址子設備節(jié)點。
#address-cells屬性指示在reg屬性中需要多少個單元(即32位值)來形成address字段。
#size-cells屬性定義子節(jié)點的reg屬性中size字段需要多少個單元(即32位值)
reg, <prop-encoded-array>, ( address , length ) 對。
virtual-reg,<u32> virtual-reg屬性指定一個有效地址,該地址映射到設備節(jié)點的reg屬性中指定的第一個物理地址。此屬性使引導程序可以為客戶端程序提供已設置的虛擬到物理的映射。
ranges,<empty> 或 <prop-encoded-array>任意數(shù)量的(child-bus-address,parent-bus-address,length)三元組。ranges屬性提供了一種定義總線的地址空間(子地址空間)和總線節(jié)點的父節(jié)點的地址空間(父地址空間)之間的映射或轉換的方法。
其中:
<0x0?0xe0000000?0x00100000>;此屬性值指定對于1024 KB的地址空間范圍,以物理0x0尋址的子節(jié)點映射到物理0xe0000000的父地址。通過這種映射,可以通過地址為0xe0004600的加載或存儲,偏移量0x4600(在reg中指定)和在range中指定的0xe0000000映射來尋址串行設備節(jié)點。
dma-ranges,<empty>或<prop-encoded-array>形式的任意數(shù)量的(child-bus-address,parent-bus-address,length)三元組。dma-ranges屬性用于描述內存映射總線的直接內存訪問(DMA)結構,該總線可以從源于該總線的DMA操作訪問其設備樹父對象。它提供了一種定義總線的物理地址空間和總線父級的物理地址空間之間的映射或轉換的方法。
child-bus-address是子總線地址空間內的物理地址。表示地址的寬度取決于總線,并且可以從此節(jié)點(出現(xiàn)dma-ranges屬性的節(jié)點)的#address-cells中確定。
parent-bus-address是父總線地址空間內的物理地址。代表父級地址的cell數(shù)量取決于總線,可以從定義父級地址空間的節(jié)點的#address-cells屬性中確定。
length指定了子地址空間中范圍的大小。可以從節(jié)點(定義了dma-ranges屬性的節(jié)點)的size-cells來確定表示大小的cell數(shù)。
總結一下
本文總結了Linux設備樹出現(xiàn)的緣由,以及設備樹節(jié)點常規(guī)概念:節(jié)點、屬性,以及標準屬性。設備樹還有中斷以及中斷映射、設備綁定、二進制格式等概念,后續(xù)有時間在學習整理。
辛苦原創(chuàng),如喜歡請點贊/在看/分享,不勝感激!
推薦閱讀:
? ??專輯|Linux文章匯總
? ??專輯|程序人生
? ??專輯|C語言
嵌入式Linux
微信掃描二維碼,關注我的公眾號?
總結
以上是生活随笔為你收集整理的从Linus Torvalds一封发飙的电邮开始谈设备树究竟是棵什么树?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Unity 渲染管线总结
- 下一篇: 安卓9.0马达框架分析