1. 程式人生 > >linux裝置樹dts移植詳解

linux裝置樹dts移植詳解

摘 要:裝置樹的引入減少了核心為支援新硬體而需要的改變,提高程式碼重用,加速了Linux
支援包的開發,使得單個核心映象能支援多個系統。作為U-Boot 和Linux 核心之間的動態
介面,本文闡述了裝置樹的資料儲存格式以及原始碼描述語法,進而分析了U-Boot 對扁平設
備樹的支援設定,Linux 核心對裝置樹的解析流程。
關鍵詞:扁平裝置樹; DTS; PowerPC; Linux
IBM、Sun 等廠家的伺服器最初都採用了Firmware(一種嵌入到硬體裝置中的程式,用
於提供軟體和硬體之間的介面),用於初始化系統配置,提供作業系統軟體和硬體之間的接
口,啟動和執行系統。後來為了標準化和相容性,IBM、Sun 等聯合推出了韌體介面IEEE 1275

標準,讓他們的伺服器如IBM PowerPC pSeries,Apple PowerPC,Sun SPARC 等均採用Open
Firmware,在執行時構建系統硬體的裝置樹資訊傳遞給核心,進行系統的啟動執行[1]。這樣
做的好處有,減少核心對系統硬體的嚴重依賴,利於加速支援包的開發,降低硬體帶來的變
化需求和成本,降低對核心設計和編譯的要求。
隨著 Linux/ppc64 核心的發展,核心程式碼從原來的arch/ppc32 和arch/ppc64 逐漸遷移到
統一的arch/powerpc 目錄,並在核心程式碼引入Open Firmware API 以使用標準韌體介面[2]。
Linux 核心在執行時,需要知道硬體的一些相關資訊。對於使用ARCH=powerpc 引數編譯的

核心映象,這個資訊需要基於Open Firmware 規範,以裝置樹的形式存在[3]。這樣核心在啟
動時讀取掃描Open Firmware 提供的裝置樹,從而獲得平臺的硬體裝置資訊,搜尋匹配的設
備驅動程式並將該驅動程式繫結到裝置。
在嵌入式 PowerPC 中,一般使用U-Boot 之類的系統引導程式碼,而不採用Open Firmware。
早期的U-Boot 使用include/asm-ppc/u-boot.h 中的靜態資料結構struct bd_t 將板子基本資訊傳
遞給核心,其餘的由核心處理。這樣的介面不夠靈活,硬體發生變化就需要重新定製編譯燒
寫引導程式碼和核心,而且也不再適應於現在的核心。為了適應核心的發展及嵌入式PowerPC

