【轉】使用BBB的device tree和cape(重新整理版)


只要你想用BBB做哪怕一丁點涉及到硬件的東西,你就不可避免地要用到cape和device tree的知識。所以盡管它們看起來很陌生而且有點復雜,但還是得學。其實用起來不難的。下面我只講使用時必須會的內容,不深究其工作原理。文中基本沒有廢話,請仔細閱讀每個字,勿遺漏細節。

 

我們已經知道beagleboard官網上有一些官方的硬件外設,比如lcd顯示屏之類的,他們管這些外設叫做cape。其實應該說只要是修改了芯片引腳功能,或占用了空閑的引腳的東西,都可以叫做cape。比如之前我們提到的開啟某些引腳的I2C功能,其實也是給設備添加了一個虛擬的(virtual)cape。當我們想要使用一個cape的時候,需要做兩件事:配置BBB引腳的功能,啟動相應的驅動程序。而device tree基本就是用來干這兩件事的。

 

下面我們就來依次認識device tree文件,修改dts文件,編譯dts文件,加載device tree,驗證是否加載成功

 

一、認識device tree文件

 
那么device tree具體是長什么樣的呢?首先要知道它們有三種格式:一個方便人類閱讀的源文件*.dts(device tree source),另兩個是經過編譯送給系統使用的文件*.dtb(device tree blob)和*.dtbo(device tree blob overlay)。
在BBB的/lib/firmware/目錄下,你可以看到很多*.dts文件。我們隨便打開一個(BB-UART1-00A0.dts)看看它們長什么樣:
  1. /*  
  2.  * Copyright (C) 2013 CircuitCo  
  3.  *  
  4.  * Virtual cape for UART1 on connector pins P9.24 P9.26  
  5.  *  
  6.  * This program is free software; you can redistribute it and/or modify  
  7.  * it under the terms of the GNU General Public License version 2 as  
  8.  * published by the Free Software Foundation.  
  9.  */    
  10. /dts-v1/;    
  11. /plugin/;    
  12.     
  13.     
  14. / {    
  15.     compatible = "ti,beaglebone""ti,beaglebone-black";    
  16.     
  17.     
  18.         /* identification */    
  19.         part-number = "BB-UART1";    
  20.         version = "00A0";    
  21.     
  22.     
  23.         /* state the resources this cape uses */    
  24.         exclusive-use =    
  25.                 /* the pin header uses */    
  26.                 "P9.24",        /* uart1_txd */    
  27.                 "P9.26",        /* uart1_rxd */    
  28.                 /* the hardware ip uses */    
  29.                 "uart1";    
  30.     
  31.     
  32.         fragment@0 {    
  33.                 target = <&am33xx_pinmux>;    
  34.                 __overlay__ {    
  35.                         bb_uart1_pins: pinmux_bb_uart1_pins {    
  36.                                 pinctrl-single,pins = <    
  37.                                         0x184 0x20 /* P9.24 uart1_txd.uart1_txd MODE0 OUTPUT (TX) */    
  38.                                         0x180 0x20 /* P9.26 uart1_rxd.uart1_rxd MODE0 INPUT (RX) */    
  39.                                 >;    
  40.                         };    
  41.                 };    
  42.         };    
  43.     
  44.     
  45.         fragment@1 {    
  46.                 target = <&uart2>; /* really uart1 */    
  47.                 __overlay__ {    
  48.                         status = "okay";    
  49.                         pinctrl-names = "default";    
  50.                         pinctrl-0 = <&bb_uart1_pins>;    
  51.                 };    
  52.         };    
  53. };   
可以看到,dts文件是一個樹形結構,是由若干節點和屬性組成的。compatible = "ti,beaglebone", "ti,beaglebone-black"; 這行代碼上面相鄰行的斜杠"/"代表根節點,下面的fragment@0和fragment@1是其兩個子節點。其中根節點下面的屬性聲明了本dts文件適用的平台,它的名字、版本號,使用了哪些引腳和硬件資源等。fragment@0節點中配置了兩個BBB引腳的功能,把它們設置成了uart1的tx和rx功能。fragment@1節點中使能了uart1這個硬件設備(啟用了相應的驅動)。

