嵌入式 裝置樹解析

來源:互聯網
上載者:User
              /* add by starby */       name = "chosen";       bootargs = "root=/dev/ram rw console=ttyS0,115200";       linux,stdout-path = "/soc8349@e0000000/serial@4500";   };

};


3.1 根節點

裝置樹的起始點稱之為根節點"/"。屬性model指明了目標板平台或模組的名稱,屬性compatible值指明和目標板為同一系列的相容的開發板名稱。對於大多數32位平台,屬性#address-cells和#size-cells的值一般為1。

3.2 CPU節點

/cpus節點是根節點的子節點,對於系統中的每一個CPU,都有相應的節點。/cpus節點沒有必須指明的屬性,但指明#address-cells = <1>和 #size-cells = <0>是個好習慣,這同時指明了每個CPU節點的reg屬性格式,方便為物理CPU編號。此節點應包含板上每個CPU的屬性。CPU名稱一般寫作PowerPC,<name>,例如Freescale會使用PowerPC,8349來描述本文的MPC8349E處理器。CPU節點的單元名應該是cpu@0的格式,此節點一般要指定device_type(固定為"cpu"),一級資料/指令緩衝的表項大小,一級資料/指令緩衝的大小,核心、匯流排時鐘頻率等。在上面的樣本中通過系統引導代碼動態填寫時鐘頻率相關項目。

3.3 系統記憶體節點

此節點用於描述目標板上實體記憶體範圍,一般稱作/memory節點,可以有一個或多個。當有多個節點時,需要後跟單元地址予以區分;只有一個單元地址時,可以不寫單元地址,預設為0。此節點包含板上實體記憶體的屬性,一般要指定device_type(固定為"memory")和reg屬性。其中reg的屬性值以<起始地址 空間大小>的形式給出,如上樣本中目標板記憶體起始地址為0,大小為256M位元組。

3.4 /chosen節點

這個節點有一點特殊。通常,這裡由Open Firmware存放可變的環境資訊,例如參數,預設輸入輸出裝置。這個節點中一般指定bootargs及linux,stdout-path屬性值。bootargs屬性設定為傳遞給核心命令列的參數字串。linux,stdout-path常常為標準終端裝置的節點路徑名,核心會以此作為預設終端。U-Boot在1.3.0版本後添加了對扁平裝置樹FDT的支援,U-Boot載入Linux核心、Ramdisk檔案系統(如果使用的話)和裝置樹二進位鏡像到實體記憶體之後,在啟動執行Linux核心之前,它會修改裝置樹二進位檔案。它會填充必要的資訊到裝置樹中,例如MAC地址、PCI匯流排數目等。U-Boot也會填寫裝置樹檔案中的“/chosen”節點,包含了諸如串口、根裝置(Ramdisk、硬碟或NFS啟動)等相關資訊。U-Boot源碼common/cmd_bootm.c的如下代碼,顯示了在執行核心代碼前將調用ft_setup函數填寫裝置樹。
if defined(CONFIG_OF_FLAT_TREE)
   /*    * Create the /chosen node and modify the blob with board specific    * values as needed.    */   ft_setup(of_flat_tree, kbd, initrd_start, initrd_end);   /* ft_dump_blob(of_flat_tree); */
endif

3.5 片上系統SOC節點

