日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

设备树的引入及简明教程

發(fā)布時間:2025/4/5 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 设备树的引入及简明教程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

    • 1 設備樹的引入與作用
    • 2 設備樹的語法
      • 2.1 設備樹語法概覽
      • 2.2 Devicetree 格式
        • 2.2.1 DTS 文件的格式
        • 2.2.2 node 的格式
        • 2.2.3 properties 的格式
      • 2.3 dts 文件包含 dtsi 文件
      • 2.4 常用屬性
        • 2.4.1 #address-cells、#size-cells
        • 2.4.2 compatible
        • 2.4.3 model
        • 2.4.4 status
        • 2.4.5 reg
        • 2.4.6 name(過時了,建議不用)
        • 2.4.7 device_type(過時了,建議不用)
      • 2.5 常用的屬性
        • 2.5.1 根節(jié)點
        • 2.5.2 CPU 節(jié)點
        • 2.5.3 memory 節(jié)點
        • 2.5.4 chosen 節(jié)點
    • 3 編譯、更換設備樹
      • 3.1 在內(nèi)核中直接 make
      • 3.2 手工編譯
      • 3.3 給開發(fā)板更換設備樹文件

1 設備樹的引入與作用

以 LED 驅(qū)動為例,如果你要更換 LED 所用的 GPIO 引腳,需要修改驅(qū)動程序源碼、重新編譯驅(qū)動、重新加載驅(qū)動。在內(nèi)核中,使用同一個芯片的板子,它們所用的外設資源不一樣,比如 A 板用 GPIO A,B 板用 GPIO B。而 GPIO 的驅(qū)動程序既支持 GPIO A 也支持 GPIO B,你需要指定使用哪一個引腳,怎么指定?在 c 代碼中指定。

隨著 ARM 芯片的流行,內(nèi)核中針對這些 ARM 板保存有大量的、沒有技術(shù)含量的文件。Linus 大發(fā)雷霆:“this whole ARM thing is a f*cking pain in the ass”。于是,Linux 內(nèi)核開始引入設備樹。設備樹并不是重新發(fā)明出來的,在 Linux 內(nèi)核中其他平臺如 PowerPC,早就使用設備樹來描述硬件了。Linus 發(fā)火之后,內(nèi)核開始全面使用設備樹來改造,神人就神人。

有一種錯誤的觀點,說“新驅(qū)動都是用設備樹來寫了”。設備樹不可能用來寫驅(qū)動。請想想,要操作硬件就需要去操作復雜的寄存器,如果設備樹可以操作寄存器,那么它就是“驅(qū)動”,它就一樣很復雜。
設備樹只是用來給內(nèi)核里的驅(qū)動程序,指定硬件的信息。比如 LED 驅(qū)動,在內(nèi)核的驅(qū)動程序里去操作寄存器,但是操作哪一個引腳?這由設備樹指定。

你可以事先體驗一下設備樹,板子啟動后執(zhí)行下面的命令:
ls /sys/firmware/

devicetree fdt

/sys/firmware/devicetree 目錄下是以目錄結(jié)構(gòu)程現(xiàn)的 dtb 文件, 根節(jié)點對應 base 目錄, 每一個節(jié)點對應一個目錄, 每一個屬性對應一個文件。

這些屬性的值如果是字符串,可以使用 cat 命令把它打印出來;對于數(shù)值,可以用 hexdump 把它打印出來。

一個單板啟動時,u-boot 先運行,它的作用是啟動內(nèi)核。U-boot 會把內(nèi)核和設備樹文件都讀入內(nèi)存,然后啟動內(nèi)核。在啟動內(nèi)核時會把設備樹在內(nèi)存中的地址告訴內(nèi)核。


2 設備樹的語法

2.1 設備樹語法概覽

為什么叫“樹”?


怎么描述這棵樹?
我們需要編寫設備樹文件(dts: device tree source),它需要編譯為 dtb(device tree blob)文件,內(nèi)核使用的是 dtb 文件。dts 文件是根本,它的語法很簡單。

下面是一個設備樹示例:

它對應的 dts 文件如下:

2.2 Devicetree 格式

2.2.1 DTS 文件的格式

DTS 文件布局(layout):

/dts-v1/; // 表示版本 [memory reservations] // 格式為: /memreserve/ <address> <length>; / {[property definitions][child nodes] };

2.2.2 node 的格式

設備樹中的基本單元,被稱為“node”,其格式為:

[label:] node-name[@unit-address] {[properties definitions][child nodes] };

label 是標號,可以省略。label 的作用是為了方便地引用 node,比如:

/dts-v1/; / { uart0: uart@fe001000 {compatible="ns16550";reg=<0xfe001000 0x100>; }; };

可以使用下面 2 種方法來修改 uart@fe001000 這個 node:

// 在根節(jié)點之外使用 label 引用 node: &uart0 {status = “disabled”; }; // 或在根節(jié)點之外使用全路徑: &{/uart@fe001000} {status = “disabled”; };

2.2.3 properties 的格式

簡單地說,properties 就是“name=value”,value 有多種取值方式。

Property 格式 1:
[label:] property-name = value;

Property 格式 2(沒有值):
[label:] property-name;

Property 取值只有 3 種:

  • arrays of cells(1 個或多個 32 位數(shù)據(jù), 64 位數(shù)據(jù)使用 2 個 32 位數(shù)據(jù)表示)
  • string(字符串),
  • bytestring(1 個或多個字節(jié))

示例:
a. Arrays of cells : cell 就是一個 32 位的數(shù)據(jù),用尖括號包圍起來interrupts = <17 0xc>;
b. 64bit 數(shù)據(jù)使用 2 個 cell 來表示,用尖括號包圍起來:clock-frequency = <0x00000001 0x00000000>;
c. A null-terminated string (有結(jié)束符的字符串),用雙引號包圍起來:compatible = "simple-bus";
d. A bytestring(字節(jié)序列) ,用中括號包圍起來:
local-mac-address = [00 00 12 34 56 78]; // 每個 byte 使用 2 個16 進制數(shù)來表示
local-mac-address = [000012345678]; // 每個 byte 使用 2 個 16進制數(shù)來表示
e. 可以是各種值的組合, 用逗號隔開:
compatible = "ns16550", "ns8250";
example = <0xf00f0000 19>, "a strange property format";

2.3 dts 文件包含 dtsi 文件

設備樹文件不需要我們從零寫出來,內(nèi)核支持了某款芯片比如 imx6ull,在內(nèi)核的 arch/arm/boot/dts目錄下就有了能用的設備樹模板,一般命名為 xxxx.dtsi。“i”表示“include”,被別的文件引用的。

我們使用某款芯片制作出了自己的單板,所用資源跟 xxxx.dtsi 是大部分相同,小部分不同,所以需要引腳 xxxx.dtsi 并修改。dtsi 文件跟 dts 文件的語法是完全一樣的。dts 中可以包含.h 頭文件,也可以包含 dtsi 文件,在.h 頭文件中可以定義一些宏。

示例:

/dts-v1/; #include <dt-bindings/input/input.h> #include "imx6ull.dtsi" / {// …… };

2.4 常用屬性

2.4.1 #address-cells、#size-cells

cell 指一個 32 位的數(shù)值,address-cells:address 要用多少個 32 位數(shù)來表示;size-cells:size 要用多少個 32 位數(shù)來表示。

比如一段內(nèi)存,怎么描述它的起始地址和大小?

下例中,address-cells 為 1,所以 reg 中用 1 個數(shù)來表示地址,即用 0x80000000 來表示地址;size cells 為 1,所以 reg 中用 1 個數(shù)來表示大小,即用 0x20000000 表示大小:

/ { #address-cells = <1>; #size-cells = <1>; memory { reg = <0x80000000 0x20000000>;}; };

2.4.2 compatible

“compatible”表示“兼容”,對于某個 LED,內(nèi)核中可能有 A、B、C 三個驅(qū)動都支持它,那可以這樣
寫:

led { compatible = “A”, “B”, “C”; };

內(nèi)核啟動時,就會為這個 LED 按這樣的優(yōu)先順序為它找到驅(qū)動程序:A、B、C。

根節(jié)點下也有 compatible 屬性,用來選擇哪一個“machine desc”:一個內(nèi)核可以支持 machine A,也支持 machine B,內(nèi)核啟動后會根據(jù)根節(jié)點的 compatible 屬性找到對應的 machine desc 結(jié)構(gòu)體,執(zhí)行其中的初始化函數(shù)。

compatible 的值,建議取這樣的形式:“manufacturer,model”,即“廠家名,模塊名”。

注意:machine desc 的意思就是“機器描述”,學到內(nèi)核啟動流程時才涉及。

2.4.3 model

model 屬性與 compatible 屬性有些類似,但是有差別。compatible 屬性是一個字符串列表,表示可以你的硬件兼容 A、B、C 等驅(qū)動;model 用來準確地定義這個硬件是什么。

比如根節(jié)點中可以這樣寫:

/ { compatible = "samsung,smdk2440", "samsung,mini2440"; model = "jz2440_v3"; };

它表示這個單板,可以兼容內(nèi)核中的“smdk2440”,也兼容“mini2440”。從 compatible 屬性中可以知道它兼容哪些板,但是它到底是什么板?用 model 屬性來明確。

2.4.4 status

dtsi 文件中定義了很多設備,但是在你的板子上某些設備是沒有的。這時你可以給這個設備節(jié)點添加一個 status 屬性,設置為“disabled”:

&uart1 {status = "disabled"; };

2.4.5 reg

reg 的本意是 register,用來表示寄存器地址。但是在設備樹里,它可以用來描述一段空間。反正對于 ARM 系統(tǒng),寄存器和內(nèi)存是統(tǒng)一編址的,即訪問寄存器時用某塊地址,訪問內(nèi)存時用某塊地址,在訪問方法上沒有區(qū)別。

reg 屬性的值,是一系列的“address size”,用多少個 32 位的數(shù)來表示 address 和 size,由其父節(jié)點的#address-cells、#size-cells 決定。

示例:

/dts-v1/; / { #address-cells = <1>; #size-cells = <1>; memory { reg = <0x80000000 0x20000000>; }; };

2.4.6 name(過時了,建議不用)

它的值是字符串,用來表示節(jié)點的名字。在跟 platform_driver 匹配時,優(yōu)先級最低。
compatible 屬性在匹配過程中,優(yōu)先級最高。

2.4.7 device_type(過時了,建議不用)

它的值是字符串,用來表示節(jié)點的類型。在跟 platform_driver 匹配時,優(yōu)先級為中。
compatible 屬性在匹配過程中,優(yōu)先級最高。

2.5 常用的屬性

2.5.1 根節(jié)點

dts 文件中必須有一個根節(jié)點:

/dts-v1/; / { model = "SMDK24440"; compatible = "samsung,smdk2440"; #address-cells = <1>; #size-cells = <1>; };

根節(jié)點中必須有這些屬性:

#address-cells // 在它的子節(jié)點的 reg 屬性中, 使用多少個 u32 整數(shù)來描述地址(address) #size-cells // 在它的子節(jié)點的 reg 屬性中, 使用多少個 u32 整數(shù)來描述大小(size) compatible // 定義一系列的字符串, 用來指定內(nèi)核中哪個 machine_desc 可以支持本設備// 即這個板子兼容哪些平臺// uImage : smdk2410 smdk2440 mini2440 ==> machine_descmodel // 咱這個板子是什么// 比如有 2 款板子配置基本一致, 它們的 compatible 是一樣的// 那么就通過 model 來分辨這 2 款板子

2.5.2 CPU 節(jié)點

一般不需要我們設置,在 dtsi 文件中都定義好了:

cpus { #address-cells = <1>; #size-cells = <0>; cpu0: cpu@0 {.......} };

2.5.3 memory 節(jié)點

芯片廠家不可能事先確定你的板子使用多大的內(nèi)存,所以 memory 節(jié)點需要板廠設置,比如:

memory { reg = <0x80000000 0x20000000>; };

2.5.4 chosen 節(jié)點

我們可以通過設備樹文件給內(nèi)核傳入一些參數(shù),這要在 chosen 節(jié)點中設置 bootargs 屬性:

chosen { bootargs = "noinitrd root=/dev/mtdblock4 rw init=/linuxrc console=ttySAC0,115200"; };

3 編譯、更換設備樹

我們一般不會從零寫 dts 文件,而是修改。程序員水平有高有低,改得對不對?需要編譯一下。并且內(nèi)
核直接使用 dts 文件的話,就太低效了,它也需要使用二進制格式的 dtb 文件。

3.1 在內(nèi)核中直接 make

設置 ARCH、CROSS_COMPILE、PATH 這三個環(huán)境變量后,進入 ubuntu 上板子內(nèi)核源碼的目錄,執(zhí)行如下命令即可編譯 dtb 文件:
make dtbs V=1

以野火的 IMX6UL 為例,可以看到如下輸出:

mkdir -p arch/arm/boot/dts/ ; arm-linux-gnueabihf-gcc -E -Wp,-MD,arch/arm/boot/dts/.imx6ull-14x14-ebf-mini.dtb.d.pre.tmp -nostdinc-I./arch/arm/boot/dts -I./arch/arm/boot/dts/include -I./drivers/of/testcase-data -undef -D__DTS__ -x assembler-with-cpp -o arch/arm/boot/dts/.imx6ull-14x14-ebf-mini.dtb.dts.tmp arch/arm/boot/dts/imx6ull-14x14-ebf-mini.dts ; ./scripts/dtc/dtc -O dtb -o arch/arm/boot/dts/imx6ull-14x14-ebf-mini.dtb-b 0 -i arch/arm/boot/dts/ -Wno-unit_address_vs_reg -d arch/arm/boot/dts/.imx6ull-14x14-ebf-mini.dtb.d.dtc.tmp arch/arm/boot/dts/.imx6ull-14x14-ebf-mini.dtb.dts.tmp ;

它首先用 arm-linux-gnueabihf-gcc 預處理 dts 文件,把其中的.h 頭文件包含進來,把宏展開。然后使用 scripts/dtc/dtc 生成 dtb 文件。

可見,dts 文件之所以支持“#include”語法,是因為 arm-linux-gnueabihf-gcc 幫忙。

如果只用 dtc 工具,它是不支持”#include”語法的,只支持“/include”語法。

3.2 手工編譯

除非你對設備樹比較了解,否則不建議手工使用 dtc 工具直接編譯。

內(nèi)核目錄下 scripts/dtc/dtc 是設備樹的編譯工具,直接使用它的話,包含其他文件時不能使用“#include”,而必須使用“/incldue”。

編譯、反編譯的示例命令如下,“-I”指定輸入格式,“-O”指定輸出格式,“-o”指定輸出文件:

./scripts/dtc/dtc -I dts -O dtb -o tmp.dtb arch/arm/boot/dts/xxx.dts // 編譯 dts 為 dtb
./scripts/dtc/dtc -I dtb -O dts -o tmp.dts arch/arm/boot/dts/xxx.dtb // 反編譯 dtb 為 dts

3.3 給開發(fā)板更換設備樹文件

對于 100ask-am335x 單板 :
設備樹文件是:內(nèi)核源碼目錄中 arch/arm/boot/dts/100ask-am335x.dtb,要更換板子上的設備樹文件,啟動板子后,更換這個文件:/boot/100ask-am335x.dtb。

總結(jié)

以上是生活随笔為你收集整理的设备树的引入及简明教程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 在线看中文字幕 | 日本在线观看www | 国产 日韩 欧美 成人 | 欧美xxxx69 | 中文字幕人妻丝袜二区 | 国产成人在线电影 | 国产成人亚洲欧洲在线 | 欧美日韩一区二区在线播放 | 亚洲成人网在线播放 | 欧美精品123区 | 女人叉开腿让男人桶 | 在线亚洲观看 | 欧美日韩欧美日韩在线观看视频 | 亚洲成av人影院 | 亚洲视频第一页 | 欧美性一区二区 | 亚色中文| se婷婷| 久久少妇av | 久久免费成人 | 精品一区二区三区在线免费观看 | 黄色片上床 | 欧美一区二区影院 | 奇米影视首页 | 国产婷婷色一区二区在线观看 | 亚洲成熟少妇视频在线观看 | 久久99国产精品久久99果冻传媒 | 精品熟妇视频一区二区三区 | 91精品国产一区二区无码 | 九九影视理伦片 | 久久精品一二区 | 3d动漫精品啪啪一区二区下载 | 国产午夜网站 | 精品免费在线观看 | 污污小说在线观看 | 欧美区在线观看 | jizz一区二区三区 | 国产亚洲女人久久久久毛片 | 午夜免费福利网站 | 亚洲网址在线观看 | 久久精品国产77777蜜臀 | 欧美日p视频| 日本天堂网在线观看 | 国产黄a三级三级看三级 | 精品视频区| 麻豆自拍视频 | 亚洲综合网址 | 性久久久久久久久久久久 | 天海翼av在线 | 亚洲一线视频 | 色拍拍视频 | 亚洲精品乱码久久久久久写真 | 草一色| 久久爱一区 | 亚洲三区在线 | 青青草午夜 | 国产成人 综合 亚洲 | youjizzcom日本| 久久机热 | 美女扒开尿口给男人看 | 国色综合 | 爆操日本美女 | 翔田千里x88aⅴ | 在线91观看 | 中文字幕有码av | 国产一级特黄视频 | 91国产在线免费观看 | 亚洲图片 欧美 | 黄色一级免费 | 看黄色一级 | 欧美a v在线播放 | 亚洲欧美偷拍视频 | 青春草在线视频观看 | 欧美黄色a级片 | 国产一区二区在线免费观看视频 | 国产黑丝在线观看 | 琪琪色在线视频 | 欧美色偷偷 | 日本在线一区二区三区 | 91福利在线导航 | 精品人妻少妇一区二区 | 丝袜熟女一区二区 | av在线中文| 就爱啪啪网 | 国产伦精品一区二区三区 | 亲子伦视频一区二区三区 | 一级黄色片免费在线观看 | 美腿丝袜亚洲综合 | 免费簧片在线观看 | 天天做天天干 | 日本精品视频网站 | 色戒电影未测减除版 | 老女人乱淫| 免费一级特黄毛大片 | 美女污污网站 | 成人精品在线视频 | 日韩精品三区 | 国产精品精品久久久久久 | 亚洲日本片 |