i2c设备:ts、camera、audio、gsensor、e2prom

I2C基本协议:

写:开始 -> 设备地址 -> 写标志 -> 应答 -> 内部地址 -> 应答 -> 数据 -> 应答 -> 停止

读:开始 -> 设备地址 -> 写标志 -> 应答 -> 内部地址 -> 应答 -> 停止 -> 开始 -> 设备地址 -> 读标志 -> 应答 -> 数据 -> 应答 -> 停止

开始信号:在SCL为高电平期间,SDA从高电平变为低电平

结束信号:在SCL为高电平期间,SDA从低电平变为高电平

应答信号:主设备发送完一个字节,释放SDA,SDA被从设备拉低为ACK,没有被拉低为NACK。

I2C传输数据时,SCL为高电平时采集SDA信号(有效),SCL为低电平时SDA可变化(无效)。

i2c驱动框架:

应用层

----------------------------------------------------------------------------

i2c driver 层:需要程序员实现

1、与用户进行交互--->fops

2、知道数据是什么,但是不知道如何传输个硬件

----------------------------------------------------------------------------

i2c core 层:

维护i2c总线,负责进行匹配

代码位置:drivers/i2c/i2c-core.c

----------------------------------------------------------------------------

i2c adapter 层:

1、与硬件进行交互

2、直到如何将数据传输给硬件,但不知道数据是什么

代码位置:drivers/i2c/i2c-xxx.c

----------------------------------------------------------------------------

i2c_adapter 结构体

struct i2c_adapter {
  struct module *owner;  // 所属的模块

  const struct i2c_algorithm *algo;  // 总线通信方法结构体指针

  void *algo_data;  // algorithm数据

  int retries;  // 重试次数

  struct device dev;   // 适配器设备

  char name[48];  // 适配器名称

  ... ...
};

i2c_algorithm 结构体

struct i2c_algorithm {
  int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);  // i2c传输函数指针
  int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write,  // smbus 传输函数指针
    u8 command, int size, union i2c_smbus_data *data);

  u32 (*functionality) (struct i2c_adapter *);  // 返回适配器支持的功能
};

i2c_driver 结构体

struct i2c_driver {
  unsigned int class;

  int (*probe)(struct i2c_client *, const struct i2c_device_id *);
  int (*remove)(struct i2c_client *);

  struct device_driver driver;  // 设备驱动结构体
  const struct i2c_device_id *id_table;

  ... ...
};

i2c_client 结构体

struct i2c_client {
  unsigned short flags;  // 标志
  unsigned short addr;   // 低7位芯片地址
  char name[I2C_NAME_SIZE];  // 设备名称
  struct i2c_adapter *adapter;   // 依附的 i2c_adapter 
  struct i2c_driver *driver;   // 依附的 i2c_driver 
  struct device dev;   // 设备结构体
  int irq;   // 设备中断
  struct list_head detected;  // 链表头
};

i2c_msg 结构体

struct i2c_msg {
  __u16 addr;   // 从设备地址
  __u16 flags;  // 读写标志
  __u16 len;   // 消息包长度
  __u8 *buf;   // 消息包数据
};

i2c adapter 层中使用的是平台设备总线,每个i2c控制器有一个 platform_device,但只有一个 platform_driver,匹配成功后会执行 xxx_probe,每个platform_device 都会生成一个i2c适配器(struct i2c_adapter),i2c adapter 层会生成 i2c_client,并将 i2c_adapter 包含在 i2c_client;

在 i2c driver 层,i2c_client 和 i2c_driver 在 i2c 总线上匹配成功后,会执行 i2c driver 层的 probe 函数,此时 i2c driver 层会获取到 i2c_client 信息,读写通过 i2c_client ---> adapter ---> algo ---> master_xfer 就可以完成与从设备通信。