不要被dts文件復雜的外表嚇到!dts文件確實有一定的編寫規則,但是這不是我們要操心的。因為BBB已經提供了足夠多現成的dts文件,我們要做的就是: 1、看懂它們,2、學會復制和粘貼。
 

二、修改dts文件

 
我們的最終目的是寫出符合自己需求的dts文件,那么單單復制粘還是不夠的,我們有時候需要修改里面那些屬性的值。那么這些屬性都是什么含義呢?其實它們都是有據可循的:www.kernel.org/doc/Documentation/devicetree/bindings/ 。提示一點,文檔有點亂,請多用Ctrl+F。

前面說到dts里主要有兩部分內容:修改BBB引腳功能和啟動驅動程序。上面的網址里只告訴了驅動程序的屬性,那么 引腳功能該如何配置
以前面給出的代碼為例,這幾行代碼是用來配置引腳功能的:
  1. pinctrl-single,pins = <   
  2. 0x184 0x20 /* P9.24 uart1_txd.uart1_txd MODE0 OUTPUT (TX) */   
  3. 0x180 0x20 /* P9.26 uart1_rxd.uart1_rxd MODE0 INPUT (RX) */   
  4. >;   
其中第一列的0x184和0x180分別是P9.24和P9.26的地址,第二列的0X20代表要配置成什么功能。它們都是怎么確定的呢?這里就要用到pdf文檔《BBB引腳功能速查表》了(請百度找此表,在EEWORLD論壇的一篇帖子中)。我們首先找到P9.24所在的行(在第2頁的中間),然后在第三列中可以看到它的偏移地址(OFFSET)是184。至於功能配置,我們按照pdf第2頁下面的GPIO Settings提示來寫。我們需要把這個引腳配置成“快速模式”、“使能輸入”、“使能下拉”、“功能0(uart1_txd)”。每一位按照相應的功能來寫,即00100000,即0x20。
 
如何查看BBB當前的引腳功能呢?
  1. cat /sys/kernel/debug/pinctrl/44e10800.pinmux/pins  
因為這個目錄很常用,我把它存成了環境變量$PINS。以后我使用 cat $PINS 就可以了。
一般這句后面還會加上grep命令來顯示特定的引腳功能,同樣在《BBB引腳功能速查表》中第三列找到P9.24的地址是0x984,所以可以這樣查找:
  1. root@beaglebone:~# cat $PINS | grep 984  
  2. pin 97 (44e10984) 00000037 pinctrl-single  
可以看到,這個引腳的當前功能是0x37,即00110111,從最后三位看出是功能7,查表知是GPIO功能。

另外一個要注意的是每個dts里根節點下都有這兩個屬性:
  1. part-number = "BB-UART1";  
  2. version = "00A0";  
第一個是名字,第二個是版本號。你自己寫的dts文件要新起一個名字,版本號則必須按照00A0,00A1……這樣的順序依次排下去。你的dts文件名必須是“名字+版本號.dts”的格式,如這里的BB-UART1-00A0.dts。
 

三、編譯dts文件

 
寫好dts文件以后,要把它轉化成系統可識別的格式。上面說到有dtb和dtbo兩種格式,我們這里要轉化成的是dtbo格式。因為BBB的Angstrom系統在上電啟動的時候就加載了一個dtb文件,給每個引腳配置了默認的功能,加載了需要加載的驅動程序。因為這個dtb文件已經加載,我們在系統運行着的情況下是不能修改它的。我們能做的,是在系統這個dtb的基礎上,“疊加(Overlay)”一些新的功能,因此要用dtbo(dtb overlay)格式。

實際上,dts和dtbo文件可以隨時編譯和反編譯,即dts可以生成dtbo,dtbo也可以復原成dts(但是復原的dts里沒有注釋等無用的東西了)。編譯和反編譯使用的命令都是相同的:dtc(device tree compile)。
dts編譯成dtbo:
  1. dtc -I dts -O dtb -@ BB-UART1-00A0.dts > BB-UART1-00A0.dtbo  