平臺的千變萬化,吸收標準Open Firmware 的優點,U-Boot 引入了扁平裝置樹FDT 這樣的
動態介面,使用一個單獨的FDT blob(二進位制大物件,是一個可以儲存二進位制檔案的容器)
儲存傳遞給核心的引數[3]。一些確定資訊,例如cache 大小、中斷路由等直接由裝置樹提供,
而其他的資訊,例如eTSEC 的MAC 地址、頻率、PCI 匯流排數目等由U-Boot 在執行時修改。
U-Boot 使用扁平裝置樹取代了bd_t,而且也不再保證對bd_t 的後向相容。
2 裝置樹概念
簡單的說,裝置樹是一種描述硬體配置的樹形資料結構,有且僅有一個根節點[4]。它包
含了有關CPU、實體記憶體、匯流排、串列埠、PHY 以及其他外圍裝置資訊等。該樹繼承了Open
Firmware IEEE 1275 裝置樹的定義。作業系統能夠在啟動時對此結構進行語法分析,以此配
置核心,載入相應的驅動。
3 裝置樹儲存格式
U-Boot 需要將裝置樹在記憶體中的儲存地址傳給核心。該樹主要由三大部分組成:頭
(Header)、結構塊(Structure block)、字串塊(Strings block)。裝置樹在記憶體中的存
儲佈局圖1 如下:
圖1 裝置樹儲存格式圖
Fig1 The layout of a DT block
3.1 頭(header)
頭主要描述裝置樹的基本資訊,如裝置樹魔數標誌、裝置樹塊大小、結構塊的偏移地址
等,其具體結構boot_param_header 如下。這個結構中的值都是以大端模式表示,並且偏移
地址是相對於裝置樹頭的起始地址計算的。
3.2 結構塊(structure block)
扁平裝置樹結構塊是線性化的樹形結構,和字串塊一起組成了裝置樹的主體,以節點
形式儲存目標板的裝置資訊。在結構塊中,節點起始標誌為常值巨集OF_DT_BEGIN_NODE,
節點結束標誌為巨集OF_DT_END_NODE;子節點定義在節點結束標誌前。一個節點可以概
括為以OF_DT_BEGIN_NODE 開始,包括節點路徑、屬性列表、子節點列表,最後以
OF_DT_END_NODE 結束的序列,每一個子節點自身也是類似的結構。
3.3 字串塊(Strings block)
為了節省空間,將一些屬性名,尤其是那些重複冗餘出現的屬性名,提取出來單獨存放
到字串塊。這個塊中包含了很多有結束標誌的屬性名字串。在裝置樹的結構塊中儲存了
這些字串的偏移地址,這樣可以很容易地查詢到屬性名字串。字串塊的引入節省了嵌
入式系統較為緊張的儲存空間。
4 裝置樹原始碼DTS 表示
裝置樹原始碼檔案(.dts)以可讀可編輯的文字形式描述系統硬體配置裝置樹,支援C/C++
方式的註釋,該結構有一個唯一的根節點“/”,每個節點都有自己的名字並可以包含多個
子節點。裝置樹的資料格式遵循了Open Firmware IEEE standard 1275。本文只簡述裝置樹的
資料佈局及語法,Linux 板級支援包開發者應該詳細參考IEEE 1275 標準[5]及其他文獻[2] [4]。
為了說明,首先給出基於PowerPC MPC8349E 處理器的最小系統的裝置樹原始碼示例。
可以看到,這個裝置樹中有很多節點,每個節點都指定了節點單元名稱。每一個屬性後面都
給出相應的值。以雙引號引出的內容為ASCII 字串,以尖括號給出的是32 位的16 進位制
值。這個樹結構是啟動Linux 核心所需節點和屬性簡化後的集合,包括了根節點的基本模式
資訊、CPU 和實體記憶體佈局,它還包括通過/chosen 節點傳遞給核心的命令列引數資訊。
/ {
model = "MPC8349EMITX";
compatible = "MPC8349EMITX", "MPC834xMITX", "MPC83xxMITX";
#address-cells = <1>; /* 32bit address */
#size-cells = <1>; /* 4GB size */
cpus {
#address-cells = <1>;
#size-cells = <0>;
PowerPC,[email protected] {
device_type = "cpu";
reg = <0>;
d-cache-line-size = <20>; /* 32 Bytes */
i-cache-line-size = <20>;
d-cache-size = <8000>; /* L1 dcache, 32K */
i-cache-size = <8000>;
timebase-frequency = <0>; /* from bootloader */
bus-frequency = <0>;
clock-frequency = <0>;
};
};
memory {
device_type = "memory";
reg = <00000000 10000000>; /* 256MB */
};
chosen {
name = "chosen";
bootargs = "root=/dev/ram rw console=ttyS0,115200";
linux,stdout-path = "/[email protected]/[email protected]";
};
};
4.1 根節點
裝置樹的起始點稱之為根節點"/"。屬性model 指明瞭目標板平臺或模組的名稱,屬性
compatible 值指明和目標板為同一系列的相容的開發板名稱。對於大多數32 位平臺,屬性
#address-cells 和#size-cells 的值一般為1。
4.2 CPU 節點
/cpus 節點是根節點的子節點,對於系統中的每一個CPU,都有相應的節點。/cpus 節點
沒有必須指明的屬性,但指明#address-cells = <1>和 #size-cells = <0>是個好習慣,這同時指
明瞭每個CPU 節點的reg 屬性格式,方便為物理CPU 編號。
此節點應包含板上每個CPU 的屬性。CPU 名稱一般寫作PowerPC,<name>,例如
Freescale 會使用PowerPC,8349 來描述本文的MPC8349E 處理器。CPU 節點的單元名應該是
[email protected] 的格式,此節點一般要指定device_type(固定為"cpu"),一級資料/指令快取的表項
大小,一級資料/指令快取的大小,核心、匯流排時鐘頻率等。在上面的示例中通過系統引導
程式碼動態填寫時鐘頻率相關項。
4.3 系統記憶體節點
此節點用於描述目標板上實體記憶體範圍,一般稱作/memory 節點,可以有一個或多個。
當有多個節點時,需要後跟單元地址予以區分;只有一個單元地址時,可以不寫單元地址,
預設為0。
此節點包含板上實體記憶體的屬性,一般要指定device_type(固定為"memory")和reg
屬性。其中reg 的屬性值以<起始地址空間大小>的形式給出,如上示例中目標板記憶體起始
地址為0,大小為256M 位元組。
4.4 /chosen 節點
這個節點有一點特殊。通常,這裡由Open Firmware 存放可變的環境資訊,例如引數,
預設輸入輸出裝置。
這個節點中一般指定bootargs 及linux,stdout-path 屬性值。bootargs 屬性設定為傳遞給內
核命令列的引數字串。linux,stdout-path 常常為標準終端裝置的節點路徑名,核心會以此作
為預設終端。
U-Boot 在1.3.0 版本後添加了對扁平裝置樹FDT 的支援,U-Boot 載入Linux 核心、
Ramdisk 檔案系統(如果使用的話)和裝置樹二進位制映象到實體記憶體之後,在啟動執行Linux
核心之前,它會修改裝置樹二進位制檔案。它會填充必要的資訊到裝置樹中,例如MAC 地址、
PCI 匯流排數目等。U-Boot 也會填寫裝置樹檔案中的“/chosen”節點,包含了諸如串列埠、根
裝置(Ramdisk、硬碟或NFS 啟動)等相關資訊。
4.5 片上系統SOC 節點
此節點用來描述片上系統SOC,如果處理器是SOC,則此節點必須存在。頂級SOC 節
點包含的資訊對此SOC 上的所有裝置可見。節點名應該包含此SOC 的單元地址,即此SOC
記憶體對映暫存器的基址。SOC 節點名以/soc<SOCname>的形式命名,例如MPC8349 的SOC
節點是"soc8349"。
在屬性中應該指定device_type(固定為"soc")、ranges、bus-frequency 等屬性。ranges
屬性值以<bus_addr parent_bus_addr size>的形式指定。SOC 節點還包含目標板使用的每個
SOC 裝置子節點,應該在裝置樹中儘可能詳細地描述此SOC 上的外圍裝置。如下給出帶有
看門狗裝置的SOC 節點DTS 示例。
[email protected] {
#address-cells = <1>;
#size-cells = <1>;
device_type = "soc";
compatible = "simple-bus";
ranges = <0 e0000000 100000>; /* size 1MB */
reg = <e0000000 00000200>;
bus-frequency = <0>; /* from bootloader */
{
device_type = "watchdog";
compatible = "mpc83xx_wdt";
reg = <200 100>; /* offset: 0x200 */
};
};
4.6 其他裝置節點
分級節點用來描述系統上的匯流排和裝置,類似物理匯流排拓撲,能很方便的描述裝置間的
關係。對於系統上的每個匯流排和裝置,在裝置樹中都有其節點。對於這些裝置屬性的描述和
定義請詳細參考IEEE 1275 標準及本文參考文獻[2]。
裝置樹的中斷系統稍顯複雜,裝置節點利用interrupt-parent 和interrupts 屬性描述到中
斷控制器的中斷連線。其中interrupt-parent 屬性值為中斷控制器節點的指標,#interrupts 屬
性值描述可觸發的中斷訊號,其值格式與中斷控制器的interrupt-cells 屬性值有關。一般
#interrupt-cells 屬性值為2,interrupts 屬性就對應為一對描述硬體中斷號和中斷觸發方式的
十六進位制值。
5 扁平裝置樹編譯
根據嵌入式板的裝置資訊寫裝置樹原始碼檔案(.dts)通常比較簡單,但是手寫二進位制的
扁平裝置樹(.dtb)就顯得比較複雜了。裝置樹編譯器dtc 就是用來根據裝置樹原始碼的文字
檔案生成裝置樹二進位制映象的。dtc 編譯器會對輸入檔案進行語法和語義檢查,並根據Linux
核心的要求檢查各節點及屬性,將裝置樹原始碼檔案(.dts)編譯二進位制檔案(.dtb),以保證
核心能正常啟動。dtc 編譯器的使用方法如下所示[6]:
dtc [ -I dts ] [ -O dtb ] [ -o opt_file ] [ -V opt_version ] ipt_file
2.6.25 版本之後的核心原始碼已經包含了dtc 編譯器。在配置編譯核心時選中
CONFIG_DTC,會自動生成裝置樹編譯器dtc。將編寫的目標板裝置樹檔案mpc8349emitx.dts
放到核心原始碼的arch/powerpc/boot/dts/目錄下,利用核心Makefile 生成blob 的簡單規則,使
用以下命令亦可完成裝置樹的dtc 編譯:
$ make mpc8349emitx.dtb
6 U-Boot 相關設定說明
為使 U-Boot 支援裝置樹,需要在板子配置標頭檔案中設定一系列巨集變數。如本文在
MPC8349E 處理器目標板中移植的U-Boot 配置如下:
/* pass open firmware flat tree */
#define CONFIG_OF_LIBFDT 1
#undef CONFIG_OF_FLAT_TREE
#define CONFIG_OF_BOARD_SETUP 1
#define CONFIG_OF_HAS_BD_T 1
#define CONFIG_OF_HAS_UBOOT_ENV 1
啟動引導程式碼U-Boot 在完成自己的工作之後,會載入Linux 核心,並將扁平裝置樹的
地址傳遞給核心,其程式碼形式如下:
#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)
if (of_flat_tree) { /* device tree; boot new style */
/*
* Linux Kernel Parameters (passing device tree):
* r3: pointer to the fdt, followed by the board info data
* r4: physical pointer to the kernel itself
* r5: NULL
* r6: NULL
* r7: NULL
*/
(*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0);
/* does not return */
}
#endif
arch/powerpc 核心的入口有且只有一個,入口點為核心映象的起始。此入口支援兩種調
用方式,一種是支援Open Firmware 啟動,另一種對於沒有OF 的引導程式碼,需要使用扁平
裝置樹塊,如上示例程式碼。暫存器r3 儲存指向裝置樹的實體地址指標,暫存器r4 儲存為內
核在實體記憶體中的地址,r5 為NULL。其中的隱含意思為:假設開啟了mmu,那麼這個mmu
的對映關係是1:1 的對映,即虛擬地址和實體地址是相同的。
7 Linux 核心對裝置樹的解析
扁平裝置樹描述了目標板平臺中的裝置樹資訊。每個裝置都有一個節點來描述其資訊,
每個節點又可以有子節點及其相應的屬性。核心原始碼中include/linux/of.h 及drivers/of/base.c
等檔案中提供了一些Open Firmware API,通過這些API,核心及裝置驅動可以查詢到相應
的裝置節點,讀取其屬性值,利用這些資訊正確地初始化和驅動硬體。
圖2 核心及驅動對扁平裝置樹的解析
Fig2 Interaction from kernel and drivers with the FDT blob
8 結論
本文介紹了裝置樹的起源及其優點,進而闡述了裝置樹的資料儲存格式以及原始碼描述語
法,給出了裝置樹的編譯方法,最後引出了移植過程中的U-Boot 相關設定說明及核心的解
析過程分析。裝置樹為嵌入式系統向Linux 核心傳遞引數的動態介面,本文以MPC8349E
處理器目標板上的DTS 移植經歷作總結,希望對嵌入式PowerPC Linux 開發者具有一定的
參考價值,可以加快嵌入式PowerPC Linux 開發中的裝置樹DTS 移植過程。
[3] DENX. Flattened Device Tree Blob [EB/OL]. http://www.denx.de/wiki/view/DULG/LinuxFDTBlob, 2009
[5] SN. The Openmware Home Page [EB/OL]. http://playground.sun.com/1275/home.html