以下代码为S5PV210读写AT24C02:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/i2c.h>
#include <linux/slab.h> #include <asm/ioctl.h>
#include <asm/uaccess.h>
#include <asm/io.h> struct e2prom_private {
int size;
int version;
}; struct global_e2prom {
struct i2c_client *client;
struct e2prom_private *private;
}; struct global_e2prom *e2prom_dev; //i2c_master_send(const struct i2c_client * client,const char * buf,int count)
//i2c_master_recv(const struct i2c_client * client,char * buf,int count)
int at24_i2c_send(struct i2c_client *client, char *buf, int count)
{
int ret; struct i2c_adapter *adapter = client->adapter;
struct i2c_msg msg; msg.addr = client->addr;
msg.flags = ;
msg.len = count;
msg.buf = buf; ret = i2c_transfer(adapter, &msg, ); return (ret == ) ? count : ret;
} int at24_i2c_recv(struct i2c_client *client, char *buf, int count)
{
int ret; struct i2c_adapter *adapter = client->adapter;
struct i2c_msg msg; msg.addr = client->addr;
msg.flags = I2C_M_RD;
msg.len = count;
msg.buf = buf; ret = i2c_transfer(adapter, &msg, ); return (ret == ) ? count : ret;
} int at24_drv_open(struct inode *inode, struct file *filp)
{
printk("-----%s-----\n", __func__); return ;
} int at24_drv_close(struct inode *inode, struct file *filp)
{
printk("-----%s-----\n", __func__); return ;
} ssize_t at24_drv_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
int ret; printk("-----%s-----\n", __func__); if ((size < ) || (size > e2prom_dev->private->size))
{
printk("read size error\n");
return -EINVAL;
} char *tmp = kzalloc(size, GFP_KERNEL);
if (tmp == NULL)
{
printk("kzalloc fail\n");
return -ENOMEM;
} ret = at24_i2c_recv(e2prom_dev->client, tmp, size);
if (ret < )
{
printk("at24_i2c_recv error\n");
ret = -EIO;
goto err_free;
} ret = copy_to_user(buf, tmp, size);
if (ret > )
{
printk("copy_to_user error\n");
ret = -EFAULT;
goto err_free;
} kfree(tmp); return size; err_free:
kfree(tmp); return ret;
} ssize_t at24_drv_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
int ret; printk("-----%s-----\n", __func__); if ((size < ) || (size > e2prom_dev->private->size))
{
printk("write size error\n");
return -EINVAL;
} char *tmp = kzalloc(size, GFP_KERNEL);
if (tmp == NULL)
{
printk("kzalloc fail\n");
return -ENOMEM;
} ret = copy_from_user(tmp, buf, size);
if (ret > )
{
printk("copy_from_user error\n");
ret = -EINVAL;
goto err_free;
} ret = at24_i2c_send(e2prom_dev->client, tmp, size);
if (ret < )
{
printk("at24_i2c_send error\n");
ret = -EIO;
goto err_free;
} kfree(tmp); return size; err_free:
kfree(tmp); return ret;
} const struct file_operations at24_fops = {
.open = at24_drv_open,
.release = at24_drv_close,
.read = at24_drv_read,
.write = at24_drv_write,
}; struct miscdevice at24_miscdev = {
.minor = MISC_DYNAMIC_MINOR,  //自动分配次设备号
.name = "e2prom_dev",  //用于生成设备节点
.fops = &at24_fops,
}; int i2c_at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
int ret; e2prom_dev = kzalloc(sizeof(struct global_e2prom), GFP_KERNEL);
if (e2prom_dev == NULL)
{
printk("kzalloc fail\n");
return -ENOMEM;
} e2prom_dev->client = client;
e2prom_dev->private = (struct e2prom_private *)id->driver_data;
misc_register(&at24_miscdev); return ;
} int i2c_at24_remove(struct i2c_client *client)
{
misc_deregister(&at24_miscdev);
kfree(e2prom_dev); return ;
} struct e2prom_private at24c02_private = {
.size = ,
.version = 0x01,
}; const struct i2c_device_id at24_id_table[] = {
{"at24c02", (kernel_ulong_t)&at24c02_private},
}; struct i2c_driver at24_drv = {
.probe = i2c_at24_probe,
.remove = i2c_at24_remove,
.driver = {
.name = "at24_drv",
},
.id_table = &at24_id_table,  //name用于匹配
}; static int __init i2c_at24_drv_init(void)
{
return i2c_add_driver(&at24_drv);
} static void __exit i2c_at24_drv_exit(void)
{
i2c_del_driver(&at24_drv);
} module_init(i2c_at24_drv_init);
module_exit(i2c_at24_drv_exit); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Aaron Lee");