此節點用來描述片上系統SOC,如果處理器是SOC,則此節點必須存在。頂級SOC節點包含的資訊對此SOC上的所有裝置可見。節點名應該包含此SOC的單元地址,即此SOC記憶體映射寄存器的基址。SOC節點名以/soc<SOCname>的形式命名,例如MPC8349的SOC節點是"soc8349"。在屬性中應該指定device_type(固定為"soc")、ranges、bus-frequency等屬性。ranges屬性值以<bus_addr parent_bus_addr size>的形式指定。SOC節點還包含目標板使用的每個SOC裝置子節點,應該在裝置樹中儘可能詳細地描述此SOC上的外圍裝置。如下給出帶有看門狗裝置的SOC節點DTS樣本。      soc8349@e0000000 {          #address-cells = <1>;          #size-cells = <1>;          device_type = "soc";          compatible = "simple-bus";          ranges = <0 e0000000 100000>;        /* 1MB size */          reg = <e0000000 00000200>;          bus-frequency = <0>;              /* From bootloader */
           wdt@200 {              device_type = "watchdog";              compatible = "mpc83xx_wdt";              reg = <200 100>;                    /* Offset: 0x200 */         };

3.6 其他裝置節點

分級節點用來描述系統上的匯流排和裝置,類似物理匯流排拓撲,能很方便的描述裝置間的關係。對於系統上的每個匯流排和裝置,在裝置樹中都有其節點。對於這些裝置屬性的描述和定義請詳細參考IEEE 1275及Linux核心文檔booting-without-of.txt。裝置樹的中斷系統稍顯複雜,裝置節點利用interrupt-parent和interrupts屬性描述到中斷控制器的中斷串連。其中interrupt-parent屬性值為中斷控制器節點的指標,#interrupts屬性值描述可觸發的中斷訊號,其值格式與中斷控制器的interrupt-cells屬性值有關。一般#interrupt-cells屬性值為2,interrupts屬性就對應為一對描述硬體中斷號和中斷觸發方式的十六進位值。其具體內容見參考文獻[x](Open Firmware Recommended Practice: Interrupt Mapping Version 0.9".  The document is available at: <http://playground.sun.com/1275/practice>.)


4 裝置樹編譯

由於核心只識別二進位格式的扁平裝置樹,因此需要一個特殊的裝置樹編譯器"dtc",將裝置樹源碼檔案(.dts)編譯二進位檔案(.dtb)。dtc編譯器會對輸入檔案進行文法和語義檢查,並根據Linux核心的要求檢查各節點及屬性,將裝置樹源碼檔案(.dts)編譯二進位檔案(.dtb),以保證核心能正常啟動。最新的dtc編譯器Git倉庫位於www.gdl.com,可以通過如下命令獲得源碼$git clone http://www.gdl.com/projects/dtc.gitdtc編譯器的使用方法如下所示[6]:dtc [-I <input_fomat>] [-O <ouput_fomat>] [-o output_filename] [-V output_version] input_filenameinput_format可以使用以下三個參數:dtb: 表示輸入檔案為dtb檔案;dts: 表示輸入檔案為dts檔案;fs: 表示輸入檔案為與/proc/device-tree檔案的格式相同。output_format可以使用以下三個參數:dtb: 表示輸出檔案為dtb檔案;dts: 表示輸出檔案為dts檔案;asm: 表示輸出檔案為組合語言檔案;如果output_format為“dtb”是,ouput_version用來規定產生的dtb檔案的版本號碼,目前dtb檔案可用的版本號碼為1,2,3,16或17,output_format的預設值為17。-S指定的是產生的dtb檔案的大小,需要適當地擴大以供u-boot 建立/chose節點時使用。input_filename和output_filename分別為輸入和輸出檔案名。從dtc編譯器的使用方法中發現,dtc編譯器不僅可以實現dts檔案到dtb檔案的轉換,也可以實現dtb檔案到dts檔案的轉換。
Linux源碼的arch/powerpc/boot/dts/目錄下存放了很多dts檔案,可以作為參考檔案。另外dtc編譯器在核心源碼2.6.25版本之後已經被包含進去。在2.6.26版本之後,產生blob的簡單規則已經加入makefile,如下命令:$ make ARCH=powerpc canyonlands.dtb
也可以根據自己的硬體修改好dts檔案後,用下面類似命令產生dtb檔案。$ dtc -f -I dts -O dtb -R 8 -S 0x3000 test.dts  > mpc836x_mds.dtb$ mkimage -A ppc -O Linux -T flat_dt -C none -a 0x300000 -e 0 -d mpc836x_mds.dtb mpc836x_mds.dtu
註:最新的U-Boot使用dtb鏡像檔案。而freescale的U-Boot需要如上使用mkimage為dtb添加鏡像資訊。

5 U-Boot相關設定

為使U-Boot支援裝置樹,需要在板子配置標頭檔中設定一系列宏變數。如本文在MPC8349E處理器目標板中移植的U-Boot配置如下:

/* pass open firmware flat tree */ define CONFIG_OF_LIBFDT 1 undef CONFIG_OF_FLAT_TREE define CONFIG_OF_BOARD_SETUP 1 define CONFIG_OF_HAS_BD_T 1 define CONFIG_OF_HAS_UBOOT_ENV 1

啟動引導代碼U-Boot在完成自己的工作之後,會載入Linux核心,並將扁平裝置樹的地址傳遞給核心,其代碼形式如下: if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)

   if (of_flat_tree) { /* device tree; boot new style */       /*        * Linux Kernel Parameters (passing device tree):        *   r3: pointer to the fdt, followed by the board info data        *   r4: physical pointer to the kernel itself        *   r5: NULL        *   r6: NULL        *   r7: NULL        */       (*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0);       /* does not return */   }
