裝置驅動程式與核心模組

裝置樹(device tree)

在個人電腦上,核心可以問 PCI 與 USB 匯流排「插了什麼?」,它們回以一份清單——硬體是自我描述的。但在許多嵌入式板子上(想想手機或路由器晶片),硬體就只是擺在那裡:某個固定位址上的 UART、另一處的 I2C 控制器,接到特定的中斷線,卻沒有辦法列舉它們。核心要怎麼得知有什麼、在哪裡?裝置樹是一個資料檔,向核心描述那些不可發現的硬體。

具體而言,裝置樹是一棵節點構成的樹,每個節點描述一塊硬體:它的類型(一個 'compatible' 字串,如 "ti,omap4-uart")、它暫存器的實體位址、它用哪個中斷、它的時脈等等。它以原始碼格式(.dts)撰寫、編譯成一個精簡的二進位塊(.dtb),並由開機載入器在開機時交給核心。核心開機時走遍這棵樹;對每個節點,它找出 'compatible' 字串相符的驅動程式,並以該節點的屬性呼叫該驅動程式的 probe,於是驅動程式從樹中得知它的暫存器位址與 IRQ,而非把它們寫死。在 x86 與許多伺服器上,等價的角色由 ACPI 表扮演,韌體為了同樣的目的——描述固定硬體與電源管理——而提供它們。

裝置樹之所以重要,是因為它把核心與板子專屬的接線解耦:一份核心二進位檔可以在許多板子上執行,每塊板子各自提供自己的裝置樹,而不必把位址烤進程式碼。一個誠實的區分:裝置樹(與 ACPI)是給無法自我宣告的硬體用的。像 PCI 與 USB 這種可發現的匯流排不需要它——它們在執行期被列舉。而裝置樹只描述硬體;它不是驅動程式,也不含程式碼。.dts 裡一個錯誤的位址或中斷會產生一個能 probe、卻對錯誤地方溝通的驅動程式。

// 一個裝置樹節點(.dts),描述一個 UART: uart0: serial@4806a000 { compatible = "ti,omap4-uart"; // 哪個驅動程式相符 reg = <0x4806a000 0x100>; // 暫存器位址、大小 interrupts = <72>; // 哪條 IRQ 線 }; // 核心把 'compatible' 媒合到驅動程式並 probe 它

一個裝置樹節點告訴核心某裝置的類型、暫存器位址與 IRQ——是資料而非程式碼——讓相符的驅動程式能 probe 它。

裝置樹與 ACPI 只描述不可發現的硬體且不含驅動程式碼;可發現的匯流排(PCI、USB)在執行期被列舉,兩者都不需要。.dts 裡錯誤的 reg/interrupt 會把一個本來正確的驅動程式導向錯誤的地方。

又称
DTflattened device treeFDT裝置樹