當前位置:編程學習大全網 - 編程語言 - 如何在ARM Linux上使用FDT和initrd

如何在ARM Linux上使用FDT和initrd

這文章算是最近工作的備忘。

FDT是ARM

Linux最新的設備驅動程序信息表,使用FDT的內核,就不用像過去的內核那樣,壹個板子加壹個mach的C文件,所有的設備信息可以記錄在壹個樹狀信息文件裏面。

目前這方面資料比較少,我以AM335x處理器為例概括壹下FDT的使用:

FDT僅僅是壹個信息的目錄和參數表,要使用某個功能內核中還必須有相應的驅動程序代碼

FDT的源文件位置在:arch/arm/boot/dts,例如,TI的Beagle bone black,源文件是arch/arm/boot/dts/am335x_boneblack.dts

FDT在make ARCH=arm的時候就會自動生成,也可用make ARCH=arm

dtbs來生成,例如TI的Beagle bone black生成的文件是arch/arm/boot/dts/am335x_boneblack.dtb,這是壹個二進制文件

要想新增妳自定義的FDT,請修改arch/arm/boot/dts/Makefile,並在相應的Kconfig中增加config選項,例如,TI的Beagle

bone black,Kconfig的位置在arch/arm/mach-omap2/Kconfig

FDT的dtb文件由u-boot傳遞給內核,u-boot必須把這個文件拷貝到內核解壓地址之後的某個位置,確保內核解壓的時候不會覆蓋,然後使用“bootm

[內核地址] - [dtb地址]”來啟動內核

如果dtb文件不正確,對於3.10以上的內核,可能什麽顯示都沒有,3.8內核,可能就顯示到Uncompressing kernel......done

FDT的編寫規則說明在Documentation/devicetree/bindings,不同的設備有相應的txt文件說明,其中的“compatible”可以作為關鍵字搜索驅動程序的源文件,例如,AM335x的GPIO,用“ti,omap4-gpio”為關鍵字,可以找到其代碼位於drivers/gpio/gpio-omap.c

FDT可以包含子文件,比如am335x_boneblack.dts就包含了am33xx.dtsi,am335x-bone-common.dtsi

以壹個例子來說明編寫規則,我的板子上,I2C0上掛了壹個音頻CODEC,其地址是0x18,型號是TLV320AIC3104IRHBT。

先找到i2c0節點的位置,這在arch/arm/boot/dts/am33xx.dtsi中:

i2c0: i2c@44e0b000

{

compatible =

"ti,omap4-i2c";

#address-cells =

<1>;

#size-cells =

<0>;

ti,hwmods =

"i2c1";

reg = <0x44e0b000

0x1000>;

interrupts =

<70>;

status =

"disabled";

};

要在這個節點上掛東西,可以直接在am33xx.dtsi中掛,可以寫成這樣:

i2c0: i2c@44e0b000

{

compatible =

"ti,omap4-i2c";

#address-cells =

<1>;

#size-cells =

<0>;

ti,hwmods =

"i2c1";

reg = <0x44e0b000

0x1000>;

interrupts =

<70>;

status =

"okay";

tlv320aic3x: tlv320aic3x@18 {

compatible = "ti,tlv320aic3x";

reg = <0x18>;

status = "okay";

AVDD-supply = <&ldo4_reg>;

IOVDD-supply = <&ldo4_reg>;

DRVDD-supply = <&ldo4_reg>;

DVDD-supply = <&ldo4_reg>;

};

};

其中compatible字串“ti,tlv320aic3x”是在Documentation/devicetree/bindings裏面全文搜索“tlv320aic”獲得的,“tlv320aic3x:

tlv320aic3x@18”遵循的是“標識符:名稱@地址”的格式,前面的“i2c0:

i2c@44e0b000”也是這個格式。這裏的標識符可以在包含這個文件的文件或這個文件的其他位置引用,因此,可以使用arch/arm/boot/dts/am335x-boneblack.dts包含arch/arm/boot/dts/am33xx.dtsi,然後在am335x-boneblack.dts裏寫:

&i2c0 {

status = "okay";

tlv320aic3x: tlv320aic3x@18 {

compatible = "ti,tlv320aic3x";

reg = <0x18>;

status = "okay";

AVDD-supply = <&ldo4_reg>;

IOVDD-supply = <&ldo4_reg>;

DRVDD-supply = <&ldo4_reg>;

DVDD-supply = <&ldo4_reg>;

};

};

