-設(shè)備樹介紹(四))
什么是設(shè)備樹三種文件格式設(shè)備樹工作原理與核心機(jī)制設(shè)備樹數(shù)據(jù)流架構(gòu)設(shè)備樹核心數(shù)據(jù)結(jié)構(gòu)設(shè)備樹與驅(qū)動(dòng)匹配機(jī)制DTS 語法基礎(chǔ)節(jié)點(diǎn)定義關(guān)鍵屬性詳解數(shù)據(jù)類型引用其他節(jié)點(diǎn)Phandle編寫一個(gè)簡(jiǎn)單的 LED 驅(qū)動(dòng)設(shè)備樹編譯設(shè)備樹調(diào)試技巧如何查看運(yùn)行時(shí)設(shè)備樹常用命令查看完整設(shè)備樹結(jié)構(gòu)?查看某個(gè)屬性的值?查看特定設(shè)備節(jié)點(diǎn)?使用 dtc 工具反編譯 DTB?什么是設(shè)備樹設(shè)備樹Device Tree是一種描述硬件配置的數(shù)據(jù)結(jié)構(gòu)它采用樹狀結(jié)構(gòu)以文本形式描述系統(tǒng)硬件資源包括CPU、內(nèi)存、總線、外設(shè)等。設(shè)備樹的核心思想是將硬件描述與操作系統(tǒng)內(nèi)核分離使得同一內(nèi)核 鏡像 能夠支持不同的硬件平臺(tái)。三種文件格式設(shè)備樹Device Tree主要包含三種文件格式每種格式在開發(fā)流程中扮演不同的角色后綴名稱說明.dtsDevice Tree Source人類可讀的文本源文件采用類似 C 語言的語法結(jié)構(gòu)。每個(gè)開發(fā)板通常對(duì)應(yīng)一個(gè)獨(dú)立的 .dts 文件用于描述該板卡的硬件配置。.dtsiDevice Tree Source Include設(shè)備樹頭文件用于定義 SoC系統(tǒng)級(jí)芯片的通用配置或公共模塊。多個(gè) .dts 文件可以引用同一個(gè) .dtsi 文件實(shí)現(xiàn)代碼復(fù)用。.dtbDevice Tree Blob編譯后的二進(jìn)制文件由 .dts 文件通過設(shè)備樹編譯器DTC生成。Bootloader 將其加載到內(nèi)存中并傳遞給 Linux 內(nèi)核使用。這三種文件構(gòu)成了設(shè)備樹從源碼編寫到最終使用的完整流程。設(shè)備樹工作原理與核心機(jī)制設(shè)備樹數(shù)據(jù)流架構(gòu)設(shè)備樹核心數(shù)據(jù)結(jié)構(gòu)// 內(nèi)核中設(shè)備樹核心數(shù)據(jù)結(jié)構(gòu)structdevice_node{constchar*name;// 節(jié)點(diǎn)名稱constchar*type;// 設(shè)備類型phandle phandle;// 節(jié)點(diǎn)句柄constchar*full_name;// 節(jié)點(diǎn)全路徑名structproperty*properties;// 屬性鏈表structdevice_node*parent;// 父節(jié)點(diǎn)structdevice_node*child;// 子節(jié)點(diǎn)structdevice_node*sibling;// 兄弟節(jié)點(diǎn)structkobjectkobj;// kobject用于sysfsunsignedlong_flags;// 內(nèi)部標(biāo)志位void*data;// 設(shè)備私有數(shù)據(jù)};structproperty{char*name;// 屬性名稱intlength;// 屬性值長(zhǎng)度void*value;// 屬性值指針structproperty*next;// 下一個(gè)屬性u(píng)nsignedlong_flags;// 內(nèi)部標(biāo)志位unsignedintunique_id;// 唯一ID};設(shè)備樹與驅(qū)動(dòng)匹配機(jī)制設(shè)備樹通過compatible屬性實(shí)現(xiàn)與驅(qū)動(dòng)的匹配// 設(shè)備樹中的定義mydevice0x10000000{compatiblevendor,device-model,generic-driver;reg0x100000000x1000;interrupts0254;};// 驅(qū)動(dòng)中的匹配表staticconststructof_device_idmy_driver_match[]{{.compatiblevendor,device-model},{.compatiblegeneric-driver},{}};MODULE_DEVICE_TABLE(of,my_driver_match);// 平臺(tái)驅(qū)動(dòng)結(jié)構(gòu)staticstructplatform_drivermy_driver{.probemy_probe,.removemy_remove,.driver{.namemy-device,.of_match_tablemy_driver_match,},};DTS 語法基礎(chǔ)節(jié)點(diǎn)定義dts /node-nameaddress{propertyvalue;};node-name節(jié)點(diǎn)名稱通常反映設(shè)備功能如 serial, i2c。address可選表示該設(shè)備在父總線上的基地址。{ … }花括號(hào)內(nèi)包含屬性和子節(jié)點(diǎn)。關(guān)鍵屬性詳解屬性說明示例?compatible?驅(qū)動(dòng)匹配標(biāo)識(shí)“rockchip,rk3568-pcie”, “snps,dw-pcie”?reg?寄存器地址/大小0x40000000 0x1000 (地址, 長(zhǎng)度)?interrupts?中斷描述GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH?clocks?時(shí)鐘引用clk_core, clk_bus?gpios?GPIO 引用gpio1 5 GPIO_ACTIVE_HIGH?status?啟用狀態(tài)“okay” (啟用), “disabled” (禁用)?pinctrl-0?引腳復(fù)用配置uart0_pins數(shù)據(jù)類型單元格Cells?用 包裹的 32 位整數(shù)。reg 0x1000 0x100;字符串?用 包裹。compatible “my-device”;字節(jié)數(shù)組?用 [ ] 包裹十六進(jìn)制。local-mac-address [00 11 22 33 44 55];字符串列表?compatible “a,b”, “c,d”;引用其他節(jié)點(diǎn)Phandle使用 label 引用其他節(jié)點(diǎn)常用于引腳配置pinctrl、時(shí)鐘、GPIO。pinctrl-0uart0_pins;// 引用名為 uart0_pins 的節(jié)點(diǎn) clocksclk_uart0;// 引用時(shí)鐘節(jié)點(diǎn)編寫一個(gè)簡(jiǎn)單的 LED 驅(qū)動(dòng)設(shè)備樹通常在 arch/arm64/boot/dts/rockchip/rk3568-your-board.dts 中添加/dts-v1/;#include rk3568.dtsi // 包含 SoC 基礎(chǔ)定義/{modelMy RK3568 Board;compatiblemyvendor,rk3568-board,rockchip,rk3568;/*1. 定義 GPIO LED 節(jié)點(diǎn) */ gpio-leds{compatiblegpio-leds;// 使用內(nèi)核自帶的 gpio-leds 驅(qū)動(dòng) led-user{labeluser-led;gpiosgpio3 RK_PD2 GPIO_ACTIVE_HIGH;// 引用 GPIO3 控制器 linux,default-triggerheartbeat;// 默認(rèn)心跳閃爍};};};/*2. 如果需要自定義引腳復(fù)用Pinctrl通常在pinctrl 節(jié)點(diǎn)下添加 */pinctrl{vcc3v3_pcie3: vcc3v3-pcie3-regulator{rockchip,pins3RK_PD2 RK_FUNC_GPIOpcfg_pull_none;};};編譯設(shè)備樹在內(nèi)核源碼根目錄執(zhí)行makeARCHarm64CROSS_COMPILEaarch64-linux-gnu- rk3568-your-board.dtb生成的 rk3568-your-board.dtb 即為最終文件。調(diào)試技巧如何查看運(yùn)行時(shí)設(shè)備樹Linux 啟動(dòng)后會(huì)將解析后的設(shè)備樹暴露在 ?/proc/device-tree/? 目錄下。這是調(diào)試的神器。常用命令查看完整設(shè)備樹結(jié)構(gòu)?ls/proc/device-tree/# 你會(huì)看到 chosen,memory,soc,aliases 等目錄查看某個(gè)屬性的值?# 查看內(nèi)核命令行參數(shù) cat/proc/device-tree/chosen/bootargs # 查看根節(jié)點(diǎn)的 compatible cat/proc/device-tree/compatible查看特定設(shè)備節(jié)點(diǎn)?# 假設(shè)你的 LED 節(jié)點(diǎn)路徑是/gpio-leds/led-user cat/proc/device-tree/gpio-leds/led-user/gpios # 注意二進(jìn)制數(shù)據(jù)直接 cat 可能亂碼可用 hexdump hexdump-C/proc/device-tree/gpio-leds/led-user/gpios使用 dtc 工具反編譯 DTB?如果你只有 .dtb 文件想看看里面寫了什么dtc-I dtb-O dts-o output.dts input.dtb