国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

扁平設(shè)備樹FDT在ARM Linux中的應(yīng)用研究

2017-04-14 09:42:36羅名駒陳益民賈志文
關(guān)鍵詞:源碼內(nèi)核代碼

羅名駒,陳益民,賈志文

(廣東工業(yè)大學(xué) 信息工程學(xué)院,廣州 510006)

扁平設(shè)備樹FDT在ARM Linux中的應(yīng)用研究

羅名駒,陳益民,賈志文

(廣東工業(yè)大學(xué) 信息工程學(xué)院,廣州 510006)

引入Flattened Device Tree(扁平設(shè)備樹,F(xiàn)DT)到ARM Linux后,Linux內(nèi)核可以通過FDT獲取板級硬件的細節(jié)信息,這樣就減少了Linux 內(nèi)核中arch/arm目錄下大量描述板級硬件細節(jié)信息的冗余代碼,把大多數(shù)與板級硬件特性相關(guān)的代碼放在設(shè)備樹文件和設(shè)備驅(qū)動中,提高了代碼的復(fù)用性,避免了ARM Linux內(nèi)核為支持新硬件進行大量修改,提高了ARM Linux板級支持的開發(fā)速度,也使得使用現(xiàn)有的內(nèi)核鏡像去引導(dǎo)具有相同芯片集的硬件平臺成為可能。

扁平設(shè)備樹;ARM;Linux kernel

引 言

在Flattened Device Tree(FDT)還沒有引入ARM Linux內(nèi)核之前,Linux內(nèi)核代碼arch/arm目錄下有大量重復(fù)的代碼來描述板級硬件的細節(jié)信息。正是這些用來描述板級硬件細節(jié)信息的代碼使ARM Linux內(nèi)核代碼變得越來越冗余。

2011年3月17日,Linus Torvalds在ARM Linux郵件列表寫到“this whole ARM thing is a fucking pain in the ass”,這引起了ARM Linux社區(qū)激烈的討論。ARM社區(qū)為改變Linux內(nèi)核代碼冗余的情況引入了FDT。使用FDT后,Linux內(nèi)核可以直接通過FDT獲取硬件的細節(jié)信息,這使得ARM Linux內(nèi)核中的冗余編碼大大減少,同時也使得用一個內(nèi)核鏡像去引導(dǎo)同一類ARM芯片集的硬件平臺成為可能。

1 FDT組成和結(jié)構(gòu)

FDT是一種描述板級硬件配置的樹形數(shù)據(jù)結(jié)構(gòu),來源于 Open Firmware (OF)[1],并繼承了Open Firmware IEEE 1275 設(shè)備樹的定義[2]。

在Flattened Device Tree中,可描述板級硬件的信息包括[3]:CPU的數(shù)量和類別、內(nèi)存基地址和大小、總線和橋、中斷控制器、Clock控制器、GPIO控制器和外圍設(shè)備。

Bootloader在啟動的過程中把FDT二進制代碼加載到內(nèi)存,Linux內(nèi)核會根據(jù)FDT傳遞進來的硬件信息展開,得到Linux內(nèi)核所需的硬件設(shè)備信息。

1.1 FDT源文件(Device tree source)

FDT源文件(.dts)[4]由節(jié)點(node)和屬性(property)組成,每個節(jié)點可包含子節(jié)點和屬性。在Linux內(nèi)核的arch/arm/boot/dts/目錄下存放著.dts文件,通常一個板級硬件對應(yīng)著一個.dts文件。

下面是一個簡單設(shè)備樹源碼示例:

/{

model = "MyBoardName"

compatible= "MyBoardFamilyName"

#address-cells = <1>

#size-cells = <1>

aliases {

i2c0 = &i2c0;

i2s0 = &i2s0;

spi0 = &spi0;

};

cpus {

#address-cells = <1>;

#size-cells = <0>;

cpu@0{

compatible = "arm,Cortex-a9";

device_type = "cpu";

reg = <0>;

};

};

memory@0{

name = "memory"

device_type = "memory"

reg = <0x00000000 0x20000000>

}

chosen{

name = "chosen"

bootargs="console=ttySAC0,115200 root=/dev/

mmcblk0p5"

}

}

從FDT源碼示例可以看到,設(shè)備樹的基本單元由節(jié)點組成,每個節(jié)點都由節(jié)點單元名稱標(biāo)識,并且每一個屬性都有相對應(yīng)的值。節(jié)點用節(jié)點名字標(biāo)識,其形式為node-name@unit-address。

