先分析一個完整的設備樹,是怎么表達各種外設信息的。
以imux6ull開發板為例進行說明。
這個文件里就一個設備信息
才這么點內容,是不是出問題了?當然不是,我們知道dts文件是可包含的,所以,最終形成的一個完整文件就是把各文件給整合起來,以根結點為起始的一個文件。 根據前面了解到的知識,這里應該是對已有外設的信息的追加,不過我們暫時不管這里,而是根據包含關系找到起始的地方,然后順著往下看。
梳理后,有如下包含關系:
imx6ull-14x14-evk-emmc.dts包含了imx6ull-14x14-evk.dts;
imx6ull-14x14-evk.dts又包含了imx6ull.dtsi;
imx6ull.dtsi又包含了skeleton.dtsi;
skeleton:骨骼,骨架;框架;梗概,綱要
再往上就沒有了
skeleton.dtsi
先看看skeleton.dtsi文件
skeleton.dtsi 文件是用于設備樹的通用頭文件,通常被包含在其他設備樹源文件(.dts 或 .dtsi)中。它定義了一些基本節點和屬性,以滿足設備樹的基本要求。以下是對 skeleton.dtsi 文件內容的詳細解釋:
根節點
/ {:這是設備樹的根節點,每個設備樹文件有且僅有一個根節點。在包含 skeleton.dtsi 的文件中,這個根節點會與其他文件的根節點合并,最終形成一個統一的設備樹結構。
地址單元和大小單元
#address-cells = <1>;:指定了該設備樹中地址單元的數量。對于大多數簡單的設備樹節點,地址單元數量為 1 即可滿足需求。這意味著在描述設備的地址信息時,使用一個單元(通常是 32 位或 64 位的值)來表示地址。例如,對于內存設備的基地址,就可以用一個這樣的地址單元來指定。
#size-cells = <1>;:定義了大小單元的數量。同樣,對于很多設備節點,大小單元數量設為 1 就足夠了。它用于描述設備所占用的內存或資源的大小,比如內存區域的大小、寄存器塊的大小等,以一個單元的值來表示具體的字節數。
chosen 節點
chosen { };:這是一個特殊的節點,通常用于在設備樹中標記一些被選擇或推薦的設置。在內核引導過程中,引導加載程序可能會根據這個節點中的信息來進行一些特定的配置或初始化操作。不過在 skeleton.dtsi 中,這個節點暫時沒有包含任何具體的子節點或屬性。
aliases 節點
aliases { };:用于創建設備樹中的別名。通過別名,可以給設備樹中的節點起一個更易讀、更有意義的名字,方便在其他部分的設備樹文件中引用。這有助于提高設備樹的可讀性和可維護性。但在 skeleton.dtsi 中,目前也沒有具體的別名定義。
memory 節點
memory { device_type = "memory"; reg = <0 0>; };:定義了一個內存設備節點。device_type = "memory" 明確指出這是一個內存類型的設備。reg = <0 0> 表示該內存設備的起始地址為 0x00000000,大小為 0x00000000(這里的大小為 0 可能是一個占位符,實際的內存大小會在具體的設備樹文件中根據硬件情況進行設置)。這個內存節點是設備樹中描述系統內存的基礎模板,其他具體的內存設備節點可以在繼承這個節點的基礎上進行修改和擴展。
總的來說,skeleton.dtsi 文件提供了設備樹的基本框架和一些常用的節點定義,使得其他的設備樹文件可以在此基礎上進行擴展和定制,從而減少代碼的重復編寫,提高設備樹的可維護性和可擴展性。 可見,該文件只是一個最基礎的框架性模版,沒有具體的設備信息。
imx6ull.dtsi
接下來看imx6ull.dtsi這個文件,這個文件的內容比較多。
imx6ull.dtsi 文件是一個設備樹包含文件(Device Tree Include File),用于描述 I.MX6ULL SoC(System on Chip)的內部外設信息。可見,是一個描述芯片信息的設備樹包含文件。因此,建議不要在該文件中包含片外的外設。 不過雖然看著很長,其實總體上就那么幾類信息,大部分的長度都在soc片上外設或者控制器等上面。 imx6ull.dtsi 文件是一個設備樹包含文件(Device Tree Include File),用于描述 I.MX6ULL SoC(System on Chip)的內部外設信息。以下是對該文件內容的詳細解釋:
頭文件引用
時鐘、GPIO、中斷控制器相關頭文件:
#include <dt-bindings/clock/imx6ul-clock.h>:
包含了與 I.MX6ULL 時鐘配置相關的綁定信息,這些信息定義了時鐘的各種屬性、頻率范圍等,以便在設備樹中對時鐘進行準確的描述和配置。
#include <dt-bindings/gpio/gpio.h>:
提供了 GPIO(通用輸入輸出端口)的相關信息,如 GPIO 的編號、功能、狀態等定義,使得在設備樹中可以正確地描述和使用 GPIO 引腳。
#include <dt-bindings/interrupt-controller/arm-gic.h>:
包含了 ARM 通用中斷控制器(GIC)的綁定信息,這對于處理 I.MX6ULL 的中斷機制非常重要,通過該頭文件可以在設備樹中準確地設置中斷控制器的屬性和行為。
針腳功能相關頭文件:
#include "imx6ull-pinfunc.h" 和 #include "imx6ull-pinfunc-snvs.h":
這兩個頭文件定義了 I.MX6ULL 的針腳功能和特殊非易失性存儲(SNVS)相關的針腳功能。它們指定了各個針腳的用途、電氣特性等,對于連接外部設備以及正確配置芯片的引腳功能至關重要。
#include "skeleton.dtsi":
這是一個基礎的設備樹框架頭文件,通常包含了一些通用的設備樹節點定義和基本的結構信息,為后續具體的設備樹描述提供了一個基礎模板。
根節點及子節點
根節點:
/ {:這是設備樹的根節點,所有的其他節點都是直接或間接地掛在這個根節點下面。在設備樹的語法中,根節點使用反斜杠“/”表示,它是整個設備樹的起點,代表了整個系統的硬件資源。
別名節點(aliases):
別名節點用于為設備樹中的節點創建易于理解和使用的別名。比如在這里將flexcan1 這個節點命名為 can0,這樣在其他地方引用 can0 時,實際上就是指代 flexcan1 節點。這種別名機制方便了設備樹的編寫和閱讀,尤其是對于復雜的硬件系統,可以通過有意義的別名來快速定位和引用特定的硬件設備。
CPU 節點(cpus):
這段設備樹代碼定義了一個 CPU 節點(
cpus
)及其子節點?cpu0
,主要用于描述 ARM Cortex-A7 處理器的硬件特性和運行參數。下面是對關鍵屬性的詳細解析:1. 父節點?
cpus
?的屬性cpus {#address-cells = <1>; // 子節點地址用 1 個 cell 表示#size-cells = <0>; // 子節點地址無需描述大小(0 個 cells)... };
#address-cells = <1>
?和?#size-cells = <0>
:
由于 CPU 是 “編號型設備”(通過 ID 區分,而非連續地址空間),因此子節點?cpu0
?的?reg
?屬性僅需 1 個 cell 表示 CPU 編號(無需大小)。2. 子節點?
cpu0: cpu@0
?的核心屬性(1)基本標識屬性
cpu0: cpu@0 {compatible = "arm,cortex-a7"; // 兼容的 CPU 型號(Cortex-A7)device_type = "cpu"; // 設備類型為 CPU(標準屬性)reg = <0>; // CPU 編號為 0(對應父節點的 #address-cells 配置)... };
compatible
:用于匹配 CPU 驅動(如 ARM 架構的 CPU 核心驅動)。device_type = "cpu"
:內核識別 CPU 節點的標準屬性(固定值)。reg = <0>
:表示這是第 0 號 CPU(多核系統中會有?cpu@1
、cpu@2
?等)。(2)時鐘與電源管理屬性
clock-latency = <61036>; // 時鐘切換延遲(單位:納秒) operating-points = </* kHz uV */996000 1275000792000 1225000528000 1175000396000 1025000198000 950000 >; fsl,soc-operating-points = <...>; // 飛思卡爾平臺的 SoC 級電壓配置 fsl,low-power-run; // 支持低功耗運行模式(飛思卡爾自定義屬性)
clock-latency
:CPU 頻率切換所需的延遲時間(此處為 61036ns),用于內核動態調頻(DVFS)決策。operating-points
:定義 CPU 支持的 “頻率 - 電壓” 組合(動態調頻的關鍵參數):
例如,當 CPU 運行在 996MHz 時,核心電壓需為 1275mV;降頻到 198MHz 時,電壓可降至 950mV(平衡性能與功耗)。fsl,soc-operating-points
:飛思卡爾(Freescale)平臺特有的 SoC 級電壓配置(可能用于外圍總線與 CPU 電壓協同)。(3)時鐘源配置
clocks = <&clks IMX6UL_CLK_ARM>,<&clks IMX6UL_CLK_PLL2_BUS>,... // 共 11 個時鐘源 clock-names = "arm", "pll2_bus", ...; // 時鐘源的名稱(與 clocks 一一對應)
clocks
:指定 CPU 相關的時鐘源(通過 phandle?<&clks>
?引用時鐘控制器節點?clks
,并通過宏定義指定具體時鐘)。
例如?IMX6UL_CLK_ARM
?表示 CPU 核心時鐘,IMX6UL_CLK_PLL1
?表示主 PLL 時鐘。clock-names
:為每個時鐘源命名,方便驅動程序按名稱引用(如驅動中通過?"arm"
?找到 CPU 核心時鐘)。總結
這段設備樹代碼完整描述了 i.MX6UL 芯片中 Cortex-A7 處理器(cpu0)的基本信息、頻率 / 電壓配置、時鐘源及電源管理特性,是內核初始化 CPU、實現動態調頻和電源管理的關鍵依據。其中:
- 標準屬性(
compatible
、reg
、operating-points
)確保內核通用驅動能識別 CPU;- 廠商自定義屬性(
fsl,soc-operating-points
、fsl,low-power-run
)用于適配飛思卡爾平臺的特殊硬件邏輯;- 時鐘相關屬性則為內核提供了 CPU 時鐘管理的具體參數。
中斷控制器節點(intc):
這段設備樹代碼定義了一個?中斷控制器節點(
intc
),對應 ARM Cortex-A7 處理器的通用中斷控制器(GIC),用于管理系統中所有硬件設備的中斷請求。下面對每個關鍵屬性進行詳細解析,幫助理解中斷控制器在設備樹中的配置邏輯:1. 節點基本信息:
intc: interrupt-controller@00a01000
- 節點名稱:
interrupt-controller@00a01000
- 前綴?
interrupt-controller
?明確標識該節點是 “中斷控制器”(符合設備樹規范的命名習慣);@00a01000
?是中斷控制器的基地址,與后續?reg
?屬性中第一個地址段一致,用于直觀關聯硬件地址。- 節點標簽:
intc
為節點定義的別名,方便設備樹其他節點通過?&intc
?快速引用該中斷控制器(例如外設節點聲明 “使用?intc
?管理中斷”)。2. 核心屬性解析
(1)
compatible = "arm,cortex-a7-gic"
- 作用:聲明中斷控制器的兼容性,用于內核匹配對應的 GIC 驅動程序。
- 含義:
"arm,cortex-a7-gic"
?表示該中斷控制器是 ARM Cortex-A7 處理器配套的 GIC(通常為 GIC-400 或 GICv2 架構);- 內核中專門的 GIC 驅動(如?
drivers/irqchip/irq-gic.c
)會通過?of_match_table
?匹配該字符串,從而初始化中斷控制器硬件。(2)
#interrupt-cells = <3>
作用:定義 “引用該中斷控制器時,需要用幾個?
cell
(32 位整數)描述一個中斷請求”,是中斷控制器節點的核心配置。為什么是 3 個?
cell
?
ARM GIC 架構下,一個完整的中斷描述需要 3 個參數,格式和含義固定為:<中斷類型 中斷號 觸發方式>
- 第 1 個?
cell
:中斷類型(如?0
?表示 SPI 中斷,1
?表示 PPI 中斷 ——SPI 是外設共享中斷,PPI 是 CPU 私有中斷);- 第 2 個?
cell
:中斷號(GIC 分配給該中斷的唯一編號,如?23
?對應某 UART 的中斷號);- 第 3 個?
cell
:觸發方式(如?0x04
?表示上升沿觸發,0x08
?表示下降沿觸發,0x10
?表示高電平觸發)。示例:某 UART 節點引用該中斷控制器時,會這樣聲明中斷:
interrupts = <0 23 0x04>; // 類型=SPI(0),中斷號=23,觸發方式=上升沿(0x04)
(3)
interrupt-controller
- 作用:空屬性(無值),僅用于標識該節點是中斷控制器,內核解析時會將其歸類為 “中斷管理設備”,允許其他節點通過?
interrupt-parent
?屬性關聯它。- 必要性:所有中斷控制器節點必須包含該屬性,否則內核無法識別其功能,后續外設無法綁定中斷。
(4)
reg = <0x00a01000 0x1000>, <0x00a02000 0x100>
- 作用:描述中斷控制器的物理地址空間(寄存器基地址和占用大小),內核驅動通過這些地址訪問 GIC 寄存器,實現中斷的使能、屏蔽、優先級配置等操作。
- 兩個地址段的含義(GIC 架構特性):
- 第一個地址段?
<0x00a01000 0x1000>
:對應 GIC 的?Distributor(分發器)?寄存器區域;
- 功能:管理全局中斷(如中斷分配、優先級設置、向 CPU 分發中斷請求);
- 大小?
0x1000
(4KB):覆蓋 Distributor 的所有控制寄存器。- 第二個地址段?
<0x00a02000 0x100>
:對應 GIC 的?CPU Interface(CPU 接口)?寄存器區域;
- 功能:CPU 與 GIC 交互的接口(如 CPU 確認中斷、清除中斷、屏蔽當前 CPU 的中斷);
- 大小?
0x100
(256B):覆蓋 CPU Interface 的核心寄存器。3. 該節點的核心作用
整個?
intc
?節點的目的是:
- 告訴內核 “在?
0x00a01000
?和?0x00a02000
?地址有一個 GIC 中斷控制器”;- 定義 “其他外設引用中斷時,需用 3 個參數描述中斷信息”;
- 讓內核加載對應的 GIC 驅動,初始化硬件后,接管整個系統的中斷管理(如響應外設中斷請求、分發到對應 CPU 處理)。
時鐘節點(clocks):
這段設備樹代碼定義了一個?
clocks
?節點,包含了多個子節點,用于描述系統中的固定時鐘源(fixed-clock
)。這些節點主要用于向內核提供時鐘頻率信息,是系統時鐘管理的基礎配置。下面詳細解析每個部分的作用:1. 父節點?
clocks
?的屬性clocks {#address-cells = <1>; // 子節點地址用 1 個 cell 表示#size-cells = <0>; // 子節點地址無需描述大小(0 個 cells)... };
#address-cells = <1>
?和?#size-cells = <0>
:
由于時鐘源是 “編號型設備”(通過 ID 區分,而非連續地址空間),因此子節點的?reg
?屬性僅需 1 個 cell 表示時鐘編號(無需大小)。2. 子節點:固定時鐘源(
fixed-clock
)的配置每個子節點(如?
ckil: clock@0
)都描述了一個固定時鐘源,核心屬性如下:(1)
ckil: clock@0
(32.768kHz 低頻時鐘)ckil: clock@0 {compatible = "fixed-clock"; // 標識為固定頻率時鐘reg = <0>; // 時鐘編號為 0(對應父節點配置)#clock-cells = <0>; // 引用該時鐘時無需額外參數clock-frequency = <32768>; // 時鐘頻率為 32768Hz(32.768kHz)clock-output-names = "ckil"; // 時鐘輸出名稱(供驅動引用) };
- 作用:通常作為系統的實時時鐘(RTC)或低功耗定時器的基準時鐘(32.768kHz 是常見的低頻時鐘頻率,適合長周期計時)。
(2)
osc: clock@1
(24MHz 高頻振蕩器)osc: clock@1 {compatible = "fixed-clock";reg = <1>; // 時鐘編號為 1#clock-cells = <0>;clock-frequency = <24000000>;// 時鐘頻率為 24MHzclock-output-names = "osc"; // 輸出名稱為 "osc" };
- 作用:通常作為系統主振蕩器(Oscillator),為 PLL(鎖相環)提供基礎時鐘,進而生成 CPU、總線等高頻時鐘(24MHz 是嵌入式系統中常見的高頻基準頻率)。
(3)
ipp_di0: clock@2
?和?ipp_di1: clock@3
(未啟用的時鐘)???
ipp_di0: clock@2 {compatible = "fixed-clock";reg = <2>;#clock-cells = <0>;clock-frequency = <0>; // 頻率為 0,表示未啟用或無效clock-output-names = "ipp_di0"; };
- 作用:
clock-frequency = <0>
?通常表示該時鐘源當前未使用(可能是預留的接口,或依賴外部硬件觸發后才有效)。ipp_di
?可能對應圖像處理器(IPP)的輸入時鐘,需根據具體硬件場景啟用。3. 關鍵屬性解析
(1)
compatible = "fixed-clock"
- 標識該節點是固定頻率時鐘(頻率不可動態調整),內核會匹配通用的?
fixed-clock
?驅動(無需針對特定硬件編寫驅動)。(2)
#clock-cells = <0>
- 定義 “引用該時鐘時需要多少個 cell 作為參數”。此處為?
0
?表示:引用該時鐘時無需額外參數(僅需通過 phandle 指向該節點即可)。
示例:某外設需要使用?osc
?時鐘時,配置如下:some_device {clocks = <&osc>; // 直接引用 &osc 即可,無需額外參數clock-names = "osc_clk"; };
(3)
clock-frequency
- 聲明時鐘的固定頻率(單位:Hz),是該節點的核心參數。內核和驅動通過讀取該值獲取時鐘頻率,用于計算定時器周期、波特率等(如 UART 波特率需基于時鐘頻率配置)。
(4)
clock-output-names
- 為時鐘輸出命名,方便調試和驅動中按名稱識別時鐘(如內核日志中會顯示該名稱,便于定位時鐘來源)。
4. 整體作用
這些?
fixed-clock
?節點是系統時鐘樹的 “根節點”,為后續的時鐘控制器(如 PLL、分頻器)提供初始基準時鐘。例如:
osc
(24MHz)可能輸入到 PLL,通過倍頻生成 CPU 核心時鐘(如 1GHz);ckil
(32.768kHz)直接供給 RTC 模塊,用于記錄系統時間。內核通過這些節點獲取基礎時鐘頻率后,才能進一步配置復雜的時鐘樹(分頻、倍頻、多路切換),確保所有外設(UART、SPI、ADC 等)在正確的時鐘頻率下工作。
總結
這段代碼定義了系統的基礎固定時鐘源,核心作用是向內核提供 “不可調整的基準頻率” 信息。其中:
ckil
?和?osc
?是活躍的基準時鐘,為系統和外設提供基礎計時信號;ipp_di0
/ipp_di1
?是預留的時鐘接口,可能用于擴展硬件;- 所有節點通過?
fixed-clock
?兼容屬性,被內核通用驅動識別和管理,無需額外開發驅動。這些時鐘是整個系統時鐘管理的起點,后續復雜的時鐘配置(如動態調頻、外設時鐘開關)都依賴這些基礎頻率。
系統節點(soc):
這是個非常大的節點,里面包含了基本的soc外設
先從整體上看看
這段設備樹代碼是?i.MX6UL 芯片的 SoC 核心節點配置,通過層級化結構(
soc
?父節點 + 子總線 / 外設節點)完整描述了芯片內部的總線架構、核心外設(如 GPIO、UART、SPI)、時鐘 / 電源管理模塊等硬件資源。它是內核識別和初始化 SoC 硬件的 “藍圖”,下面從?架構邏輯、核心模塊、關鍵屬性?三方面展開解析:一、整體架構:SoC 節點的層級邏輯
soc
?節點是整個芯片硬件描述的 “根容器”,采用?“總線 - 外設” 分層設計,符合嵌入式系統的硬件拓撲(類似電腦的 “主板 - PCIe 總線 - 顯卡 / 硬盤” 結構),核心層級如下:soc(根節點) ├─ 核心功能模塊(總線頻率管理、電源管理、SRAM等) │ ├─ busfreq(總線頻率動態調整) │ ├─ pmu(CPU性能監控單元) │ ├─ ocrams/ocram(片上SRAM,用于低功耗場景或臨時數據存儲) │ └─ dma_apbh(APBH總線DMA控制器,用于外設數據傳輸) ├─ 三大 AIPS 總線節點(AIPS1/AIPS2/AIPS3,管理不同外設組) │ ├─ AIPS1(0x02000000 地址段):管理 SPI、UART、PWM、GPIO、CAN 等常用外設 │ ├─ AIPS2(0x02100000 地址段):管理 USB、以太網、SDHC(SD卡)、I2C、CSI(攝像頭)等高速/擴展外設 │ └─ AIPS3(0x02200000 地址段):管理加密(DCP)、隨機數(RNG)、低功耗相關外設(如 SNVS) └─ 系統控制模塊(時鐘、中斷、電源、引腳復用)├─ clks(CCM 時鐘控制器,管理全芯片時鐘)├─ gpc(通用電源控制器,管理電源域和中斷分發)├─ anatop(模擬拓撲控制器,管理電源 regulators)├─ iomuxc(引腳復用控制器,配置GPIO功能)└─ snvs(安全非易失性存儲,管理RTC、電源鍵)
這種分層設計的核心目的是:按地址段和功能歸類外設,讓內核能高效遍歷和初始化硬件(例如通過?
ranges
?屬性映射物理地址,通過?compatible
?匹配驅動)。二、核心模塊解析:關鍵子節點的功能與屬性
1.?
soc
?根節點的基礎屬性soc {#address-cells = <1>; // 子節點地址用 1 個 cell(32位整數)表示#size-cells = <1>; // 子節點地址空間大小用 1 個 cell 表示compatible = "simple-bus"; // 標識為“簡單總線”,內核按總線邏輯管理子節點interrupt-parent = <&gpc>; // 默認中斷父節點為 GPC(電源與中斷控制器)ranges; // 地址無偏移(子節點物理地址 = 父節點地址空間內的地址)... };
#address-cells
/#size-cells
:由于 SoC 外設地址是連續的 32 位物理地址,用 1 個 cell 即可描述地址和大小(例如?reg = <0x0209c000 0x4000>
?表示地址?0x0209c000
,大小?16KB
)。ranges
:空屬性表示 “子節點地址直接映射到物理地址”,無需地址轉換(常見于 SoC 內部外設)。2. 核心功能模塊(非總線類節點)
這類節點是 SoC 運行的 “基礎支撐”,負責頻率、電源、數據傳輸等核心能力:
(1)
busfreq
:總線頻率動態管理busfreq {compatible = "fsl,imx_busfreq"; // 飛思卡爾總線頻率驅動匹配clocks = <&clks IMX6UL_CLK_PLL2_PFD2>, ...; // 關聯總線相關時鐘源clock-names = "pll2_pfd2_396m", ...; // 時鐘源命名,方便驅動引用fsl,max_ddr_freq = <400000000>; // DDR 最大頻率(400MHz) };
- 功能:動態調整 AHB/AXI 總線頻率,平衡系統性能與功耗(例如高負載時提頻,低負載時降頻)。
- 關鍵屬性:
fsl,max_ddr_freq
?限制 DDR 內存的最高工作頻率,避免硬件過載。(2)
ocram
/ocrams
:片上 SRAMocram: sram@00905000 {compatible = "mmio-sram"; // 內存映射型 SRAMreg = <0x00905000 0x1B000>; // 地址 0x00905000,大小 108KB };
- 功能:片上靜態內存,比 DDR 內存速度更快、功耗更低,常用于:
- 低功耗模式下的數據暫存(如休眠時保存上下文);
- DMA 傳輸的臨時緩沖區;
- 實時性要求高的代碼(如中斷服務函數)。
(3)
dma_apbh
:APBH 總線 DMA 控制器dma_apbh: dma-apbh@01804000 {compatible = "fsl,imx6ul-dma-apbh", "fsl,imx28-dma-apbh";reg = <0x01804000 0x2000>; // DMA 控制器寄存器地址interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>, ...; // DMA 通道中斷#dma-cells = <1>; // 引用 DMA 時需 1 個 cell(通道號)dma-channels = <4>; // 支持 4 個 DMA 通道 };
- 功能:卸載 CPU 數據傳輸壓力,實現外設(如 NAND Flash、UART)與內存的直接數據交互(DMA 傳輸)。
- 示例引用:
gpmi-nand
(NAND 控制器)通過?dmas = <&dma_apbh 0>
?綁定 DMA 第 0 通道,實現 NAND 數據的高速讀寫。3. AIPS 總線節點:外設的 “管理中心”
AIPS
(Advanced Intelligent Peripheral Subsystem)是 i.MX6UL 的外設總線架構,按地址段分為 AIPS1/AIPS2/AIPS3,每個總線節點管理一組功能相近的外設,以?AIPS1?為例:aips1: aips-bus@02000000 {compatible = "fsl,aips-bus", "simple-bus";reg = <0x02000000 0x100000>; // 總線地址范圍:0x02000000 ~ 0x020FFFFF(1MB)ranges; // 地址無偏移spba-bus@02000000 { // SPBA 子總線(低速外設總線)compatible = "fsl,spba-bus", "simple-bus";reg = <0x02000000 0x40000>; // 子總線地址范圍:0x02000000 ~ 0x0203FFFFranges;ecspi1: ecspi@02008000 { ... }; // SPI1 外設uart1: serial@02020000 { ... }; // UART1 外設};gpio1: gpio@0209c000 { ... }; // GPIO1 外設pwm1: pwm@02080000 { ... }; // PWM1 外設 };
- 總線分工:
- AIPS1:管理低速 / 常用外設(SPI、UART、GPIO、PWM、CAN),地址段?
0x02000000 ~ 0x020FFFFF
;- AIPS2:管理高速 / 擴展外設(USB、以太網、SDHC、I2C、CSI),地址段?
0x02100000 ~ 0x021FFFFF
;- AIPS3:管理安全 / 低功耗外設(DCP 加密、RNG 隨機數、SNVS 低功耗模塊),地址段?
0x02200000 ~ 0x022FFFFF
。spba-bus
:AIPS 下的子總線,專門管理更低速的外設(如早期 SPI、UART),減少對主總線的占用。4. 系統控制模塊:SoC 的 “大腦”
這類節點負責 SoC 的全局控制(時鐘、電源、中斷、引腳),是硬件初始化的核心:
(1)
clks
:CCM 時鐘控制器clks: ccm@020c4000 {compatible = "fsl,imx6ul-ccm"; // 匹配 i.MX6UL 的 CCM 驅動reg = <0x020c4000 0x4000>; // CCM 寄存器地址(16KB)#clock-cells = <1>; // 引用時鐘時需 1 個 cell(時鐘 ID,如 IMX6UL_CLK_ARM)clocks = <&ckil>, <&osc>; // 輸入基準時鐘(32.768kHz 低頻鐘、24MHz 晶振)clock-names = "ckil", "osc"; };
- 功能:生成和分配全芯片的時鐘信號(如 CPU 核心時鐘、外設時鐘),支持動態調頻(DVFS)。
- 關鍵屬性:
#clock-cells = <1>
?表示其他外設引用時鐘時,需傳入 “時鐘 ID”(如?clocks = <&clks IMX6UL_CLK_UART1_SERIAL>
?表示 UART1 的串行時鐘)。(2)
gpc
:電源與中斷控制器gpc: gpc@020dc000 {compatible = "fsl,imx6ul-gpc", "fsl,imx6q-gpc";reg = <0x020dc000 0x4000>; // GPC 寄存器地址interrupt-controller; // 標識為中斷控制器#interrupt-cells = <3>; // 中斷描述需 3 個 cell(類型、編號、觸發方式)interrupt-parent = <&intc>; // 最終中斷父節點為 GIC(全局中斷控制器) };
- 功能:
- 電源管理:控制 SoC 各電源域(如 CPU 核心域、外設域)的上電 / 下電;
- 中斷分發:將外設中斷請求(如 UART 接收中斷)轉發給 GIC,再分配給 CPU 處理。
(3)
iomuxc
:引腳復用控制器iomuxc: iomuxc@020e0000 {compatible = "fsl,imx6ul-iomuxc";reg = <0x020e0000 0x4000>; // IOMUXC 寄存器地址 };
- 功能:i.MX6UL 的 GPIO 引腳支持 “復用功能”(如同一引腳可作為 UART_TX、SPI_SCK 或普通 GPIO),
iomuxc
?節點通過寄存器配置引腳功能,例如:
- 將引腳?
GPIO1_IO03
?復用為?UART1_TX
;- 配置引腳的上下拉電阻、驅動能力。
(4)
anatop
:模擬電源控制器anatop: anatop@020c8000 {compatible = "fsl,imx6ul-anatop", "syscon";reg = <0x020c8000 0x1000>; // ANATOP 寄存器地址reg_arm: regulator-vddcore@140 { // CPU 核心電源 regulatorcompatible = "fsl,anatop-regulator";regulator-name = "cpu";regulator-min-microvolt = <725000>; // 最小 725mVregulator-max-microvolt = <1450000>; // 最大 1450mVregulator-always-on; // 始終上電(CPU 核心不可掉電)}; };
- 功能:管理 SoC 的模擬電源(如 CPU 核心電壓、外設電壓),通過?
regulator
?子節點配置電壓范圍,支持動態調壓(配合 CPU 調頻,如高頻時提壓、低頻時降壓)。三、外設節點共性:如何識別和初始化外設
所有外設節點(如?
uart1
、ecspi1
、gpio1
)都遵循統一的配置邏輯,核心屬性包括:以?
屬性名 作用 compatible
匹配驅動(如? fsl,imx6ul-uart
?匹配 i.MX6UL 的 UART 驅動)reg
外設寄存器的物理地址和大小(如? 0x02020000 0x4000
?表示 UART1 地址)interrupts
外設中斷配置(如? GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH
?表示 SPI 中斷)clocks
/clock-names
外設依賴的時鐘源(如 UART 需要? ipg
?總線時鐘和?serial
?串行時鐘)dmas
/dma-names
外設綁定的 DMA 通道(如高速 UART 用 DMA 實現數據收發) status
外設使能狀態( "okay"
?表示啟用,"disabled"
?表示禁用)uart1
?為例,其配置邏輯為:uart1: serial@02020000 {compatible = "fsl,imx6ul-uart"; // 匹配 UART 驅動reg = <0x02020000 0x4000>; // UART1 寄存器地址(16KB)interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; // 中斷:SPI類型,編號26,高電平觸發clocks = <&clks IMX6UL_CLK_UART1_IPG>, <&clks IMX6UL_CLK_UART1_SERIAL>; // 依賴的兩個時鐘clock-names = "ipg", "per"; // 時鐘命名(總線時鐘、串行時鐘)status = "disabled"; // 默認禁用,需根據硬件啟用 };
四、總結:這段設備樹的核心作用
- 硬件抽象:將 i.MX6UL 的復雜硬件(數百個寄存器、數十個外設)抽象為結構化的節點,讓內核無需硬編碼地址即可訪問硬件;
- 驅動匹配:通過?
compatible
?屬性將外設與驅動關聯(如?fsl,imx6ul-gpio
?匹配 GPIO 驅動),實現 “硬件無關” 的驅動設計;- 參數配置:為外設提供初始化參數(如時鐘頻率、中斷觸發方式、DMA 通道),內核加載驅動時直接讀取這些參數,無需修改代碼;
- 靈活性:通過?
status
?屬性啟用 / 禁用外設,通過?ranges
?調整地址映射,適配不同的硬件版型(如有的板子用 UART1,有的用 UART2)。簡單來說,這段設備樹是?“內核與硬件之間的翻譯官”,沒有它,內核無法識別 i.MX6UL 的任何外設,系統也無法啟動。?
imx6ull-14x14-evk.dts
imx6ull-14x14-evk.dts和imx6ull.dtsi有啥區別?
在嵌入式 Linux 開發中,
imx6ull-14x14-evk.dts
和imx6ull.dtsi
都是設備樹文件,用于描述硬件信息,但它們的作用和適用范圍有明顯區別:
imx6ull.dtsi(設備樹包含文件)
- 這是 i.MX6ULL 處理器的通用基礎設備樹文件,包含了該芯片共有的硬件描述(如 CPU 核心、內部外設控制器、內存接口等)
- 它不針對特定開發板,而是所有基于 i.MX6ULL 芯片的板卡都可以復用的通用部分
- 通常以
.dtsi
為擴展名,表示 "device tree include",用于被其他設備樹文件引用imx6ull-14x14-evk.dts(具體板卡設備樹)
- 這是 NXP 官方 i.MX6ULL 14x14 EVK 開發板的專用設備樹文件
- 它基于
imx6ull.dtsi
擴展,添加了該特定開發板的硬件信息(如板載外設、引腳配置、外部設備等)- 是最終會被編譯為
.dtb
(設備樹二進制)文件并被內核使用的文件簡單來說:
imx6ull.dtsi
是芯片級的通用描述,imx6ull-14x14-evk.dts
是基于特定開發板的具體實現,前者被后者通過#include
語句引用,形成完整的硬件描述。這種分層設計的好處是:不同板卡可以共享芯片級的通用描述,只需關注各自板級硬件的差異部分,減少重復代碼。
再來看看imx6ull-14x14-evk.dts文件,這個文件的內容也比較長,其實就是描述特定開發板的設備信息的,也有對芯片信息的進一步補充。 imx6ull-14x14-evk.dts 文件是用于描述 i.MX6ULL 14x14 EVK(Evaluation Kit,評估套件)硬件的 Device Tree Source(設備樹源)文件。以下是對該文件內容的詳細解釋:
頭文件引用
#include <dt-bindings>:引入與輸入設備相關的綁定定義,為后續描述輸入設備節點提供基礎信息和屬性綁定。
#include "imx6ull.dtsi":包含 i.MX6ULL 芯片通用的設備樹包含文件,其中定義了 i.MX6ULL 芯片相關的外設描述、時鐘、中斷控制器等基本信息,可在當前文件中直接使用這些預定義的節點和屬性。
根節點及基本屬性
/ {:根節點,代表整個設備樹的根,所有其他的節點都是直接或間接掛在這個根節點下面。
model = "Freescale i.MX6 ULL 14x14 EVK Board";:定義了該設備樹所對應的開發板型號,即 Freescale(現 NXP)的 i.MX6ULL 14x14 EVK 評估板。
compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";:指定了設備的兼容屬性,表明該設備與 “fsl,imx6ull-14x14-evk” 和 “fsl,imx6ull” 兼容,這樣內核在加載設備樹時可以根據這些兼容字符串來匹配相應的驅動程序。
chosen { stdout-path = &uart1; };:選擇了默認的控制臺輸出設備,這里將 uart1 設置為系統啟動時的默認控制臺輸出端口,以便在系統啟動過程中輸出日志信息。
內存節點
memory { reg = <0x80000000 0x20000000>; };:描述了內存區域的起始地址和大小,0x80000000 是內存的起始物理地址,0x20000000 是內存的大小,表示該評估板上有 512MB 的內存可供使用。
保留內存節點
reserved-memory {:定義了一些需要保留的內存區域,這些區域通常用于特定的硬件功能或未來的擴展,不允許常規的內存訪問。
#address-cells = <1>; #size-cells = <1>; ranges;:指定了地址單元和大小單元的數量,以及使用范圍來描述保留內存的區域。
linux,cma { compatible = "shared-dma-pool"; reusable; size = <0x14000000>; linux,cma-default; };:保留了一塊用于 Contiguous Memory Allocator(CMA)的內存區域,大小為 0x14000000 字節(約 36MB),compatible 屬性為 "shared-dma-pool",表示這是一個共享的 DMA 池,reusable 表示該內存區域可重復使用,linux,cma-default 表示這是默認的 CMA 區域。
背光節點
backlight { compatible = "pwm-backlight"; pwms = <&pwm1 0 5000000>; brightness-levels = <0 4 8 16 32 64 128 255>; default-brightness-level = <6>; status = "okay"; };:描述了背光設備的相關信息。compatible 屬性為 "pwm-backlight",表示該背光設備使用 PWM(脈寬調制)控制。pwms 屬性指定了用于控制背光的 PWM 控制器及其參數,這里使用了 pwm1 通道 0,頻率為 5MHz。brightness-levels 定義了背光的亮度級別,從 0 到 255 共 256 級亮度可調。default-brightness-level 設置了默認的亮度級別為 6。status = "okay" 表示該背光設備工作正常。
攝像頭節點
pxp_v4l2 { compatible = "fsl,imx6ul-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2"; status = "okay"; };:定義了一個 V4L2(Video for Linux Two)接口的攝像頭設備節點。compatible 屬性列出了該攝像頭設備所兼容的驅動類型,包括 "fsl,imx6ul-pxp-v4l2"、"fsl,imx6sx-pxp-v4l2" 和 "fsl,imx6sl-pxp-v4l2",表示該攝像頭可以在使用這些 SoC(System on Chip)的開發板上通過相應的驅動程序進行視頻采集等工作。status = "okay" 表示該攝像頭設備工作正常。
電源管理節點
regulators { compatible = "simple-bus"; //省略... };:描述了電源管理相關的信息。compatible 屬性為 "simple-bus",表示這是一個簡單的電源總線。此處省略了具體的電壓調節器等電源組件的定義,實際的文件中可能會詳細列出各個電源域、電壓調節器的類型、輸出電壓等信息,用于內核對電源的管理。
CPU 供電相關節點
&cpu0 { arm-supply = <?_arm>; soc-supply = <?_soc>; dc-supply = <?_gpio_dvfs>; };:針對 CPU0 的供電配置節點。arm-supply、soc-supply 和 dc-supply 分別指定了 CPU 的不同供電域所使用的電源控制器或電源軌,如 ?_arm、?_soc 和 ?_gpio_dvfs,這些是在其他部分定義好的電源相關的節點,用于為 CPU 提供穩定的電源供應。
時鐘節點
&clks { assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>; assigned-clock-rates = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>; };:描述了時鐘相關的配置信息。assigned-clocks 和 assigned-clock-rates 屬性分別指定了分配給設備的時鐘源和時鐘頻率,這里使用了 &clks IMX6UL_CLK_PLL4_AUDIO_DIV,表示使用的是 i.MX6ULL 的 PLL4 音頻時鐘分頻后的時鐘源作為設備的時鐘輸入,具體的時鐘頻率值也在其他地方定義。
其他節點
總的來說,imx6ull-14x14-evk.dts 文件通過上述各種節點和屬性的定義,詳細地描述了 i.MX6ULL 14x14 EVK 開發板的硬件資源和配置信息,包括內存、背光、攝像頭、電源管理、CPU 供電、時鐘等方面,使得操作系統內核能夠正確地識別和使用這些硬件資源,從而實現對開發板的支持和管理。在實際的嵌入式系統開發中,根據具體的硬件設計和需求,還可能需要對該文件進行進一步的修改和擴展。
總體框架暫時就了解這么多,接下來,看一些重點細節。
重點其實是在imx6ull.dtsi和imx6ull-14x14-evk.dts這兩個文件上,因此我們也著眼于這兩個文件。
其中,板級相關的在這個imx6ull-14x14-evk.dts文件里,芯片級相關的在這個imx6ull.dtsi文件里,我們以板級imx6ull-14x14-evk.dts作為進一步的著手點來分析。
model、compatible、chosen、memory等屬性如果作為一級屬性,通常是放在板級的dts文件中,而不是放在dtsi文件中,因為這些信息基本都是用來匹配開發板的。
設備樹中的reserved-memory節點是用于預留一段內存區域的特殊節點。以下是關于該節點的詳細解釋:
定義與用途
在設備樹中,reserved-memory節點用于指定需要預留的內存區域。這些區域通常不會被操作系統或驅動程序用于常規的內存分配,而是保留給特定的硬件設備、驅動程序或系統功能使用。
典型應用場景
DMA和其他硬件加速功能:許多硬件設備(如網絡接口卡、音頻設備等)可能需要直接訪問內存而不經過CPU,這種技術稱為DMA(Direct Memory Access)。為了確保這些設備能夠安全地訪問內存,通常會在設備樹中使用reserved-memory節點來預留所需的內存區域。
避免內存沖突:通過預留特定的內存區域,可以防止操作系統或其他驅動程序錯誤地將這些內存分配給其他用途,從而避免潛在的內存沖突和系統不穩定。
節點屬性
reg:表示要預留的物理內存區域的起始地址和大小,格式為<address>, <size>。
compatible:可選屬性,用于指定預留內存區域的兼容類型,如"shared-dma-pool"表示該內存區域可用作一組設備的DMA緩沖區共享池。
no-map:可選屬性,如果存在,表示操作系統不得創建該區域的虛擬映射,也不能將其作為系統內存標準映射的一部分。
reusable:可選屬性,如果存在,表示操作系統可以使用該區域中的內存,但前提是擁有該區域的設備驅動程序能夠回收它。
等等。 看下這個
這里除了對pwm1的引用,后面還加了些其他數據,不要覺得這樣不行,無非就是后面按照這種規則去解析罷了,只要能解析到數據,就沒問題。 在設備樹(Device Tree)中,pwms = <&pwm1 0 5000000> 是一種描述 PWM(脈寬調制)控制器和其通道配置的語法。具體來說,這行代碼的含義如下:
pwms: 這是設備樹中的一個屬性,表示該設備支持 PWM 功能。
<&pwm1 0 5000000>: 這是屬性的值,描述了具體的 PWM 控制器及其配置。
詳細解釋如下:
&pwm1: 這是一個引用,指向一個名為 pwm1 的 PWM 控制器節點。& 符號表示這是一個對其他節點的引用。
0: 這是 PWM 通道號。在這個例子中,它表示使用 pwm1 控制器的第 0 個通道。
5000000: 這是 PWM 的頻率,單位是納秒(ns)。在這個例子中,PWM 的頻率為 5,000,000 納秒,即 5 MHz。
綜合起來,這行代碼的意思是:
該設備使用 pwm1 控制器的第 0 個通道。
該通道的 PWM 頻率設置為 5 MHz。
這種配置通常用于需要精確控制信號頻率的設備,如電機控制、LED 調光等應用。 這個被引用的pwm1,是在imx6ull.dtsi文件中定義的
并且在imx6ull-14x14-evk.dts的后面進行了追加
接著看電源穩壓器、聲卡、spi、iic等外設信息
…… 更多自行查看。 看下iomuxc節點
這里是個追加,其定義是在imx6ull.dtsi文件里,屬于片上soc的外設子節點
可以對子節點直接追加,可見,如果名稱是唯一的,那么是可以直接追加的。 iomuxc其實就是引腳復用控制器,這個節點里面是對引腳基本功能比如復用、驅動能力、上下拉等的描述,按照外設所用到的引腳集合在一起,比如i2c1用到的引腳
比如pwm1用到的所有引腳
等等。
pinctrl-names 屬性
pinctrl-names 屬性是一個字符串列表,它為引腳的不同狀態或功能模式提供了名稱標識。這些名稱可以代表引腳的不同復用功能、電氣特性配置或其他特定的工作狀態等,方便在設備樹中對引腳的配置進行描述和管理。通過為不同的引腳配置或功能模式指定獨特的名稱,如 “default”、“sleep”、“init” (自定義)等,使得設備樹中的其他節點可以引用這些名稱來快速定位和使用相應的引腳配置。
pinctrl-0通常用于指定設備或引腳組在默認狀態下的引腳配置。這種狀態通常是設備上電后或復位后的初始狀態。它引用了一個在設備樹的其他節點中定義的引腳組,這個引腳組包含了一組引腳及其相關的配置信息,如引腳復用功能、上下拉電阻、驅動能力等。 這兩個屬性貌似經常一起使用,是不是可以理解成,默認狀態下所使用的引腳?
當 pinctrl-names = "default" 和 pinctrl-0 = <&pinctrl_uart1> 一起出現在設備樹的一個節點中時,意味著當前節點所代表的設備或引腳組在默認狀態下,將采用 pinctrl_uart1 節點所定義的引腳配置。 考慮某種應用場景,在驅動里獲取pinctrl-names和pinctrl-0的屬性值,然后判斷pinctrl-names是否處于“default”狀態,如果是的話,那就使用pinctrl-0提供的引腳信息來進行初始化。具體的行為還得看驅動是怎么去使用這些信息的。
為了進一步理解這個問題,看下這個節點,里面pinctrl-names有三個值,然后下面就分別有pinctrl-0和pinctrl-1和pinctrl-2,和pinctrl-names的三個名稱是一一對應的,在驅動程序里肯定是根據不同的狀態判斷,去使用不同的引腳組。
iomuxc中pinctrl-names和pinctrl-0是什么屬性 在設備樹中,iomuxc 節點用于描述 IOMUXC(Input/Output Multiplexer Complex)的配置信息。該節點通常包含以下屬性: pinctrl-names 含義:定義引腳狀態,一種狀態對應一個 pinctrl-x。它為引腳的不同功能或模式提供了一種命名方式,方便在設備樹中對引腳配置進行分類和管理。例如,可以定義 “default”、”init”、”sleep” 等狀態,來分別表示引腳在默認情況下、初始化過程中以及低功耗狀態下的不同配置。 作用:通過指定不同的引腳狀態,可以在不同的場景下靈活地配置引腳的功能和屬性,滿足系統在不同運行階段的需求。比如在設備啟動時,將引腳配置為初始化狀態;在設備進入低功耗模式時,將引腳配置為睡眠狀態,以降低功耗。 pinctrl-0 含義:定義第 0 種狀態需要使用到的引腳組,可引用其他節點標識。它是一個引用屬性,通過引用其他定義了具體引腳配置的節點,來確定在該狀態下所使用的引腳設置。 作用:將引腳的實際配置信息與具體的引腳狀態相關聯。當設備的引腳狀態為 “default” 時,pinctrl-0 所引用的節點中的引腳配置信息就會被應用到相應的引腳上,從而實現對該狀態下引腳功能的設置。這樣可以方便地對不同狀態下的引腳配置進行集中管理和修改,提高代碼的可維護性和可讀性。 總的來說,pinctrl-names 和 pinctrl-0 屬性在設備樹的 iomuxc 節點中扮演著關鍵角色,它們共同協作以實現對引腳配置的靈活管理與精確控制。
iomuxc的最后一級子節點里面只有一個fls,pins屬性,這個名字也是廠家自定義的,只要能跟驅動里引用節點時的名稱對應起來即可。 fsl,pins 屬性是一個特定于 Freescale(現為 NXP)SoC 的屬性,用于描述引腳的配置信息。它通常包含一個或多個引腳配置項,每個配置項由引腳功能標識符和配置值組成。通過設置 fsl,pins 屬性,可以指定引腳的復用功能以及相關的電氣特性,如上下拉電阻、驅動能力等。這對于正確配置 SoC 的引腳以適應不同的外設功能至關重要。
繼續
iomuxc_snvs是設備樹中的一個屬性,主要用于配置與安全非易失性存儲(SNVS)子系統相關的引腳復用功能。以下是對該屬性的詳細解釋:
基本概念
iomuxc_snvs屬性通常出現在設備樹節點中,用于描述某個或某些引腳與SNVS子系統之間的關聯和配置信息。這些引腳可能具有特定的復用功能,通過該屬性進行設置和說明。
作用范圍
主要針對與SNVS子系統相關的引腳,這些引腳在系統中通常用于電源管理、安全存儲或其他與安全相關的功能。
典型用途
電源管理配置:可以指定某些引腳作為電源管理引腳,如開關機控制引腳等。通過iomuxc_snvs屬性的配置,可以確定這些引腳在系統中的具體功能和行為。
安全功能設置:對于涉及安全功能的引腳,如加密算法的硬件加速引腳、安全認證引腳等,使用iomuxc_snvs屬性進行配置,以確保系統的安全運行。
特點
引腳復用選項有限:與一般的IOMUXC寄存器相比,iomuxc_snvs屬性所涉及的引腳復用選項相對較少,通常只與特定的電源管理和安全功能相關。
安全性要求高:由于涉及到安全相關的功能,對iomuxc_snvs屬性的配置和使用需要特別小心,以確保系統的安全性和穩定性。
綜上所述,iomuxc_snvs屬性在設備樹中扮演著重要的角色,它用于配置與SNVS子系統相關的引腳復用功能,確保這些引腳能夠正確地實現電源管理和安全存儲等功能。
注意,設備樹中的節點名稱都是可以自己定義的,只要在同一層級下保持唯一即可。
設備樹中寫在前面的節點可以引用后面的節點嗎?
在設備樹中,前面的節點可以引用后面的節點。 設備樹中的節點引用通常使用phandle(物理句柄)和label(標簽)兩種方式來表示。phandle是一個32位的整數值,用于唯一標識一個節點;label是一個字符串,用于標識一個節點。通過這些方式,一個節點可以引用另一個節點,無論它們在設備樹中的位置如何。例如,可以在前面的節點中使用“&”符號和后面節點的phandle值或label來引用該節點。 設備樹中引用節點是引用節點的某個屬性還是引用整個節點,如何理解? 在設備樹中,引用節點既可以是引用節點的某個具體屬性,也可以理解為引用整個節點及其所有屬性。以下是對這兩種情況的具體解釋:
引用節點的某個屬性:
在某些情況下,一個節點可能會引用另一個節點的特定屬性值。例如,一個設備節點可能需要配置其電源管理參數,而它本身沒有直接定義這些參數,而是引用了另一個專門用于電源管理的節點中的相關屬性。
這種引用方式使得設備樹能夠更加靈活地組織和管理硬件信息,避免重復定義相同的屬性,同時也方便了設備的初始化和配置過程。
引用整個節點及其所有屬性:
更常見的情況是,一個節點引用另一個節點時,實際上是將整個被引用節點的所有屬性都納入考慮范圍。
例如,在一個復雜的嵌入式系統中,可能存在多個不同功能模塊的節點,其中一個模塊節點需要使用另一個模塊節點的資源或配置信息。通過引用整個節點,可以方便地獲取和使用該節點的所有屬性,而不僅僅是其中的某個特定屬性。
綜上所述,設備樹中的節點引用既可以指代對單個屬性的引用,也可以指代對整個節點及其所有屬性的引用。這種靈活性使得設備樹成為一種強大的工具,能夠有效地描述和管理復雜的硬件系統結構。 設備樹中如果某個屬性的屬性值是一個節點,那么如果進一步獲取屬性節點的屬性值? 在設備樹中,如果某個屬性的屬性值是一個節點,要進一步獲取該屬性節點的屬性值,可以通過以下步驟實現:
一、理解設備樹結構
節點與屬性:設備樹由節點(Node)和屬性(Property)組成。節點代表硬件設備或組件,屬性用于描述節點的特性或配置參數。
屬性值類型:屬性的值可以是多種類型,包括整數、字符串、數組、甚至是另一個節點(這種情況較少見但確實存在)。
二、定位屬性節點
查找節點:首先,需要在設備樹中找到包含目標屬性的節點。這通常通過遍歷設備樹或使用特定的查找函數(如of_find_node_by_path或of_find_node_by_name)來實現。
讀取屬性:一旦找到目標節點,就可以讀取其屬性值。如果屬性值是一個節點,那么這個屬性值實際上就是另一個節點的引用(可能是phandle、label或其他形式的引用)。
三、解析屬性節點
獲取節點引用:如果屬性值是一個節點,需要解析這個引用以獲取實際的節點對象。這通常涉及到將引用轉換為實際的節點標識符(如phandle轉換為節點指針)。
讀取節點屬性:一旦獲得了實際的節點對象,就可以像訪問普通節點一樣讀取其屬性值。這通常通過設備樹庫提供的接口函數(如of_get_property)來實現。
其實就很像json數據的鍵的值又是一個json數據。
設備樹中節點屬性的值可以是另一個節點。
以下是對這一行為的詳細解釋:
一、設備樹中的屬性值類型
屬性值的多樣性:在設備樹中,節點的屬性值可以是多種數據類型,包括整數、字符串、數組(包括字節數組和字符串數組)、以及布爾值等。
節點作為屬性值:除了上述基本數據類型外,設備樹還支持一種特殊類型的屬性值,即節點本身。這意味著一個節點的屬性值可以引用或指向另一個節點。
二、實現方式
使用phandle:在設備樹中,當一個節點的屬性值是另一個節點時,通常使用物理句柄(phandle)來表示這種引用關系。phandle是一個32位的整數值,用于唯一標識一個節點。通過指定phandle,設備樹能夠清晰地表達節點之間的層次和依賴關系。
語法規則:為了在設備樹中表示phandle,需要使用特定的語法。例如,在設備樹源碼中,可以使用“&”符號后跟節點標簽名或phandle來引用其他節點。同時,為了將phandle與屬性相關聯,可能需要使用“<”和“>”符號來包含phandle值。
三、應用場景
硬件復用:在嵌入式系統中,多個設備或組件可能會共享相同的硬件資源(如中斷控制器、時鐘源等)。通過在設備樹中使用節點作為屬性值,可以方便地實現硬件資源的共享和復用。
模塊化設計:設備樹中的節點引用也有助于實現模塊化設計。通過將相關的節點組織在一起,并使用屬性值進行引用,可以構建出更加清晰、易于維護的設備樹結構。
四、注意事項
循環引用:雖然設備樹允許節點屬性的值是另一個節點,但需要注意避免循環引用的情況。循環引用可能導致設備樹解析器進入無限循環,從而無法正確解析設備樹。
語義清晰性:當使用節點作為屬性值時,應確保這種引用關系具有明確的語義意義。這有助于提高設備樹的可讀性和可維護性。
綜上所述,設備樹中節點屬性的值確實可以是另一個節點,并且這種特性在嵌入式系統的硬件描述和配置中發揮著重要作用。通過合理使用節點引用和phandle機制,可以構建出更加靈活、可擴展和可維護的設備樹結構。
更多補充
中斷結點
?
#interrupt-cells
是一個整數類型的屬性,用于指定在設備樹的中斷描述中使用多少個單元來表示一個中斷。例如,如果#interrupt-cells
的值為2,那么在描述每個中斷時,需要使用2個單元的數據來表示相關信息。注意,不是對應的reg,具體對應著什么,暫時我也不知道,后面再看。在設備樹中,
interrupt-controller
屬性通常是一個空屬性,其作用是聲明當前節點是一個中斷控制器。通過設置interrupt-controller
屬性(即使為空),可以讓設備樹和系統清晰地知道該節點代表的是一個中斷控制器設備。這有助于在復雜的硬件架構中快速識別和定位負責中斷處理的設備,方便系統對其進行正確的配置和管理。在設備樹中,存在各種不同類型的設備節點,如CPU、內存、I/O設備等。interrupt-controller
屬性為空可以作為一種簡單的標識方式,將中斷控制器與其他普通設備區分開來,避免混淆,確保系統能夠準確地識別和處理中斷相關的設備。?上面的#interrupt-cells應該對應的是子結點的interrupts屬性的表示個數。
?interrupts
屬性是一個整數數組,用于指定與該設備相關聯的中斷請求信號的信息。每個元素通常包含兩個主要部分信息,一是中斷控制器的引用(通過 phandle 或設備樹節點路徑表示),二是中斷編號或中斷名稱(具體取決于設備和平臺的表示方式)。?例如,
interrupts = <&intc 23 0x04>;
這個屬性值中,&intc
是中斷控制器的設備樹節點標簽,23
是中斷編號,0x04
表示中斷觸發類型(如上升沿觸發等)。作用與意義
硬件中斷配置:它告訴操作系統或硬件抽象層(HAL)當設備需要產生中斷時,應該向哪個中斷控制器發送信號,以及使用哪個中斷號。這樣,當設備發生特定事件(如數據接收、錯誤發生等)需要通知處理器時,處理器能夠正確地響應并執行相應的中斷服務程序。
系統資源分配和管理:系統可以根據
interrupts
屬性的信息,為設備分配合適的中斷處理資源,確保不同設備的中斷請求能夠得到及時、準確的處理,避免中斷沖突和混亂。驅動程序開發:對于設備驅動開發者來說,
interrupts
屬性提供了關鍵的信息,以便編寫正確的中斷處理代碼。驅動程序需要根據這個屬性的值來注冊相應的中斷處理函數,使設備能夠正常工作。常見屬性值的含義
中斷編號:如果
interrupts
屬性值中只包含一個數字,那么這個數字通常代表中斷編號。例如,在一些簡單的系統中,interrupts = <5>;
表示設備使用中斷編號為 5 的中斷線。中斷名稱:在某些情況下,可能會使用中斷名稱來代替中斷編號。例如,
interrupts = <"irq_name">;
這里的"irq_name"
是在設備樹中定義的一個中斷名稱標識符。這種方式可以使設備樹更加易讀和可維護,尤其是當中斷編號較多且不易理解時。復合值:有些復雜的設備可能會有更復雜的
interrupts
屬性值,包含多個單元的復合值。這些復合值可能包括中斷域、觸發方式、CPU 接口信息等。例如,interrupts = <gic_ppi>;
這個屬性值中,GIC_PPI
表示這是一個與通用中斷控制器(GIC)相關的私有外設中斷(PPI),37
是中斷號,1
表示中斷觸發類型等信息。總之,設備樹中的
interrupts
屬性至關重要,它不僅明確了設備的中斷請求信號細節,還為系統資源分配、驅動程序開發提供了關鍵依據,確保了硬件中斷的有效管理和設備的正常運行。?具體還要看程序里是怎么獲取的。
#clock-cells
?
通過指定
#clock-cells
的值,可以明確子節點的時鐘信息在設備樹中應該如何被表示和解析。例如,如果#clock-cells = <2>
,則表示該節點下的子節點時鐘信息將使用 2 個單元的數據來描述。這有助于系統準確地理解和處理不同節點的時鐘配置信息,確保硬件設備的時鐘設置能夠被正確地識別和應用。
芯片上的外設通常都作為soc結點的子結點。
?設備樹的語法規定了屬性值可以是整數、字符串、數組等多種形式。當屬性值為數組時,尖括號用于標識數組的開始和結束。分開寫尖括號并不影響設備樹編譯器對屬性值的解析,因為編譯器會按照設備樹的語法規則正確處理這種寫法。例如,對于一個包含多個數值的數組屬性
reg = <0x1000 0x2000 0x3000>;
,無論是連續寫還是分開寫尖括號,如reg = <0x1000>,<0x2000>,<0x3000>;
,中間以逗號或者空格隔開應該都可以,設備樹編譯器都能識別并將其解析為一個包含三個元素的數組。也可以分行寫reg = <0x1000>,
??
<0x2000>,
??
<0x3000>;
??比如:
?
gpio-controller
?
在設備樹(Device Tree)中,
gpio-controller
屬性通常用于標識某個節點代表一個 GPIO(通用輸入輸出)控制器。這個屬性告訴系統該節點下的硬件資源是與 GPIO 控制相關的,使得操作系統能夠正確地識別和使用這些 GPIO 引腳。
使用pinctrl子系統時,我們通常都會將所有的pin引腳信息都放在一起;然后具體被哪個外設使用時,需要再在對應外設節點中引用pin信息。
目前還是沒太搞明白,pin,gpio和具體外設之間的設備樹的關系,所有的引腳都是pin,需要先設置好pin的復用功能、驅動能力以及上下拉等基本屬性;如果是復用為gpio,那么就作為gpio這種外設功能;但是,gpio也需要依附其他外設來使用的。這里要搞清楚,gpio是一種片上外設,一般都定義在soc節點中吧?然后片外的外設,就不放在soc里面?這塊還得再研究研究,捋一捋。
clock-latency
在設備樹(Device Tree)中,
clock-latency
?是一個用于描述時鐘切換延遲的屬性,主要用于告知內核時鐘在不同頻率或源之間切換時所需的時間(通常以納秒為單位)。這一屬性幫助內核更精確地管理時鐘資源,尤其是在涉及動態調頻(DVFS)或電源管理的場景中。1. 基本作用
- 定義時鐘切換延遲:
clock-latency
?的值表示時鐘從一種狀態(如當前頻率)切換到另一種狀態(如目標頻率)所需的最小時間(單位:納秒)。- 輔助電源管理決策:內核的電源管理模塊(如 CPUFreq)會根據此延遲值,判斷是否進行時鐘頻率切換。例如,若切換延遲過大,頻繁切換可能導致功耗或性能損失,內核會據此調整策略。
2. 典型使用場景
clock-latency
?通常出現在與時鐘相關的設備節點中,尤其是需要動態調整頻率的硬件(如 CPU、GPU、總線控制器等):cpu0: cpu@0 {compatible = "arm,cortex-a53";reg = <0x0>;clocks = <&cpu_clk>;clock-latency = <100000>; // 時鐘切換延遲為 100,000 納秒(0.1 毫秒)operating-points-v2 = <&cpu_opp_table>; };
在上述示例中:
clock-latency = <100000>
?表示該 CPU 的時鐘在不同頻率間切換時,至少需要 100,000 納秒才能完成。- 內核在進行動態調頻時,會參考此值避免過于頻繁的切換(例如,短暫的負載波動可能不足以抵消切換帶來的延遲開銷)。
3. 注意事項
- 單位是納秒:值的單位固定為納秒(ns),需根據硬件手冊填寫實際測量的延遲時間。
- 與其他屬性配合使用:通常與?
operating-points-v2
(定義不同工作點的頻率 / 電壓)或?clocks
(指定時鐘源)等屬性結合,共同實現動態時鐘管理。- 可選屬性:并非所有時鐘相關節點都需要此屬性,僅在設備支持動態時鐘切換且需要內核優化切換策略時使用。
總結
clock-latency
?是設備樹中用于描述時鐘切換延遲的屬性,其核心作用是幫助內核在電源管理和動態調頻中做出更合理的決策,平衡性能與功耗。它的值需根據硬件特性填寫,直接影響時鐘切換策略的有效性。