《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 嵌入式技術(shù) > 業(yè)界動(dòng)態(tài) > 設(shè)備樹使用簡(jiǎn)介

設(shè)備樹使用簡(jiǎn)介

2019-10-31
來源:致遠(yuǎn)電子
關(guān)鍵詞: FDT 設(shè)備樹 Linux

  摘要:是不是所有的Linux內(nèi)核都是完美的,?畢竟諸多黑客效力于此,當(dāng)然不是,,至少在內(nèi)核3.x版本之前不是,,之前的代碼臃腫,代碼利用率較低,,直到設(shè)備樹的引入,,徹底改善這一情況;

  一,、FDT的概念

  系統(tǒng)啟動(dòng)時(shí),,Bootloader開始加載,將內(nèi)核文件,,如zImage讀取到內(nèi)存中,,內(nèi)核按照我們的代碼,逐一去配置每個(gè)寄存器,,每個(gè)外設(shè),,似乎沒有什么問題。但是試想一下,,100種ARM芯片,,就要寫100個(gè)配置文件么?當(dāng)然,,如果你非要這么做,,我也無話可說。如果能抽象出一種數(shù)據(jù)結(jié)構(gòu),,它可以直接抽象出內(nèi)核需要配置的所有硬件以及硬件屬性,,BootLoader預(yù)讀取到內(nèi)存中,在內(nèi)核啟動(dòng)以后,,可以直接配置,,對(duì)于用戶而言,配置MCU的外圍時(shí)我們直接面對(duì)的就只是這個(gè)DTS文件,,極其方便快捷,。FDT準(zhǔn)確來講是一種數(shù)據(jù)結(jié)構(gòu),使得硬件可以用形如XML的描述語言來描述,。

  二,、設(shè)備樹結(jié)構(gòu)

設(shè)備樹使用簡(jiǎn)介388.png

  圖一 設(shè)備樹結(jié)構(gòu)

  設(shè)備樹一般包含以上內(nèi)容:

  根節(jié)點(diǎn)“/”下的model ,,這個(gè)一般為字符串類型,它描述了廠商以及板子名稱,;

  根節(jié)點(diǎn)“/”下的compitable,,這個(gè)一般為字符串類型,用以匹配model選定的開發(fā)板對(duì)應(yīng)的代碼,;包括后續(xù)外圍驅(qū)動(dòng)的匹配均是有這個(gè)compitable來完成,;

  根節(jié)點(diǎn)“/”下的aliases,這個(gè)設(shè)備節(jié)點(diǎn)只能放在根節(jié)點(diǎn)目錄,,主要用以存放外設(shè)的別名,,簡(jiǎn)單講,"/soc/aips-bus@02000000/spba-bus@02000000/serial@02020000"其實(shí)是一個(gè)串口,,但是開發(fā)人員自己看起來并不直觀,,我可以在aliases中寫作:serial ="/soc/aips-bus@02000000/spba-bus@02000000/serial@02020000";serial即可代替剛才的串口設(shè)備,;

  根節(jié)點(diǎn)“/”下的chosen:這個(gè)并非物理設(shè)備節(jié)點(diǎn),,而是內(nèi)核啟動(dòng)參數(shù)的節(jié)點(diǎn),類似于uboot階段的bootargs參數(shù),;

  當(dāng)然,,這個(gè)節(jié)點(diǎn)也可以是子節(jié)點(diǎn),不一定要在根節(jié)點(diǎn)下,;

  實(shí)例:chosen {

  stdout-path = &uart1;

  };

  ?snvs@020b0000:除以上節(jié)點(diǎn),,剩下的我一般稱之為物理設(shè)備節(jié)點(diǎn)(可能不準(zhǔn)確),以snvs外設(shè)舉例,,直接舉例,;

  實(shí)例:snvs@020b0000{

  conpitable = “fsl,imx6ul-snvs”;

  reg = <0x020b0000 0x4000>;

  interrupts = <0x0 0x4 0x4>;

  };

  (1)“@”后面緊跟就是該外設(shè)在MCU總線的地址,,這個(gè)不難理解,,可以理解為外設(shè)的基地址,外設(shè)模型 name@addresss;”

 ?。?)“compitable”:如上陳述,,非常關(guān)鍵的屬性,匹配外設(shè)驅(qū)動(dòng),,屬性模型 compitable = “[manufacture,[model]]”;

 ?。?)“reg”:該屬性為外設(shè)地址屬性,第一個(gè)參數(shù)為該節(jié)點(diǎn)總線地址,,后者為地址長(zhǎng)度,;

  (4)“interrupt”:顧名思義,,該外設(shè)的中斷,,para1表示該中斷是不是SPI中斷(shared peripheral interrupt),,注意名詞區(qū)分,參數(shù)值為1表示為SPI中斷,,反之不是SPI中斷,;para2是該中斷號(hào);para3表示觸發(fā)方式,,參數(shù)值為1,,表示上升沿觸發(fā),為4表示高電平觸發(fā),;如果需要低電平以及下降沿觸發(fā),,硬件需要加非門;

  三,、編譯設(shè)備樹與反編譯

  設(shè)備樹編譯,,我們都知道使用如下命令編譯:

  make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-  dtbs  或者

  make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-  all

  實(shí)際上,是dtc這個(gè)文件在負(fù)責(zé)把dts解釋成dtb文件,,該文件在內(nèi)核源碼根目錄 ./scripts/dtc

  編譯命令:

  ./scripts/dtc/dtc –I dts –O dtb /home/gyh/tmp/imx6y2c-256m.dtb  ./arch/arm/boot/dts/imx6y2c-256m.dts

  反編譯命令:

  ./scripts/dtc/dtc -I dtb -O dts -o /home/gyh/tmp/imx6y2c_asm.dts   ./arch/arm/boot/dts/imx6y2c-256m.dtb

  對(duì)于Linux命令的使用,,可以使用help cmdname 或者man cmdname,對(duì)于dtc,,非內(nèi)建命令,,man dtc:

  -I <input format>

  Input formats are:

  dts - device tree source text

  dtb - device tree blob

  fs - /proc/device-tree style directory

  -O <output format>

  Output formats are:

  dts - device tree source text

  dtb - device tree blob

  asm - assembler source

  系統(tǒng)提供的dts一般引用dtsi這個(gè)母設(shè)備樹,所以大量外設(shè)都是直接引用dtsi中的,,因此很難理解這些字符串是怎樣的匹配驅(qū)動(dòng)程序的,,但是一旦將已經(jīng)生產(chǎn)的dtb文件反編譯,生產(chǎn)的dts文件將更直觀,;但是易讀性也更差,。這并不矛盾;我選擇,,” /”  ,”chosen” ,”aliases”三個(gè)節(jié)點(diǎn)來對(duì)比,。

