linux设备驱动(3)I2C驱动

i2c驱动程序的核心是创建i2c_driver结构体

/* This is the driver that will be inserted */
static struct i2c_driver at24cxx_driver = {
    .driver = {
        .name    = "at24cxx",
    },
    .id        = I2C_DRIVERID_AT24Cxx,
    .attach_adapter    = at24cxx_attach_adapter,
    .detach_client    = at24cxx_detach_client,
};

再at24cxx_attach_adapter里面

static int at24cxx_attach_adapter(struct i2c_adapter *adapter)
{
    return i2c_probe(adapter, &addr_data, at24cxx_detect);
}

当probe到设备后, at24cxx_detect会被调用

这里有两个需要完成的

(1) 配置addr_data

(2)at24cxx_detect

对于addr_data

/*
 * Generic i2c probe
 * concerning the addresses: i2c wants 7 bit (without the r/w bit), so ‘>>1‘
 */
static unsigned short normal_i2c[] = {
    0x50,                         /* 7位地址 */
    I2C_CLIENT_END,
};

static unsigned short ignore = I2C_CLIENT_END;

static struct i2c_client_address_data addr_data = {
    .normal_i2c        = normal_i2c,
    .probe            = &ignore,
    .ignore            = &ignore,
};

而在 at24cxx_detect中主要有

(1) 设置一个i2c_client 结构体变量

(2) 设置它

(3) 注册

首先创建全局i2c_client变量

static struct i2c_client *at24cxx_client;
static int at24cxx_detect(struct i2c_adapter *adapter, int address, int kind)
{
    printk(KERN_INFO "at24cxx_detect \n");
    int err = 0;

    /* 分配  */
    at24cxx_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);

    /* 设置 */
    at24cxx_client->addr = address;
    at24cxx_client->adapter = adapter;
    at24cxx_client->driver = &at24cxx_driver;
    at24cxx_client->flags = 0;

    /* Fill in the remaining client fields */
    strlcpy(at24cxx_client->name, "at24cxx", I2C_NAME_SIZE);

    /* Tell the I2C layer a new client has arrived */
    if ((err = i2c_attach_client(at24cxx_client)))
        goto exit_kfree;

exit_kfree:
    kfree(at24cxx_client);

    return err;
}

i2c设置好了, 数据传输使用i2c_transfer

int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)

因此, 数据传送是需要构造设置msg

与用户程序交互的读:

static int at24cxx_read (struct file *file, char __user *usrbuf, size_t len, loff_t *offset)
{
    /*
    * buf[0]   addr
    * buf[1]   data
    */
    int ret;
    unsigned char address;
    unsigned char data;

    struct i2c_msg msg[2];

    if(len != 2)
        return -EFAULT;

    if(copy_from_user(&address, usrbuf, 1))
        res = -EFAULT;

    /* i2c 传输 */
    /* 先发送地址 */
    msg[0].addr = at24cxx_client->addr;   // dest
    msg[0].buf = &address;                // src
    msg[0].flags = 0;                     // write
    msg[0].len = 1;                       // len

    /* 再读 */
    msg[1].addr = at24cxx_client->addr;   // dest
    msg[2].buf = &data;                   // src
    msg[1].flags = I2C_M_RD;                     // read
    msg[1].len = 1;                       // len

    ret = i2c_transfer(at24cxx_client->adapter, msg, 2);
    if(ret == 2)
    {
        if(copy_to_user(&usrbuf, &data, 1))
            res = -EFAULT;
        return 1;
    }
    else
        return -EIO;

    return 0;
}

写:

static int at24cxx_write (struct file *file, const char __user *usrbuf, size_t len, loff_t *offset)
{
    /*
    * buf[0]   addr
    * buf[1]   data
    */
    int ret;
    unsigned char buf[2];
    struct i2c_msg msg[1];

    if(len != 2)
        return -EFAULT;

    if(copy_from_user(buf, usrbuf, 2))
        res = -EFAULT;

    /* i2c 传输 */
    msg[0].addr = at24cxx_client->addr;   // dest
    msg[0].buf = buf;                     // src
    msg[0].flags = 0;                     // write
    msg[0].len = 2;                       // len
    ret = i2c_transfer(at24cxx_client->adapter, msg, 1);
    if(ret == 1)
        return 2;
    else
        return -EIO;
}

原文地址:https://www.cnblogs.com/hulig7/p/9901760.html

时间: 2024-10-19 10:53:58

linux设备驱动(3)I2C驱动的相关文章

乾坤合一~Linux设备驱动之I2C核心、总线以及设备驱动

我思念的城市已是黄昏 为何我总对你一往情深 曾经给我快乐 也给我创伤 曾经给我希望 也给我绝望 我在遥远的城市 陌生的人群 感觉着你遥远的忧伤 我的幻想 你的忧伤,像我的的绝望,那样漫长,,,,,这是今天的旋律,直入心底~~~~~~~~~~~~~~~~ 在Linux 系统中,I2C 驱动由3 部分组成,即I2C 核心.I2C 总线驱动和I2C 设备驱动,I2C 总线仅仅使用SCL.SDA 这两根信号线就实现了设备之间的数据交互,极大地简化了对硬件资源和PCB 板布线空间的占用 1 Linux的I

linux驱动之i2c子系统mpu6050设备驱动