(1) 根節(jié)點

每個設(shè)備樹源碼文件里面有且僅有一個根節(jié)點,且節(jié)點名必須是“/”。根節(jié)點下有若干個節(jié)點,每個節(jié)點中的屬性(property)描述了該節(jié)點的特性。根節(jié)點下包含的屬性有:model為板級硬件模塊的名稱;#address-cells表示該目標(biāo)板或者硬件模塊的地址線;#size-cells表示該目標(biāo)板或者硬件模塊的地址線寬度。

(2) CPU節(jié)點

CPU節(jié)點描述了CPU的特性,每一個CPU都有一個與之一一對應(yīng)的CPU節(jié)點。CPU節(jié)點下常用的屬性有[5]:#address-cells表示CPU的地址線;#size-cells表示CPU的地址線寬度;device_type為節(jié)點設(shè)備類型,必須設(shè)為“cpu”;reg用于指定CPU的編號。

(3) memory 節(jié)點

memory節(jié)點是FDT文件必備的節(jié)點,它定義了板級硬件物理內(nèi)存的起始地址和大小。該節(jié)點下常用的屬性有:

device_type為節(jié)點設(shè)備類型,必須設(shè)為“memory”;

reg用

指定內(nèi)存地址和大小,例如<0x00000000 0x20000000>表示內(nèi)存地址從0x0000 0000開始,大小為512 MB的內(nèi)存節(jié)點。

(4) SoC節(jié)點

SoC節(jié)點描述了CPU上集成的外設(shè)接口,例如I2C、SPI、串口等。SoC節(jié)點包含的屬性有:device_type為節(jié)點設(shè)備類型,必須設(shè)為“soc”;ranges節(jié)點表示SoC寄存器地址。

(5) chosen節(jié)點

chosen節(jié)點不是用來描述硬件資源的信息,而是向Linux 內(nèi)核傳遞一些運行時的參數(shù)。使用chosen節(jié)點可以取代Bootloader通過tag list傳遞運行參數(shù)給Linux 內(nèi)核。例如:bootargs這個屬性傳遞的是command line的信息;initrd-start這個屬性傳遞是initrd的開始地址。

(6) aliases節(jié)點

aliases節(jié)點定義了一些節(jié)點的別名。在FDT源文件中引用一個節(jié)點時要指明相對于根節(jié)點的絕對路徑,例如/node-name-1/node-name-2。aliases 節(jié)點定義一些節(jié)點路徑的別名,使引用節(jié)點變得簡潔。

Linux內(nèi)核開發(fā)者把SoC芯片公用的.dts文件單獨分離出來,保存為.dtsi文件。當(dāng)其他.dts文件需要使用這些公共的.dtsi文件時,就把該.dtsi包含進去。大部分的ARM SoC的.dtsi文件都引用了arch/arm/boot/dts/skeleton.dtsi這個設(shè)備樹源碼文件。

1.2 FDT源碼編譯器(Device tree compiler)

FDT源碼編譯器是將FDT源碼文件(.dts)編譯為FDT二進制文件(.dtb)的工具。配置Linux內(nèi)核時,選中CONFIG_DTC選項,Linux內(nèi)核在編譯的過程中會自動編譯生成設(shè)備樹編譯器。在Linux內(nèi)核源碼根目錄下運行make dtbs命令時,設(shè)備樹源碼編譯器會把選中的.dts編譯成.dtb。

1.3 FDT二進制文件(Device tree blob)

使用設(shè)備樹源碼編譯器把.dts格式的設(shè)備樹源碼文件編譯成.dtb格式的FDT二進制文件。在制作板級硬件啟動鏡像時,通常會在指定區(qū)域存放.dtb文件,Bootloader在引導(dǎo)內(nèi)核的過程中會把該.dtb文件讀取到特定內(nèi)存區(qū)域中。

2 FDT在ARM Linux中的應(yīng)用

ARM Linux未引入FDT時,ARM Linux內(nèi)核在arch/arm/plat-xxx和arch/arm/mach-xxx做的主要工作是[6]:

注冊platform_device,綁定resource:

static struct resource xxx_resources[] = {

[0] = {

.start= …,

.end= …,

.flags= IORESOURCE_MEM,

},

[1] = {

.start=…,

.end=…,

.flags=IORESOURCE_IRQ,

},

};

