標籤:
只要你想用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";
-
-
- [email protected] {
- 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) */
- >;
- };
- };
- };
-
-
- [email protected] {
- target = <&uart2>; /* really uart1 */
- __overlay__ {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&bb_uart1_pins>;
- };
- };
- };
可以看到,dts檔案是一個樹形結構,是由若干節點和屬性群組成的。compatible = "ti,beaglebone", "ti,beaglebone-black"; 這行代碼上面相鄰行的斜杠"/"代表根節點,下面的[email protected]和[email protected]是其兩個子節點。其中根節點下面的屬性聲明了本dts檔案適用的平台,它的名字、版本號碼,使用了哪些引腳和硬體資源等。[email protected]節點中配置了兩個BBB引腳的功能,把它們設定成了uart1的tx和rx功能。[email protected]節點中使能了uart1這個硬體裝置(啟用了相應的驅動)。
不要被dts檔案複雜的外表嚇到!dts檔案確實有一定的編寫規則,但是這不是我們要操心的。因為BBB已經提供了足夠多現成的dts檔案,我們要做的就是:1、看懂它們,2、學會複製和粘貼。 二、修改dts檔案 我們的最終目的是寫出符合自己需求的dts檔案,那麼單單複製粘還是不夠的,我們有時候需要修改裡面那些屬性的值。那麼這些屬性都是什麼含義呢?其實它們都是有據可循的: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引腳功能速查表》了(請百度找此表,在EEWORLD論壇的一篇文章中)。我們首先找到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,所以可以這樣尋找:
- [email protected]:~# 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 [email protected] 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 [email protected] 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上執行命令後得到輸出:
- [email protected]:~# 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 了。
【轉】使用BBB的device tree和cape(重新整理版)