以下是mpu6050简单的驱动实现,mpu6050是I2C接口的6轴传感器,可以作为字符设备注册到内核,本代码运行环境是3.4.2内核,4.3.2版本的编译链,12.04版本的Ubuntu,硬件环境是jz2440开发板: 按照之前分析的I2C驱动框架,mpu6050驱动主要是实现外设端的驱动,主要是注册外设到I2C总线,而外设端注册到I2C总线包括device及driver两个部分注册到I2C总线,采用分离的设计思想,详情见代码: device注册到I2C总线: #include <linux/

linux驱动之I2C

include/linux/i2c.h struct i2c_msg;struct i2c_algorithm;struct i2c_adapter;struct i2c_client;struct i2c_driver;union i2c_smbus_data; I2C驱动主要包含三部分:I2C核心.I2C总线驱动.I2C设备驱动,它们主要的数据结构在目录:/include/linux/i2c.h struct i2c_driver 1 /* 2 * A driver is capable o

linux驱动之i2c学习

最近在研究linux的i2c驱动,从最底层i2c控制器初始化到应用层与i2c设备交互基本打通了. 一.linux的i2c架构可以用下图表示: IIC适配器对应一条i2c总线,linux里面用i2c_adapter结构表示.总线下的i2c设备用i2c_client结构表示.algorithm是i2c的通信协议,IIC核心层负责注册/注销i2c_adapter.注册/注销i2c_client.注册i2c总线等操作.i2c-dev对应的是i2c-dev.c,它负责将总线实例化为一个i2c_client

《Linux设备驱动开发详解(第3版)》海量更新总结

本博实时更新<Linux设备驱动开发详解(第3版)>的最新进展. 2015.2.26 几乎完成初稿. [F]是修正或升级:[N]是新增知识点:[D]是删除的内容 第1章 <Linux设备驱动概述及开发环境构建>[D]删除关于LDD6410开发板的介绍[F]更新新的Ubuntu虚拟机[N]添加关于QEMU模拟vexpress板的描述 第2章 <驱动设计的硬件基础> [N]增加关于SoC的介绍:[N]增加关于eFuse的内容:[D]删除ISA总线的内容了:[N]增加关于SP

Linux I2C驱动编写要点

继续上一篇博文没讲完的内容“针对 RepStart 型i2c设备的驱动模型”,其中涉及的内容有:i2c_client 的注册.i2c_driver 的注册.驱动程序的编写. 一.i2c 设备的注册分析:在新版本内核的i2c驱动模型中,支持多种方式来注册 i2c 设备,在Documentation/i2c/instantiating-devices文件中有讲到,在内核中对应的抽象数据结构就是 struct i2c_client. (1)Declare the I2C devices by bus

Linux设备驱动开发基础

1.驱动概述和开发环境搭建 1.1驱动设备的作用 对设备驱动最通俗的解释就是"驱动硬件设备行动".驱动与底层硬件直接打交道,按照硬件设备的具体工作方式,读写设备的寄存器,完成设备的轮训.中断处理.DMA通信,进行物理内存向虚拟内存的映射等,最终让通信设备能收发数据,让显示设备能显示文字和画面,让存储设备能记录文件和数据. 由此可见,设备驱动充当了硬件和应用软件之间的纽带,他使得应用软件只需要调用系统软件的应用编程接口(API)就可让硬件去完成要求的工作.在系统中没有操作系统的情况下,工

《Linux设备驱动开发具体解释(第3版)》进展同步更新

本博实时更新<Linux设备驱动开发具体解释(第3版)>的最新进展. 2015.2.26 差点儿完毕初稿. 本书已经rebase到开发中的Linux 4.0内核,案例多数基于多核CORTEX-A9平台. [F]是修正或升级:[N]是新增知识点:[D]是删除的内容 第1章 <Linux设备驱动概述及开发环境构建>[D]删除关于LDD6410开发板的介绍[F]更新新的Ubuntu虚拟机[N]加入关于QEMU模拟vexpress板的描写叙述 第2章 <驱动设计的硬件基础> [

linux设备驱动第一篇:基础知识点

首先,我们知道驱动是内核的一部分,那么驱动在内核中到底扮演了什么角色呢? 设备驱动程序在内核中的角色:他们是一个个独立的"黑盒子",使某个特定的硬件响应一个定义良好的内部编程接口,这些接口完全隐藏了设备的工作细节.(说白了,驱动程序除了对外提供特定的接口外,任何实现细节对应用程序都是不可见的.)用户的操作通过一组标准化的调用执行,而这些调用独立于特定的驱动程序.驱动程序的任务是把这些标准化调用映射到实际硬件的设备特有操作上. 在编写驱动程序时,程序员应该特别注意下面这个概念:编写访问硬

【转】Linux设备驱动之sysfs

Sysfs文件系统是一个类似于proc文件系统的特殊文件系统,用于将系统中的设备组织成层次结构,并向用户模式程序提供详细的内核数据结构信息. 去/sys看一看,localhost:/sys#ls /sys/block/ bus/ class/ devices/ firmware/ kernel/ module/ power/Block目录:包含所有的块设备Devices目录:包含系统所有的设备,并根据设备挂接的总线类型组织成层次结构Bus目录:包含系统中所有的总线类型Drivers目录:包括内核