日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

1、設(shè)備樹的概念

在內(nèi)核源碼中,存在大量對(duì)板級(jí)細(xì)節(jié)信息描述的代碼。這些代碼充斥在/arch/arm/plat-xxx和/arch/arm/mach-xxx目錄,對(duì)內(nèi)核而言這些platform設(shè)備、resource、i2c_board_info、spi_board_info以及各種硬件的platform_data絕大多數(shù)純屬垃圾冗余代碼。為了解決這一問題,ARM內(nèi)核版本3.x之后引入了原先在Power PC等其他體系架構(gòu)已經(jīng)使用的Flattened Device Tree。

開源文檔中對(duì)設(shè)備樹的描述是,一種描述硬件資源的數(shù)據(jù)結(jié)構(gòu),它通過bootloader將硬件資源傳給內(nèi)核,使得內(nèi)核和硬件資源描述相對(duì)獨(dú)立。

Device Tree可以描述的信息包括CPU的數(shù)量和類別、內(nèi)存基地址和大小、總線和橋、外設(shè)連接、中斷控制器和中斷使用情況、GPIO控制器和GPIO使用情況、Clock控制器和Clock使用情況。

另外,設(shè)備樹對(duì)于可熱插拔的設(shè)備不進(jìn)行具體描述,它只描述用于控制該熱插拔設(shè)備的控制器。

設(shè)備樹的主要優(yōu)勢(shì):對(duì)于同一SOC的不同主板,只需更換設(shè)備樹文件.dtb即可實(shí)現(xiàn)不同主板的無差異支持,而無需更換內(nèi)核文件。

(注:要使得3.x之后的內(nèi)核支持使用設(shè)備樹,除了內(nèi)核編譯時(shí)需要打開相對(duì)應(yīng)的選項(xiàng)外,bootloader也需要支持將設(shè)備樹的數(shù)據(jù)結(jié)構(gòu)傳給內(nèi)核。)

2、設(shè)備樹的組成和使用