Linux I2C设备驱动的更多相关文章

  1. Linux I2C设备驱动编写(二)

    在(一)中简述了Linux I2C子系统的三个主要成员i2c_adapter.i2c_driver.i2c_client.三者的关系也在上一节进行了描述.应该已经算是对Linux I2C子系统有了初步 ...

  2. Linux I2C设备驱动编写(一)

    在Linux驱动中I2C系统中主要包含以下几个成员: I2C adapter 即I2C适配器 I2C driver 某个I2C设备的设备驱动,可以以driver理解. I2C client 某个I2C ...

  3. 【转】Linux I2C设备驱动编写(二)

    原文网址:http://www.cnblogs.com/biglucky/p/4059582.html 在(一)中简述了Linux I2C子系统的三个主要成员i2c_adapter.i2c_drive ...

  4. 【转】Linux I2C设备驱动编写(一)

    原文网址:http://www.cnblogs.com/biglucky/p/4059576.html 在Linux驱动中I2C系统中主要包含以下几个成员: I2C adapter 即I2C适配器 I ...

  5. Linux I2C设备驱动编写(一)【转】

    本文转载自:http://blog.csdn.net/airk000/article/details/21345457 在Linux驱动中I2C系统中主要包含以下几个成员: I2C adapter 即 ...

  6. Linux I2C设备驱动编写(三)-实例分析AM3359

    TI-AM3359 I2C适配器实例分析 I2C Spec简述 特性: 兼容飞利浦I2C 2.1版本规格 支持标准模式(100K bits/s)和快速模式(400K bits/s) 多路接收.发送模式 ...

  7. 【转】Linux I2C设备驱动编写(三)-实例分析AM3359

    原文网址:http://www.cnblogs.com/biglucky/p/4059586.html TI-AM3359 I2C适配器实例分析 I2C Spec简述 特性: 兼容飞利浦I2C 2.1 ...

  8. i2c设备驱动注册

      Linux I2C设备驱动编写(二) 原创 2014年03月16日 23:26:50   在(一)中简述了Linux I2C子系统的三个主要成员i2c_adapter.i2c_driver.i2c ...

  9. Linux i2c子系统(一) _动手写一个i2c设备驱动

    i2c总线是一种十分常见的板级总线,本文以linux3.14.0为参考, 讨论Linux中的i2c驱动模型并利用这个模型写一个mpu6050的驱动, 最后在应用层将mpu6050中的原始数据读取出来 ...

随机推荐

  1. MapReduce数据筛选

    需求: 编写MapReduce程序算出高峰时间段(如9-10点)哪张表被访问的最频繁的表,以及这段时间访问这张表最多的用户,以及这个用户访问这张表的总时间开销. 测试数据: TableName(表名) ...

  2. Jquery.LazyLoad.js实现图片延迟加载功能

    从网上下载来的版本多多少少都有些BUG,尤其是加载后在IE6和IE7下图片闪动是个大问题,在网上查了很久,也没有找到相关的解决方案.没解决方案,就得发挥咱DIY的精神,自己想法解决,分析了BUG,理了 ...

  3. c语言字符处理函数常见使用集合

    1.最近看一些开源项目代码时,总会看到 c 语言中一些  "str" 开头的处理字符串的用法,有的之前没用到过,特此记录,随时看到随时添加. 这里不提出源码,只是一些使用说明加例子 ...

  4. CentOS 5 上使用yum同时安装32位和64位包的解决方法

    在centos上使用yum在线安装软件包的时候,有时候会同时安装32位和64位的包.并且在update的时候也会更新双份. 其实让yum只安装64位的包,只要在 /etc/yum.conf 中加个 e ...

  5. Boot 横向布局

    <div class="form-group"> <label for="name" class="col-lg-2 control ...

  6. NumPy使用 Matplotlib 绘制直方图

    NumPy - 使用 Matplotlib 绘制直方图 NumPy 有一个numpy.histogram()函数,它是数据的频率分布的图形表示. 水平尺寸相等的矩形对应于类间隔,称为bin,变量hei ...

  7. chrome关闭后还在进程中运行

    1.网上搜到信息: 设置 “即使关闭浏览器也后台运行” 取消打勾 2.然后我找了一下,应该是这个选项:“关闭 Google Chrome 后继续运行后台应用” 3. 4. 5.

  8. web项目在iis配置好后不能正确访问问题集锦,以及IIS常规设置

    6.IIS配置好,项目无法访问,注意项目对应的应用程序池的net版本是否正确,是否集成(一般都是集成,很少是经典) 本项目用的4.0,可IIS默认程序池为2.0,将2.0改为4.0就行.   7.HT ...

  9. shiro源码解析--------欢迎指出错误地方,还有一起讨论一下ShiroFilterFactoryBean配置过滤URL规则

    啦啦啦啦 啦啦啦啦啦 啦啦啦啦啦 啦啦啦啦啦 啦啦啦啦啦 啦啦啦啦啦 啦啦啦啦啦 啦啦啦啦啦 啦啦啦啦啦 啦啦啦啦啦 啦啦啦啦啦 啦啦啦啦啦 啦啦啦啦啦 啦啦啦啦啦 啦啦啦啦啦 啦啦啦啦啦 啦啦啦啦啦 ...

  10. 【Python】函数对象

    转:作者:Vamei 出处:http://www.cnblogs.com/vamei 函数也是一个对象,具有属性(可以使用dir()查询).作为对象,它还可以赋值给其它对象名,或者作为参数传递. la ...