linux设备驱动之 i2c设备驱动 at24c08驱动程序分析

本文详细分析了Linux内核2.6.22版本中i2c设备驱动的工作原理,从驱动入口函数`eeprom_init`开始,探讨了i2c设备的探测过程,特别是`i2c_probe`函数和`attach_adapter`的使用。接着,通过一个具体的例子讲解了如何编写AT24C08的I2C驱动,包括驱动结构体的定义、探测函数`gq_at24cxx_detect`的实现以及读写操作的接口设计。最后,给出了测试代码,展示了驱动的读写功能。
摘要由CSDN通过智能技术生成

linux-2.6.22源码分析\linux-2.6.22\drivers\i2c\chips\eeprom.c为例,分析i2c设备驱动程序的原理

1.从驱动的入口函数开始分析
  eeprom_init
    >i2c_add_driver(&eeprom_driver)
      >i2c_register_driver(THIS_MODULE, driver)
        >is_newstyle_driver(driver) //这是一处宏定义:#define is_newstyle_driver(d) ((d)->probe || (d)->remove)
        /*用于判断是否是新风格的驱动,新风格的驱动i2c_driver成员的probe与remove函数指针都为空*/
        接下来填充i2c_driver的owner与bus成员
        >driver_register(&driver->driver)
          >bus_add_driver(&driver->driver)也就是(struct device_driver * drv)//添加成功返回0
        >list_add_tail(&driver->list,&drivers)//把该i2c_driver添加到链表drivers全局变量中
        >list_for_each_entry(adapter, &adapters, list) //遍历adapters适配器链表的所有成员
         {driver->attach_adapter(adapter);}        //调用i2c_driver->attach_adapter
   
    在eeprom.c中定义了一个全局变量:
  static struct i2c_driver eeprom_driver = {
   .driver = {
    .name = "eeprom",
   },
   .id  = I2C_DRIVERID_EEPROM,
   .attach_adapter = eeprom_attach_adapter,
   .detach_client = eeprom_detach_client,
  };
  

2.i2c设备的探测过程分析
   在1中遍历调用了适配器链表中的每一个成员的attach_adapter成员函数,来完成i2c设备的探测
   driver->attach_adapter(adapter)
   等效于
   eeprom_attach_adapter
     >i2c_probe(adapter, &addr_data, eeprom_detect)
     //当探测到i2c设备后会调用第三个参数所指的函数:也就是函数eeprom_detect。
     /*在i2c.h头文件中定义了addr_data全局变量
   *static struct i2c_client_address_data addr_data = {   \
    * .normal_i2c = normal_i2c,     \
    * .probe  = probe,     \
    * .ignore  = ignore,     \
    * .forces  = forces,     \
    *}

      */
      函数原型为:
      i2c_probe(struct i2c_adapter *adapter,
       struct i2c_client_address_data *address_data,
       int (*found_proc) (struct i2c_adapter *, int, int))
        >判断是否强制识别 if(address_data->forces),如果设置了i2c_client_address_data的
        成员.forces则强制识别,采取相应的措施。
        >i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)//检查是否支持SMBUS_QUICK方式
        >for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2){
         判断if(address_data->probe[i] || address_data->probe[i] == ANY_I2C_BUS)成立则:
           >i2c_probe_address(adapter,address_data->probe[i + 1],-1, found_proc);
             >i2c_check_addr(adapter, addr)
               >__i2c_check_addr(adapter, addr)//检查地址是否可用
             >i2c_smbus_xfer(adapter, addr, 0, 0, 0,I2C_SMBUS_QUICK, NULL)
             >如果定义了adapter->algo->smbus_xfer则调用:
             adapter->algo->smbus_xfer(adapter,addr,flags,read_write,command,size,data)
            
                >found_proc(adapter, addr, kind)//也就是调用i2c_probe函数的第三个参数
                 (该参数为一个函数)
               
             >否则调用:
             i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,command,size,da

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值