(DT系列一)DTS結構及其編譯方法

DTS結構及其編譯方法


一:主要問題

1,需要了解dtsidts的關係

2,dts的結構模型

3,dts是如何被編譯的,以及編譯後會生成一個什麼文件.


二:參考文字

1DTS(device tree source)

.dts文件是一種ASCII文本格式的DeviceTree描述。基本上,在ARMLinux內,一個.dts文件對應一個ARMmachine,一般放置在內核的arch/arm/boot/dts/目錄。由於一個SoC可能對應多machine(一個SoC可以對應多個產品和電路板),勢必這些.dts文件需包含許多共同的部分。Linux內核爲了簡化,把SoC公用的部分或者多個machine共同的部分一般提煉爲.dtsi,類似於C語言的頭文件。其他的machine對應的.dtsinclude這個.dtsi



2dts的結構模型

爲了瞭解DeviceTree的結構,我們首先給出一個DeviceTree的示例:

/o device-tree
      |- name ="device-tree"
      |- model ="MyBoardName"
      |-compatible = "MyBoardFamilyName"
     |- #address-cells = <2>
      |-#size-cells = <2>
      |-linux,phandle = <0>
      |
     o cpus
      | | - name = "cpus"
     | | - linux,phandle = <1>
      | |- #address-cells = <1>
      | | -#size-cells = <0>
      | |
     | o PowerPC,970@0
      | |- name ="PowerPC,970"
      | |-device_type = "cpu"
      | |-reg = <0>
      | |-clock-frequency = <0x5f5e1000>
     | |- 64-bit
      | |- linux,phandle =<2>
      |
     o memory@0
      | |- name ="memory"
      | |- device_type= "memory"
      | |- reg =<0x00000000 0x00000000 0x00000000 0x20000000>
     | |- linux,phandle = <3>
     |
      o chosen
       |- name = "chosen"
       |- bootargs = "root=/dev/sda2"
       |- linux,phandle = <4>



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



3dts是如何被編譯的,以及編譯後會生成一個什麼文件。

    1. DTC(device tree compiler)

dtc是將.dts編譯爲.dtb的工具。DTC的源代碼位於內核的scripts/dtc目錄,在Linux內核使能了DeviceTree的情況下,編譯內核時,主機工具dtc會被編譯出來,對應scripts/dtc/Makefile中的hostprogs-y:= dtc”這一hostprogs編譯target

Linux內核的arch/arm/boot/dts/Makefile中,描述了當某種SoC被選中後,哪些.dtb文件會被編譯出來。舉例如下:

如與VEXPRESS對應的.dtb包括:

<span lang="en-US">	dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \</span>
        <span lang="en-US">	vexpress-v2p-ca9.dtb \</span>
        <span lang="en-US">	vexpress-v2p-ca15-tc1.dtb \</span>
        <span lang="en-US">	vexpress-v2p-ca15_a7.dtb \</span>
        <span lang="en-US">	xenvm-4.2.dtb</span>

Linux下,我們可以單獨編譯DeviceTree文件。當我們在Linux內核下運行makedtbs時,若我們之前選擇了ARCH_VEXPRESS,上述.dtb都會由對應的.dts編譯出來。因爲arch/arm/Makefile中含有一dtbs編譯target項目。

    1. DeviceTree Blob (.dtb)

.dtb.dtsDTC編譯後的二進制格式的DeviceTree描述,可由Linux內核解析。通常在我們爲電路板製作NANDSD啓動image時,會爲.dtb文件單獨留下一個很小的區域以存放之,之後bootloader在引導kernel的過程中,會先讀取該.dtb到內存。

  1. 源代碼體現

有兩種方式使用DT。第一種可包含多個dtb,編入dt.img,放入boot.img。第二種只包含一個dtb,直接追加到kernelimage後面,放入boot.img
dtc
編譯在kernel/AndroidKernel.mk中定義。先用定義"DTS_NAMES"變量,它的每個entry(記爲"DTS_NAME"變量,下面的$$arch)中可能有archrev兩部分,和.config中相關配置有關,用下面方法找出。

<span style="color:#333333;"><span style="font-size:10pt"><span lang="en-US">while (<>) {</span></span></span>
<span style="color:#333333;"><span style="font-size:10pt"><span lang="en-US">$$a = $$1 if /CONFIG_ARCH_((?:MSM|QSD|MPQ)[a-zA-Z0-9]+)=y/;</span></span></span>
<span style="color:#333333;"><span style="font-size:10pt"><span lang="en-US">$$r = $$1 if /CONFIG_MSM_SOC_REV_(?!NONE)(\w+)=y/;</span></span></span>
<span style="color:#333333;"><span style="font-size:10pt"><span lang="en-US">$$arch = $$arch.lc("$$a$$r ") if /CONFIG_ARCH_((?:MSM|QSD|MPQ)[a-zA-Z0-9]+)=y/</span></span></span>
<span style="color:#333333;"><span style="font-size:10pt"><span lang="en-US">} print $$arch;</span></span></span>

得到上述"DTS_NAMES"變量,用"$(DTS_NAME)*.dts"方式去"kernel/arch/arm/boot/dts/"下匹配。見下面的定義,其中"cat"命令就是生成帶DTkernelimage

<span style="color:#333333;"><span style="font-size:10pt"><span lang="en-US">define append-dtb</span></span></span>
<span style="color:#333333;"><span style="font-size:10pt"><span lang="en-US">mkdir -p $(KERNEL_OUT)/arch/arm/boot;\</span></span></span>
<span style="color:#333333;"><span style="font-size:10pt"><span lang="en-US">$(foreach DTS_NAME, $(DTS_NAMES), \</span></span></span>
<span style="color:#333333;">   <span lang="en-US"><span style="font-size:10pt">$(foreach d, $(DTS_FILES), \</span></span></span>
<span style="color:#333333;">      <span lang="en-US"><span style="font-size:10pt">$(DTC) -p 1024 -O dtb -o $(call DTB_FILE,$(d)) $(d); \</span></span></span>
<span style="color:#333333;">      <span lang="en-US"><span style="font-size:10pt">cat $(KERNEL_ZIMG) $(call DTB_FILE,$(d)) > $(call ZIMG_FILE,$(d));))</span></span></span>
<span style="color:#333333;"><span style="font-size:10pt"><span lang="en-US">endef</span></span></span>

第二種方式沒看到後續如何放入boot.img。對於第一種方式,會用"device/qcom/common/generate_extra_images.mk"中定義的下面規則編出"dt.img"

<span style="color:#333333;"><span style="font-size:10pt"><span lang="en-US">$(INSTALLED_DTIMAGE_TARGET): $(DTBTOOL) $(INSTALLED_KERNEL_TARGET)</span></span></span>
<span style="color:#333333;">        <span lang="en-US"><span style="font-size:10pt">$(build-dtimage-target)</span></span></span>

"build/core/Makefile"中用下面語句使它被編入boot.img

<span style="color:#333333;"><span style="font-size:10pt"><span lang="en-US">ifeq ($(strip $(BOARD_KERNEL_SEPARATED_DT)),true)</span></span></span>
<span style="color:#333333;">  <span lang="en-US"><span style="font-size:10pt">INTERNAL_BOOTIMAGE_ARGS += --dt $(INSTALLED_DTIMAGE_TARGET)</span></span></span>
<span style="color:#333333;">  <span lang="en-US"><span style="font-size:10pt">BOOTIMAGE_EXTRA_DEPS   s:= $(INSTALLED_DTIMAGE_TARGET)</span></span></span>
<span style="color:#333333;"><span style="font-size:10pt"><span lang="en-US">endif</span></span></span>


轉自:http://blog.csdn.net/lichengtongxiazai/article/details/38941891

發佈了34 篇原創文章 · 獲贊 5 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章