設(shè)備樹包含DTC(device tree compiler),DTS(device tree source和DTB(device tree blob)。其對(duì)應(yīng)關(guān)系如下圖所示:

linux內(nèi)核設(shè)備樹及編譯

 

2.1 DTS和DTSI(源文件)

.dts文件是一種ASCII文本對(duì)Device Tree的描述,放置在內(nèi)核的/arch/arm/boot/dts目錄。一般而言,一個(gè).dts文件對(duì)應(yīng)一個(gè)ARM的machine。

由于一個(gè)SOC可能有多個(gè)不同的電路板( .dts文件為板級(jí)定義, .dtsi文件為SoC級(jí)定義),而每個(gè)電路板擁有一個(gè) .dts。這些dts勢(shì)必會(huì)存在許多共同部分,為了減少代碼的冗余,設(shè)備樹將這些共同部分提煉保存在.dtsi文件中,供不同的dts共同使用。.dtsi的使用方法,類似于C語言的頭文件,在dts文件中需要進(jìn)行include .dtsi文件。當(dāng)然,dtsi本身也支持include 另一個(gè)dtsi文件。

2.2 DTC (編譯工具)

DTC為編譯工具,dtc編譯器可以把dts文件編譯成為dtb,也可把dtb編譯成為dts文件。在3.x內(nèi)核版本中,DTC的源碼位于內(nèi)核的scripts/dtc目錄,內(nèi)核選中CONFIG_OF,編譯內(nèi)核的時(shí)候,主機(jī)可執(zhí)行程序DTC就會(huì)被編譯出來。 即scripts/dtc/Makefile中

hostprogs-y := dtcalways := $(hostprogs-y) 

在內(nèi)核的
arch/arm/boot/dts/Makefile中,若選中某種SOC,則與其對(duì)應(yīng)相關(guān)的所有dtb文件都將編譯出來。在linux下,make dtbs可單獨(dú)編譯dtb。以下截取了TEGRA平臺(tái)的一部分。

ifeq ($(CONFIG_OF),y)dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb tegra30-beaver.dtb tegra114-dalmore.dtb tegra124-ardbeg.dtb 

在2.6.x版本內(nèi)核中,只在powerpc架構(gòu)下使用了設(shè)備樹,DTC的源碼位于內(nèi)核的arch/powerpc/boot/dtc-src目錄,編譯內(nèi)核后,可將DTC編譯出來,DTC編譯工具位于arch/powerpc/boot目錄下。

2.3 DTB (二進(jìn)制文件)

DTC編譯.dts生成的二進(jìn)制文件(.dtb),bootloader在引導(dǎo)內(nèi)核時(shí),會(huì)預(yù)先讀取.dtb到內(nèi)存,進(jìn)而由內(nèi)核解析。

在2.6.x版本內(nèi)核中,在powerpc架構(gòu)下,dtb文件可以單獨(dú)進(jìn)行編譯,編譯命令格式如下:

dtc [-I input-format] [-O output-format][-o output-filename] [-V output_version] input_filename

參數(shù)說明

input-format:
- “dtb”: “blob” format
- “dts”: “source” format.
- “fs” format.
output-format:
- “dtb”: “blob” format
- “dts”: “source” format
- “asm”: assembly language file
output_version:

定義”blob”的版本,在dtb文件的字段中有表示,支持1 2 3和16,默認(rèn)是3,在16版本上有許多特性改變

(1) Dts編譯生成dtb

./dtc -I dts -O dtb -o B_dtb.dtb A_dts.dts

把A_dts.dts編譯生成B_dtb.dtb

(2) Dtb編譯生成dts

./dtc -I dtb -O dts -o A_dts.dts A_dtb.dtb

把A_dtb.dtb反編譯生成為A_dts.dts

在linux 3.x內(nèi)核中,可以使用make的方式進(jìn)行編譯。

2.4 Bootloader(boottloader支持)

Bootloader需要將設(shè)備樹在內(nèi)存中的地址傳給內(nèi)核。在ARM中通過bootm或bootz命令來進(jìn)行傳遞。

bootm [kernel_addr] [initrd_address] [dtb_address],其中kernel_addr為內(nèi)核鏡像的地址,initrd為initrd的地址,dtb_address為dtb所在的地址。若initrd_address為空,則用“-”來代替。

(小編自己整理了一些個(gè)人覺得比較好的學(xué)習(xí)書籍、視頻資料有需要的可以私信回復(fù)【內(nèi)核】自行免費(fèi)領(lǐng)取哦!!

3、linux內(nèi)核對(duì)硬件的描述方式

在以前的內(nèi)核版本中:

1)內(nèi)核包含了對(duì)硬件的全部描述;

2)bootloader會(huì)加載一個(gè)二進(jìn)制的內(nèi)核鏡像,并執(zhí)行它,比如uImage或者zImage;

3)bootloader會(huì)提供一些額外的信息,成為ATAGS,它的地址會(huì)通過r2寄存器傳給內(nèi)核;

ATAGS包含了內(nèi)存大小和地址,kernel command line等等;

4)bootloader會(huì)告訴內(nèi)核加載哪一款board,通過r1寄存器存放的machine type integer;

5)U-Boot的內(nèi)核啟動(dòng)命令:bootm <kernel img addr>

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

linux內(nèi)核設(shè)備樹及編譯

 

現(xiàn)今的內(nèi)核版本使用了Device Tree:

1)內(nèi)核不再包含對(duì)硬件的描述,它以二進(jìn)制的形式單獨(dú)存儲(chǔ)在另外的位置:the device tree blob

2)bootloader需要加載兩個(gè)二進(jìn)制文件:內(nèi)核鏡像和DTB

內(nèi)核鏡像仍然是uImage或者zImage;

DTB文件在arch/arm/boot/dts中,每一個(gè)board對(duì)應(yīng)一個(gè)dts文件;

