IoT之嵌入式Linux設(shè)備樹機(jī)制
Part 01
● Linux設(shè)備樹機(jī)制的介紹 ●
1.1 概念
設(shè)備樹(device tree)是一種描述硬件資源的數(shù)據(jù)結(jié)構(gòu),起源于Open Firmware(OF:開源固件)。在Linux kernel v2.6之前的版本,關(guān)于ARM架構(gòu)的板級(jí)硬件資源均通過.c和.h文件寫“死”在arch/arm/plat-xxx和arch/arm/mach-xxx目錄下,在開發(fā)一款設(shè)備時(shí),Linux kernel中充斥著許多無用的硬件信息,不利于閱讀和維護(hù)。在Linux ARM kernel v3.x之后正式引入設(shè)備樹機(jī)制,主要是為減少這類無用的硬件板級(jí)信息被寫入Linux kernel中污染內(nèi)核,有了設(shè)備樹,則可通過它來將所需的硬件信息傳遞給Linux kernel。
1.2 組成
設(shè)備樹主要包含dts(device tree source,源文件)、dtc(device tree compiler,編譯工具)和dtb(device tree blob,二進(jìn)制文件)。
dts 是設(shè)備樹描述的源文件,在ARM架構(gòu)下,一個(gè)dts對(duì)應(yīng)一個(gè)設(shè)備,一般位于arch/arm(64)/boot/dts目錄下,該文件一般會(huì)有包含對(duì)應(yīng)名稱的.dtsi文件,類似于c語言的頭文件,主要是一些SOC的宏定義共性部分。
dtc 是設(shè)備樹的編譯工具,類似于gcc等編譯器,但與gcc不同的是dtc無需外部安裝,是由內(nèi)核自帶的??梢詫?dts文件編譯成.dtb文件。
dtb 是設(shè)備樹二進(jìn)制文件,可被Linux kernel識(shí)別解析,也可被bootloader解析。
dtbo 是overlay編譯出來的二進(jìn)制文件。
dts、dtc和dtb三者間的關(guān)系如下圖:
Part 02
● 設(shè)備樹框架和dts文件語法格式 ●
2.1 設(shè)備樹基本框架
設(shè)備樹文件基本結(jié)構(gòu)主要有以下幾部分,其形式有點(diǎn)類似xml文件。
- 單根節(jié)點(diǎn)(root):/
- 節(jié)點(diǎn)名稱:圖中的"node1"和"node2"
- 子節(jié)點(diǎn):"child-node1"和"child-node2"
- 節(jié)點(diǎn)地址:node@xxx
- 屬性(property):是一組鍵值對(duì),包括屬性名稱(property name)和屬性值(property value)
- 標(biāo)簽(label,可選項(xiàng))
??https://elinux.org/Device_Tree_Usage#Basic_Data_Format??
值得注意的是,“/”是根節(jié)點(diǎn),每個(gè)設(shè)備樹文件僅有一個(gè),當(dāng)在設(shè)備樹中發(fā)現(xiàn)有多個(gè)根節(jié)點(diǎn)時(shí),在編譯過程中這些根節(jié)點(diǎn)會(huì)合并成一個(gè)。
2.2 dts文件語法格式
與c語言類似,dts同樣支持頭文件,其頭文件擴(kuò)展名為.dtsi,一般通過#include xxx來引用。
例如,以全志H616這款芯片為例,基于Linux v4.9版本的orangepi開發(fā)板的時(shí)鐘節(jié)點(diǎn)(部分)如下:
上述中,特別重要的compatible屬性,它可以以“,”格式指定名稱的優(yōu)先選擇。設(shè)備樹中每個(gè)代表設(shè)備的節(jié)點(diǎn)都要有一個(gè)compatible屬性,它是OS用于決定綁定到設(shè)備驅(qū)動(dòng)的關(guān)鍵特征。
Part 03
● 設(shè)備樹的修改與內(nèi)核編譯安裝 ●
在編寫模塊的驅(qū)動(dòng)程序時(shí),為不影響內(nèi)核結(jié)構(gòu),通常在外部目錄下建立一個(gè)用于存放編寫的驅(qū)動(dòng)源碼和編譯生成的.ko的文件夾,生成的.ko可以在系統(tǒng)啟動(dòng)后單獨(dú)加載運(yùn)行,且無需和內(nèi)核一起編譯,方便更新。其流程一般為:makefile文件編寫,接著進(jìn)行驅(qū)動(dòng)源碼編寫(可找優(yōu)秀的架構(gòu)進(jìn)行修改,填充細(xì)節(jié),如compatible,讀、寫操作等),然后編譯生成.ko文件,進(jìn)一步修改與單板相關(guān)的設(shè)備樹文件(.dts),在.dts文件中添加或刪除相應(yīng)的設(shè)備節(jié)點(diǎn)信息,最后編譯整個(gè)內(nèi)核文件,當(dāng)內(nèi)核編譯完成后,使用如下命令卸載舊版本的內(nèi)核與安裝新版本內(nèi)核:
重啟單板后,用uname -a 命令查看內(nèi)核信息,在新編譯的內(nèi)核上,用insmod 命令將生成的.ko模塊加載上,cat 命令查看設(shè)備節(jié)點(diǎn)信息。
需要注意的是,設(shè)備樹的使用需要在編譯kernel時(shí)做好對(duì)應(yīng)的配置,還需bootloader支持,否則也無法將數(shù)據(jù)結(jié)構(gòu)傳參給kernel。