[轉]使用Beaglebone Black的SPI


分類: Beaglebone Black   678人閱讀   評論(6)   收藏   舉報
 

目錄(?)[+]

 

SPI是可以全雙工通信的一種串行總線,兩個設備之間雙向通信的話一般使用3根線:SCLK,MISO,MOSI,多個設備之間雙向通信的話,每個設備還需要再加上一根地址線CSn。相比之下I2C只能半雙工,而且一般需要上拉電阻,但無論幾個設備,都只需要2根線。更多基礎知識請谷歌百度。

Beaglebone Black使用的AM3359芯片上有兩個SPI,但SPI1連接到了板子的HDMI芯片上,所以除非禁用HDMI,否則我們只能使用SPI0。本文將利用自帶的spidev驅動使能SPI0,並進行一下簡單的驗證。

配置device tree

首先我們用我在《使用BBB的I2C》這篇文章中使用的方法檢驗一下SPI相關的引腳功能是否配置正確。檢查結果是,不正確,也就是說SPI默認是沒有啟用的,新版arm linux配置硬件的方式是利用device tree,所以我們必須要配置一個device tree來啟用它。我們先到 /lib/firmware 目錄中看看有沒有現成的device tree source (.dts)文件可供使用。我們發現有一個BB-SPI0-00A0.dts。內容如下

 

  1. /dts-v1/;  
  2. /plugin/;  
  3.   
  4. / {  
  5.     compatible = "ti,beaglebone""ti,beaglebone-black";  
  6.   
  7.     /* identification */  
  8.     part-number = "BB-SPI0";  
  9.     version = "00A0";  
  10.   
  11.     /* state the resources this cape uses */  
  12.     exclusive-use =  
  13.         /* the pin header uses */  
  14.         "P9.17",    /* spi0_cs0 */  
  15.         "P9.18",    /* spi0_d1 */  
  16.         "P9.21",    /* spi0_d0 */  
  17.         "P9.22",    /* spi0_sclk */  
  18.         /* the hardware ip uses */  
  19.         "spi0";  
  20.   
  21.     fragment@0 {  
  22.         target = <&am33xx_pinmux>;  
  23.         __overlay__ {  
  24.             /* default state has all gpios released and mode set to uart1 */  
  25.             bb_spi0_pins: pinmux_bb_spi0_pins {  
  26.                 pinctrl-single,pins = <  
  27.                     0x150 0x30  /* spi0_sclk.spi0_sclk, INPUT_PULLUP | MODE0 */  
  28.                     0x154 0x30  /* spi0_d0.spi0_d0, INPUT_PULLUP | MODE0 */  
  29.                     0x158 0x10  /* spi0_d1.spi0_d1, OUTPUT_PULLUP | MODE0 */  
  30.                     0x15c 0x10  /* spi0_cs0.spi0_cs0, OUTPUT_PULLUP | MODE0 */  
  31.                 >;  
  32.             };  
  33.         };  
  34.     };  
  35.   
  36.     fragment@1 {  
  37.         target = <&spi0>; /* spi0 is numbered correctly */  
  38.         __overlay__ {  
  39.             status = "okay";  
  40.             pinctrl-names = "default";  
  41.             pinctrl-0 = <&bb_spi0_pins>;  
  42.   
  43.             #address-cells = <1>;  
  44.             #size-cells = <0>;  
  45.   
  46.             /* add any spi devices connected here */  
  47.             /* note that you can do direct SPI via spidev now */  
  48.   
  49.             // commented out example of an adafruit 1.8" TFT display  
  50.             // from firmare/capes/cape-bone-adafruit-lcd-00A0.dts  
  51.             // lcd@0 {  
  52.             //  #address-cells = <1>;  
  53.             //  #size-cells = <0>;  
  54.             //  
  55.             //  compatible = "adafruit,tft-lcd-1.8-red", "sitronix,st7735";  
  56.             //  reg = <0>;  
  57.             //  
  58.             //  spi-max-frequency = <8000000>;  
  59.             //  spi-cpol;  
  60.             //  spi-cpha;  
  61.             //  
  62.             //  pinctrl-names = "default";  
  63.             //  pinctrl-0 = <&bone_adafruit_lcd_pins>;  
  64.             //  
  65.             //  st7735-rst = <&gpio4 19 0>;  
  66.             //  st7735-dc = <&gpio4 21 0>;  
  67.             // };  
  68.         };  
  69.     };  
  70. };  

 

 

