zoukankan      html  css  js  c++  java
  • linux下IIC驱动程序

    IIC总线驱动共3个部分 :IIC核心,IIC总线驱动,IIC设备驱动。
    1> IIC核心:提供总线驱动和设备驱动的注册和注销方法 
    2> IIC总线驱动:是对适配器端的实现 
    3> IIC设备驱动:是对设备端的实现
    框架图:
    IIC总线驱动用于识别IIC设备,提供读写函数,提供如何收发数据,但是不知道数据的具体含义。在内核源代码的drivers/i2c/busses/目录中有很多IIC总线驱动,例如S3C2440,对应i2c-s3c2410.c。
    i2c_add_adapter 作用
    <a> 将adapter放入链表
    <b>调用driver中的attach_adapter函数
    <c>在attach_adapte函数中调用i2c_probe函数
    <d>用adapter的master_xfer函数发信号,确定有没有该设备,如果有,调用i2c_probe中的定义的发现这个设备后要调用的函数。
    i2c设备驱动程序功能(以drivers/i2c/chip/eeprom.c为例)。
    <a>分配构造一个i2c_driver
    static struct i2c_driver eeprom_driver = {
         .driver = {
              .name = "eeprom",
         },  
         .id  = I2C_DRIVERID_EEPROM,  
         .attach_adapter = eeprom_attach_adapter,  
         .detach_client = eeprom_detach_client, 
    };
    <b>使用i2c_add_driver函数将i2c_driver放入链表
    <c>从adapter链表取出适配器调用driver的attach_adapter函数, 在attach_adapter中调用i2c_probe函数,用adapter的master_xfer发信号,确定有没有该设备,如果有,调用i2c_probe中定义的发现这个设备后要调用的函数。
    代码清单如下:
    1.定义变量并设置地址
    static unsigned short ignore[] = {I2C_CLIENT_END};
    static unsigned short normal_addr = {0x50, I2C_CLIENT_END};
    static unsigned short force_addr[] = {ANY_I2C_BUS, 0x60, I2C_CLIENT_END};
    static unsigned short *forces[] = {force_addr, NULL};
     
    static struct i2c_client_address_data addr_data = {
         .normal_i2c = normal_addr,
         .probe = ignore,
         .ignore = ignore,
         //.forces = forces,
    };
    static struct i2c_driver at24cxx_driver;
    static int major;
    static struct class *cls;
    struct i2c_client *at24cxx_client;
    2.入口函数和出口函数
    static int at24cxx_init(void)
    {
        i2c_add_driver(&at24cxx_driver);
        return 0;
    }
     
    static void at24cxx_exit(void)
    {
        i2c_del_driver(&at24cxx_driver);
    }
    3.分配构造i2c_driver结构体
    static struct i2c_driver at24cxx_driver = {
        .driver = {
             .name = "at24cxx",
         },
        .attach_adapter = at24cxx_attach,
        .detach_adapter = at24cxx_detach,
    };
    static int at24cxx_attach(struct i2c_adapter *adapter)
    {
        return i2c_probe(adapter, &addr_data, at24cxx_detect);
    }
    static int at24cxx_detect(struct i2c_adapter *adapter, int address, int kind)
    {
        at24cxx_client = kzmalloc(sizeof(struct i2c_client), GFP_KERNEL);
        at24cxx_client->addr = address;
        at24cxx_client->adapter = adapter;
        at24cxx_client->driver = &at24cxx_driver;
        strcpy(at24cxx_driver->name, "at24cxx");
        i2c_attach_client(at24cxx_client);
        major = register_chrdev(0, "at24cxx", &at24cxx_fops);
        cls = class_create(THIS_MODULE, "at24cxx");
        device_create(cls, NULL, MKDEV(major, 0), NULL, "at24cxx");
        return 0;
    }
    static int at24cxx_detach(struct i2c_client *client)
    {
        device_destroy(cls, MKDEV(major, 0));
        class_destroy(cls);
        unregister_chrdev(major, "at24cxx");
        i2c_detach_client(client);
        kfree(i2c_get_clientdata(client));
    }
    4.构造并初始化file_operations结构体
    static struct file_operations at24cxx_fops = {
        .owner = THIS_MODULE,
        .read = at24cxx_read,
        .write = at24cxx_write,
    };
    static ssize_t at24cxx_read(struct file *file, char __user *buf, size_t size, loff_t *offset)
    {
        unsigned char address;
        unsigned char data;
        struct i2c_msg msg[2];
        int ret;
     
        if (size != 1)
             return -EINVAL;
        copy_from_user(&address, buf, 1);
        msg[0].addr = at24cxx_client->addr;
        msg[0].buf = &address;
        msg[0].len = 1;
        msg[0].flags = 0;
        
        msg[1].addr = at24cxx_client->addr;
        msg[1].buf = &data;
        msg[1].len = 1;
        msg[1].flags = I2C_M_RD;
     
        ret = i2c_transfer(at24cxx_client->adapter, msg, 2);
        if (ret == 2) {
             copy_to_user(buf, &data, 1);
             return 1;
         } else {
             return -EIO;
         }
    }
    static ssize_t at24cxx_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
    {
        unsigned char val[2];
        struct i2c_msg msg[1];
        int ret;
     
        if (size != 2) {
             return -EINVAL;
         }
        copy_from_user(val, buf, 2);
        msg[0].addr = at24cxx_client->addr;
        msg[0].buf = val;
        msg[0].len = 2;
        msg[0].flags = 0;
        
        ret = i2c_transfer(at24cxx_client->adapter, msg, 1);
        if (ret == 1) {
            return 2;
         } else {
             return -EIO;
         }
    }
  • 相关阅读:
    【LayUi】表格中显示图片
    【LayUi】laydate.render报错:日期格式不合法
    【C#】日期格式化(关于12小时制和24小时制)
    【JavaScript】for循环使用splice()方法
    【LayUi】 动态table操作:edit、switch、tool、checkbox
    【LayUi】vue绑定数据随笔
    【LayUi】中国省市复选框
    【LayUi】动态数据表格+分页+CheckBox
    【LayUi】下拉框
    SQL Server自动生成存储过程(Insert,Update)
  • 原文地址:https://www.cnblogs.com/zpehome/p/3822088.html
Copyright © 2011-2022 走看看