天天看點

AM335x裝置樹DTS移值

=============================================

問題一:以前的Linux Kernel如何描述硬體,現在又如何描述呢?

在以前的核心版本中:

1)核心包含了對硬體的全部描述;

2)bootloader會加載一個二進制的核心鏡像,并執行它,比如uImage或者zImage;

3)bootloader會提供一些額外的資訊,成為ATAGS,它的位址會通過r2寄存器傳給核心;

    ATAGS包含了記憶體大小和位址,kernel command line等等;

4)bootloader會告訴核心加載哪一款board,通過r1寄存器存放的machine type integer;

5)U-Boot的核心啟動指令:bootm

6)Barebox變量:bootm.image (?)

AM335x裝置樹DTS移值

現今的核心版本使用了Device Tree:

1)核心不再包含對硬體的描述,它以二進制的形式單獨存儲在另外的位置:the device tree blob

2)bootloader需要加載兩個二進制檔案:核心鏡像和DTB

    核心鏡像仍然是uImage或者zImage;

    DTB檔案在arch/arm/boot/dts中,每一個board對應一個dts檔案;

3)bootloader通過r2寄存器來傳遞DTB位址,通過修改DTB可以修改記憶體資訊,kernel command line,以及潛在的其它資訊;

4)不再有machine type;

5)U-Boot的核心啟動指令:bootm -

6)Barebox變量:bootm.image,bootm.oftree

AM335x裝置樹DTS移值

有些bootloader不支援Device Tree,或者有些專門給特定裝置寫的版本太老了,也不包含。為了解決這個問題,CONFIG_ARM_APPENDED_DTB被引進。

    它告訴核心,在緊跟着核心的位址裡查找DTB檔案;

    由于沒有built-in Makefile rule來産生這樣的核心,是以需要手動操作:

        cat arch/arm/boot/zImage arch/arm/boot/dts/myboard.dtb > my-zImage

        mkimage ... -d my-zImage my-uImage

    (cat這個指令,還能夠直接合并兩個mp3檔案哦!so easy!)

另外,CONFIG_ARM_ATAG_DTB_COMPAT選項告訴核心去bootloader裡面讀取ATAGS,并使用它們更新DT。

=============================================

問題二:現在Linux Kernel使用的Device Tree到底是個什麼東東?

引用the Power.org Standard for Embedded Power Architecture Platform Requirements (ePAPR)的定義:

1)ePAPR使用device tree的概念描述硬體。boot程式會加載device tree到client program's memory中,并将device tree的指針傳遞給client;

2)device tree是一個樹形資料結構with nodes,用來描述系統的physical devices;

3)一個ePAPR-complient device tree描述的裝置資訊不能被client program讀取;

AM335x裝置樹DTS移值

From Source to binary

1)在ARM系統中,所有的DTS檔案放置在arch/arm/boot/dts中:

    .dts檔案為闆級定義

    .dtsi檔案為SoC級定義

2)Device Tree Compiler工具,将源代碼編譯成二進制形式;

    它的源代碼放置在scripts/dtc中

3)編譯器會産生DTB檔案,bootloader會加載這個DTB檔案,核心在boot時去解析它;

4)arch/arm/boot/dts/Makefile會指定産生哪個DTB檔案;

AM335x裝置樹DTS移值

上圖是pdf裡面自帶的例子,我再從arch/arm/boot/dts/am33xxx.dtsi中摘錄了兩個:

                uart0: [email protected] {

                        compatible = "ti,omap3-uart";

                        ti,hwmods = "uart1";

                        clock-frequency = <48000000>;

                        reg = <0x44e09000 0x2000>;

                        interrupts = <72>;

                        status = "disabled";

                };

                uart1: [email protected] {

                        compatible = "ti,omap3-uart";

                        ti,hwmods = "uart2";

                        clock-frequency = <48000000>;

                        reg = <0x48022000 0x2000>;

                        interrupts = <73>;

                        status = "disabled";

                };

對比圖檔中的注釋,就能夠知道對于uart0這個外設:

Node name: serial

Unit Address: 0x44e09000

compatible: 定義了裝置的programming model,允許作業系統識别對應的程式驅動;

clock-frequency: 48000000,晶振頻率為24MHz,這應該是PLL倍頻後的輸出(?);

reg: 寄存器的位址和寄存器長度,uart0的位址起始為0x44e09000,長度為0x2000;

interrupts: 中斷号;

status: 狀态值,初始的時候為disabled,即禁用它;

=============================================

問題三:Device Tree的編寫規則是怎樣的?

1)Device Tree inclusion不一定要做成monolithic,它們可以分散在不同的檔案中,互相包含;

2).dtsi檔案是被包含的,.dts檔案才是最終的Device Trees;

3).dts檔案包含了闆級資訊;

4)including工作主要是将including file覆寫到included file上面;

