深入浅出spi驱动之数据结构(一) -凯发app官方网站

凯发app官方网站-凯发k8官网下载客户端中心 | | 凯发app官方网站-凯发k8官网下载客户端中心
  • 博客访问: 1125430
  • 博文数量: 146
  • 博客积分: 190
  • 博客等级: 入伍新兵
  • 技术积分: 5225
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-06 08:24
个人简介

慢行者

文章分类

全部博文(146)

文章存档

2013年(145)

2012年(1)

相关博文
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·

分类: linux

2013-04-26 11:10:48

allein.cao原创作品,转载请注明出处:

内核版本: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]
  1. <preclass="csharp"name="code">
  2. # makefile for kernel spi drivers. 
  3. ………………………………………………. 
  4. # small core, mostly translating board-specific 
  5. # config declarations into driver model code 
  6. obj-$(config_spi_master)        = spi.o             
  7.  
  8. # spi master controller drivers (bus) 
  9. ………………………………………………… 
  10. obj-$(config_spi_bitbang)       = spi_bitbang.o 
  11. ………………………………………………… 
  12. obj-$(config_spi_s3c24xx_gpio)      = spi_s3c24xx_gpio.o 
  13. obj-$(config_spi_s3c24xx)       = spi_s3c24xx.o 
  14. ………………………………………………… 
  15. #   ... add above this line ... 
  16.  
  17. # spi protocol drivers (device/link on bus) 
  18. obj-$(config_spi_spidev)    = spidev.o 
  19. ………………………………………………… 
  20. #   ... add above this line ...pre> 
  21. <pre>pre> 
  22. <p>p> 
  23. <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> 
  24. <preclass="csharp"name="code">config spi_s3c24xx_gpio 
  25.     tristate "samsung s3c24xx series spi by gpio" 
  26.     depends on arch_s3c2410 && experimental 
  27.     select spi_bitbang 
  28.     help 
  29.       spi driver for samsung s3c24xx series arm socs using 
  30.       gpio lines to provide the spi bus. this can be used where 
  31.       the inbuilt hardware cannot provide the transfer mode, or 
  32.       where the board is using non hardware connected pins. 
  33. pre> 
  34. <p>在此,我们以spi控制器方式进行分析。p> 
  35. <p>p> 
  36. <ul> 
  37. <li>数据结构li>ul> 
  38. <p>p> 
  39. <p>spi驱动涉及的数据结构主要位于/include/linux/spi.h,对各个结构有比较详细的解释,限于篇幅,简单介绍如下:p> 
  40. <p>1、spi_device代表一个外围spi设备,由master controller driver注册完成后扫描bsp中注册设备产生的设备链表并向spi_bus注册产生。p> 
  41. <p>p> 
  42. <preclass="csharp"name="code">struct spi_device { 
  43.     struct device       dev;            //设备模型使用 
  44.     struct spi_master   *master;        //设备使用的master结构 
  45.     u32         max_speed_hz;   //通讯时钟 
  46.     u8          chip_select;        //片选号,每个master支持多个spi_device 
  47.     u8          mode;           //设备支持的模式,如片选是高or低? 
  48. #define spi_cpha    0x01            /* clock phase */ 
  49. #define spi_cpol    0x02            /* clock polarity */ 
  50. #define spi_mode_0  (0|0)           /* (original microwire) */ 
  51. #define spi_mode_1  (0|spi_cpha) 
  52. #define spi_mode_2  (spi_cpol|0) 
  53. #define spi_mode_3  (spi_cpol|spi_cpha) 
  54. #define spi_cs_high 0x04            /* chipselect active high? */ 
  55. #define spi_lsb_first   0x08            /* per-word bits-on-wire */ 
  56. #define spi_3wire   0x10            /* si/so signals shared */ 
  57. #define spi_loop    0x20            /* loopback mode */ 
  58. #define spi_no_cs   0x40            /* 1 dev/bus, no chipselect */ 
  59. #define spi_ready   0x80            /* slave pulls low to pause */ 
  60.     u8          bits_per_word;  //每个字长的比特数 
  61.     int         irq;                //中断号 
  62.     void            *controller_state;  //控制器寄存器状态 
  63.     void            *controller_data; 
  64.     char            modalias[spi_name_size];    //设备名称 
  65. }; 
  66. pre> 
  67. <p>2、  spi_driver代表一个spi protocol drivers,即外设驱动。p> 
  68. <p>p> 
  69. <preclass="csharp"name="code">struct spi_driver { 
  70.     const struct spi_device_id *id_table;       //支持的spi_device设备表 
  71.     int         (*probe)(struct spi_device *spi);   //probe函数 
  72.     int         (*remove)(struct spi_device *spi); 
  73.     void            (*shutdown)(struct spi_device *spi); 
  74.     int         (*suspend)(struct spi_device *spi, pm_message_t mesg); 
  75.     int         (*resume)(struct spi_device *spi); 
  76.     struct device_driver    driver;     //设备模型使用 
  77. }; 
  78. pre> 
  79. <p>3、spi_master代表一个主机控制器,此处即s3c2440中的spi控制器p> 
  80. <p>p> 
  81. <preclass="csharp"name="code">struct spi_master { 
  82.     struct device   dev;            //设备模型使用 
  83.     s16         bus_num;    //master编号,s3c2440有2个spi控制器,编号为0 1 
  84.     u16         num_chipselect;     //支持的片选的数量,从设备的片选号不能大于这个数量 
  85.     u16         dma_alignment; 
  86.     /* spi_device.mode flags understood by this controller driver */ 
  87.     u16         mode_bits; //master支持的设备模式 
  88.  
  89.     /* other constraints relevant to this driver */ 
  90.     u16         flags;      //一些额外的标志 
  91. #define spi_master_half_duplex  bit(0)      /* can't do full duplex */ 
  92. #define spi_master_no_rx    bit(1)      /* can't do buffer read */ 
  93. #define spi_master_no_tx    bit(2)      /* can't do buffer write */ 
  94.  
  95.     int         (*setup)(struct spi_device *spi);  //设置模式、时钟等 
  96.  
  97.     int         (*transfer)(struct spi_device *spi, //数据发送函数 
  98.                         struct spi_message *mesg); 
  99.  
  100.     /* called on release() to free memory provided by spi_master */ 
  101.     void            (*cleanup)(struct spi_device *spi);   
  102. }; 
  103. pre> 
  104. <p>4、spi_transfer代表一个读写缓冲对,包含接收缓冲区及发送缓冲区,其实,spi_transfer的发送是通过构建spi_message实现,通过将spi_transfer中的链表transfer_list链接到spi_message中的transfers,再以spi_message形势向底层发送数据。<spanstyle="color: red;">每个span><spanstyle="color: red;">spi_transferspan><spanstyle="color: red;">都可以对传输的一些参数进行设置,使得span><spanstyle="color: red;">master 
  105. controllerspan><spanstyle="color: red;">按照它要求的参数进行数据发送。span>p> 
  106. <p>p> 
  107. <preclass="csharp"name="code">struct spi_transfer { 
  108.     const void  *tx_buf;    //发送缓冲区 
  109.     void        *rx_buf;        //接收缓冲区 
  110.     unsigned    len;            //缓冲区长度 
  111.  
  112.     dma_addr_t  tx_dma; 
  113.     dma_addr_t  rx_dma; 
  114.  
  115.     unsigned    cs_change:1;    // 当前spi_transfer发送完成之后重新片选? 
  116.     u8      bits_per_word;  //每个字长的比特数,0代表使用spi_device中的默认值 
  117.     u16     delay_usecs;        //发送完成一个spi_transfer后延时时间 
  118.     u32     speed_hz;       //速率 
  119.  
  120.     struct list_head transfer_list; //用于链接到spi_message 
  121. };<spanstyle="color: rgb(255, 0, 0);"> 
  122. span>pre>5、spi_message代表spi消息,由多个spi_ transfer段组成: 
  123. <p>struct spi_message {p> 
  124. <preclass="csharp"name="code">    struct list_head    transfers;      // spi_transfer链表队列 
  125.  
  126.     struct spi_device   *spi;           //该消息的目标设备 
  127.  
  128.     unsigned        is_dma_mapped:1; 
  129.  
  130.     /* completion is reported through a callback */ 
  131.     void            (*complete)(void *context);  //消息完成后调用的回调函数 
  132.     void            *context;       //回调函数参数 
  133.     unsigned        actual_length; //实际传输的数据长度 
  134.     int         status; //该消息的发送结果,0:成功 
  135.  
  136.     struct list_head    queue;      //用于添加到bitbang的list 
  137.     void            *state; 
  138. };pre><preclass="csharp"name="code">pre><prestyle="text-align: left;"class="csharp"name="code">6、s3c24xx_spi代表具体的s3c2440中的spi控制器,包含了控制器的信息,如中断,寄存器等信息,定义于/drivers/spi/spi_s3c24xx.c(因为该结构与具体的硬件有关,属于linux里面的非通用代码)pre><preclass="csharp"name="code"><preclass="csharp"name="code"><divstyle="text-align: left;"> 
  139. div><pre>pre><preclass="csharp"name="code">pre><preclass="csharp"name="code">struct s3c24xx_spi { 
  140.     /* bitbang has to be first */ 
  141.     struct spi_bitbang   bitbang;   //见下面分析 
  142.     struct completion    done; 
  143.  
  144.     void __iomem        *regs; 
  145.     int          irq; 
  146.     int          len; 
  147.     int          count; 
  148.  
  149.     void            (*set_cs)(struct s3c2410_spi_info *spi, 
  150.                       int cs, int pol); 
  151.  
  152.     /* data buffers */ 
  153.     const unsigned char *tx; 
  154.     unsigned char       *rx; 
  155.  
  156.     struct clk      *clk; 
  157.     struct resource     *ioarea; 
  158.     struct spi_master   *master; 
  159.     struct spi_device   *curdev; 
  160.     struct device       *dev; 
  161.     struct s3c2410_spi_info *pdata; 
  162. }; 
  163. pre>7、struct spi_bitbang是具体的负责信息传输的数据结构,它维护一个workqueue_struct,每收到一个消息,都会向其中添加一个work_struct,由内核守护进程在将来的某个时间调用该work_struct中的function进行消息发送。 
  164. <p>p> 
  165. <p>p> 
  166. <palign="left">p> 
  167. <preclass="csharp"name="code">struct spi_bitbang { 
  168.     struct workqueue_struct *workqueue; //工作队列头,spi master初始化时建立     
  169.     struct work_struct  work;   //spi master初始化时初始化 
  170.  
  171.     spinlock_t      lock; 
  172.     struct list_head    queue;  //挂接spi_message 
  173.     u8          busy;   //忙标志 
  174.     u8          use_dma; 
  175.     u8          flags;      /* extra spi->mode support */ 
  176.  
  177.     struct spi_master   *master;    //对应的spi_master 
  178.  
  179.     /* setup_transfer() changes clock and/or wordsize to match settings 
  180.      * for this transfer; zeroes restore defaults from spi_device. 
  181.      */ 
  182.     int (*setup_transfer)(struct spi_device *spi,   //对数据传输进行设置 
  183.             struct spi_transfer *t); 
  184.  
  185.     void    (*chipselect)(struct spi_device *spi, int is_on);   //控制片选 
  186. #define bitbang_cs_active   1   /* normally ncs, active low */ 
  187. #define bitbang_cs_inactive 0 
  188.  
  189.     /* txrx_bufs() may handle dma mapping for transfers that don't 
  190.      * already have one (transfer.{tx,rx}_dma is zero), or use pio 
  191.      */ 
  192.     int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t);   //实际的数据传输函数 
  193.  
  194.     /* txrx_word[spi_mode_*]() just looks like a shift register */ 
  195.     u32 (*txrx_word[4])(struct spi_device *spi, 
  196.             unsigned nsecs, 
  197.             u32 word, u8 bits); 
  198. }; 
  199. pre><br> 
  200. <br> 
  201. <p>p> 
  202. <pre>pre> 
  203. <preclass="csharp"name="code">pre><pre>pre> 
  204. <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.  
  226. pre>pre> 
阅读(5793) | 评论(0) | 转发(3) |
给主人留下些什么吧!~~
")); function link(t){ var href= $(t).attr('href'); href ="?url=" encodeuricomponent(location.href); $(t).attr('href',href); //setcookie("returnouturl", location.href, 60, "/"); }
网站地图