從這個文件里我們能得到很多信息(我在此嘮叨兩句,也算跟大家分享一下我學習的過程),首先我們從exclusive-use這一部分能看出來AM3359芯片對SPI引腳的命名是跟一般不太一樣的,它沒用MISO和MOSI,而是D0和D1。通過查詢4000頁手冊我們得知,原來是因為這兩個引腳的功能是可以通過配置寄存器來互換的。默認的對應方式如下


再接着看,發現有一句注釋 

 

  1. /* note that you can do direct SPI via spidev now */  

 

這個spidev就是我們要用的spi驅動,然后谷歌一下它的用法就可以了。再下面有一些被注釋掉的東西,是要根據不同設備來替換的。

(以下操作都在Beaglebone上進行)

我們把自帶的文件復制一份,保存為 BB-SPI0-01-00A0.dts ,然后增加一個節點,內容如下(就是原文件中注釋部分要替換的內容)

  1. spidev@0 {  
  2.        spi-max-frequency = <24000000>;  
  3.        reg = <0>;  
  4.        compatible = "linux,spidev";  
  5. };  
保存以后編譯這個dts文件

 

  1. dtc -O dtb -o BB-SPI0-01-00A0.dtbo -b 0 -@ BB-SPI0-01-00A0.dts  

 

然后把生成的.dtbo文件放到/lib/firmware目錄中

 

  1. cp BB-SPI0-01-00A0.dtbo /lib/firmware/  

 

然后把它“插”到“插槽”中(請看我的博文《聊聊Beaglebone Black的cape和device tree overlay》)

 

  1. echo BB-SPI0-01 > /sys/devices/bone_capemgr.*/slots  
OK,這時我們進入/dev目錄中就會發現比原來多了一個設備 spidev1.0 ,說明device tree配置沒有問題,該設備已成功加載。

 

 

使用SPI

因為我手邊沒有SPI設備,所以我把D0和D1也就是P9.18和P9.21這兩個引腳連接起來進行自發自收,如果收到了發送的數據即成功。時鍾線就不必管了,因為自己跟自己的時鍾肯定是同步的。
 
測試程序使用的是linux自帶的一個spidev_test.c程序(下載地址是 https://www.kernel.org/doc/Documentation/spi/,不過還是建議直接把整個kernel下載下來比較方便搜索查詢)。這個程序的內容就是發送一串16進制數,然后 printf 接收到的內容(不知道這串數有沒有什么別的含義)。
 
下面把這個文件傳到Beaglebone上,用gcc編譯一下,生成可執行文件spidev_test。假設現在就在這個文件的目錄下,那么我們輸入
  1. ./spidev_test -D /dev/spidev1.0  
來進行測試。得到輸出
  1. spi mode: 0  
  2. bits per word: 8  
  3. max speed: 500000 Hz (500 KHz)  
  4.   
  5. FF FF FF FF FF FF   
  6. 40 00 00 00 00 95   
  7. FF FF FF FF FF FF   
  8. FF FF FF FF FF FF   
  9. FF FF FF FF FF FF   
  10. DE AD BE EF BA AD   
  11. F0 0D   
說明測試成功了。否則會輸出一串FF。
 

為什么dts文件要那樣改?

剛剛我在自帶的 BB-SPI0-00A0.dts文件中加了一個節點,然后向其中加了幾個屬性,SPI0就能用了。增加一個節點還能夠理解,但為什么要加這幾個屬性?這個問題我想了幾天也沒想得很清楚。不過我知道的是,這3個屬性缺一不可。
 
其中compatible屬性是每個節點必須有的,它的作用是將這個設備和某個驅動進行綁定。比如這里就是將這個spi設備與 linux -> spidev 這個驅動綁定。我把逗號換成了箭頭,是因為我覺得其實這個逗號表達的是從屬關系,用箭頭更合適。但是,我在kernel文件中翻遍了也沒找到哪里有“linux,spidev”這樣的字眼。spidev驅動倒是找到了,而且在這個驅動文件中發現了如下內容
  1. static const struct of_device_id spidev_dt_ids[] = {  
  2.     { .compatible = "rohm,dh2228fv" },  
  3.     {},  
  4. };  
我試着把 BB-SPI0-01-00A0.dts里的 compatible 值換成 “rohm,dh2228fv”,結果居然也成功了!這似乎說明以后如果我們知道要用哪個驅動的話,到驅動文件里搜索compatible找到相應內容就可以了。不過,我遺憾地發現大部分驅動文件里都沒有這個屬性。可能只有一些硬件外設的驅動,或者是別的公司做的驅動里才會有。所以,我又迷惘了……


免責聲明!

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



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