設(shè)備樹使用簡(jiǎn)介2425.png

  圖二 BSP提供的dts文件

設(shè)備樹使用簡(jiǎn)介2442.png 

圖三 反編譯的dts文件

  對(duì)同一個(gè)chosen節(jié)點(diǎn):BSP中dts描述為stdout-path = &uart1;這樣很難想象它是怎樣把該外設(shè)定義為標(biāo)準(zhǔn)輸出的,但是如果看反編譯文件可以較好的理解,,標(biāo)準(zhǔn)輸出被重定向到某個(gè)可以作為輸出的外設(shè)地址,;

  四、設(shè)備樹節(jié)點(diǎn)添加與驗(yàn)證

 ?。?)直接在dts文件中查找,,是否已經(jīng)存在你需要的外設(shè)節(jié)點(diǎn);如果有,,且該外設(shè)支持多從機(jī)或者多節(jié)點(diǎn),,直接在該節(jié)點(diǎn)下面,添加子節(jié)點(diǎn),,以GPIO_LED為例,。

設(shè)備樹使用簡(jiǎn)介2657.png

  圖四 GPIO_LEDS節(jié)點(diǎn)

 ?。?)假設(shè),你需要添加一個(gè)黃色的LED,,那么仿照已經(jīng)存在的節(jié)點(diǎn),,復(fù)制一個(gè)節(jié)點(diǎn)在母節(jié)點(diǎn)下,命名為green-led,同時(shí)用GPIO3_4為該LED驅(qū)動(dòng)引腳,;你希望在arm板上叫他,,My_Cute(這個(gè)名字不好),那么最后修改如下:

設(shè)備樹使用簡(jiǎn)介2789.png

  圖五 增加yellow-led節(jié)點(diǎn)

 ?。?)節(jié)點(diǎn)添加完成,,引用了GPIO3_4,所以你需要確認(rèn)該MCU引腳已經(jīng)配置為GPIO功能,,這里直接貼出配置代碼:MX6UL_PAD_LCD_RESET__GPIO3_IO04 0x40017059

