Chinaunix首页 | 论坛 | 博客
  • 博客访问: 237468
  • 博文数量: 54
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 431
  • 用 户 组: 普通用户
  • 注册时间: 2014-07-26 09:36
文章分类

全部博文(54)

分类: LINUX

2014-09-14 12:27:02

目录:

1 通讯协议概述
    1.1 总线特点

    1.2 总线结构
    1.3 总线协议
2 时序关系
3 寄存器操作流程
4  I2C设备驱动框架
  4.1  I2C设备层 
    4.1.2 I2C设备
    4.1.2 I2C设备驱动
    4.1.3 I2C设备和驱动的关系
  4.2 I2C总线层 
                                                                                                                                
     4.2.1 总线适配器
    
     4.2.2 适配器驱动
  4.3 设备层与驱动层关系
5 I2C设备驱动的书写
  5.1
I2C设备驱动书写流程
 
 



正文:

1 通讯协议概述

    I2C是Philips公司开发的,支持一个主机(master)连多个从机(Slave),且主从可切换的两线式串行总线通讯协议。
    设备连接到总线的方式: 开漏(OC门)或集电级开路的“线与”逻辑,空闲时由上拉电阻维持sda,scl的高电平状态。                                            
                                                                                                                                                      
1.1 总线特点
                                                                                                                                         
    (1).每一个连接到总线上的设备都可以通过唯一的设备地址进行访问.                                                                                      
    (2).串行的8位双向数据传输,位速率在标准模式下可达100kb/s,在快速模式下可达400kb/s;高速模式下可以达到3.4M每秒.
    (3).总线长度最长7.6米左右.
    (4).片上滤波器可以增加抗干扰能力,保证数据完成传输.                                                                                                
    (5).连接到一条I2C总线上的设备数量只受到最大电容400pf的限制.                                                                                        
    (6).多主机系统,通过冲突检测和延时等待来保护数据不被破坏.

1.2 总线结构:   
                                                                                                                                          
                                                                          
      

1.3 总线协议





2 时序关系

(1) 空闲状态:SCL时钟线,SDA数据线 均为高电平                                                                                                                
(2) 开始判断:SCL保持高电平时,SDA从高电平向低电平切换    ---主设备产生
(3) 结束判断:SCL保持高电平时,SDA从低电平向高电平切换    ---主设备产生
(4) 数据变化:SDA必须在SCL的高电平周期保持稳定,在SCL的低电平周期才可改变电平.发送的数据位的顺序,是从高位开始(MSB),还是从低
                      位开始(LSB).                                                                                                                                               
(5) 应答机制:在ACK应答确认周期时, 主机释放SDA,从机把SDA拉低,并在SCLK高电平时保持住. 如果从机来不及处理,可以一直拉低SDA,使
                      得主机等待.                                                                                                                                               
(6) 总线仲裁(争抢):当多个I2C设备同时拉低SDA,争抢主机所有权时。可通过后续它们发送的Slave address 做为判断.
                              第一次发送地址位为低电平的设备获得主机所有权.                                               
 

3 寄存器操作流程:

    (1) Master发送I2C addr(7bit)和rw操作1(1bit),等待ACK                                                                                            
    (2) Slave发送ACK                                                                                                                                    
    (3) Master发送reg addr(8bit),等待ACK                                                                                                             
    (4) Slave发送ACK                                                                                                                                            
    (5) Master发起START                                                                                                                                 
    (6) Master发送I2C addr(7bit)和r操作1(1bit),等待ACK                                                                                             
    (7) Slave发送ACK                                                                                                                                    
    (8) Slave发送data(8bit),即寄存器里的值                                                                                                           
    (9) Master发送ACK                                                                                                                                           
    (10) 第8步和第9步可以重复多次,即顺序读多个寄存器  

4  I2C设备驱动框架:                                                                                                                              

    I2C设备驱动可以分为:    设备层,总线层。                                                                                                                
    I2C设备驱动程序相关数据结构:i2c_driver(设备层),i2c_client(设备层),i2c_algorithm(总线层),i2c_adapter(总线层).                              
    注意:一个系统中可以有多个总线层,也就是包含多个总线控制器,也可以由多个设备层,包含不同的i2c设备.
                                                                                                               
4.1  I2C设备层:
    I2C设备层由I2C设备和驱动程序组成。   

4.1.1 I2C设备:                                                                                                                                  
    一个I2C设备由一个i2c_client数据结构进行描述。                                                                                                     

