zoukankan      html  css  js  c++  java
  • 和菜鸟一起学linux总线驱动之初识spi驱动主要结构

           既然知道了协议了,那么就可以开始去瞧瞧linux kenerl中的spi的驱动代码了,代码中有很多的结构体,还是对主要的结构体先做个了解吧,那样才可以很好的理解驱动。主要是include/linux/spi.h

     

    首先是SPI的主机和从机通信接口,也就是SPI总线,

    extern struct bus_type spi_bus_type;
    
     

    bus_type定义在linux/device.h

     

    struct bus_type {
           const char              *name;     //总线的名字
           struct bus_attribute *bus_attrs;
           struct device_attribute    *dev_attrs;
           struct driver_attribute    *drv_attrs; 
    
    //总线上的device和driver的匹配,匹配成功返回非0值
           int (*match)(struct device *dev, struct device_driver *drv);
           int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
           //当新的device或driver加到总线上的时候,调用driver中的probe函数经行匹配
           int (*probe)(struct device *dev);
           int (*remove)(struct device *dev);
           void (*shutdown)(struct device *dev);
           int (*suspend)(struct device *dev, pm_message_t state);
           int (*resume)(struct device *dev);
           const struct dev_pm_ops *pm;
           struct subsys_private *p;
    };
    
    

    SPI设备

     

    struct spi_device {
          struct device          dev;
          struct spi_master    *master;    //SPI控制器
           u32                max_speed_hz;  //最大时钟频率
           u8                  chip_select;     //片选
           u8                  mode;          //SPI模式
    #define    SPI_CPHA     0x01                     /* clock phase */
    #define    SPI_CPOL     0x02                     /* clock polarity */
    #define    SPI_MODE_0       (0|0)                     /* (original MicroWire) */
    #define    SPI_MODE_1       (0|SPI_CPHA)
    #define    SPI_MODE_2       (SPI_CPOL|0)
    #define    SPI_MODE_3       (SPI_CPOL|SPI_CPHA)
    #define    SPI_CS_HIGH      0x04                     /* chipselect active high? */
    #define    SPI_LSB_FIRST    0x08                     /* per-word bits-on-wire */
    #define    SPI_3WIRE   0x10                     /* SI/SO signals shared */
    #define    SPI_LOOP     0x20                     /* loopback mode */
    #define    SPI_NO_CS   0x40                     /* 1 dev/bus, no chipselect */
    #define    SPI_READY  0x80                     /* slave pulls low to pause */
           u8                  bits_per_word;              //一次传输的bits,可以是8、16、32,默认是8
           int                 irq;                 
           void               *controller_state;
           void               *controller_data;        
           char               modalias[SPI_NAME_SIZE];  //别名,用于device和driver的匹配
    };
    
    


     

     

    SPI驱动

     

    struct spi_driver {
           const struct spi_device_id *id_table;
           int                 (*probe)(struct spi_device *spi);  //绑定驱动和SPI设备
             int                 (*remove)(struct spi_device *spi);
           void               (*shutdown)(struct spi_device *spi);
           int                 (*suspend)(struct spi_device *spi, pm_message_t mesg);
           int                 (*resume)(struct spi_device *spi);
    
           struct device_driver         driver;
    };
    
    


     

    SPI主控制器

     

    struct spi_master {
           struct device   dev;   //驱动的设备接口
           struct list_head list;        //SPI控制器的链表头
           s16                bus_num;    //总线号
    
           /* chipselects will be integral to many controllers; some others
            * might use board-specific GPIOs.
            */
           u16                num_chipselect;    //SPI设备的片选号
             u16                dma_alignment;     //dma模式  
     
            /* spi_device.mode flags understood by this controller driver */
           u16                mode_bits;         
    
           /* other constraints relevant to this driver */
           u16                flags;
    
    #define SPI_MASTER_HALF_DUPLEX    BIT(0)           /* can't do full duplex */
    #define SPI_MASTER_NO_RX   BIT(1)           /* can't do buffer read */
    #define SPI_MASTER_NO_TX    BIT(2)           /* can't do buffer write */
    
            /* lock and mutex for SPI bus locking */
          spinlock_t              bus_lock_spinlock;
           struct mutex           bus_lock_mutex;
    
            bool               bus_lock_flag;
           int                 (*setup)(struct spi_device *spi);   //更新SPI设备的模式和SPI设备的采样时钟
           int                 (*transfer)(struct spi_device *spi,    //添加一个消息到控制器的传输队列
                                              struct spi_message *mesg);
           void               (*cleanup)(struct spi_device *spi);
    
    };
    
    


     

    SPI传输

     

    struct spi_transfer {
          /* it's ok if tx_buf == rx_buf (right?)
           * for MicroWire, one buffer must be null
            * buffers must work with dma_*map_single() calls, unless
            *   spi_message.is_dma_mapped reports a pre-existing mapping
            */
    
         const void       *tx_buf;    //要写的数据
           void        *rx_buf;                //要读的数据
           unsigned  len;                       //数据长度
    
     
    
           dma_addr_t    tx_dma;       //tx_buf的DMA地址
           dma_addr_t    rx_dma;         //rx_buf的DMA地址
    
          unsigned  cs_change:1;
          u8           bits_per_word;       //传输的bytes数,不选就用默认的
           u16         delay_usecs;                  //微秒延时,用以传输数据后,改变片选信号前
           u32         speed_hz;            //传输速率,不选就用默认的
    
           struct list_head transfer_list;     //传输链表,用以传输spi_message
    
    };
    
    


     

    SPI消息

     

    struct spi_message {
           struct list_head       transfers;   // 
    
           struct spi_device     *spi;      //加到传输队列中的spi设备
            unsigned         is_dma_mapped:1;   //DMA传输控制位
    
           /* completion is reported through a callback */
           void               (*complete)(void *context);      //传输完成
           void               *context;                                    //complete函数的参数                
           unsigned         actual_length;             //所有成功传输字段的总长度
           int                 status;                                 //传输成功返回0,否则返回错误
    
     
    
           /* for optional use by whatever driver currently owns the
           * spi_message ...  between calls to spi_async and then later
            * complete(), that's the spi_master controller driver.
            */
    
           struct list_head       queue;
           void               *state;
    
    };
    
    


     

    SPI bitbang

     

    struct spi_bitbang {
           struct workqueue_struct *workqueue;
           struct work_struct   work;
    
           spinlock_t              lock;
           struct list_head       queue;
    
           u8                  busy;
           u8                  use_dma;
           u8                  flags;             /* extra spi->mode support */
    
           struct spi_master    *master;
    
           /* setup_transfer() changes clock and/or wordsize to match settings
          * for this transfer; zeroes restore defaults from spi_device.
            */
           int   (*setup_transfer)(struct spi_device *spi,
                         struct spi_transfer *t);
    
            void (*chipselect)(struct spi_device *spi, int is_on);
    #define    BITBANG_CS_ACTIVE      1     /* normally nCS, active low */
    #define    BITBANG_CS_INACTIVE   0
    
     
    
           /* txrx_bufs() may handle dma mapping for transfers that don't
            * already have one (transfer.{tx,rx}_dma is zero), or use PIO
            */
           int   (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t);
    
           /* txrx_word[SPI_MODE_*]() just looks like a shift register */
           u32  (*txrx_word[4])(struct spi_device *spi,
                         unsigned nsecs,
                         u32 word, u8 bits);
    
    };
    
    


            在SPI控制器里面最常用的用来处理传输的结构体spi_bitbang了。

     

    SPI borad info

    struct spi_board_info {
     /* the device name and module name are coupled, like platform_bus;
      * "modalias" is normally the driver name.
      *
      * platform_data goes to spi_device.dev.platform_data,
      * controller_data goes to spi_device.controller_data,
      * irq is copied too
      */
     char  modalias[SPI_NAME_SIZE];
     const void *platform_data;
     void  *controller_data;
     int  irq;
    
     /* slower signaling on noisy or low voltage boards */
     u32  max_speed_hz;
    
    
     /* bus_num is board specific and matches the bus_num of some
      * spi_master that will probably be registered later.
      *
      * chip_select reflects how this chip is wired to that master;
      * it's less than num_chipselect.
      */
     u16  bus_num;
     u16  chip_select;
    
     /* mode becomes spi_device.mode, and is essential for chips
      * where the default of SPI_CS_HIGH = 0 is wrong.
      */
     u8  mode;
    
     /* ... may need additional spi_device chip config data here.
      * avoid stuff protocol drivers can set; but include stuff
      * needed to behave without being bound to a driver:
      *  - quirks like clock rate mattering when not selected
      */
    };
    
    

           控制器里会读取borad info里的参数

    SPI gpio_platform_data

     

    struct spi_gpio_platform_data {
           unsigned  sck;
           unsigned  mosi;
           unsigned  miso;
    
           u16         num_chipselect;
    
    };
    
    


            因为我用的比较多的是GPIO模拟的,所以还是记录下这个从platform传进来的管脚号。

     

           OK,对于SPI用到的结构体基本上已经介绍完了,那么接下来就介绍其主要函数了。

     

  • 相关阅读:
    安装VMware Tools和设置屏幕
    线程
    制作数据集-解析篇
    制作数据集-应用篇
    tf.train.examle函数
    输入手写数字输出识别结果——分析篇
    输入手写数字输出识别结果
    断点续训
    UC972开发板,参考实验8,完成定时器触发信号输出实验
    hz和s和脉冲
  • 原文地址:https://www.cnblogs.com/wuyida/p/6300060.html
Copyright © 2011-2022 走看看