static struct platform_device xxx_device={

name="xxx",

.id=-1,

.dev= {

.platform_data=&xxx_data,

},

.resource=xxx_resources,

.num_resources=ARRAY_SIZE(xxx_resources),

};

注冊i2c_board_info、spi_board_info等:

static struct i2c_board_info __initdataxxx_i2c_devices[]={

{I2C_BOARD_INFO("name", 0x1a), },

};

static struct spi_board_infoxxx_spi_devices[] ={

{/* DataFlash chip */

.modalias="mtd_dataflash",

.chip_select=1,

.max_speed_hz=15*1000*1000,

.bus_num=0,

},

};

填充由MACHINE_START和MACHINE_END包圍起來的的一系列callback函數(shù):

MACHINE_START(xxx_board,"ARM-xxx")

.atag_offset=0x100,

.map_io=xxx_map_io,

.init_early=xxx_init_early,

.init_irq=xxx_init_irq,

.timer=& xxx_timer,

.handle_irq=gic_handle_irq,

.init_machine=xxx _init,

.restart=xxx_board _restart,

MACHINE_END

使用FDT后,resource信息可以從.dts節(jié)點中的reg、interrupts等屬性得到; Linux內(nèi)核中板級硬件的回調(diào)函數(shù)通過調(diào)用函數(shù)of_platform_bus_probe(NULL,xxx_of_bus_ids, NULL),即可自動展開所有的platform_device。

假設(shè)有一款A(yù)RM芯片的板級硬件,Linux內(nèi)核在arch/arm/mach-xxx/的板級文件中使用如下方式展開.dts文件中的設(shè)備節(jié)點對應(yīng)的平臺設(shè)備信息:

static struct of_device_id xxx_of_bus_ids[]__initdata = {

{ .compatible="simple-bus", },

{},

};

void __init xxx_mach_init(void){

of_platform_bus_probe(NULL,xxx_of_bus_ids, NULL);

}

#ifdef CONFIG_ARCH_XXX

DT_MACHINE_START(XXX_DT, "Generic XXX (Flattened Device Tree)")

……

.init_machine=xxx_mach_init,

……

MACHINE_END

#endif

把I2C、SPI等這些硬件設(shè)備信息填充到對應(yīng)的FDT源碼文件中的I2C controller、SPI controller節(jié)點上去,I2C host驅(qū)動、SPI host驅(qū)動的probe函數(shù)在注冊主設(shè)備的時候獲得這些硬件信息:

i2c2: i2c@e1a00000 {

compatible="yyyy,xxxx-i2c";

reg=<0xe1a00000 0x1000>;

#address-cells=<1>;

#size-cells=<0>;

……

};

spi0: spi@e1300000 {

compatible="yyyy,xxxx-spi";

reg=<0xe1300000 0x1000>;

#address-cells=<1>;

#size-cells=<0>;

……

};

MACHINE_START和MACHINE_END包圍起來的一系列板級硬件callback函數(shù)變成為:

static const char * constxxx_dt_match[]__initconst={

"arm,xxx_board",

NULL,

};

DT_MACHINE_START(XXX_BOARD_DT, "ARM-xxx")

.dt_compat=xxx_dt_match,

.smp=smp_ops(xxx_board_smp_ops),

.map_io=xxx_dt_map_io,

.init_early=xxx_dt_init_early,

.init_irq=xxx_dt_init_irq,

.timer=&xxx_dt_timer,

.init_machine=xxx_dt_init,

.handle_irq=gic_handle_irq,

.restart=xxx_board_restart,

MACHINE_END

.dt_compat成員是用來表明相關(guān)的板級硬件與.dts文件中根節(jié)點的compatible屬性的兼容關(guān)系。如果Bootloader傳遞給內(nèi)核的設(shè)備樹中根結(jié)點的compatible屬性出現(xiàn)在某個板級硬件的.dt_compat表中,相關(guān)的板級硬件就與對應(yīng)的設(shè)備樹匹配,被執(zhí)行相關(guān)板級硬件的初始化函數(shù)。

對驅(qū)動來說,當(dāng)驅(qū)動與.dts中描述的設(shè)備節(jié)點匹配后,會執(zhí)行驅(qū)動的probe()函數(shù)。對于平臺驅(qū)動而言,需要添加一個OF匹配表。例如.dts文件的"acme,xxx-i2c-bus"兼容I2C控制器節(jié)點的OF匹配表為:

static const struct of_device_idxxx_i2c_of_match[]={

{.compatible="yyy,xxx-i2c-bus ", },

{},

};

