[轉]使用Beaglebone Black的SPI

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

目錄(?)[+]linux

 

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

Beaglebone Black使用的AM3359芯片上有兩個SPI,但SPI1鏈接到了板子的HDMI芯片上,因此除非禁用HDMI,不然咱們只能使用SPI0。本文將利用自帶的spidev驅動使能SPI0,並進行一下簡單的驗證。ide

配置device tree

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

 

  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上進行)ui

咱們把自帶的文件複製一份,保存爲 BB-SPI0-01-00A0.dts ,而後增長一個節點,內容以下(就是原文件中註釋部分要替換的內容)this

  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目錄中spa

 

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

 

而後把它「插」到「插槽」中(請看個人博文《聊聊Beaglebone Black的cape和device tree overlay》).net

 

  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找到相應內容就能夠了。不過,我遺憾地發現大部分驅動文件裏都沒有這個屬性。可能只有一些硬件外設的驅動,或者是別的公司作的驅動裏纔會有。因此,我又迷惘了……
相關文章
相關標籤/搜索