3)bootloader通過r2寄存器來傳遞DTB地址,通過修改DTB可以修改內(nèi)存信息,kernel command line,以及潛在的其它信息;

4)不再有machine type;

5)U-Boot的內(nèi)核啟動(dòng)命令:bootm <kernel img addr> - <dtb addr>

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

linux內(nèi)核設(shè)備樹及編譯

 

有些bootloader不支持Device Tree,或者有些專門給特定設(shè)備寫的版本太老了,也不包含。為了解決這個(gè)問題,CONFIG_ARM_AppENDED_DTB被引進(jìn)。

它告訴內(nèi)核,在緊跟著內(nèi)核的地址里查找DTB文件;

由于沒有built-in Makefile rule來產(chǎn)生這樣的內(nèi)核,因此需要手動(dòng)操作:

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

(cat這個(gè)命令,還能夠直接合并兩個(gè)mp3文件哦!so easy!)

另外,
CONFIG_ARM_ATAG_DTB_COMPAT選項(xiàng)告訴內(nèi)核去bootloader里面讀取ATAGS,并使用它們升級(jí)DT。

4、DTB加載及解析過程

linux內(nèi)核設(shè)備樹及編譯

 

先從uboot里的do_bootm出發(fā),根據(jù)之前描述,DTB在內(nèi)存中的地址通過bootm命令進(jìn)行傳遞。在bootm中,它會(huì)根據(jù)所傳進(jìn)來的DTB地址,對(duì)DTB所在內(nèi)存做一系列操作,為內(nèi)核解析DTB提供保證。上圖為對(duì)應(yīng)的函數(shù)調(diào)用關(guān)系圖。

在do_bootm中,主要調(diào)用函數(shù)為do_bootm_states,第四個(gè)參數(shù)為bootm所要處理的階段和狀態(tài)。

在do_bootm_states中,bootm_start會(huì)對(duì)lmb進(jìn)行初始化操作,lmb所管理的物理內(nèi)存塊有三種方式獲取。起始地址,優(yōu)先級(jí)從上往下:

  1. 環(huán)境變量“bootm_low”
  2. 宏CONFIG_SYS_SDRAM_BASE(在tegra124中為0x80000000)
  3. gd->bd->bi_dram[0].start

大小:

  1. 環(huán)境變量“bootm_size”
  2. gd->bd->bi_dram[0].size

經(jīng)過初始化之后,這塊內(nèi)存就歸lmb所管轄。接著,調(diào)用bootm_find_os進(jìn)行kernel鏡像的相關(guān)操作,這里不具體闡述。

還記得之前講過bootm的三個(gè)參數(shù)么,第一個(gè)參數(shù)內(nèi)核地址已經(jīng)被bootm_find_os處理,而接下來的兩個(gè)參數(shù)會(huì)在bootm_find_other中執(zhí)行操作。

首先,bootm_find_other根據(jù)第二個(gè)參數(shù)找到ramdisk的地址,得到ramdisk的鏡像;然后根據(jù)第三個(gè)參數(shù)得到DTB鏡像,同檢查kernel和ramdisk鏡像一樣,檢查DTB鏡像也會(huì)進(jìn)行一系列的校驗(yàn)工作,如果校驗(yàn)錯(cuò)誤,將無法正常啟動(dòng)內(nèi)核。另外,uboot在確認(rèn)DTB鏡像無誤之后,會(huì)將該地址保存在環(huán)境變量“fdtaddr”中。

接著,uboot會(huì)把DTB鏡像reload一次,使得DTB鏡像所在的物理內(nèi)存歸lmb所管理:


boot_fdt_add_mem_rsv_regions會(huì)將原先的內(nèi)存DTB鏡像所在的內(nèi)存置為reserve,保證該段內(nèi)存不會(huì)被其他非法使用,保證接下來的reload數(shù)據(jù)是正確的;

②boot_relocate_fdt會(huì)在bootmap區(qū)域中申請(qǐng)一塊未被使用的內(nèi)存,接著將DTB鏡像內(nèi)容復(fù)制到這塊區(qū)域(即歸lmb所管理的區(qū)域)

