
——驅動負責怎么干活,設備樹負責告訴它活在哪
設備樹是很多人學嵌入式 Linux 時的第一個攔路虎。
你明明只是想點個 LED、讀個按鍵、掛個 I2C 傳感器,結果教程一上來就讓你改 .dts、看 compatible、寫 reg、配 interrupts。剛從裸機或 RTOS 過來的人,很容易覺得這東西繞。
裸機里我直接寫寄存器地址不就完了嗎?為什么 Linux 非要搞一套設備樹?
其實
設備樹解決的是“硬件描述”和“驅動邏輯”分離的問題。
驅動不要寫死某塊板子的所有細節。設備樹負責告訴內核:這塊板子上到底有什么硬件,它們掛在哪,地址是多少,中斷怎么接。
假設你有一個 I2C 溫度傳感器。裸機里你可能會這么想:I2C 地址是 0x48,掛在 I2C1 上,中斷腳接 GPIOA3,那我直接在驅動里寫死不就好了?
如果只有一塊板,這么做確實簡單。
但 Linux 面對的不是一塊板。一個 SoC 可能被做成十幾種開發板、幾十種產品。傳感器可能掛在 I2C1,也可能掛在 I2C3;中斷腳可能接 GPIOA3,也可能接 GPIOB7;有的板有這個傳感器,有的板根本沒有。
如果這些都寫進驅動里,驅動很快會變成這樣:
這就不是驅動了,這是板卡大雜燴。
設備樹就是為了解決這個問題:板子的硬件差異寫在設備樹里,驅動只關心這個設備應該怎么工作。
設備樹不是描述軟件邏輯的,它描述硬件。
常見內容包括:
compatible | |
reg | |
interrupts | |
clocks | |
gpios | |
status | |
你可以把設備樹理解成板級硬件說明書,只不過這份說明書不是給人看的,而是給內核看的。
比如一個驅動問:“我負責的設備在哪?”設備樹回答:“這個設備在 I2C1,地址 0x48,中斷接 GPIOA3,compatible 是 xxx。”
然后內核根據 compatible 把設備和驅動匹配起來。
compatible 是設備樹里最關鍵的字段之一。
它的作用可以簡單理解為:
告訴內核:這個設備和哪個驅動兼容。
Linux 驅動里通常會有一個匹配表,里面寫著自己支持哪些 compatible 字符串。內核啟動時,會拿設備樹里的設備節點去和驅動匹配。匹配上了,就調用驅動的 probe 函數。
流程大概是這樣:

所以如果你設備樹里的 compatible 寫錯了,驅動可能根本不會 probe。很多新手調驅動調半天,最后發現不是代碼沒執行,而是設備和驅動壓根沒匹配上。
這個分工一定要想清楚:
設備樹不應該寫業務邏輯。
驅動也不應該寫死板級連接。
這就是設備樹的核心價值。
你會在設備樹里經常看到:
這個字段很直白,就是控制設備是否啟用。
很多 SoC 的 .dtsi 文件會把芯片內部控制器都描述出來,但默認可能是 disabled。具體到某塊板子,如果這個控制器真的用上了,就在板級 .dts 里把它改成 okay,并補上引腳、外設節點等信息。
這也是設備樹分層的一個好處:
.dtsi 描述芯片公共硬件.dts 描述具體板子的硬件連接SoC 是同一個,但板子可以不同。
設備樹很重要,但不要把它當成萬能配置文件。
它適合描述硬件事實,不適合塞業務策略。比如這個 GPIO 接了哪個按鍵,適合放設備樹;但按下這個按鍵以后進入哪個業務頁面,就不該放設備樹。
一個簡單判斷是:
如果換一套應用業務,這個信息仍然是硬件事實,那它適合放設備樹。
比如 I2C 地址、中斷腳、供電 GPIO,這些是硬件事實。至于產品邏輯、協議規則、業務策略,那是應用層或驅動參數該考慮的事。
設備樹看起來繞,但它解決的問題很現實:
同一個驅動,要適配不同板子的硬件連接。
它把“這塊板子有什么硬件、怎么連接”從驅動里拿出來,交給設備樹描述。驅動只負責“這個設備怎么工作”。
記住這幾句話:
compatible 決定設備和驅動怎么匹配reg 描述地址interrupts 描述中斷status 決定設備是否啟用.dtsi 偏芯片公共描述,.dts 偏板級描述你第一次改設備樹時,最容易卡在哪里?compatible、reg,還是 pinctrl?