5)inclusion使用DT操作符/include/,或者在某些少量的核心釋出版中,由于DTS是使用了C preprocessor,是以推薦#include。

AM335x裝置樹DTS移值

由這張圖可見,如果included file中的某項,被including file檔案定義了,則會使用後者的定義,也就是使用更上層更新的定義;如果沒有被定義,則添加進入。

1)bindings是device tree裡面可已包含的specific types and classes of devices。

2)compatible特征描述了節點編譯的specific binding;

3)當為一個裝置建立新的device tree時,應該建立a binding來描述裝置的全部細節。

=============================================

問題四:在哪裡可以找到Device Tree的文檔呢?

1)所有可被核心識别的Device Tree bindings在文檔Documentation/devicetree/bindings裡面;

2)每個binding文檔描述了哪些properties可以被接受,可以使用哪些值,哪些特征是必須的,哪些是可選的;

3)所有新的Device Tree bindings必須讓代碼維護者稽核,送出到[email protected]上。這用來保證它們的正确性和一緻性。

=============================================

問題五:Device Tree中的常見關鍵字含義是什麼?

Device Tree organization: top-level nodes

在裝置的最頂層節點上,一般可以發現如下這些:

cpus:描述了系統的CPU

memory:定義了RAM的位址和大小

chosen:定義了boot時被系統固件選擇或定義的參數;可用來傳遞kernel command line;

aliases:定義了certain nodes的shotcuts;

一個或多個總線定義;

一個或多個闆上裝置定義;

下面是am33xx.dtsi中的定義:

/ {

        compatible = "ti,am33xx";

        interrupt-parent = <&intc>;

        aliases {

                i2c0 = &i2c0;

                i2c1 = &i2c1;

                i2c2 = &i2c2;

                serial0 = &uart0;

                serial1 = &uart1;

                serial2 = &uart2;

                serial3 = &uart3;

                serial4 = &uart4;

                serial5 = &uart5;

                d_can0 = &dcan0;

                d_can1 = &dcan1;

                usb0 = &usb0;

                usb1 = &usb1;

                phy0 = &usb0_phy;

                phy1 = &usb1_phy;

                ethernet0 = &cpsw_emac0;

                ethernet1 = &cpsw_emac1;

        };

        cpus {

                #address-cells = <1>;

                #size-cells = <0>;

                [email protected] {

                        compatible = "arm,cortex-a8";

                        device_type = "cpu";

                        reg = <0>;

                        operating-points = <

                                720000  1285000

                                600000  1225000

                                500000  1125000

                                275000  1125000

                        >;

                        voltage-tolerance = <2>;

                        clocks = <&dpll_mpu_ck>;

                        clock-names = "cpu";

                        clock-latency = <300000>;

                };

        };

        pmu {

                compatible = "arm,cortex-a8-pmu";

                interrupts = <3>;

        };

        soc {

                compatible = "ti,omap-infra";

                mpu {

                        compatible = "ti,omap3-mpu";

                        ti,hwmods = "mpu";

                };

        };

};

從上面的代碼裡面可以找出四個compatible,分别是:

top: compatible = "ti,am33xx";

cpu0: compatible = "arm,cortex-a8";

pmu: compatible = "arm,cortex-a8-pmu";

soc: compatible = "ti,omap-infra";

怎樣使用compatible呢?

方法一是用來比對DT_MACHINE結構體中的dt_compat域,方法二是使用of_machine_is_compatible函數。

在總線中,一般要定義compatile、#address-cells、#size-cells、ranges,比如:

       i2c0: [email protected] {

                compatible = "ti,omap4-i2c";

                #address-cells = <1>;

                #size-cells = <0>;

                ti,hwmods = "i2c1";

                reg = <0x44e0b000 0x1000>;

                interrupts = <70>;

                status = "disabled";

        };

=============================================

問題六:有關DT的政策,你應該了解的~

DT是一種硬體描述,而不是一種配置。

它應該描述硬體的構成,和硬體工作的方式;

它不應該描述那種硬體配置你更加喜歡;

例如:

    你可以在DT中描述是否硬體配置支援DMA;

    但是你不要在DT中描述你是否想要DMA。

1)DT獨立于OS,它也需要非常穩定;

2)最初的設想是,DTBs由生産廠家燒寫進晶片中,使用者直接安裝系統就好了;

3)當Device Tree binding被定義,并且在DTBs使用之後,它就不能再改變,但可以擴充;

4)這意味着Device Tree binding是核心的二進制程式接口(ABI),它需要same care;

5)但是核心開發者意識到了這個很難達到,并且會減慢驅動程式的內建:

    ARM Kernel Mini-submit discussions放松了這些限制;

    未來在Kernel Summit時會有additional discussion;

Basic guidelines for binding design:

1) A precise compatible string is better than a vague one.

參考文獻:http://events.linuxfoundation.org/sites/events/files/slides/petazzoni-device-tree-dummies.pdf