OMAP3630下的Linux SPI总线驱动分析(1)

2019-07-24 15:25发布

1 SPI概述
      SPI是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口,是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。SPI是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便。
      SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要4根线,事实上3根也可以。也是所有基于SPI的设备共有的,它们是SDI(数据输入),SDO(数据输出),SCLK(时钟),CS(片选)。
      MOSI(SDO):主器件数据输出,从器件数据输入。
      MISO(SDI):主器件数据输入,从器件数据输出。
      SCLK :时钟信号,由主器件产生。
      CS:从器件使能信号,由主器件控制。
      其中CS是控制芯片是否被选中的,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),对此芯片的操作才有效,这就允许在同一总线上连接多个SPI设备成为可能。需要注意的是,在具体的应用中,当一条SPI总线上连接有多个设备时,SPI本身的CS有可能被其他的GPIO脚代替,即每个设备的CS脚被连接到处理器端不同的GPIO,通过操作不同的GPIO口来控制具体的需要操作的SPI设备,减少各个SPI设备间的干扰。
      SPI是串行通讯协议,也就是说数据是一位一位从MSB或者LSB开始传输的,这就是SCK时钟线存在的原因,由SCK提供时钟脉冲,MISO、MOSI则基于此脉冲完成数据传输。 SPI支持4-32bits的串行数据传输,支持MSB和LSB,每次数据传输时当从设备的大小端发生变化时需要重新设置SPI Master的大小端。


2 Linux SPI驱动总体架构
      在2.6的linux内核中,SPI的驱动架构可以分为如下三个层次:SPI 核心层、SPI控制器驱动层和SPI设备驱动层。
      Linux 中SPI驱动代码位于drivers/spi目录。
2.1 SPI核心层
      SPI核心层是Linux的SPI核心部分,提供了核心数据结构的定义、SPI控制器驱动和设备驱动的注册、注销管理等API。其为硬件平台无关层,向下屏蔽了物理总线控制器的差异,定义了统一的访问策略和接口;其向上提供了统一的接口,以便SPI设备驱动通过总线控制器进行数据收发。
      Linux中,SPI核心层的代码位于driver/spi/ spi.c。由于该层是平台无关层,本文将不再叙述,有兴趣可以查阅相关资料。
2.2 SPI控制器驱动层
      SPI控制器驱动层,每种处理器平台都有自己的控制器驱动,属于平台移植相关层。它的职责是为系统中每条SPI总线实现相应的读写方法。在物理上,每个SPI控制器可以连接若干个SPI从设备。
      在系统开机时,SPI控制器驱动被首先装载。一个控制器驱动用于支持一条特定的SPI总线的读写。一个控制器驱动可以用数据结构struct spi_master来描述。
      在include/liunx/spi/spi.h文件中,在数据结构struct spi_master定义如下:
  1.     /**
  2.      * struct spi_master - interface to SPI master controller
  3.      * @dev: device interface to this driver
  4.      * @bus_num: board-specific (and often SOC-specific) identifier for a
  5.      *  given SPI controller.
  6.      * @num_chipselect: chipselects are used to distinguish individual
  7.      *  SPI slaves, and are numbered from zero to num_chipselects.
  8.      *  each slave has a chipselect signal, but it's common that not
  9.      *  every chipselect is connected to a slave.
  10.      * @setup: updates the device mode and clocking records used by a
  11.      *  device's SPI controller; protocol code may call this.  This
  12.      *  must fail if an unrecognized or unsupported mode is requested.
  13.      *  It's always safe to call this unless transfers are pending on
  14.      *  the device whose settings are being modified.
  15.      * @transfer: adds a message to the controller's transfer queue.
  16.      * @cleanup: frees controller-specific state
  17.      *
  18.      * Each SPI master controller can communicate with one or more @spi_device
  19.      * children.  These make a small bus, sharing MOSI, MISO and SCK signals
  20.      * but not chip select signals.  Each device may be configured to use a
  21.      * different clock rate, since those shared signals are ignored unless
  22.      * the chip is selected.
  23.      *
  24.      * The driver for an SPI controller manages access to those devices through
  25.      * a queue of spi_message transactions, copying data between CPU memory and
  26.      * an SPI slave device.  For each such message it queues, it calls the
  27.      * message's completion function when the transaction completes.
  28.      */  
  29.     struct spi_master {  
  30.         struct device   dev;  
  31.       
  32.         /* other than negative (== assign one dynamically), bus_num is fully
  33.          * board-specific.  usually that simplifies to being SOC-specific.
  34.          * example:  one SOC has three SPI controllers, numbered 0..2,
  35.          * and one board's schematics might show it using SPI-2.  software
  36.          * would normally use bus_num=2 for that controller.
  37.          */  
  38.         s16         bus_num;  
  39.       
  40.         /* chipselects will be integral to many controllers; some others
  41.          * might use board-specific GPIOs.
  42.          */  
  43.         u16         num_chipselect;  
  44.       
  45.         /* setup mode and clock, etc (spi driver may call many times) */  
  46.         int         (*setup)(struct spi_device *spi);  
  47.       
  48.         /* bidirectional bulk transfers
  49.          *
  50.          * + The transfer() method may not sleep; its main role is
  51.          *   just to add the message to the queue.
  52.          * + For now there's no remove-from-queue operation, or
  53.          *   any other request management
  54.          * + To a given spi_device, message queueing is pure fifo
  55.          *
  56.          * + The master's main job is to process its message queue,
  57.          *   selecting a chip then transferring data
  58.          * + If there are multiple spi_device children, the i/o queue
  59.          *   arbitration algorithm is unspecified (round robin, fifo,
  60.          *   priority, reservations, preemption, etc)
  61.          *
  62.          * + Chipselect stays active during the entire message
  63.          *   (unless modified by spi_transfer.cs_change != 0).
  64.          * + The message transfers use clock and SPI mode parameters
  65.          *   previously established by setup() for this device
  66.          */  
  67.         int         (*transfer)(struct spi_device *spi,  
  68.                             struct spi_message *mesg);  
  69.       
  70.         /* called on release() to free memory provided by spi_master */  
  71.         void            (*cleanup)(struct spi_device *spi);  
  72.     };  
复制代码


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
11条回答
zhangbo1985
2019-07-25 18:23
SPI是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口,是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。

一周热门 更多>