注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

LINUX驱动之SPI子系统之二SPI的基本数据结构2  

2012-10-18 20:40:02|  分类: LINUX内核驱动 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
 

LINUX驱动之SPI子系统之二SPI的基本数据结构2

今天接着讲余下的几个数据结构,主要讲spi_board_info,spi_message,spi_transfer,先看它们的定义:


1.   struct spi_board_info {  

2.   char     modalias[32];   //设备与驱动匹配的唯一标识  

3.   const void    *platform_data;  

4.   void     *controller_data;  

5.   int        irq;  

6.   u32     max_speed_hz;  

7.   u16        bus_num;       //设备所归属的总线编号  

8.   u16      chip_select;  

9.   u8      mode;  


}; 

boardinfo是用来管理spi_board_info的结构,spi_board_info通过spi_register_board_info(struct spi_board_info const *info, unsigned n)交由boardinfo来管理,并挂到board_list链表上,list_add_tail(&bi->list,&board_list);

[cpp] view plaincopy


1.   struct boardinfo {   

2.    /*用于挂到链表头board_list上*/  

3.   struct list_head  list;  

4.   /*管理的spi_board_info的数量*/  

5.   unsigned  n_board_info;  

6.   /*存放结构体spi_board_info*/  

7.   struct spi_board_info    board_info[0];  


}; 


1.   struct spi_message {  

2.   struct list_head    transfers;   //此次消息的传输队列,一个消息可以包含多个传输段  

3.   struct spi_device *spi;        //传输的目的设备  

4.   unsigned      is_dma_mapped:1;  //如果为真,此次调用提供dma和cpu虚拟地址  

5.   void          (*complete)(void *context);  //异步调用完成后的回调函数  

6.   void         *context;                    //回调函数的参数  

7.   unsigned      actual_length;               //此次传输的实际长度  

8.   int         status;                      //执行的结果,成功被置0,否则是一个负的错误码  

9.   struct list_head   queue;  

10.  void          *state;  


};  


1.   struct spi_transfer {  

2.   const void *tx_buf;  //要写入设备的数据(必须是dma_safe),或者为NULL  

3.   void       *rx_buf;  //要读取的数据缓冲(必须是dma_safe),或者为NULL  

4.   unsigned   len;      //tx和rx的大小(字节数),这里不是指它的和,而是各自的长度,他们总是相等的  

5.   dma_addr_t    tx_dma;   //如果spi_message.is_dma_mapped是真,这个是tx的dma地址  

6.   dma_addr_t rx_dma;   //如果spi_message.is_dma_mapped是真,这个是rx的dma地址  

7.   unsigned   cs_change:1;    //影响此次传输之后的片选,指示本次tranfer结束之后是否要重新片选并调用setup改变设置,这个标志可以较少系统开销u8      

8.   bits_per_word;  //每个字长的比特数,如果是0,使用默认值  

9.   u16        delay_usecs;    //此次传输结束和片选改变之间的延时,之后就会启动另一个传输或者结束整个消息  

10.  u32       speed_hz;       //通信时钟。如果是0,使用默认值  

11.  struct list_head transfer_list; //用来连接的双向链表节点  

12.  };  


SPI的数据是封装到spi_transfer这个数据结构中,然后这个数据结构再封装到spi_message,,最后这个消息再挂接到spi_bitbang里面的内核提供的队列struct list_head queue上。这样,就可以实现严格的串行数据通信,保证数据的正确。

SPI通信的数据流大致是:
    1、用户请求=>Protocoldriver分析请求,生成SPI通信帧=>Controllerdriver将通信帧发送到SPI总线上;
    2、SPI设备传回数据=>Controllerdriver从SPI总线上读回=>Protocol解析通信数据并上报;

其中Protocol和Controller之间的交互中,SPI帧是一个比较关键的数据结构。Protocol通过分析上层请求生成这种帧,并且解析这种帧得到SPI设备的响应的结果。Controller通过和SPI总线交互,收发这样的帧。在Linux内核中,这个帧通过一个叫做spi_message的结构来实现。

    在有数据请求时,Protocol解析请求生成这个帧,并发送到SPI核心子系统。SPI核心子系统通过Protocol设备的信息,找到对应的Controller设备,并将这个帧发送给Controller。Controller接受到这个帧后发送到SPI总线上。返程类似。

由浅入深,不能盲目急躁。

  评论这张
 
阅读(1063)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017