日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

奇小葩讲设备树(1/5)-- Linux设备树详解(一) 基础知识

發布時間:2023/12/15 linux 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 奇小葩讲设备树(1/5)-- Linux设备树详解(一) 基础知识 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

關于設備樹,之前就經過詳細的系統培訓,但是本著會用就行的原則,對各個知識點都沒有進行系統的總結。都是用到哪里學哪里,時間長了,基本也忘記了。所以對于后期知識各個知識點進行總結,本章主要討論一下內容,能看懂和修改對應模塊的dts文件。

  • dts的引入
  • dts的基本語法和基本格式介紹
  • dts的組成,各個模塊使用方法
  • 1. dts為何物

    在傳統Linux內核中,ARM架構的板極硬件細節過多地被硬編碼在arch/arm/plat-xxx和arch/arm/mach-xxx,比如板上的platform設備、resource、i2c_board_info、spi_board_info以及各種硬件的platform_data,這些板級細節代碼對內核來講只不過是垃圾代碼。而采用Device Tree后,許多硬件的細節可以直接透過它傳遞給Linux,而不再需要在kernel中進行大量的冗余編碼。導致ARM的merge工作量較大,其次ARM很多的代碼都是垃圾,代碼里面有若干愚蠢的table,而多個人在維護這個table,從而導致了沖突。最后linux發出

    Gaah.Guys, this whole ARM thing is a f*cking pain in the ass.

    之后經過一些討論,對ARM平臺的相關code做出如下相關規范調整,這個也正是引入DTS的原因。

    1、ARM的核心代碼仍然保存在arch/arm目錄下
    2、ARM SoC core architecture code保存在arch/arm目錄下
    3、ARM SOC的周邊外設模塊的驅動保存在drivers目錄下
    4、ARM SOC的特定代碼在arch/arm/mach-xxx目錄下
    5、ARM SOC board specific的代碼被移除,由DeviceTree機制來負責傳遞硬件拓撲和硬件資源信息。

    本質上,Device Tree改變了原來用code方式將HW配置信息嵌入到內核代碼的方法,改用bootloader傳遞一個DB的形式。對于嵌入式系統,在系統啟動階段,bootloader會加載內核并將控制權轉交給內核,此外,還需要把上述的三個參數信息傳遞給kernel,以便kernel可以有較大的靈活性。在linux kernel中,Device Tree的設計目標就是如此。
    在devie tree中,可描述的信息包括:

    1、CPU的數量和類別
    2、內存基地址和大小
    3、總線和橋
    4、外設連接
    5、中斷控制器和中斷的使用情況
    6、GPIO控制器和GPIO使用情況
    7、clock控制器和clock使用情況

    它基本就是一棵電路板上的CPU、總線、設備組成的樹,Bootloader會將這棵樹傳遞給內核,然后內核來識別這棵樹,并根據它展開出Linux內核中的platform_device、i2c_client、spi_device等設備,而這些設備用到的內存、IRQ等資源,也被傳遞給內核,內核會將這些資源綁定給展開的相應設備

    2. DTS基本知識

    2.1 dts

    硬件的相應信息都會寫在.dts為后綴的文件中,每一款硬件可以單獨寫一份xxxx.dts,一般在Linux源碼中存在大量的dts文件,對于arm架構可以在arch/arm/boot/dts找到相應的dts,一個dts文件對應一個ARM的machie。

    2.2 dtsi

    值得一提的是,對于一些相同的dts配置可以抽象到dtsi文件中,然后類似于C語言的方式可以include到dts文件中,對于同一個節點的設置情況,dts中的配置會覆蓋dtsi中的配置。

    2.3 dtc

    dtc是編譯dts的工具,可以在Ubuntu系統上通過指令apt-get install device-tree-compiler安裝dtc工具,不過在內核源碼scripts/dtc路徑下已經包含了dtc工具;

    2.4 dtb

    dtb(Device Tree Blob),dts經過dtc編譯之后會得到dtb文件,dtb通過Bootloader引導程序加載到內核。所以Bootloader需要支持設備樹才行;Kernel也需要加入設備樹的支持;

    3. DTS結構

    /dts-v1/; / {node1 {a-string-property = "A string";a-string-list-property = "first string", "second string";// hex is implied in byte arrays. no '0x' prefix is requireda-byte-data-property = [01 23 34 56];child-node1 {first-child-property;second-child-property = <1>;a-string-property = "Hello, world";};child-node2 {};};node2 {an-empty-property;a-cell-property = <1 2 3 4>; /* each number (cell) is a uint32 */child-node1 {};}; };

    device tree的基本單元是node。這些node被組織成樹狀結構,除了root node,每個node都只有一個parent。一個device tree文件中只能有一個root node。每個node中包含了若干的property/value來描述該node的一些特性。每個node用節點名字(node name)標識,節點名字的格式是node-name@unit-address。如果該node沒有reg屬性(后面會描述這個property),那么該節點名字中必須不能包括@和unit-address。unit-address的具體格式是和設備掛在那個bus上相關。例如對于cpu,其unit-address就是從0開始編址,以此加一。而具體的設備,例如以太網控制器,其unit-address就是寄存器地址。root node的node name是確定的,必須是“/”。 也就是說設備樹源文件的結構為

    • 1個root節點”/”;
    • root節點下面含一系列子節點,“node1” and “node2”
    • 節點node1和下又含有一系列子節點,“child-node1” and “child-node2”
    • 各個節點都有一系列屬性
      • 這些屬性可能為空,如an-empty-property
      • 可能為字符串,如a-string-property
      • 可能為字符串樹組,如a-string-list-property
      • 可能為Cells(由u32整數組成),如second-child-property

    4 DTS語法介紹

    了解了基本的device tree的結構后,我們總要把這些結構體現在device tree source code上來。在linux kernel中,擴展名是dts的文件就是描述硬件信息的device tree source file,在dts文件中,一個node被定義成:

    [label:] node-name[@unit-address] {[properties definitions][child nodes] }

    “[]”表示option,因此可以定義一個只有node name的空節點,label方便在dts文件中引用
    基本數據類型:

    • text string(以null結束),以雙引號括起來,如:
      • string-property = “a string”
    • cells 是32位無符號整形數,以尖括號括起來,如
      • cell-property = <0xbeef 123 0xabcd1234>
    • binary data 以方括號括起來,如:
      • binary-property = [0x01 0x23 0x45 0x67];
    • 不同類型數據可以在同一個屬性中存在,以逗號分格,如:
      • mixed-property = “a string”, [0x01 0x23 0x45 0x67], <0x12345678>;
    • 多個字符串組成的列表也使用逗號分格,如:
      • string-list = “red fish”,“blue fish”;

    5 dts的組成

    5.1 標準屬性

    5.1.1 compatible

    每一個dts文件都是由一個root的根節點組成,內核通過根節點“/”的兼容性即可判斷它啟動的是什么設備,其代碼結構如下

    / {model = "Spreadtrum SC9830A-5 V1.0.0 Smartphone Board";compatible = "sprd,sp9830a-5h10-ga1", "sprd,sc9830";chosen {bootargs = "earlycon=sprd_serial,0x70100000,115200n8 loglevel=8 console=ttyS1,115200n8 init=/init root=/dev/ram0 rw androidboot.hardware=sc9830";linux,initrd-start = <0x85500000>;linux,initrd-end = <0x855a3212>;}; };
  • model屬性值是,它指定制造商的設備型號。推薦的格式是:“manufacturer,model”,其中manufacturer是一個字符串描述
    制造商的名稱,而型號指定型號。
  • compatible屬性值是,指定了系統的名稱,是一個字符串列表,它包含了一個“<制造商>,<型號>”形式的字符串。重要的是要指定一個確切的設備,并且包括制造商的名字,以避免命名空間沖突。
  • chosen 節點不代表一個真正的設備,但功能與在固件和操作系統間傳遞數據的地點一樣,如根參數,取代以前bootloader的啟動參數,控制臺的輸入輸出參數等
  • 5.1.2 #address-cells和#size-cells

    • #address-cells = <1>: 基地址、片選號等絕對起始地址所占字長,單位uint32
    • #size-cells = <1>: 長度所占字長,單位uint32
    soc {#address-cells = <1>;#size-cells = <1>;serial {compatible = "ns16550";reg = <0x4600 0x100>;clock-frequency = <0>;interrupts = <0xA 0x8>;interrupt-parent = <&ipic>;}; };

    5.1.3 CPU addressing

    在討論尋址時,CPU節點代表了最簡單的情況。 每個CPU都分配有一個唯一的ID,并且沒有與CPU ID相關聯的大小。

    cpus {#address-cells = <1>;#size-cells = <0>;cpu@0 {compatible = "arm,cortex-a9";reg = <0>;};cpu@1 {compatible = "arm,cortex-a9";reg = <1>;};};

    在cpus節點,#address-cells被設置成了1,#size-cells被設置成了0。這是說子reg值是單獨的uint32,它用無大小字段表示地址。在此情況下,這兩個cpu分配到的地址為0和1。Cpu節點的#size-cells是0因為每個cpu只分配到了一個單獨的地址。
    你仍然需要注意reg值班需要與節點名的值相匹配。按照慣例,如果一個節點有一個reg屬性,那么這個節點名稱必須包括unit-address,這是reg屬性的第一個address值。

    5.1.4 Memory Mapped Devices

    與在cpu節點中單獨的address值不同,內存映射設備被分配了一系列將要響應的地址,因此不僅需要包含內存的基地址而且還需要映射地址的長度,因此需要使用#size-cells用來表示在每個子reg元組中長度字段的大小。在以下示例中,每個address值為1 cell(32 bits),每個長度值也是1 cell,這在32 bit系統是比較典型的。64 bit設備也許會為#address-cells和#size-cells使用數值2,在device tree中獲取64 bit addressing。

    /dts-v1/;/ {#address-cells = <1>;#size-cells = <1>;...serial@101f0000 {compatible = "arm,pl011";reg = <0x101f0000 0x1000 >;};serial@101f2000 {compatible = "arm,pl011";reg = <0x101f2000 0x1000 >;};gpio@101f3000 {compatible = "arm,pl061";reg = <0x101f3000 0x10000x101f4000 0x0010>;};interrupt-controller@10140000 {compatible = "arm,pl190";reg = <0x10140000 0x1000 >;};spi@10115000 {compatible = "arm,pl022";reg = <0x10115000 0x1000 >;};... };

    5.1.5 Non Memory Mapped Devices

    處理器總線的其它設備為非內存映射設備。他們有地址范圍,但不能被CPU直接尋址。母設備的驅動程序將代替CPU進行間接訪問。以i2c設備為例,每個設備都分配了一個地址,但沒有長度或范圍與之相匹配。這與CPU地址分配很相似。

    i2c@1,0 {compatible = "acme,a1234-i2c-bus";#address-cells = <1>;#size-cells = <0>;reg = <1 0 0x1000>;rtc@58 {compatible = "maxim,ds1338";reg = <58>;};};

    5.1.6 Ranges (Address Translation)

    我們已經討論過如何向設備分配地址,但此時這些地址只是本地設備節點,還沒有說明如何從那些地址里映射到cpu可以使用的地址。根節點經常描述地址空間的CPU視圖。根節點的子節點已經使用了CPU的address domain,所以不需要任何明確的映射。例如,serial@101f0000設備被直接分配了地址0x101f0000。
    根節點的非直接子節點是無法使用CPU的address domain的。為了在deivce tree獲取內存映射地址必須指定如何從一個域名將地址轉換到另一個。Ranges屬性就用于此目的。以下是添加了ranges屬性的device tree示例。

    /dts-v1/; / {compatible = "acme,coyotes-revenge";#address-cells = <1>;#size-cells = <1>;...external-bus {#address-cells = <2>#size-cells = <1>;ranges = <0 0 0x10100000 0x10000 // Chipselect 1, Ethernet1 0 0x10160000 0x10000 // Chipselect 2, i2c controller2 0 0x30000000 0x1000000>; // Chipselect 3, NOR Flashethernet@0,0 {compatible = "smc,smc91c111";reg = <0 0 0x1000>;};i2c@1,0 {compatible = "acme,a1234-i2c-bus";#address-cells = <1>;#size-cells = <0>;reg = <1 0 0x1000>;rtc@58 {compatible = "maxim,ds1338";reg = <58>;};};flash@2,0 {compatible = "samsung,k8f1315ebm", "cfi-flash";reg = <2 0 0x4000000>;};}; };

    Ranges是一個地址轉換列表。每個輸入ranges表格的是包含子地址的元組,母地址和子地址空間的范圍大小。每個字段的大小都由獲取的子地址的#address-cells值,母地址的#address-cell值和子地址的#size-cells值而定。以外部總線為例,子地址是2 cells,母地址是1 cell,大小也為1 cell。轉換三個ranges:

    • Offset 0 from chip select 0 is mapped to address range 0x10100000…0x1010ffff
    • Offset 0 from chip select 1 is mapped to address range 0x10160000…0x1016ffff
    • Offset 0 from chip select 2 is mapped to address range 0x30000000…0x30ffffff

    例如上面的總線是有片選的,就需要描述片選及片選的偏移量,在說明地址時,還需要說明地址映射范圍

    5.1.7 status

    device tree中的status標識了設備的狀態,使用status可以去禁止設備或者啟用設備,看下設備樹規范中的status可選值

    valueDescription
    “okay”表示設備正在運行
    “disabled”表示該設備目前尚未運行,但將來可能會運行
    “fail”表示設備無法運行。 在設備中檢測到嚴重錯誤,確實如此沒有修理就不可能投入運營
    “fail-sss”表示設備無法運行。 在設備中檢測到嚴重錯誤,它是沒有修理就不可能投入運營。 值的sss部分特定于設備并指示檢測到的錯誤情況

    5.2 中斷映射

    與遵循樹的自然結構而進行的地址轉換不同,機器上的任何設備都可以發起和終止中斷信號。另外地址的編址也不同于中斷信號,前者是設備樹的自然表示,而后者者表現為獨立于設備樹結構的節點之間的鏈接。 下圖顯示了設備的自然結構以及每個節點在邏輯中斷樹中的位置。

    上圖包括以下部分:

    • open-pic中斷控制器是中斷樹的根
    • 中斷樹根有三個子設備,它們將中斷直接路由到open-pic
      • device1
      • PCI host controller
      • GPIO Controller
    • 存在三個中斷域; 一個以開放式pic節點為根,一個在PCI主橋節點,一個在GPIO Controller節點上
    • 有兩個nexus節點; 一個位于PCI主橋,一個位于GPIO控制器。
    屬性屬性值描述
    #interruptsprop-encoded-array一個設備節點屬性,該屬性主要描述了中斷的HW interrupt ID以及類型
    #interrupt-parentphandle該屬性主要描述了該設備的interrupt request line連接到哪一個interrupt controller,那些沒有 interrupt-parent 的節點則從它們的父節點中繼承該屬性
    #interrupts-extendedphandle prop-encoded-array列出了設備生成的中斷,當設備連接到多個中斷控制器
    #interrupt-cellsu32這是中斷控制器節點的屬性,用來標識這個控制器需要幾個單位做中斷描述符(類似于 #address-cells 和 #size-cells),則子節點的interrupts一個cell三個32bits整型值: <中斷域 中斷 觸發方式>
    #interrupt-controllerempty一個空屬性用來聲明這個node接收中斷信號

    下面顯示了具有PCI總線控制器和采樣中斷的設備片段

    soc {compatible = "simple-bus";#address-cells = <1>;#size-cells = <1>;open-pic {clock-frequency = <0>;interrupt-controller;#address-cells = <0>;#interrupt-cells = <2>;};pci {#interrupt-cells = <1>;#size-cells = <2>;#address-cells = <3>;interrupt-map-mask = <0xf800 0 0 7>;interrupt-map = </ * IDSEL 0x11 - PCI slot 1* /0x8800 0 0 1 &open-pic 2 1 / * INTA* /0x8800 0 0 2 &open-pic 3 1 / * INTB* /0x8800 0 0 3 &open-pic 4 1 / * INTC* /0x8800 0 0 4 &open-pic 1 1 / * INTD* // * IDSEL 0x12 - PCI slot 2* /0x9000 0 0 1 &open-pic 3 1 / * INTA* /0x9000 0 0 2 &open-pic 4 1 / * INTB* /0x9000 0 0 3 &open-pic 1 1 / * INTC* /0x9000 0 0 4 &open-pic 2 1 / * INTD* />;}; };

    5.3 特殊節點

    aliases節點為了解決節點路徑名過長的問題,引入了節點別名的概念,可以引用到一個全路徑的節點。如/external-bus/ethernet@0,0,但當用戶想知道具體內容的時候顯得太累贅,“哪個設備是eth0?”

    aliases {ethernet0 = &eth0;serial0 = &serial0;};

    當為設備分配一個標識符的時候,操作系統更傾向于使用aliases

    總結

    以上是生活随笔為你收集整理的奇小葩讲设备树(1/5)-- Linux设备树详解(一) 基础知识的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。