dtbo反編譯成dts:
  1. dtc -I dtb -O dts BB-UART1-00A0.dtbo > BB-UART1-00A0.dts  
(注:有的網站上編譯用的是這樣的命令:dtc -O dtb -o BB-UART1-00A0.dtbo -b 0 -@ BB-UART1-00A0.dts,其實都一樣啦。我覺得上面給出的寫法更好記一點。)

四、加載dtbo文件

 
加載之前,一定記住要把編譯好的dtbo文件放到/lib/firmare/目錄中,否則程序是找不到你的dtbo文件的。

Beaglebone Black中用一個叫做cape manager的軟件管理所有的cape,不論它是實實在在的擴展板,還是虛擬的cape。這個軟件的目錄是
/sys/devices/bone_capemgr.8/(這里的數字也有可能是9,與啟動順序有關,你可以直接用*代替它)。這個目錄內有一個叫做slots的文件,這就是capemgr這個軟件的對外接口。我們要加載某個cape的話,只需要向這個文件中寫入dts文件里定義的名字(part-number屬性)即可:
  1. echo BB-UART1 > /sys/devices/bone_capemgr.8/slots  
slot這個單詞是“插槽”的意思,看,很形象吧!我要插上一個cape,就向這個“插槽”里“插入”(echo)相應的設備。echo這個命令的含義是“向標准設備輸出”嘛。因為這個目錄很常用,所以我把它存成環境變量$SLOTS,這樣以后只需寫 echo BB-UART1 > $SLOTS 即可了。

(注:如果那個dtbo有多個版本,比如有00A0,00A1,00A2這3個版本,如果你只寫 echo BB-UART1 > $SLOTS 的話,它會自動加載最新的版本。而且,必須保證從00A0開始每個版本都存在才可以成功加載,就是說,如果/lib/firmware/目錄中只有00A2這一個版本的話,加載會失敗。但是,你可以通過 echo BB-UART1:00A2 > $SLOTS 像這樣添加版本號來加載某個特定版本。)
 

五、查看和卸載已加載的cape

使用命令:
  1. cat $SLOTS  
可以查看當前已經加載的所有cape。比如在我的BBB上執行命令后得到輸出:
  1. root@beaglebone:~# cat $SLOTS  
  2.  0: 54:P---L Beaglebone LCD4 Cape,00A1,BeagleboardToys,BB-BONE-LCD4-01  
  3.  1: 55:PF---  
  4.  2: 56:PF---  
  5.  3: 57:PF---  
  6.  4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G  
  7.  7: ff:P-O-L Override Board Name,00A0,Override Manuf,BB-ADC  
  8.  8: ff:P-O-L Override Board Name,00A0,Override Manuf,BB-UART1  
前面說了slots是“插槽”的意思,可以看到我這里已經“插入”了4個cape,包括1個實體的LCD cape和3個虛擬cape。

BBB可以插入4個實體cape,它們只能插在0、1、2、3這四個slot里,這也是1、2、3號slot是空白的原因。后面的slot里都是虛擬cape,只要引腳不沖突,可以不限數量地添加。一旦你的dtbo文件使用的引腳與已加載的cape有沖突,就會提示:
  1. -sh: echo: write error: File exists  
另外注意上面顯示的幾個已加載cape里的這部分內容“ff:P-O-L”,這里最后的“L”代表這個cape已經被load,即已經啟用。也許你將來會遇到雖然顯示在$SLOTS里,但是沒有這個“L”的cape,那樣的話它基本等於不存在。

至於卸載cape,假設我要卸載我的第8個cape,按照官方的說法,應當這樣操作:
  1. echo -8 > $SLOTS  
但因為系統bug的原因,這樣操作會導致系統重啟……所以目前只能通過重啟系統來卸載cape。等出系統更新也許就解決這個bug 了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM