Device Tree中的.dts和dtsi檔案介紹
1. ARM Device Tree起源
Linus Torvalds在2011年3月17日的ARM Linux郵件列表宣稱“this whole ARM thing is a f*cking pain in the ass”,引發ARM Linux社群的地震,隨後ARM社群進行了一系列的重大修正。在過去的ARM Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥著大量的垃圾程式碼,相當多數的程式碼只是在描述板級細節,而這些板級細節對於核心來講,不過是垃圾,如板上的platform裝置、resource、i2c_board_info、spi_board_info以及各種硬體的platform_data。讀者有興趣可以統計下常見的s3c2410、s3c6410等板級目錄,程式碼量在數萬行。社群必須改變這種局面,於是PowerPC等其他體系架構下已經使用的Flattened Device Tree(FDT)進入ARM社群的視野。Device Tree是一種描述硬體的資料結構,它起源於 OpenFirmware (OF)。在Linux 2.6中,ARM架構的板極硬體細節過多地被硬編碼在arch/arm/plat-xxx和arch/arm/mach-xxx,採用Device Tree後,許多硬體的細節可以直接透過它傳遞給Linux,而不再需要在kernel中進行大量的冗餘編碼。
Device Tree由一系列被命名的結點(node)和屬性(property)組成,而結點本身可包含子結點。所謂屬性,其實就是成對出現的name和value。在Device Tree中,可描述的資訊包括(原先這些資訊大多被hard code到kernel中):
- CPU的數量和類別
- 記憶體基地址和大小
- 匯流排和橋
- 外設連線
- 中斷控制器和中斷使用情況
- GPIO控制器和GPIO使用情況
- Clock控制器和Clock使用情況
2. Device Tree組成和結構
整個Device Tree牽涉面比較廣,即增加了新的用於描述裝置硬體資訊的文字格式,又增加了編譯這一文字的工具,同時Bootloader也需要支援將編譯後的Device Tree傳遞給Linux核心。DTS (device tree source)
.dts檔案是一種ASCII 文字格式的Device Tree描述,此文字格式非常人性化,適合人類的閱讀習慣。基本上,在ARM Linux在,一個.dts檔案對應一個ARM的machine,一般放置在核心的arch/arm/boot/dts/目錄。由於一個SoC可能對應多個machine(一個SoC可以對應多個產品和電路板),勢必這些.dts檔案需包含許多共同的部分,Linux核心為了簡化,把SoC公用的部分或者多個machine共同的部分一般提煉為.dtsi,類似於C語言的標頭檔案。其他的machine對應的.dts就include這個.dtsi。譬如,對於VEXPRESS而言,vexpress-v2m.dtsi就被vexpress-v2p-ca9.dts所引用, vexpress-v2p-ca9.dts有如下一行:/include/ "vexpress-v2m.dtsi"
當然,和C語言的標頭檔案類似,.dtsi也可以include其他的.dtsi,譬如幾乎所有的ARM SoC的.dtsi都引用了skeleton.dtsi。
.dts(或者其include的.dtsi)基本元素即為前文所述的結點和屬性:
- / {
- node1 {
- a-string-property = "A string";
- a-string-list-property = "first string", "second string";
- a-byte-data-property = [0x01 0x23 0x34 0x56];
- child-node1 {
- first-child-property;
- second-child-property = <1>;
- a-string-property = "Hello, world";
- };
- child-node2 {
- };
- };
- node2 {
- an-empty-property;
- a-cell-property = <1 2 3 4>; /* each number (cell) is a uint32 */
- child-node1 {
- };
- };
- };
1個root結點"/";
root結點下面含一系列子結點,本例中為"node1" 和 "node2";
結點"node1"下又含有一系列子結點,本例中為"child-node1" 和 "child-node2";
各結點都有一系列屬性。這些屬性可能為空,如" an-empty-property";可能為字串,如"a-string-property";可能為字串陣列,如"a-string-list-property";可能為Cells(由u32整陣列成),如"second-child-property",可能為二進位制數,如"a-byte-data-property"。
下面以一個最簡單的machine為例來看如何寫一個.dts檔案。假設此machine的配置如下:
1個雙核ARM Cortex-A9 32位處理器;
ARM的local bus上的記憶體對映區域分佈了2個串列埠(分別位於0x101F1000 和 0x101F2000)、GPIO控制器(位於0x101F3000)、SPI控制器(位於0x10170000)、中斷控制器(位於0x10140000)和一個external bus橋;
External bus橋上又連線了SMC SMC91111 Ethernet(位於0x10100000)、I2C控制器(位於0x10160000)、64MB NOR Flash(位於0x30000000);
External bus橋上連線的I2C控制器所對應的I2C總線上又連線了Maxim DS1338實時鐘(I2C地址為0x58)。
其對應的.dts檔案為:
- / {
- compatible = "acme,coyotes-revenge";
- #address-cells = <1>;
- #size-cells = <1>;
- interrupt-parent = <&intc>;
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
- [email protected] {
- compatible = "arm,cortex-a9";
- reg = <0>;
- };
- [email protected] {
- compatible = "arm,cortex-a9";
- reg = <1>;
- };
- };
- [email protected] {
- compatible = "arm,pl011";
- reg = <0x101f0000 0x1000 >;
- interrupts = < 1 0 >;
- };
- [email protected] {
- compatible = "arm,pl011";
- reg = <0x101f2000 0x1000 >;
- interrupts = < 2 0 >;
- };
- [email protected] {
- compatible = "arm,pl061";
- reg = <0x101f3000 0x1000
- 0x101f4000 0x0010>;
- interrupts = < 3 0 >;
- };
- intc: [email protected] {
- compatible = "arm,pl190";
- reg = <0x10140000 0x1000 >;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
- [email protected] {
- compatible = "arm,pl022";
- reg = <0x10115000 0x1000 >;
- interrupts = < 4 0 >;
- };
- 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
- [email protected],0 {
- compatible = "smc,smc91c111";
- reg = <0 0 0x1000>;
- interrupts = < 5 2 >;
- };
- [email protected],0 {
- compatible = "acme,a1234-i2c-bus";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1 0 0x1000>;
- interrupts = < 6 2 >;
- [email protected] {
- compatible = "maxim,ds1338";
- reg = <58>;
- interrupts = < 7 3 >;
- };
- };
- [email protected],0 {
- compatible = "samsung,k8f1315ebm", "cfi-flash";
- reg = <2 0 0x4000000>;
- };
- };
- };
在.dts檔案的每個裝置,都有一個compatible 屬性,compatible屬性使用者驅動和裝置的繫結。compatible 屬性是一個字串的列表,列表中的第一個字串表徵了結點代表的確切裝置,形式為"<manufacturer>,<model>",其後的字串表徵可相容的其他裝置。可以說前面的是特指,後面的則涵蓋更廣的範圍。如在arch/arm/boot/dts/vexpress-v2m.dtsi中的Flash結點:
- [email protected],00000000 {
- compatible = "arm,vexpress-flash", "cfi-flash";
- reg = <0 0x00000000 0x04000000>,
- <1 0x00000000 0x04000000>;
- bank-width = <4>;
- };
再比如,Freescale MPC8349 SoC含一個串列埠裝置,它實現了國家半導體(National Semiconductor)的ns16550 暫存器介面。則MPC8349串列埠裝置的compatible屬性為compatible = "fsl,mpc8349-uart", "ns16550"。其中,fsl,mpc8349-uart指代了確切的裝置, ns16550代表該裝置與National Semiconductor 的16550 UART保持了暫存器相容。
接下來root結點"/"的cpus子結點下面又包含2個cpu子結點,描述了此machine上的2個CPU,並且二者的compatible 屬性為"arm,cortex-a9"。
注意cpus和cpus的2個cpu子結點的命名,它們遵循的組織形式為:<name>[@<unit-address>],<>中的內容是必選項,[]中的則為可選項。name是一個ASCII字串,用於描述結點對應的裝置型別,如3com Ethernet介面卡對應的結點name宜為ethernet,而不是3com509。如果一個結點描述的裝置有地址,則應該給出@unit-address。多個相同型別裝置結點的name可以一樣,只要unit-address不同即可,如本例中含有[email protected]、[email protected]以及[email protected]與[email protected]這樣的同名結點。裝置的unit-address地址也經常在其對應結點的reg屬性中給出。ePAPR標準給出了結點命名的規範。
可定址的裝置使用如下資訊來在Device Tree中編碼地址資訊:
- reg
- #address-cells
- #size-cells
root結點的子結點描述的是CPU的檢視,因此root子結點的address區域就直接位於CPU的memory區域。但是,經過匯流排橋後的address往往需要經過轉換才能對應的CPU的memory對映。external-bus的ranges屬性定義了經過external-bus橋後的地址範圍如何對映到CPU的memory區域。
- ranges = <0 0 0x10100000 0x10000 // Chipselect 1, Ethernet
- 1 0 0x10160000 0x10000 // Chipselect 2, i2c controller
- 2 0 0x30000000 0x1000000>; // Chipselect 3, NOR Flash
Device Tree中還可以中斷連線資訊,對於中斷控制器而言,它提供如下屬性:
interrupt-controller – 這個屬性為空,中斷控制器應該加上此屬性表明自己的身份;
#interrupt-cells – 與#address-cells 和 #size-cells相似,它表明連線此中斷控制器的裝置的interrupts屬性的cell大小。
在整個Device Tree中,與中斷相關的屬性還包括:
interrupt-parent – 裝置結點透過它來指定它所依附的中斷控制器的phandle,當結點沒有指定interrupt-parent 時,則從父級結點繼承。對於本例而言,root結點指定了interrupt-parent = <&intc>;其對應於intc: i[email protected],而root結點的子結點並未指定interrupt-parent,因此它們都繼承了intc,即位於0x10140000的中斷控制器。
interrupts – 用到了中斷的裝置結點透過它指定中斷號、觸發方法等,具體這個屬性含有多少個cell,由它依附的中斷控制器結點的#interrupt-cells屬性決定。而具體每個cell又是什麼含義,一般由驅動的實現決定,而且也會在Device Tree的binding文件中說明。譬如,對於ARM GIC中斷控制器而言,#interrupt-cells為3,它3個cell的具體含義Documentation/devicetree/bindings/arm/gic.txt就有如下文字說明:
- 01 The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
- 02 interrupts.
- 03
- 04 The 2nd cell contains the interrupt number for the interrupt type.
- 05 SPI interrupts are in the range [0-987]. PPI interrupts are in the
- 06 range [0-15].
- 07
- 08 The 3rd cell is the flags, encoded as follows:
- 09 bits[3:0] trigger type and level flags.
- 10 1 = low-to-high edge triggered
- 11 2 = high-to-low edge triggered
- 12 4 = active high level-sensitive
- 13 8 = active low level-sensitive
- 14 bits[15:8] PPI interrupt cpu mask. Each bit corresponds to each of
- 15 the 8 possible cpus attached to the GIC. A bit set to '1' indicated
- 16 the interrupt is wired to that CPU. Only valid for PPI interrupts.
![](http://static.blog.csdn.net/images/save_snippets.png)
除了中斷以外,在ARM Linux中clock、GPIO、pinmux都可以透過.dts中的結點和屬性進行描述。
相關推薦
Device Tree中的.dts和dtsi檔案介紹
1. ARM Device Tree起源 Linus Torvalds在2011年3月17日的ARM Linux郵件列表宣稱“this whole ARM thing is a f*cking pain in the ass”,引發ARM Linux社群的地震,隨後A
Android開發專案中的build.gradle檔案介紹
在開發android專案中,我們通常會遇到兩個build.gradle檔案。如下圖所示: 一個用於整個專案,另一個用於app應用模組。應用於整個專案的內容很少,沒啥好解釋的,內容保持預設不變就行了。我們要了解和經常編輯的是app/build.grad
xmlhttp中readyState和status的介紹
xmlhttp.readyState的值及解釋: 0:請求未初始化(還沒有呼叫 open())。 1:請求已經建立,但是還沒有傳送(還沒有呼叫 send())。 2:請求已傳送,正在處理中(通常現在可以從響應中獲取內容頭)。 3:請求在處理中;通常響應中已有部分資料可用了,但是伺服器
JVM中記憶體和GC的介紹
最近聽聞很多裁員潮,寒冬潮的訊息,所以才會有下面這些總結,給道友準備,也是為自己! 希望自己用不到................. 記憶體分佈 jvm將記憶體分為了堆,方法區,程式計數器,棧(虛擬機器棧),本地方法棧5個區域,有些是執行緒共有的有的是執行緒共享的。下面就簡單就這幾個區域做簡單說明。 程
FPGA開發中sof和elf檔案的合併與格式轉換
0. 本文目的 有關sof和elf檔案的合併方法非常多,但真正好用而且經得起推敲的寥寥無幾。通過相關資料的學習以及工程實踐,現將個人的操作方法及收穫進行總結,希望能給正在學習FPGA的夥伴們提供一點點幫助! Nios工程開發包括兩個環節,前期的核心硬體開發
Eclipse中.setting目錄下檔案介紹
Eclipse專案中系統檔案介紹 一. 寫在前面 文章較長,可以直接到感興趣的段落,或者直接關鍵字搜尋; 請原諒作者掌握的程式語言少,這裡只研究Java相關的專案; 每一個檔案僅僅做一個常見內容的簡單介紹,這些知識多數來自於實踐理解和網路搜尋,可能會不全面,更詳細的可以看
springboot中fastJson和properties檔案佔位符解析
1.介紹 fastJson是阿里巴巴出品的一款速度極快的json解析工具 properties配置檔案有時無法解析某些佔位符 2.使用 直接放到springboot啟動類中即可
敏捷開發團隊中PO和SM角色介紹
敏捷開發中的PO即Product Owner,字面意思是產品或業務負責人,即熟悉該產品所有業務相關的邏輯、流程、設定等方面事宜的人員,一般可由產品經理擔任,也可由熟悉業務的開發人員擔任。如果敏捷團隊是在一起辦公的(指一個辦公室內坐在一起的),建議由產品經理擔任,本身產品經理
關於device tree中的interrupts選項
隨著Linux的發展,dts技術是大勢所趨。裡面的interrupts = < >這個裡面的是1個數,有的是2個數,有的是3個數。這裡囉嗦兩句,筆記一下。 這個數目,是由這個屬性來定的。#interrupt-cells ,如果當前節點找不到,就是跟隨父節點
移植u-boot-2011.03到S3C2440(utu2440)的方法與步驟###8. u-boot引導啟動nand flash中核心和根檔案系統cramfs和使用者檔案系統yaffs2支援
rivers/rtc/hctosys.c: unable to open rtc device (rtc0)uncorrectable error : <3>uncorrectable error : <3>end_request: I/O error, dev mtdblock2,
c中標頭檔案在cpp檔案中引用和.h檔案引用的思考
我們在編寫程式中標頭檔案是經常使用的。但是標頭檔案是應該包含在.H檔案中還是在.cpp檔案中。在這個當中有什麼樣去區別呢。 假如說我們編寫了一個a.cpp 。我們將a.cpp檔案的變數和函式申明在a.h中。在a.h檔案有使用了b.中定義的型別type1資料
跟我來學小程式(一)專案目錄和專案檔案介紹
大家好,我是一個愛舉鐵的程式設計師Shr。 本篇檔案介紹小程式專案的目錄和專案檔案。 原始碼地址: https://github.com/ShrMus/wechat_xcx/tree/master/demo_20180603 一、新建專案 開啟微信web
根據正則表示式匹配頁面中js和css檔案
// 匹配 List<string> srcList = new List<string>(); List<string> linkList = new List<string>();
Amazon EFS價格_亞馬遜雲中設定和擴充套件檔案儲存
每月計費的儲存量按照全月內使用的平均儲存空間計算。您的儲存用量以“GB/月”為單位進行衡量,月底合計該值,得出您的月度費用。 每月計費的吞吐量按照該月的平均預置吞吐量計算。您的吞吐量以“MB/s/月”為單位進行衡量,月底合計該值,得出您的月度費用。
Amazon EFS常見問題_亞馬遜雲中設定和擴充套件檔案儲存
問: 什麼是預置吞吐量?應在何時使用? 預置吞吐量使 Amazon EFS 客戶能夠預置檔案系統的吞吐量(無需考慮儲存的資料量),從而優化檔案系統的吞吐效能,以滿足應用程式的需求。 Amazon EFS 預置吞吐量適用於吞吐量 (MB/
Spring原始碼學習--Spring中IOC和AOP的介紹
前言: 控制反轉(Inversion of Control,英文縮寫為IoC); 面向切面程式設計(Aspect Oriented Programming,英文縮寫為AOP) 我們是在使用spring框架的過程中,很大一部分是為了使用IoC(依賴注入),和
servlet學習之servlet中cookie和session的介紹
前言 記得在校招的時候總是會問及怎樣解決http的無狀態問題,其實自己知道有隱藏表單,cookie,令牌,session等技術可是具體的流程及由來,還有應用我是一臉懵逼的。。。 大綱 Cookie概述Cookie使用的三個步驟Cookie的機制Cookie的安全問題Sess
Java中類和物件詳細介紹
static void main(String[] args) { //1 int i = 2; changeValue(2);//方法中x複製了i的值,為2,方法執行結束x=6,但是i的值不變 System.out.prin
VS中bin和obj檔案引發的問題
在敲機房收費系統的時候通常都會遇到這個問題:“未能載入檔案或程式集“DAL”或它的某一個依賴項。系統找不到指定的檔案”。 解決方案: 修改將DAL的輸出目錄 修改到UI/bin
父容器div內的子元素div為float時,父元素無法撐開(或高度自適應)的解決方式以及css中position和float的介紹
先簡單給出父元素無法高度自適應時的解決方案: 第一種:在父容器上設定 overflow:auto或者hidden可以讓它自動包含子元素,從而具有了實際的height值。 第二種:在子元素的最下面加上一個 空元素,並且設定clear:both,但