注:若環(huán)境變量中,指定“fdt_high”參數(shù),則會(huì)根據(jù)該值,調(diào)用lmb_alloc_base函數(shù)來分配DTB鏡像reload的地址空間。若分配失敗,則會(huì)停止bootm操作。因而,不建議設(shè)置fdt_high參數(shù)。

接下來,do_bootm會(huì)根據(jù)內(nèi)核的類型調(diào)用對(duì)應(yīng)的啟動(dòng)函數(shù)。與linux對(duì)應(yīng)的是do_bootm_linux。

  • ① boot_prep_linux

為啟動(dòng)后的kernel準(zhǔn)備參數(shù)

  • ② boot_jump_linux
linux內(nèi)核設(shè)備樹及編譯

 

以上是boot_jump_linux的片段代碼,可以看出:若使用DTB,則原先用來存儲(chǔ)ATAG的寄存器R2,將會(huì)用來存儲(chǔ).dtb鏡像地址。

boot_jump_linux最后將調(diào)用kernel_entry,將.dtb鏡像地址傳給內(nèi)核。

下面我們來看下內(nèi)核的處理部分:

在arch/arm/kernel/head.S中,有這樣一段:

linux內(nèi)核設(shè)備樹及編譯

 

_vet_atags定義在
/arch/arm/kernel/head-common.S中,它主要對(duì)DTB鏡像做了一個(gè)簡(jiǎn)單的校驗(yàn)。

linux內(nèi)核設(shè)備樹及編譯

 

真正解析處理dbt的開始部分,是setup_arch->setup_machine_fdt。這部分的處理在第五部分的machine_mdesc中有提及。

linux內(nèi)核設(shè)備樹及編譯

 

如圖,是setup_machine_fdt中的解析過程。

  • 解析chosen節(jié)點(diǎn)將對(duì)boot_command_line進(jìn)行初始化。
  •  解析根節(jié)點(diǎn)的{size,address}將對(duì)dt_root_size_cells,dt_root_addr_cells進(jìn)行初始化。為之后解析memory等其他節(jié)點(diǎn)提供依據(jù)。
  •  解析memory節(jié)點(diǎn),將會(huì)把節(jié)點(diǎn)中描述的內(nèi)存,加入memory的bank。為之后的內(nèi)存初始化提供條件。
  •  解析設(shè)備樹在函數(shù)unflatten_device_tree中完成,它將.dtb解析成device_node結(jié)構(gòu)(第五部分有其定義),并構(gòu)成單項(xiàng)鏈表,以供OF的API接口使用。

下面主要結(jié)合代碼分析:/drivers/of/fdt.c

linux內(nèi)核設(shè)備樹及編譯

 


linux內(nèi)核設(shè)備樹及編譯

 


linux內(nèi)核設(shè)備樹及編譯

 


linux內(nèi)核設(shè)備樹及編譯

 


linux內(nèi)核設(shè)備樹及編譯

 


linux內(nèi)核設(shè)備樹及編譯

 


linux內(nèi)核設(shè)備樹及編譯

 

總的歸納為:

① kernel入口處獲取到uboot傳過來的.dtb鏡像的基地址

② 通過early_init_dt_scan()函數(shù)來獲取kernel初始化時(shí)需要的bootargs和cmd_line等系統(tǒng)引導(dǎo)參數(shù)。

③ 調(diào)用unflatten_device_tree函數(shù)來解析dtb文件,構(gòu)建一個(gè)由device_node結(jié)構(gòu)連接而成的單向鏈表,并使用全局變量of_allnodes保存這個(gè)鏈表的頭指針。

④ 內(nèi)核調(diào)用OF的API接口,獲取of_allnodes鏈表信息來初始化內(nèi)核其他子系統(tǒng)、設(shè)備等。

分享到:
標(biāo)簽:內(nèi)核 linux
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績?cè)u(píng)定