点击(此处)折叠或打开

  1. --/include/linux/i2c.h
  2.                                                                                                                                                        
  3. struct i2c_client {
  4.         unsigned short flags;      /* 标志位:I2C_CLIENT_TEN 表示设备使用10位芯片地址
                                                                     I2C_CLIENT_PEC 表示设备使用SMBus Packet Error Checking */
  5.         unsigned short addr;     /* 设备地址,低7位存储芯片地址 */
  6.                                                                                                                                                        
  7.         char name[I2C_NAME_SIZE];     /* 设备名称 */
  8.         struct i2c_adapter *adapter;    /* 依附的适配器,适配器指明所属总线 */
  9.         struct i2c_driver *driver;         /* 设备驱动程序指针 */
  10.         struct device dev;                      /* 设备结构体 */
  11.         int irq;                                         /* 设备申请的中断号 */
  12.         struct list_head detected;         /* 已被发现的设备链表 */
  13. }
    设备地址:                                                                                                                                                                      
       7---------------------------------------------------------------------------0                                                                                              
       |  R/W'(1 bit)  |  器件类型(4 bit)  |  自定义地址(3 bit) |                                                                                        
        ----------------------------------------------------------------------------                                                                                         
 (1) 由于rw的不同,所以i2c设备存在读地址、写地址两个地址。                                                                                              
 (2) 器件类型已经由器件厂商固化,自定义地址通常由引脚电平来确定,因此同一i2c总线上相同类型的设备最多挂8个。                                         
 (3) 如果在两条不同的i2c总线上挂接来两块类型和地址相同的芯片,那么这两块芯片的地址是相同的,这显然时冲突的,解决办法是为总线适配器指定一个id,那么新的芯片地址就是总线适配器的id和设备地址两部分组成。 

4.1.2 I2C设备驱动:
    I2C设备驱动使用i2c_driver进行描述。

点击(此处)折叠或打开

  1. --/include/linux/i2c.h

  2. struct i2c_driver {
  3.                                                                                                                                                        
  4.         unsigned int class;                                             /* 驱动类型 */
  5.                                                                                                                                                        
  6.         int (*attach_adapter)(struct i2c_adapter *); /* 检测到适配器时调用的函数 */
  7.         int (*detach_adapter)(struct i2c_adapter *); /* 卸载适配器时调用的函数 */
  8.                                                                                                                                                        
  9.         int (*probe)(struct i2c_client *, const struct i2c_device_id *); /* 设备动态探测函数 */
  10.         int (*remove)(struct i2c_client *);                                                 /* 设备动态移除函数 */
  11.                                                                                                                                                        
  12.         void (*shutdown)(struct i2c_client *);                                 /* 设备关闭 */
  13.         int (*suspend)(struct i2c_client *, pm_message_t mesg); /* 设备挂起 */
  14.         int (*resume)(struct i2c_client *);                                        /* 设备唤醒 */
  15.                                                                                                                                                        
  16.         void (*alert)(struct i2c_client *, unsigned int data);
  17.                                                                                                                                                        
  18.         int (*command)(struct i2c_client *client, unsigned int cmd, void *arg); /* 设备命令控制,类似ioctl */
  19.                                                                                                                                                        
  20.         struct device_driver driver;                /* 设备驱动 */
  21.         const struct i2c_device_id *id_table; /* 设备id表 */
  22.                                                                                                                                                        
  23.         int (*detect)(struct i2c_client *, struct i2c_board_info *);     /* 自动探测设备的回调函数,一般不会执行 */
  24.         const unsigned short *address_list;
  25.         struct list_head clients;                     /* 指向驱动支持的设备 */
  26. };
                                                                                                                                                      
说明:                                                                                                                                                 
   若设备不支持probe、remove则需实现attach_* 函数。 两者只选一个,否则出现“i2c-core:driver driver-name is confused”的警告。                                                                                                                                                                              
4.1.3 I2C设备和驱动的关系:                                                                                                     
     通过指针互联。                                                                                                                                    
                                                                                                                                                                               
    I2C client                  I2C client                    I2C client                                                                               
                                                                                                                                           
 
4.2 I2C总线层:                                                                                                                                   
     I2C驱动层由总线适配器和适配器驱动组成。                                                                                                           

4.2.1 总线适配器:                                                                                                                            
                                                                                                                                                       
    I2C总线适配器就是一个I2C总线控制器,在物理上连接若干个II设备。                                                                                     
    I2C总线适配器本质上是一个物理设备,其主要功能是完成I2C总线控制器相关的数据通信。                                                                   
                                                                                                                                                       

