[转]使用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找到相应内容就能够了。不过,我遗憾地发现大部分驱动文件里都没有这个属性。可能只有一些硬件外设的驱动,或者是别的公司作的驱动里才会有。因此,我又迷惘了……
相关文章
相关标签/搜索