深入浅出spi驱动之数据结构(一)

来源:互联网 发布:淘宝买手机花呗分期购 编辑:程序博客网 时间:2024/06/06 20:49

Allein.Cao原创作品,转载请注明出处:

 http://blog.csdn.net/alleincao/article/details/7522418

内核版本:2.6.32.2

硬件:S3C2440 

SPI总线是一种比较通用的数据传输总线,遵从主从模式,由主设备发起通讯请求,通常工作于全双工模式,由4条数据时钟线组成,下面这段话摘自s3c2440数据手册:

There are 4 I/O pin signals associated with SPItransfers: SCK (SPICLK0,1), MISO (SPIMISO0,1) data line, MOSI (SPIMOSI0,1) dataline and active low /SS (nSS0,1) pin (input).

  • 确定驱动文件

 SPI作为Linux里面比较小的一个子系统,其驱动程序位于/drivers/spi/*目录,首先,我们可以通过Makefile及Kconfig来确定我们需要看的源文件:

Makefile:

[html] view plain copy
  1. <pre name="code" class="csharp">#  
  2. # Makefile for kernel SPI drivers.  
  3. #  
  4. ……………………………………………….  
  5. # small core, mostly translating board-specific  
  6. # config declarations into driver model code  
  7. obj-$(CONFIG_SPI_MASTER)        += spi.o              
  8.   
  9. # SPI master controller drivers (bus)  
  10. …………………………………………………  
  11. obj-$(CONFIG_SPI_BITBANG)       += spi_bitbang.o  
  12. …………………………………………………  
  13. obj-$(CONFIG_SPI_S3C24XX_GPIO)      += spi_s3c24xx_gpio.o  
  14. obj-$(CONFIG_SPI_S3C24XX)       += spi_s3c24xx.o  
  15. …………………………………………………  
  16. #   ... add above this line ...  
  17.   
  18. # SPI protocol drivers (device/link on bus)  
  19. obj-$(CONFIG_SPI_SPIDEV)    += spidev.o  
  20. …………………………………………………  
  21. #   ... add above this line ...</pre>  
  22. <pre></pre>  
  23. <p></p>  
  24. <p>通过以上分析我们知道,spi驱动由三部分组成,分别是core(spi.c),master controller driver (spi_s3c24xx.c or spi_s3c24xx_gpio.)以及SPIprotocol drivers (spidev.c),这里spi_s3c24xx_gpio.c文件是用普通的io口来模拟spi时序,具体见Kconfig描述:</p>  
  25. <pre name="code" class="csharp">config SPI_S3C24XX_GPIO  
  26.     tristate "Samsung S3C24XX series SPI by GPIO"  
  27.     depends on ARCH_S3C2410 && EXPERIMENTAL  
  28.     select SPI_BITBANG  
  29.     help  
  30.       SPI driver for Samsung S3C24XX series ARM SoCs using  
  31.       GPIO lines to provide the SPI bus. This can be used where  
  32.       the inbuilt hardware cannot provide the transfer mode, or  
  33.       where the board is using non hardware connected pins.  
  34. </pre>  
  35. <p>在此,我们以spi控制器方式进行分析。</p>  
  36. <p></p>  
  37. <ul>  
  38. <li>数据结构</li></ul>  
  39. <p></p>  
  40. <p>Spi驱动涉及的<a href="http://lib.csdn.net/base/datastructure" class="replace_word" title="算法与数据结构知识库" target="_blank" style="color:#df3434; font-weight:bold;">数据结构</a>主要位于/include/<a href="http://lib.csdn.net/base/linux" class="replace_word" title="Linux知识库" target="_blank" style="color:#df3434; font-weight:bold;">linux</a>/spi.h,对各个结构有比较详细的解释,限于篇幅,简单介绍如下:</p>  
  41. <p>1、Spi_device代表一个外围spi设备,由master controller driver注册完成后扫描BSP中注册设备产生的设备链表并向spi_bus注册产生。</p>  
  42. <p></p>  
  43. <pre name="code" class="csharp">struct spi_device {  
  44.     struct device       dev;            //设备模型使用  
  45.     struct spi_master   *master;        //设备使用的master结构  
  46.     u32         max_speed_hz;   //通讯时钟  
  47.     u8          chip_select;        //片选号,每个master支持多个spi_device  
  48.     u8          mode;           //设备支持的模式,如片选是高or低?  
  49. #define SPI_CPHA    0x01            /* clock phase */  
  50. #define SPI_CPOL    0x02            /* clock polarity */  
  51. #define SPI_MODE_0  (0|0)           /* (original MicroWire) */  
  52. #define SPI_MODE_1  (0|SPI_CPHA)  
  53. #define SPI_MODE_2  (SPI_CPOL|0)  
  54. #define SPI_MODE_3  (SPI_CPOL|SPI_CPHA)  
  55. #define SPI_CS_HIGH 0x04            /* chipselect active high? */  
  56. #define SPI_LSB_FIRST   0x08            /* per-word bits-on-wire */  
  57. #define SPI_3WIRE   0x10            /* SI/SO signals shared */  
  58. #define SPI_LOOP    0x20            /* loopback mode */  
  59. #define SPI_NO_CS   0x40            /* 1 dev/bus, no chipselect */  
  60. #define SPI_READY   0x80            /* slave pulls low to pause */  
  61.     u8          bits_per_word;  //每个字长的比特数  
  62.     int         irq;                //中断号  
  63.     void            *controller_state;  //控制器寄存器状态  
  64.     void            *controller_data;  
  65.     char            modalias[SPI_NAME_SIZE];    //设备名称  
  66. };  
  67. </pre>  
  68. <p>2、  spi_driver代表一个SPI protocol drivers,即外设驱动。</p>  
  69. <p></p>  
  70. <pre name="code" class="csharp">struct spi_driver {  
  71.     const struct spi_device_id *id_table;       //支持的spi_device设备表  
  72.     int         (*probe)(struct spi_device *spi);   //probe函数  
  73.     int         (*remove)(struct spi_device *spi);  
  74.     void            (*shutdown)(struct spi_device *spi);  
  75.     int         (*suspend)(struct spi_device *spi, pm_message_t mesg);  
  76.     int         (*resume)(struct spi_device *spi);  
  77.     struct device_driver    driver;     //设备模型使用  
  78. };  
  79. </pre>  
  80. <p>3、spi_master代表一个主机控制器,此处即S3C2440中的SPI控制器</p>  
  81. <p></p>  
  82. <pre name="code" class="csharp">struct spi_master {  
  83.     struct device   dev;            //设备模型使用  
  84.     s16         bus_num;    //master编号,s3c2440有2个spi控制器,编号为0 1  
  85.     u16         num_chipselect;     //支持的片选的数量,从设备的片选号不能大于这个数量  
  86.     u16         dma_alignment;  
  87.     /* spi_device.mode flags understood by this controller driver */  
  88.     u16         mode_bits; //master支持的设备模式  
  89.   
  90.     /* other constraints relevant to this driver */  
  91.     u16         flags;      //一些额外的标志  
  92. #define SPI_MASTER_HALF_DUPLEX  BIT(0)      /* can't do full duplex */  
  93. #define SPI_MASTER_NO_RX    BIT(1)      /* can't do buffer read */  
  94. #define SPI_MASTER_NO_TX    BIT(2)      /* can't do buffer write */  
  95.   
  96.     int         (*setup)(struct spi_device *spi);  //设置模式、时钟等  
  97.   
  98.     int         (*transfer)(struct spi_device *spi, //数据发送函数  
  99.                         struct spi_message *mesg);  
  100.   
  101.     /* called on release() to free memory provided by spi_master */  
  102.     void            (*cleanup)(struct spi_device *spi);    
  103. };  
  104. </pre>  
  105. <p>4、spi_transfer代表一个读写缓冲对,包含接收缓冲区及发送缓冲区,其实,spi_transfer的发送是通过构建spi_message实现,通过将spi_transfer中的链表transfer_list链接到spi_message中的transfers,再以spi_message形势向底层发送数据。<span style="color:red">每个</span><span style="color:red">spi_transfer</span><span style="color:red">都可以对传输的一些参数进行设置,使得</span><span style="color:red">master  
  106.  controller</span><span style="color:red">按照它要求的参数进行数据发送。</span></p>  
  107. <p></p>  
  108. <pre name="code" class="csharp">struct spi_transfer {  
  109.     const void  *tx_buf;    //发送缓冲区  
  110.     void        *rx_buf;        //接收缓冲区  
  111.     unsigned    len;            //缓冲区长度  
  112.   
  113.     dma_addr_t  tx_dma;  
  114.     dma_addr_t  rx_dma;  
  115.   
  116.     unsigned    cs_change:1;    // 当前spi_transfer发送完成之后重新片选?  
  117.     u8      bits_per_word;  //每个字长的比特数,0代表使用Spi_device中的默认值  
  118.     u16     delay_usecs;        //发送完成一个spi_transfer后延时时间  
  119.     u32     speed_hz;       //速率  
  120.   
  121.     struct list_head transfer_list; //用于链接到spi_message  
  122. };<span style="color:#ff0000;">  
  123. </span></pre>5、spi_message代表spi消息,由多个spi_ transfer段组成:  
  124. <p>struct spi_message {</p>  
  125. <pre name="code" class="csharp">    struct list_head    transfers;      // spi_transfer链表队列  
  126.   
  127.     struct spi_device   *spi;           //该消息的目标设备  
  128.   
  129.     unsigned        is_dma_mapped:1;  
  130.   
  131.     /* completion is reported through a callback */  
  132.     void            (*complete)(void *context);  //消息完成后调用的回调函数  
  133.     void            *context;       //回调函数参数  
  134.     unsigned        actual_length; //实际传输的数据长度  
  135.     int         status; //该消息的发送结果,0:成功  
  136.   
  137.     struct list_head    queue;      //用于添加到bitbang的list  
  138.     void            *state;  
  139. };</pre><pre name="code" class="csharp"></pre><pre name="code" class="csharp" style="text-align: left;">6、s3c24xx_spi代表具体的s3c2440中的spi控制器,包含了控制器的信息,如中断,寄存器等信息,定义于/drivers/spi/spi_s3c24xx.c(因为该结构与具体的硬件有关,属于linux里面的非通用代码)</pre><pre name="code" class="csharp"><pre name="code" class="csharp"><div style="text-align: left;">  
  140. </div><pre></pre><pre name="code" class="csharp"></pre><pre name="code" class="csharp">struct s3c24xx_spi {  
  141.     /* bitbang has to be first */  
  142.     struct spi_bitbang   bitbang;   //见下面分析  
  143.     struct completion    done;  
  144.   
  145.     void __iomem        *regs;  
  146.     int          irq;  
  147.     int          len;  
  148.     int          count;  
  149.   
  150.     void            (*set_cs)(struct s3c2410_spi_info *spi,  
  151.                       int cs, int pol);  
  152.   
  153.     /* data buffers */  
  154.     const unsigned char *tx;  
  155.     unsigned char       *rx;  
  156.   
  157.     struct clk      *clk;  
  158.     struct resource     *ioarea;  
  159.     struct spi_master   *master;  
  160.     struct spi_device   *curdev;  
  161.     struct device       *dev;  
  162.     struct s3c2410_spi_info *pdata;  
  163. };  
  164. </pre>7、struct spi_bitbang是具体的负责信息传输的数据结构,它维护一个workqueue_struct,每收到一个消息,都会向其中添加一个work_struct,由内核守护进程在将来的某个时间调用该work_struct中的function进行消息发送。  
  165. <p></p>  
  166. <p></p>  
  167. <p align="left"></p>  
  168. <pre name="code" class="csharp">struct spi_bitbang {  
  169.     struct workqueue_struct *workqueue; //工作队列头,spi master初始化时建立      
  170.     struct work_struct  work;   //spi master初始化时初始化  
  171.   
  172.     spinlock_t      lock;  
  173.     struct list_head    queue;  //挂接spi_message  
  174.     u8          busy;   //忙标志  
  175.     u8          use_dma;  
  176.     u8          flags;      /* extra spi->mode support */  
  177.   
  178.     struct spi_master   *master;    //对应的spi_master  
  179.   
  180.     /* setup_transfer() changes clock and/or wordsize to match settings  
  181.      * for this transfer; zeroes restore defaults from spi_device.  
  182.      */  
  183.     int (*setup_transfer)(struct spi_device *spi,   //对数据传输进行设置  
  184.             struct spi_transfer *t);  
  185.   
  186.     void    (*chipselect)(struct spi_device *spi, int is_on);   //控制片选  
  187. #define BITBANG_CS_ACTIVE   1   /* normally nCS, active low */  
  188. #define BITBANG_CS_INACTIVE 0  
  189.   
  190.     /* txrx_bufs() may handle dma mapping for transfers that don't  
  191.      * already have one (transfer.{tx,rx}_dma is zero), or use PIO  
  192.      */  
  193.     int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t);   //实际的数据传输函数  
  194.   
  195.     /* txrx_word[SPI_MODE_*]() just looks like a shift register */  
  196.     u32 (*txrx_word[4])(struct spi_device *spi,  
  197.             unsigned nsecs,  
  198.             u32 word, u8 bits);  
  199. };  
  200. </pre><br>  
  201. <br>  
  202. <p></p>  
  203. <pre></pre>  
  204. <pre name="code" class="csharp"></pre><pre></pre>  
  205. <pre></pre>  
  206. <pre></pre>  
  207. <pre></pre>  
  208. <pre></pre>  
  209. <pre></pre>  
  210. <pre></pre>  
  211. <pre></pre>  
  212. <pre></pre>  
  213. <pre></pre>  
  214. <pre></pre>  
  215. <pre></pre>  
  216. <pre></pre>  
  217. <pre></pre>  
  218. <pre></pre>  
  219. <pre></pre>  
  220. <pre></pre>  
  221. <pre></pre>  
  222. <pre></pre>  
  223. <pre></pre>  
  224. <pre></pre>  
  225. <pre></pre>  
  226.      
  227. </pre></pre>  
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小孩上课不认真听讲怎么办 一年级孩子上课不认真听讲怎么办 打了孩子很自责怎么办 4岁宝宝讲话结巴怎么办 网销客户不说话怎么办 两岁宝宝不说话怎么办? 4岁儿童说话结巴怎么办 3岁宝宝说话结巴怎么办 6岁儿童舌头短怎么办 5岁宝宝说话结巴怎么办 两岁宝宝说话晚怎么办 6岁儿童说话结巴怎么办 2岁宝宝呕吐拉稀怎么办 2岁宝宝突然呕吐怎么办 2岁宝宝呕吐发烧怎么办 2岁宝宝呕吐厉害怎么办 1岁宝宝半夜呕吐怎么办 2岁半宝宝呕吐怎么办 2岁宝宝半夜呕吐怎么办 两岁宝宝一直吐怎么办 原画师老了以后怎么办 孩子不想上学怎么办怎么去说服 嫉妒别人比我好怎么办 三岁宝宝爱打人怎么办 1岁宝宝喜欢打人怎么办 ps图层解锁不了怎么办 沈腾结婚马丽怎么办 延长甲没有纸托怎么办 高考第一志愿没录取怎么办 电子画颜料干了怎么办 数字画颜料干了怎么办 彩砂纸画不好了怎么办 宝宝吃了油画棒怎么办 2岁宝宝不爱刷牙怎么办 两岁宝宝不刷牙怎么办 1岁宝宝不爱刷牙怎么办 3岁宝宝不肯刷牙怎么办 20岁没学历迷茫怎么办 四岁了不长头发怎么办 17岁掉头发严重怎么办 头发很油,又少怎么办