設(shè)備樹使用簡(jiǎn)介2909.png

  圖六 引腳配置為GPIO

  該宏定義MX6UL_PAD_LCD_RESET__GPIO3_IO04在./arch/arm/boot/dts/imx6ull-pinfunc.h中,;針對(duì)同一個(gè)引腳的全部復(fù)用,均定義了宏,,可以直接調(diào)用,;該dts并未直接包含imx6ull-pinfunc.h,在其他dtsi中已經(jīng)包含該頭文件,;

 ?。?)如果之前已經(jīng)完全編譯過內(nèi)核,,可以直接編譯dtb,,注意不要make menuconfig或者defconfig,否則會(huì)覆蓋zImage的配置文件.config,;

  make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-  dtbs

 ?。?)編譯完成后,開發(fā)板直接進(jìn)入uboot模式,,tftp網(wǎng)絡(luò)燒寫dtb,,reset重啟生效;

  run updtb

 ?。▊渥ⅲ簎pdtb為組合命令updtb=if tftp ${fdt_file}; then nand erase.part dtb; nand write ${loadaddr} dtb ${filesize}; fi;)

 ?。?)如果dtb按照我們理解修改是正確的,那么我們將在開發(fā)板的/sys/class/leds下面看到我們的My_Cute這個(gè)LED節(jié)點(diǎn),;結(jié)果如下:

設(shè)備樹使用簡(jiǎn)介3455.png

  圖七 開發(fā)板設(shè)備截圖

  其實(shí),,可以看到/sys/class/leds下面的設(shè)備節(jié)點(diǎn)都是指向/devices/platfome/leds目錄的連接文件,也就是這里僅僅是這個(gè)設(shè)備的“快捷方式”,,我們也可以進(jìn)行文件IO操作,;

  (7)文件IO操作:打開My_Cute節(jié)點(diǎn),,可以看到以下接口可以操作,,但是我們?cè)谔砑覩PIO_LEDS并沒有添加這些屬性,。Brightness, trigger—led亮度以及觸發(fā)方式比較常用,那么問題來了,,為什么會(huì)有這些接口,。因?yàn)樗鼈兝^承了母節(jié)點(diǎn)的屬性,所以我們需要找到母節(jié)點(diǎn)設(shè)備的定義,。

設(shè)備樹使用簡(jiǎn)介3712.png

  圖八 yellow-led的操作接口

 ?。?)講道理,所有的內(nèi)核驅(qū)動(dòng)你都可以嘗試在 ./driver/下面去找,,針對(duì)led類,,我們直接進(jìn)入leds文件夾,發(fā)現(xiàn)leds的驅(qū)動(dòng)leds-gpio.c在,,在這里就可以理解led的接口為什么是這樣,;當(dāng)然優(yōu)秀的驅(qū)動(dòng)應(yīng)該還有一份清晰的文檔,你同樣可也嘗試去源碼根目錄的. /Documentation 中查找leds-gpio的使用文檔,;這里也會(huì)解釋,,我為什么會(huì)去開發(fā)板的/sys/class/leds下面去查看我增加的My_Cute節(jié)點(diǎn);

設(shè)備樹使用簡(jiǎn)介3953.png

  圖九 驅(qū)動(dòng)使用文檔

 ?。?)增加一個(gè)驅(qū)動(dòng)或者一個(gè)設(shè)備節(jié)點(diǎn)到設(shè)備樹中,,你可以先查看內(nèi)核源碼的/ Documentation目錄,其中包含了幾乎所有驅(qū)動(dòng)的使用說明以及設(shè)備樹屬性的解釋,,同時(shí)也包括大量?jī)?yōu)秀的內(nèi)核調(diào)試技巧,;再去寫節(jié)點(diǎn),也可以先模仿,,針對(duì)不懂的地方再來看文檔,,印象更為深刻。

  五,、結(jié)語

  設(shè)備樹相比于傳統(tǒng)的配置文件,,無疑是降低了Linux外設(shè)開發(fā)與使用的門檻,但是也隱藏了大量的細(xì)節(jié),,難以了解其底層的驅(qū)動(dòng)原理,;對(duì)于LINUX內(nèi)核的了解,我所認(rèn)識(shí)的還不及冰山一角,,單希望對(duì)你有一點(diǎn)幫助,。


本站內(nèi)容除特別聲明的原創(chuàng)文章之外,轉(zhuǎn)載內(nèi)容只為傳遞更多信息,,并不代表本網(wǎng)站贊同其觀點(diǎn),。轉(zhuǎn)載的所有的文章、圖片,、音/視頻文件等資料的版權(quán)歸版權(quán)所有權(quán)人所有,。本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無法一一聯(lián)系確認(rèn)版權(quán)者,。如涉及作品內(nèi)容、版權(quán)和其它問題,,請(qǐng)及時(shí)通過電子郵件或電話通知我們,,以便迅速采取適當(dāng)措施,避免給雙方造成不必要的經(jīng)濟(jì)損失,。聯(lián)系電話:010-82306118,;郵箱:[email protected]