前邊講解了內(nèi)核編譯選項(xiàng)的配置,這一節(jié)我們?cè)敿?xì)講一下設(shè)備樹(shù)。設(shè)備樹(shù)的知識(shí)是Linux驅(qū)動(dòng)開(kāi)發(fā)人員必備的技能,我們現(xiàn)在使用的Linux內(nèi)核,絕大多數(shù)都是支持設(shè)備樹(shù)功能的,掌握設(shè)備樹(shù)是軟件嵌入式工程師必備的一項(xiàng)技能。
設(shè)備樹(shù)的起源
設(shè)備樹(shù)(Device Tree)是一種描述硬件資源的數(shù)據(jù)結(jié)構(gòu),它由uboot傳遞給Linux內(nèi)核,被內(nèi)核解析,內(nèi)核根據(jù)設(shè)備樹(shù)中的硬件描述信息加載利用相應(yīng)驅(qū)動(dòng)資源。在引入設(shè)備樹(shù)之前,Linux內(nèi)核中充斥著大量的用于描述板級(jí)硬件信息的文件,擁有不同硬件資源的板卡 ,都有其對(duì)應(yīng)的板級(jí)文件或者冗余文件,隨著Linux內(nèi)核支持的板卡越來(lái)越多,板級(jí)文件也越來(lái)越多。尤其是一些冗余的文件信息導(dǎo)致了內(nèi)核的臃腫,為了解決這一問(wèn)題Linus Torvalds在2011年3月17日的ARM Linux郵件列表宣稱“this whole ARM thing is a fucking pain in the ass”,因此,ARM Linux社區(qū)作出了回應(yīng),引入了設(shè)備樹(shù)Device Tree,這樣一來(lái)許多硬件的細(xì)節(jié)可以直接透過(guò)設(shè)備樹(shù)傳遞給Linux內(nèi)核,而不再需要在內(nèi)核中進(jìn)行大量的冗余編碼來(lái)適配不同的板卡。
設(shè)備樹(shù)組成和結(jié)構(gòu)及dts、dtb、dtsi
設(shè)備樹(shù)Device Tree由一系列被命名的節(jié)點(diǎn)(node)和屬性(property)組成,而節(jié)點(diǎn)本身可包含子節(jié)點(diǎn)。所謂屬性,其實(shí)就是成對(duì)出現(xiàn)的name和value。在設(shè)備樹(shù)中,可描述的信息包括:
一、CPU的數(shù)量和類別;
二、內(nèi)存基地址和大小;
三、總線和橋;
四、外設(shè)連接;
五、中斷控制器和中斷使用情況;
六、GPIO控制器和GPIO使用情況;
七、Clock控制器和Clock使用情況;
這種以樹(shù)狀節(jié)點(diǎn)的方式描述一個(gè)設(shè)備的各種硬件信息:CPU、GPIO、時(shí)鐘、中斷、內(nèi)存等,形成類似文本文件,很好的解決了這些問(wèn)題。
它基本上就是畫一棵電路板上CPU、總線、設(shè)備組成的樹(shù),uboot在啟動(dòng)的時(shí)候會(huì)將這棵樹(shù)傳遞給內(nèi)核,然后內(nèi)核可以識(shí)別這棵樹(shù),并根據(jù)它展開(kāi)出Linux內(nèi)核中的platform_device、i2c_client、spi_device等設(shè)備,而這些設(shè)備用到的內(nèi)存、IRQ等資源,也被傳遞給了內(nèi)核,內(nèi)核會(huì)將這些資源綁定給展開(kāi)的相應(yīng)的設(shè)備。
通常由.dts文件以文本方式對(duì)系統(tǒng)設(shè)備樹(shù)進(jìn)行描述,經(jīng)過(guò)Device Tree Compiler(dtc)將dts文件轉(zhuǎn)換成二進(jìn)制文件binary device tree blob(dtb),.dtb文件可由Linux內(nèi)核解析,有了device tree就可以在不改動(dòng)Linux內(nèi)核的情況下,對(duì)不同的平臺(tái)實(shí)現(xiàn)無(wú)差異的支持,硬件有變動(dòng)時(shí)不需要重新編譯內(nèi)核或驅(qū)動(dòng)程序,只需更換相應(yīng)的dts文件即可。dtsi文件被dts文件包含引用,這類似于C語(yǔ)言C文件include包含.h文件,對(duì)于同一個(gè)節(jié)點(diǎn)的設(shè)置情況,dts中的配置會(huì)覆蓋dtsi中的配置。