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

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

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

1、設備樹的概念

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

開源文檔中對設備樹的描述是,一種描述硬件資源的數據結構,它通過bootloader將硬件資源傳給內核,使得內核和硬件資源描述相對獨立。

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

另外,設備樹對于可熱插拔的設備不進行具體描述,它只描述用于控制該熱插拔設備的控制器。

設備樹的主要優勢:對于同一SOC的不同主板,只需更換設備樹文件.dtb即可實現不同主板的無差異支持,而無需更換內核文件。

(注:要使得3.x之后的內核支持使用設備樹,除了內核編譯時需要打開相對應的選項外,bootloader也需要支持將設備樹的數據結構傳給內核。)

2、設備樹的組成和使用

設備樹包含DTC(device tree compiler),DTS(device tree source和DTB(device tree blob)。其對應關系如下圖所示:

linux內核設備樹及編譯

 

2.1 DTS和DTSI(源文件)

.dts文件是一種ASCII文本對Device Tree的描述,放置在內核的/arch/arm/boot/dts目錄。一般而言,一個.dts文件對應一個ARM的machine。

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

2.2 DTC (編譯工具)

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

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

在內核的
arch/arm/boot/dts/Makefile中,若選中某種SOC,則與其對應相關的所有dtb文件都將編譯出來。在linux下,make dtbs可單獨編譯dtb。以下截取了TEGRA平臺的一部分。

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

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

2.3 DTB (二進制文件)

DTC編譯.dts生成的二進制文件(.dtb),bootloader在引導內核時,會預先讀取.dtb到內存,進而由內核解析。

在2.6.x版本內核中,在powerpc架構下,dtb文件可以單獨進行編譯,編譯命令格式如下:

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

參數說明

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,默認是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內核中,可以使用make的方式進行編譯。

2.4 Bootloader(boottloader支持)

Bootloader需要將設備樹在內存中的地址傳給內核。在ARM中通過bootm或bootz命令來進行傳遞。

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

(小編自己整理了一些個人覺得比較好的學習書籍、視頻資料有需要的可以私信回復【內核】自行免費領取哦!!

3、linux內核對硬件的描述方式

在以前的內核版本中:

1)內核包含了對硬件的全部描述;

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

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

ATAGS包含了內存大小和地址,kernel command line等等;

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

5)U-Boot的內核啟動命令:bootm <kernel img addr>

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

linux內核設備樹及編譯

 

現今的內核版本使用了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 <kernel img addr> - <dtb addr>

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

linux內核設備樹及編譯

 

有些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。

4、DTB加載及解析過程

linux內核設備樹及編譯

 

先從uboot里的do_bootm出發,根據之前描述,DTB在內存中的地址通過bootm命令進行傳遞。在bootm中,它會根據所傳進來的DTB地址,對DTB所在內存做一系列操作,為內核解析DTB提供保證。上圖為對應的函數調用關系圖。

在do_bootm中,主要調用函數為do_bootm_states,第四個參數為bootm所要處理的階段和狀態。

在do_bootm_states中,bootm_start會對lmb進行初始化操作,lmb所管理的物理內存塊有三種方式獲取。起始地址,優先級從上往下:

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

大小:

  1. 環境變量“bootm_size”
  2. gd->bd->bi_dram[0].size

經過初始化之后,這塊內存就歸lmb所管轄。接著,調用bootm_find_os進行kernel鏡像的相關操作,這里不具體闡述。

還記得之前講過bootm的三個參數么,第一個參數內核地址已經被bootm_find_os處理,而接下來的兩個參數會在bootm_find_other中執行操作。

首先,bootm_find_other根據第二個參數找到ramdisk的地址,得到ramdisk的鏡像;然后根據第三個參數得到DTB鏡像,同檢查kernel和ramdisk鏡像一樣,檢查DTB鏡像也會進行一系列的校驗工作,如果校驗錯誤,將無法正常啟動內核。另外,uboot在確認DTB鏡像無誤之后,會將該地址保存在環境變量“fdtaddr”中。

接著,uboot會把DTB鏡像reload一次,使得DTB鏡像所在的物理內存歸lmb所管理:


boot_fdt_add_mem_rsv_regions會將原先的內存DTB鏡像所在的內存置為reserve,保證該段內存不會被其他非法使用,保證接下來的reload數據是正確的;

②boot_relocate_fdt會在bootmap區域中申請一塊未被使用的內存,接著將DTB鏡像內容復制到這塊區域(即歸lmb所管理的區域)

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

接下來,do_bootm會根據內核的類型調用對應的啟動函數。與linux對應的是do_bootm_linux。

  • ① boot_prep_linux

為啟動后的kernel準備參數

  • ② boot_jump_linux
linux內核設備樹及編譯

 

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

boot_jump_linux最后將調用kernel_entry,將.dtb鏡像地址傳給內核。

下面我們來看下內核的處理部分:

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

linux內核設備樹及編譯

 

_vet_atags定義在
/arch/arm/kernel/head-common.S中,它主要對DTB鏡像做了一個簡單的校驗。

linux內核設備樹及編譯

 

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

linux內核設備樹及編譯

 

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

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

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

linux內核設備樹及編譯

 


linux內核設備樹及編譯

 


linux內核設備樹及編譯

 


linux內核設備樹及編譯

 


linux內核設備樹及編譯

 


linux內核設備樹及編譯

 


linux內核設備樹及編譯

 

總的歸納為:

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

② 通過early_init_dt_scan()函數來獲取kernel初始化時需要的bootargs和cmd_line等系統引導參數。

③ 調用unflatten_device_tree函數來解析dtb文件,構建一個由device_node結構連接而成的單向鏈表,并使用全局變量of_allnodes保存這個鏈表的頭指針。

④ 內核調用OF的API接口,獲取of_allnodes鏈表信息來初始化內核其他子系統、設備等。

分享到:
標簽:內核 linux
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定