MODULE_DEVICE_TABLE(of,xxx_i2c_of_match);

static struct platform_driver i2c_xxx_driver={

.driver={

.name="xxx-i2c-bus ",

.owner=THIS_MODULE,

.of_match_table=xxx_i2c_of_match,

},

.probe=i2c_xxx_probe,

.remove=i2c_xxx_remove,

}

結(jié) 語

本文介紹了FDT的優(yōu)點及其在ARM Linux的用法,詳細闡述了ARM Linux引入FDT后,相關(guān)內(nèi)核板級支持包和驅(qū)動代碼的變化。在ARM Linux引入FDT后,刪除

[1] Grant Likely,Josh Boyer.A Symphony of Flavours: Using the device tree to describe embedded hardware[R].Ottawa,Canada:Linux Symposium,2008.

[2] SUN.The Open Firmware Home Page[EB/OL].[2016-10].http://playground.sun.com/1275/home.html,2005.

[3] 宋寶華.Linux設(shè)備驅(qū)動開發(fā)詳解:基于最新的Linux4.0內(nèi)核[M].北京:機械工業(yè)出版社,2015.

[4] devicetree-specification-v0.1[EB/OL].[2016-10].https://www.devicetree.org/specifications/.

[5] 邱文華.基于扁平設(shè)備樹的Linux內(nèi)核啟動方式[J].現(xiàn)代計算機:專業(yè)版,2009.

[6] ARM Linux 3.x的設(shè)備樹(Device Tree)[EB/OL].[2016-10].http://blog.csdn.net/21cnbao/article/details/8457546.

[7] Device Tree[EB/OL].[2016-10].http://elinux.org/Device_Tree.

羅名駒、賈志文(碩士研究生),主要研究方向為嵌入式系統(tǒng)應(yīng)用;陳益民(副教授),主要研究方向為測試計量技術(shù)、監(jiān)測自動化裝置、光伏產(chǎn)品監(jiān)測技術(shù)。

Application of Flattened Device Tree in ARM Linux

Luo Mingju,Chen Yimin,Jia Zhiwen

(School of Information Engineering,Guangdong University of Technology,Guangzhou 510006,China)

Flattened Device Tree is introduced into ARM Linux,that can directly put the detailed description of board-level hardware information to the Linux kernel.So the arch/arm in the Linux kernel directory’s redundant codes which describing board-level hardware details are reduced.The reusability of the Linux kernel codes is improved when we write the most board-level hardware features related code in the device tree files and device drivers.It also can avoid modifying a lot of ARM Linux kernel codes to support the new hardware,and accelerate speed to develop the ARM Linux board support package.Using the existing kernel image to boot with the same chipset hardware platform is possible.

flattened device tree;ARM;Linux kernel

TP311

A

?士然

2016-10-25)

猜你喜歡
源碼內(nèi)核代碼
基于網(wǎng)頁源碼結(jié)構(gòu)理解的自適應(yīng)爬蟲代碼生成方法
基于圖神經(jīng)網(wǎng)絡(luò)的軟件源碼漏洞檢測方法
計算機時代(2023年6期)2023-06-15 17:49:09
萬物皆可IP的時代,我們當(dāng)夯實的IP內(nèi)核是什么?
強化『高新』內(nèi)核 打造農(nóng)業(yè)『硅谷』
企業(yè)如何保護源碼
基于嵌入式Linux內(nèi)核的自恢復(fù)設(shè)計
Linux內(nèi)核mmap保護機制研究
創(chuàng)世代碼
動漫星空(2018年11期)2018-10-26 02:24:02
創(chuàng)世代碼
動漫星空(2018年2期)2018-10-26 02:11:00
創(chuàng)世代碼
動漫星空(2018年9期)2018-10-26 01:16:48
芜湖市| 揭西县| 通榆县| 新蔡县| 本溪市| 三原县| 大悟县| 屯留县| 普兰县| 永泰县| 康乐县| 开化县| 临清市| 南川市| 邢台县| 嵊泗县| 启东市| 黄山市| 凤阳县| 东乌珠穆沁旗| 丹江口市| 安化县| 巨野县| 五台县| 冕宁县| 仙居县| 洛浦县| 石城县| 台北县| 西峡县| 辽宁省| 什邡市| 玛纳斯县| 和政县| 呼玛县| 康乐县| 阿巴嘎旗| 池州市| 上虞市| 安远县| 天长市|