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

linux裝置樹dts一之移植詳解

支援包的開發,使得單個核心映象能支援多個系統。作為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

相關推薦

linux裝置dts移植

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

linux裝置dts移植

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

linux裝置dtspowerpc 平臺解析過程

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

Linux性能監控命令lsof

轉換 device symbol 能夠 基礎 打開 init 可執行文件 ive 1. lsof 命令介紹 lsof(list open files)是一個列出當前系統打開文件的工具。在linux環境下,任何事物都以文件的形式存在,通過文件不僅僅可以訪問常規數據,還可以訪問

iOS總結-UIView總結()方法

參考https://blog.csdn.net/zeng_zhiming/article/details/73469182 首先要回顧UIView繼承於UIResponder,UIResponder繼承NSObject 畫素轉換      主l

linux 高併發網路程式設計epoll

前言       I/O多路複用有很多種實現。在linux上,2.4核心前主要是select和poll,自Linux 2.6核心正式引入epoll以來,epoll已經成為了目前實現高效能網路伺服器的必備技術。儘管他們的使用方法不盡相同,但是本質上卻沒有什麼區別。本文將重點探

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核心主線瞭解dts

由這張圖可見,如果included file中的某項,被including file檔案定義了,則會使用後者的定義,也就是使用更上層更新的定義;如果沒有被定義,則新增進入。 1)bindings是device tree裡面可已包含的specific types and classes of devices。

Linux裝置語法【轉】

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

Linux裝置語法

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

第18章 ARM Linux裝置四(常用的OF API)

18.4 常用的OF API除了前文介紹的of_machine_is_compatible()、of_device_is_compatible()等常用函式以外,在Linux的BSP和驅動程式碼中,經常會使用到一些Linux中其他裝置樹的API,這些API通常被冠以of_字首

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

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

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裝置學習日記(裝置簡單介紹

一、linux裝置樹簡介1.    裝置樹是一種描述硬體的資料結構,它起源於openfirmware,採用裝置樹後,許多硬體的細節可以直接通過它傳遞給linux,而不需要在核心中進行大量冗餘編碼。2.    裝置樹由一系列被命名的節點(Node)和屬性(property)組成

Linux驅動】Linux裝置語法

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

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

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

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即

閱讀Linux裝置驅動模型原始碼 device結構體成員

【前言】         我們學習 Linux 裝置驅動,很多人在一開始往往急於想找到快速入門的方法,希望能有一個提綱挈領的使用說明來幫助我們快速理解 Linux 裝置驅動的設計思路和框架,從而擺脫掉 Linux 核心這頭龐然怪獸。我自己最初也是這樣。然而事與願違,如果學習

linux裝置gpio

#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/version.h> #include &