相關推薦

linux裝置dts移植

摘 要:裝置樹的引入減少了核心為支援新硬體而需要的改變,提高程式碼重用,加速了Linux支援包的開發,使得單個核心映象能支援多個系統。作為U-Boot 和Linux 核心之間的動態介面,本文闡述了裝置樹的資料儲存格式以及原始碼描述語法,進而分析了U-Boot 對扁平設備樹的

linux裝置dts一之移植

支援包的開發,使得單個核心映象能支援多個系統。作為U-Boot 和Linux 核心之間的動態 介面,本文闡述了裝置樹的資料儲存格式以及原始碼描述語法,進而分析了U-Boot 對扁平設 備樹的支援設定,Linux 核心對裝置樹的解析流程。 關鍵詞:扁平裝置樹; DTS; PowerPC; Linux IBM、S

linux裝置dts之powerpc 平臺解析過程

一. 在linux中,對dtb檔案解析的整個過程式如下: 1)首先將從u-boot 傳遞過來的映像基地址和dtb 檔案映像基地址儲存通用暫存器r30,r31;2)通過呼叫machine_init()、early_init_devtree()函式來獲取核心前期初始化所需的bo

Linux裝置驅動程式開發》中的virtualBox下的ubuntu在vmware下使用

最近在看宋寶華老師的《Linux裝置驅動程式開發詳解》第三版,在看到1.5小節Linux裝置驅動的開發環境構建時,我也 打算在自己電腦使用宋老師的系統(裡面有書配套的原始碼)。由於我之前電腦上已經安裝過了vmware workstation,就決定在 此環境下安裝系統。按照

Linux裝置語法【轉】

轉自:https://www.cnblogs.com/xiaojiang1025/p/6131381.html 概念 Linux核心從3.x開始引入裝置樹的概念,用於實現驅動程式碼與裝置資訊相分離。在裝置樹出現以前,所有關於裝置的具體資訊都要寫在驅動裡,一旦外圍裝置變化,驅動程式碼就要重寫。引入了裝置樹之

Linux裝置語法

概念 Linux核心從3.x開始引入裝置樹的概念,用於實現驅動程式碼與裝置資訊相分離。在裝置樹出現以前,所有關於裝置的具體資訊都要寫在驅動裡,一旦外圍裝置變化,驅動程式碼就要重寫。引入了裝置樹之後,驅動程式碼只負責處理驅動的邏輯,而關於裝置的具體資訊存放到裝置樹檔案中,

linux裝置-韋東山-專題視訊課程

linux裝置樹詳解—150人已學習 課程介紹        現在的linux核心(Linux3.X)都已支援裝置樹機制(dts),不管你是玩核心還是玩驅動,一定會碰到裝置樹,而網上雖然有很多部落格,但都講的不夠清晰,看了還是不懂,半桶水,學員急需一套講解裝置樹比較透徹的課程

Linux驅動】Linux裝置語法