&i2c0表示引用了i2c0這個標識符,然後把括號裏的內容掛載到標識符下,如果屬性的名字相同,例如status出現兩次,前面是“disabled”後面是“okay”,以後面的為準,引用標識符的次數不受限制。

也許壹開始會覺得FDT的工作過程很神秘,但妳只要用compatible的字串去全文搜索壹下C文件,然後仔細閱讀壹下,就會發現很簡單,沒過幾分鐘妳就可以自定義FDT節點的屬性了。反倒是這些操作過程我沒找到什麽文檔說,比較頭痛,所以我把這些寫出來,希望能給大家幫助。

下面說說initrd,initrd的用處是給內核壹個初始的基本文件系統,用來加載內核模塊之類的東西。很多人覺得嵌入式系統不需要initrd,也可以把initrd作為最終的根文件系統。我用initrd是用來校驗真正的根文件系統,因為在嵌入式設備上,無法預測用戶到底什麽時候關機,可能會造成文件系統問題。

initrd可以用buildroot,像制作正常文件系統壹樣做,最後把根下的linuxrc換成壹個例如下面這樣的文件:

#!/bin/sh

/bin/echo Now Check SD Card

/sbin/fsck.ext4 /dev/mmcblk0p5

雖然Documentation/initrd.txt裏面說,內核會執行initrd裏面的/sbin/init,但在我用的linux-3.8.13上,init/do_mounts_initrd.c裏面,執行的是/linuxrc,不知道是不是文檔沒有更新過來。具體的調用順序是,kernel_init(init/main.c)

> kernel_init_freeable(init/main.c)

> prepare_namespace(init/do_mounts.c)

> initrd_load(init/do_mounts_initrd.c) > handle_initrd

(init/do_mounts_initrd.c)。

在使用initrd的時候有幾點需要註意的:

不建議在initrd上掛載別的東西,會引起未知的問題,貌似看到個文章說這個,找不到了

因為上面的這條,而且在initrd的時候,內核還沒有掛載devtmpfs,因此建議使用靜態設備節點,以AM335x為例(內核參數console=/dev/ttyO0,115200n8),必須的節點有:

/dev/null

/dev/console

/dev/ttyO0

這些節點可以用fakeroot之後mknod在buildroot的output/target/dev裏創建,除了/dev/console,buildroot會自己創建,其他也可以寫到buildroot的system/device_table.txt裏面讓buildroot自動創建:

#

/dev/null

c 666 0 0

1 3

-

-

-

/dev/ttyO0 c 600

0 0 250

0

-

-

-

如果妳用的是Atmel的處理器,上面的ttyO0可能是ttyS0,如果是三星的,可能是ttySAC0,而且major和minor也會不壹樣,請自行解決。如果妳像我壹樣要檢驗SD卡,那就還必須加上SD卡的分區對應的節點。

/linuxrc可以是個程序也可以是個腳本,腳本的話,命令寫絕對路徑,而且記得把/linuxrc的mode改為755

使用initrd只需要用u-boot把buildroot制作的文件系統映像拷貝到內存裏,然後傳遞initrd=[地址],[容量]這樣的參數給內核,例如initrd=0x81300000,8M,最終的root參數可以不變,例如root=/dev/mmcblk0p5,這表示最終的root是SD卡上擴展分區中的第壹個邏輯分區。給兩個內核參數的例子:

console=ttyO0,115200n8 root=/dev/mmcblk0p5 initrd=0x81300000,8M vram=16M

consoleblank=0

console=ttyO0,115200n8 initrd=0x81300000,8M root=/dev/nfs rw

nfsroot=192.168.5.226:/home/cdu/nfsroot

ip=192.168.5.222:192.168.5.226:192.168.5.1:255.255.255.0:core335x:eth0:off

vram=16M consoleblank=0

第壹個不解釋了,第二個表示使用initrd,同時使用nfsroot。

最後啰嗦壹句,使用initrd需要在內核配置裏打開支持,這個網上的資料太多了,我就不說在哪裏了。

  • 上一篇:寶馬的發展歷史,車型及價格。
  • 下一篇:51單片機如何用壹個按鍵和壹個定時器來模擬PWM控制壹個LED燈的亮度
  • copyright 2024編程學習大全網