BBB的cape和設備樹(device tree)的使用

只要你想用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)看看它們長什麼樣:
  • /*
  • * Copyright (C) 2013 CircuitCo
  • *
  • * Virtual cape for UART1 on connector pins P9.24 P9.26
  • *
  • * This program is free software; you can redistribute it and/or modify
  • * it under the terms of the GNU General Public License version 2 as
  • * published by the Free Software Foundation.
  • */
  • /dts-v1/;
  • /plugin/;
  • / {
  •     compatible = "ti,beaglebone", "ti,beaglebone-black";
  •         /* identification */
  •         part-number = "BB-UART1";
  •         version = "00A0";
  •         /* state the resources this cape uses */
  •         exclusive-use =
  •                 /* the pin header uses */
  •                 "P9.24",        /* uart1_txd */
  •                 "P9.26",        /* uart1_rxd */
  •                 /* the hardware ip uses */
  •                 "uart1";
  •         fragment@0 {
  •                 target = <&am33xx_pinmux>;
  •                 __overlay__ {
  •                         bb_uart1_pins: pinmux_bb_uart1_pins {
  •                                 pinctrl-single,pins = <
  •                                         0x184 0x20 /* P9.24 uart1_txd.uart1_txd MODE0 OUTPUT (TX) */
  •                                         0x180 0x20 /* P9.26 uart1_rxd.uart1_rxd MODE0 INPUT (RX) */
  •                                 >;
  •                         };
  •                 };
  •         };
  •         fragment@1 {
  •                 target = <&uart2>; /* really uart1 */
  •                 __overlay__ {
  •                         status = "okay";
  •                         pinctrl-names = "default";
  •                         pinctrl-0 = <&bb_uart1_pins>;
  •                 };
  •         };
  • };



可以看到,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文件,那麼單單複製粘還是不夠的,我們有時候需要修改裏面那些屬性的值。那麼這些屬性都是什麼含義呢?其實它們都是有據可循的:https://www.kernel.org/doc/Documentation/devicetree/bindings/ 。提示一點,文檔有點亂,請多用Ctrl+F。

前面說到dts裏主要有兩部分內容:修改BBB引腳功能和啓動驅動程序。上面的網址裏只告訴了驅動程序的屬性,那麼引腳功能該如何配置呢
以前面給出的代碼爲例,這幾行代碼是用來配置引腳功能的:
  • pinctrl-single,pins = <
  • 0x184 0x20 /* P9.24 uart1_txd.uart1_txd MODE0 OUTPUT (TX) */
  • 0x180 0x20 /* P9.26 uart1_rxd.uart1_rxd MODE0 INPUT (RX) */
  • >;



其中第一列的0x184和0x180分別是P9.24和P9.26的地址,第二列的0X20代表要配置成什麼功能。它們都是怎麼確定的呢?這裏就要用到我在這篇帖子裏給出的pdf文檔《BBB引腳功能速查表》了。我們首先找到P9.24所在的行(在第2頁的中間),然後在第三列中可以看到它的偏移地址(OFFSET)是184。至於功能配置,我們按照pdf第2頁下面的GPIO Settings提示來寫。我們需要把這個引腳配置成“快速模式”、“使能輸入”、“使能下拉”、“功能0(uart1_txd)”。每一位按照相應的功能來寫,即00100000,即0x20。


如何查看BBB當前的引腳功能呢?
  • cat /sys/kernel/debug/pinctrl/44e10800.pinmux/pins



因爲這個目錄很常用,我把它存成了環境變量$PINS。以後我使用 cat $PINS 就可以了。
一般這句後面還會加上grep命令來顯示特定的引腳功能,同樣在《BBB引腳功能速查表》中第三列找到P9.24的地址是0x984,所以可以這樣查找:
  • root@beaglebone:~# cat $PINS | grep 984
  • pin 97 (44e10984) 00000037 pinctrl-single



可以看到,這個引腳的當前功能是0x37,即00110111,從最後三位看出是功能7,查表知是GPIO功能。


另外一個要注意的是每個dts里根節點下都有這兩個屬性:
  • part-number = "BB-UART1";
  • 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:
  • dtc -I dts -O dtb -@ BB-UART1-00A0.dts > BB-UART1-00A0.dtbo



dtbo反編譯成dts:
  • 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屬性)即可:
  • 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

使用命令:
  • cat $SLOTS



可以查看當前已經加載的所有cape。比如在我的BBB上執行命令後得到輸出:
  • root@beaglebone:~# cat $SLOTS
  • 0: 54:P---L Beaglebone LCD4 Cape,00A1,BeagleboardToys,BB-BONE-LCD4-01
  • 1: 55:PF---
  • 2: 56:PF---
  • 3: 57:PF---
  • 4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
  • 7: ff:P-O-L Override Board Name,00A0,Override Manuf,BB-ADC
  • 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有衝突,就會提示:
  • -sh: echo: write error: File exists




另外注意上面顯示的幾個已加載cape裏的這部分內容“ff:P-O-L”,這裏最後的“L”代表這個cape已經被load,即已經啓用。也許你將來會遇到雖然顯示在$SLOTS裏,但是沒有這個“L”的cape,那樣的話它基本等於不存在。

至於卸載cape,假設我要卸載我的第8個cape,按照官方的說法,應當這樣操作:
  • echo -8 > $SLOTS



但因爲系統bug的原因,這樣操作會導致系統重啓……所以目前只能通過重啓系統來卸載cape。等出系統更新也許就解決這個bug 了。


來源:http://bbs.elecfans.com/jishu_454965_1_1.html

發佈了17 篇原創文章 · 獲贊 14 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章