1 概念Linux核心從3.x開始引入裝置樹的概念,用於實現驅動程式碼與裝置資訊相分離。在裝置樹出現以前,所有關於裝置的具體資訊都要寫在驅動裡,一旦外圍裝置變化,驅動程式碼就要重寫。引入了裝置樹之後,驅動程式碼只負責處理驅動的邏輯,而關於裝置的具體資訊存放到裝置樹檔案中,這樣,如果只是硬體介面資訊的變化而沒有

Linux裝置

裝置樹詳解在Linux3.x版本後,arch/arm/plat-xxx和arch/arm/mach-xxx中,描述板級細節的程式碼(比如platform_device、i2c_board_info等)被大量取消,取而代之的是裝置樹,其目錄位於arch/arm/boot/dts

Linux 裝置

本文基於天嵌E9V3開發板,詳解裝置樹的規則和用法。 一、基本概念 DTS即Device Tree Source,是一個文字形式的檔案,用於描述硬體資訊,包括CPU的數量和類別、記憶體基地址和大小、中斷控制器、匯流排和橋、外設、時鐘和GPIO控制器等。 DTB即

《Linux4.0裝置驅動開發》筆記--第十八章:ARM Linux裝置

18.1 ARM裝置樹簡介 裝置舒適一種描述印鑑的資料結構,它起源於OpenFirmware(OF) 採用裝置樹前後對比: 採用裝置樹之前:ARM架構的板極硬體細節過多的被硬編碼在arch/arm/plat-xxx和arch/arm/mach-xxx中

linux裝置中的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社群的地震

第二課:linux裝置的規範(dts和dtb)

轉載請註明文章地址 http://wiki.100ask.org/Linux_devicetree 第01節_DTS格式 dts檔案通過編譯生成dtb格式檔案 屬性的定義 value取值型別 屬性名=值只有三種取值 第一種 <1 0x3

tiny4412學習(四)之移植linux-裝置(1)裝置基礎知識及GPIO中斷

#include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/gpio.h> #include <linux/of.

Linux的SOCKET編程(轉)

readv lose 服務 網絡字節序 返回值 quest avi 取數 key Linux的SOCKET編程詳解 1. 網絡中進程之間如何通信 進 程通信的概念最初來源於單機系統。由於每個進程都在自己的地址範圍內運行,為保證兩個相互通信的進 程之間既互不幹擾又

Linux基礎命令(之一)

linux 基礎命令 Linux基礎命令(之一)詳解學習linux的朋友都知道,系統大多數操作都是命令行的操作方式,當然如今也有圖形化界面的操作方式,但是多數情況下仍然使用命令的操作模式,所以命令的作用與用法是成為學好、學會Linux系統的必備前提,也是重點之一,所以今天來聊一聊一些基礎命令的用法與其

LinuxLinux定時任務Crontab命令

星期幾 ima 默認 定時 最好 表示 時間 path 配置文件 linux 系統則是由 cron (crond) 這個系統服務來控制的。Linux 系統上面原本就有非常多的計劃性工作,因此這個系統服務是默認啟動的。另 外, 由於使用者自己也可以設置計劃任務,所以, Lin

Linux 下hosts文件

domain none oca 不同 詳解 als 機器 區別 int Linux 下hosts文件詳解 主機名: 無論在局域網還是INTERNET上,每臺主機都有一個IP地址,是為了區分此臺主機和彼臺主機,也就是說IP地址就是主機的門牌號。 公網:IP地

centos/linux alternatives與update-alternatives與軟件版本切換

等等 ava 包括 blank 多個 config etc 兩種模式 版權 update-alternatives是linux系統中專門維護系統命令鏈接符的工具,通過它可以很方便的設置系統默認使用哪個命令、哪個軟件版本,比如,我們在系統中同時安裝了open jdk和

#21 在Linux裏進程管理,與pstree、ps、pgrep、pkill、pidof、top命令的應用

在linux裏進程管理詳解 與pstree、ps、pgrep、pkill、pidof、top命令的應用 進程管理: 所謂進程:process,一個活動的程序的實體的副本; 生命周期; 可能包含一個或多個執行流; 創建進程: 每個進程的組織結構是一致的: 內核在正常啟動並且全