endif
arch/powerpc核心的入口有且只有一個,進入點為核心鏡像的起始。此入口支援兩種調用方式,一種是支援Open Firmware啟動,另一種對於沒有OF的引導代碼,需要使用扁平裝置樹塊,如上範例程式碼。寄存器r3儲存指向裝置樹的物理地址指標,寄存器r4儲存為核心在實體記憶體中的地址,r5為NULL。其中的隱含意思為:假設開啟了mmu,那麼這個mmu的映射關係是1:1的映射,即虛擬位址和物理地址是相同的。

6 Linux核心對裝置的解析。

扁平裝置樹描述了目標板平台中的裝置樹資訊。每個裝置都有一個節點來描述其資訊,每個節點又可以有子節點及其相應的屬性。核心源碼中include/linux/of.h及drivers/of/base.c等檔案中提供了一些Open Firmware API,通過這些API,核心及裝置驅動可以尋找到相應的裝置節點,讀取其屬性值,利用這些資訊正確地初始化和驅動硬體。

檔案:FDT100125133436.jpg 分析Linux核心的源碼,可以看到其對扁平裝置樹的解析流程[7 待詳細分析]如下: (1)首先在核心入口處將從u-boot傳遞過來的鏡像基地址和dtb檔案映像基地址儲存通用寄存器r30和r31。 (2)通過調用machine_init()、early_init_devtree()函數來擷取核心前期初始化所需的bootargs,cmd_line等系統引導參數。 (3)根據bootargs,cmd_line等系統引導參數進入start_kernel()函數,進行核心的第二階段初始化。 (4)調用start_kernel()、setup_arch()、unflatten_device_tree()函數來解析dtb檔案,構建一個由device_node結構串連而成的單項鏈表,並使用全域變數allnodes 指標來儲存這個鏈表的頭指標。 (5)核心調用OF 提供的API函數擷取allnodes鏈表資訊來初始化核心其他子系統、裝置等。


7 核心折中

引入了裝置樹FDT blob,相應的會佔用一定的儲存空間,同時引入了FDT API代碼,相比之下核心代碼有所增加,但是一個核心鏡像可以支援多個硬體平台,不同的平台間只需修改裝置樹FDT blob即可。

8 結束語

本文介紹了裝置樹的起源及其優點,進而闡述了裝置樹的資料存放區格式以及源碼描述文法,給出了裝置樹的編譯方法,最後引出了移植過程中的U-Boot相關設定說明及核心的解析過程分析。裝置樹為嵌入式系統向Linux核心傳遞參數的動態介面,希望本文對嵌入式PowerPC Linux開發人員具有一定的參考價值,加快嵌入式PowerPC Linux開發中的裝置樹DTS移植過程。

參考文獻 [1] Matt Tyrlik. Booting Linux on Embedded PowerPCTM Systems [R]. Embedded Linux Developers Conference, 2007 [2] Benjamin Herrenschmidt, Becky Bruce, et al. Booting the Linux/ppc kernel without Open Firmware [Z]. bootint-without-of.txt from the Linux kernel source tree , 2006 [3] DENX. Flattened Device Tree Blob [EB/OL]. http://www.denx.de/wiki/view/DULG/LinuxFDTBlob, 2009 [4] Grant Likely, Josh Boyer. A Symphony of Flavours: Using the device tree to describe embedded hardware [R]. Ottawa, Canada: Linux Symposium, 2008 [5] SUN. The Open Firmware Home Page [EB/OL].http://playground.sun.com/1275/home.html, 2005 [6] David Gibson, Benjamin Herrenschmidt, OzLabs. Device trees everywhere [R]. 2006 [7] 邱文華,邱珍珍. 基於扁平裝置樹的Linux核心啟動方式[J]. 現代電腦,2009年第3期,115-118. 2009.3

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.