点击(此处)折叠或打开

  1. --/include/linux/i2c.h

  2. struct i2c_adapter {
  3.         struct module *owner;                   /* 模块计数 */
  4.         unsigned int id;                                /* alogorithm类型,在i2c_id.h中 */
  5.         unsigned int class;                           /* 允许探测驱动程序的类型 */
  6.         const struct i2c_algorithm *algo; /* 适配器驱动程序指针 */
  7.         void *algo_data;                              /* 适配器的私有数据 */
  8.                                                                                                                                                        
  9.         struct rt_mutex bus_lock;              /* 对总线进行操作时,将获得总线锁 */
  10.                                                                                                                                                        
  11.         int timeout;                                     /* 超时 in jiffies */
  12.         int retries;                                        /* 超时次数 */
  13.         struct device dev;                           /* 适配器 */
  14.                                                                                                                                                        
  15.         int nr;
  16.         char name[48];                                  /* 适配器的名字 */
  17.         struct completion dev_released;     /* 用于同步的完成量,表示适配器是否在被其他程序使用 */
  18.                                                                                                                                                        
  19.         struct list_head userspace_clients; /* 连接到总线上的设备的链表 */
  20. };

4.2.2 适配器驱动:  
                                                                                                                                
                                                                                                                                                      

点击(此处)折叠或打开

  1. --/include/linux/i2c.h

  2. struct i2c_algorithm {
  3.                                                                                                                                                        
  4.         int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, int num); /* 传输函数的指针,指向实现IIC总线通信协议的函数 */
  5.         int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,                                     /* smbus传输函数指针,指向smbus通信协议的函数 */
  6.                            unsigned short flags, char read_write,                                            /* smbus协议基于i2c总线协议,也是由2线制通线 */
  7.                            u8 command, int size, union i2c_smbus_data *data);                     /* smbus和i2c可以通过软件方式兼容,但此处一般为空*/
  8.                                                                                                                                                        
  9.         u32 (*functionality) (struct i2c_adapter *);                                                        /* 返回适配器支持哪些传输类型 */
  10. };

                                                                                                                                               
  
4.3 设备层与驱动层关系:                                                                                                                       
                                                                                                                                               
 

5 I2C设备驱动的书写

    I2C驱动框架在内核中算是比较庞大和复杂的,内核为其建立的分层分工架构使得其移植性和健壮性得到保证。但面对内核如此庞大的代码量,我们首先应该弄清楚哪些工作由内核提供,哪些工作需要针对设备进行书写,即明白自己都该做些什么。

5.1 I2C设备驱动书写流程                                                                                                                      

    在书写I2C驱动之前,应先了解驱动调用过程,以及再i2c子系统的构成。                                                          
    i2c设备驱动流程:                                                                                                                                  
                                                                                                                                                       
                       -------------------                                                                                                                    
                     |    xxx_init     |          i2c设备初始化                                                                                             
                      -------------------                                                                                                                    
                               |                                                                                                                              
                              V                                                                                                                              
                   -------------------------                                                                                                                     
                  |  i2c_add_driver |          i2c子系统中加入驱动                                                                                       
                   ------------------------                                                                                                                  
                               |                                                                                                                              
                              V                                                                                                                              
                -------------------------------                                                                                                                  
               | xxx_attach_adapter  |        适配器和驱动程序挂接                                                                                      
                -------------------------------                                                                                                                   
                               |                                                                                                                              
                              V                                                                                                                            
               --------------------------------                                                                                                                   
              |         i2c_probe         |        i2c设备探测函数                                                                                           
               --------------------------------
                              |                                                                                                                              
                             V                                                                                                                              
              ---------------------------------                                                                                                                   
             |          xxx_detect        |        i2c设备侦测函数                                                                                           
              ---------------------------------                                                                                                                   
                              |                                                                                                                              
                             V                                                                                                                              
             -----------------------------------                                                                                                                  
            |        i2c_client  init      |        i2c设备初始化                                                                                             
             -----------------------------------                                                                                                                  
                              |                                                                                                                              
                             V                                                                                                                              
             ----------------------------------                                                                                                                   
            |     i2c_attach_client    |        将设备添加到i2c子系统                                                                                     
             ----------------------------------                                                                                                                   
                             |                                                                                                                              
                            V                                                                                                                              
            ----------------------------------                                                                                                                   
           |        xxx_init_client     |        初始化i2c设备                                                                                             
            ----------------------------------                                                                                                                   

                                                                                                                



                                                                                                                         

   
                       

阅读(1839) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~