Linux I2C核心、总线与设备驱动(一)

本章导读

I2C总线仅仅使用SCLSDA两根信号线就实现了设备之间的数据交互,极大地简化对硬件资源和PCB板布线空间的占用。因此,I2C总线被非常广泛地应用在EEPROM、实时钟、小型LCD等设备与CPU的接口中。

Linux定义了系统的I2C驱动体系结构,在Linux系统中,I2C驱动由3部分组成,即I2C核心、I2C总线驱动和I2C设备驱动。这3部分相互协作,形成了非常通用、可适应性很强的I2C框架。
  
本章第1节将对Linux I2C体系结构进行分析,讲明3个组成部分各自的功能及相互联系。第2节将对Linux I2C核心进行分析,解释i2c-core.c文件的功能和主要函数的实现。第34节将分别详细介绍I2C总线驱动和I2C设备驱动的编写方法,给出可供参考的设计模板。第56节将以第34节给出的设计模板为基础,讲解S3C2410 ARM处理器I2C总线驱动及挂接在上的SAA7113H视频模拟/数字转换芯片设备驱动的编写方法。
15.1 Linux I2C
体系结构
Linux
I2C体系结构分为3个组成部分:
?  I2C
核心
I2C
核心提供了I2C总线驱动和设备驱动的注册、注销方法,I2C通信方法(即“algorithm”,笔者认为直译为运算方法并不合适,为免引起误解, 下文将直接使用“algorithm”)上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代码等。
?  I2C
总线驱动
I2C
总线驱动是对I2C硬件体系结构中适配器端的实现,适配器可由CPU控制,甚至直接集成在CPU内部。
I2C
总线驱动主要包含了I2C适配器数据结构i2c_adapterI2C适配器的algorithm数据结构i2c_algorithm和控制I2C适配器产生通信信号的函数。
经由I2C总线驱动的代码,我们可以控制I2C适配器以主控方式产生开始位、停止位、读写周期,以及以从设备方式被读写、产生ACK等。
?  I2C
设备驱动
I2C
设备驱动是对I2C硬件体系结构中设备端的实现,设备一般挂接在受CPU控制的I2C适配器上,通过I2C适配器与CPU交换数据。
I2C
设备驱动主要包含了数据结构i2c_driveri2c_client,我们需要根据具体设备实现其中的成员函数。

15.1 Linux I2C体系结构
Linux 2.6内核中,所有的I2C设备都被在sysfs文件系统中显示,存在于/sys/bus/i2c/目录,以适配器地址和芯片地址的形式列出,如:
$ tree /sys/bus/i2c/
/sys/bus/i2c/
|-- devices
|   |-- 0-0048 -> ../../../devices/legacy/i2c-0/0-0048
|   |-- 0-0049 -> ../../../devices/legacy/i2c-0/0-0049
|   |-- 0-004a -> ../../../devices/legacy/i2c-0/0-004a
|   |-- 0-004b -> ../../../devices/legacy/i2c-0/0-004b
|   |-- 0-004c -> ../../../devices/legacy/i2c-0/0-004c
|   |-- 0-004d -> ../../../devices/legacy/i2c-0/0-004d
|   |-- 0-004e -> ../../../devices/legacy/i2c-0/0-004e
|   `-- 0-004f -> ../../../devices/legacy/i2c-0/0-004f
`-- drivers
    |-- i2c_adapter
    `-- lm75
        |-- 0-0048 -> ../../../../devices/legacy/i2c-0/0-0048
        |-- 0-0049 -> ../../../../devices/legacy/i2c-0/0-0049
        |-- 0-004a -> ../../../../devices/legacy/i2c-0/0-004a
        |-- 0-004b -> ../../../../devices/legacy/i2c-0/0-004b
        |-- 0-004c -> ../../../../devices/legacy/i2c-0/0-004c
        |-- 0-004d -> ../../../../devices/legacy/i2c-0/0-004d
        |-- 0-004e -> ../../../../devices/legacy/i2c-0/0-004e
        `-- 0-004f -> ../../../../devices/legacy/i2c-0/0-004f
Linux内核源代码中的drivers目录下包含一个 i2c目录,而在i2c目录下又包含如下文件和文件夹:
?  i2c-core.c
这个文件实现了I2C核心的功能以及/proc/bus/i2c*接口。
?  i2c-dev.c
实现了I2C适配器设备文件的功能,每一个I2C适配器都被分配一个设备。通过适配器访问设备时的主设备号都为89,次设备号为0255。应用程序通过 “i2c-%d” (i2c-0, i2c-1, ..., i2c-10, ...)文件名并使用文件操作接口open()write()read()ioctl()close()等来访问这个设备。
i2c-dev.c
并没有针对特定的设备而设计,只是提供了通用的read()write()ioctl()等接口,应用层可以借用这些接口访问挂接在适配器上的I2C设备的存储空间或寄存器并控制I2C设备的工作方式。
?  chips
文件夹
这个目录中包含了一些特定的I2C设备驱动,如Dallas公司的DS1337实时钟芯片、EPSON公司的RTC8564实时钟芯片和I2C接口的EEPROM驱动等。
?  busses
文件夹
这个文件中包含了一些I2C总线的驱动,如S3C2410I2C控制器驱动为i2c-s3c2410.c
?  algos
文件夹
实现了一些I2C总线适配器的algorithm
此外,内核中的i2c.h这个头文件对i2c_driveri2c_clienti2c_adapteri2c_algorithm4个数据结构进行了定义。理解这4个结构体的作用十分关键,代码清单15.115.215.315.4分别给出了它们的定义。
代码清单15.1 i2c_adapter结构体
1  struct i2c_adapter {
2   struct module *owner;/*
所属模块*/
3  unsigned int id;   /*algorithm
的类型,定义于i2c-id.h,以I2C_ALGO_开始*/
4  unsigned int class;
5  struct i2c_algorithm *algo;/*
总线通信方法结构体指针 */
6  void *algo_data; /* algorithm
数据 */
7  int (*client_register)(struct i2c_client *);  /*client
注册时调用*/
8  int (*client_unregister)(struct i2c_client *); /*client
注销时调用*/
9  struct semaphore bus_lock;    /*
控制并发访问的自旋锁*/
10 struct semaphore clist_lock;
11 int timeout;
12 int retries;    /*
重试次数*/
13 struct device dev;  /*
适配器设备 */
14 struct class_device class_dev; /*
类设备 */
15 int nr;
16 struct list_head clients;  /* client
链表头*/
17 struct list_head list;
18 char name[I2C_NAME_SIZE];  /*
适配器名称*/
19 struct completion dev_released;    /*
用于同步*/
20 struct completion class_dev_released;
21};
代码清单15.2 i2c_algorithm结构体
1  struct i2c_algorithm {
2   int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg *msgs,
3                      int num);  /*i2c
传输函数指针*/
4   int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,   /*smbus
传输函数指针*/
5                      unsigned short flags, char read_write,
6                      u8 command, int size, union i2c_smbus_data * data);
7   int (*slave_send)(struct i2c_adapter *,char*,int);/*
i2c适配器为slave时,发送函数*/
8   int (*slave_recv)(struct i2c_adapter *,char*,int); /*
i2c适配器为slave时,接收函数*/
9   int (*algo_control)(struct i2c_adapter *, unsigned int, unsigned long); /*
类似ioctl*/
10  u32 (*functionality) (struct i2c_adapter *);/*
返回适配器支持的功能*/
11 };
上述代码第4行对应为SMBus传输函数指针,SMBus大部分基于I2C总线规范,SMBus不需增加额外引脚。与I2C总线相比,SMBus增加了一些新的功能特性,在访问时序也有一定的差异。
代码清单15.3 i2c_driver结构体
1  struct i2c_driver {
2   int id;
3   unsigned int class;
4   int (*attach_adapter)(struct i2c_adapter *); /*
依附i2c_adapter函数指针 */
5   int (*detach_adapter)(struct i2c_adapter *); /*
脱离i2c_adapter函数指针*/
6   int (*detach_client)(struct i2c_client *);  /*i2c client
脱离函数指针*/
7   int (*command)(struct i2c_client *client,unsigned int cmd, void *arg); /*
类似ioctl*/
8   struct device_driver driver;    /*
设备驱动结构体*/
9   struct list_head list;         /*
链表头*/
10 };
代码清单15.4 i2c_client结构体
1  struct i2c_client {
2   unsigned int flags;  /*
标志 */
3   unsigned short addr;     /*
7位为芯片地址 */
4   struct i2c_adapter *adapter; /*
依附的i2c_adapter*/
5   struct i2c_driver *driver;    /*
依附的i2c_driver */
6   int usage_count;     /*
访问计数  */
7   struct device dev;     /*
设备结构体 */
8   struct list_head list;       /*
链表头 */
9   char name[I2C_NAME_SIZE]; /*
设备名称 */
10  struct completion released;   /*
用于同步 */
11 };
下面分析一下i2c_driveri2c_clienti2c_adapteri2c_algorithm4个数据结构的作用及其盘根错节的关系。
?  i2c_adapter
i2c_algorithm
i2c_adapter
对应于物理上的一个适配器,而i2c_algorithm对应一套通信方法。一个I2C适配器需要i2c_algorithm中提供的通信函数来控制适配器上产生特定的访问周期。缺少i2c_algorithmi2c_adapter什么也做不了,因此i2c_adapter中包含其使用的 i2c_algorithm的指针。
i2c_algorithm
中的关键函数master_xfer()用于产生I2C访问周期需要的信号,以i2c_msg(即I2C消息)为单位。i2c_msg结构体也非常关键,代码清单15.5给出了它的定义。
代码清单15.5 i2c_msg结构体
1 struct i2c_msg {
2  __u16 addr; /*
设备地址*/
3   __u16 flags; /*
标志 */ 
4   __u16 len;  /*
消息长度*/
5   __u8 *buf;  /*
消息数据*/
6 };
?  i2c_driver
i2c_client
i2c_driver
对应一套驱动方法,是纯粹的用于辅助作用的数据结构,它不对应于任何的物理实体。i2c_client对应于真实的物理设备,每个I2C设备都需要一个i2c_client来描述。i2c_client一般被包含在i2c字符设备的私有信息结构体中。
i2c_driver
i2c_client发生关联的时刻在i2c_driverattach_adapter()函数被运行时。attach_adapter()会探测物理设备,当确定一个client存在时,把该client使用的i2c_client数据结构的adapter指针指向对应的i2c_adapterdriver指针指向该i2c_driver,并会调用i2c_adapterclient_register()函数。相反的过程发生在 i2c_driver detach_client()函数被调用的时候。
?  i2c_adpater
i2c_client
i2c_adpater
i2c_client的关系与I2C硬件体系中适配器和设备的关系一致,即i2c_client依附于i2c_adpater。由于一个适配器上可以连接多个I2C设备,所以一个i2c_adpater也可以被多个i2c_client依附,i2c_adpater中包括依附于它的i2c_client 的链表。
假设I2C总线适配器xxx上有两个使用相同驱动程序的yyy I2C设备,在打开该I2C总线的设备结点后相关数据结构之间的逻辑组织关系将如图15.2所示。


15.2 I2C驱动各数据结构关系

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/434733.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微软企业库4.1学习笔记(十)企业库的设计

在设计整个企业库的过程中,使用了一系列的最佳实践。下面列出一些里面的最佳实践: 在核心库中使用了Common模块  使用了统一的命名约定和统一的版本  在设计的过程中使用单元测试  在所有模块中包含基础结构在企业库的模块中包含了下面的模式&…

ebay注册流程_跨境电商平台eBay企业入驻流程

整个流程一共包括8个部分了解企业入驻通道企业入驻通道将帮助现有eBay大中华卖家申请并获得高刊登额度的新账户,以满足卖家在品类拓展以及站点拓展的需求。准备材料1.营业执照2.法人代表身份证明,或eBay帐户注册人身份证明(根据地区法规有不同…

Linux I2C核心、总线与设备驱动(二)

从上面的分析可知,虽然I2C硬件体系结构比较简单,但是I2C体系结构在Linux中的实现却相当复杂。当工程师拿到实际的电路板,面对复杂的 Linux I2C子系统,应该如何下手写驱动呢?究竟有哪些是需要亲自做的,哪些是…

解决Android中的ERROR: the user data image is used by another emulator. aborting的方法

解决Android中的ERROR: the user data image is used by another emulator. aborting的方法 今天调试代码的时候,突然出现这个错误,折腾了很久没有解决。最后在google上找到了大家给出的两种解决方案,下面给出这两种方法的链接博客&#xff1…

mtu设置失败_Oracle RAC该调整网卡MTU值

在Oracle RAC的环境中,如果我们发现OSW监控数据显示包重组失败率过高,就需要引起足够的重视,因为这很可能会引发member kill/Node kill等重大故障,甚至在有些场景会连带影响到所有RAC节点不可用。一般我们会选择调整ipfrag相关参数…

i2c_add_driver函数用法

I2C的设备驱动是通过i2c_add_driver(&my_driver)向i2c-core注册的,my_driver中的核心是detach和attach函数,在attach中通过probe探测到总线上的设备并把设备和 驱动建立连接以完成设备的初始化。如何探测总线上的设备、Linux中i2c设备地址如何标识并…

基因组印记

基因组印记是指来自父方和母方的等位基因在通过精子和卵子传递给子代时发生了修饰,使带有亲代印记的等位基因具有不同的表达特性,这种修饰常为DNA甲基化修饰,也包括组蛋白乙酰化、甲基化等修饰。在生殖细胞形成早期,来自父方和母方…

判断字段长度大于某长度_判断数据库性能只能通过count(*)?No,这些优化方案了解一下!...

大多数用户在体验数据库时,接触到的最早的sql语句就是count(*),因此用户判断数据库性能时通常也会通过count(*)进行比较。但在执行时通常会出现一个问题:对某个表做count(*)时需对全表数据进行扫描,当表中包含数据量较大的字段时&…

linux下i2c接口的电容触摸屏驱动开发

原文地址: http://hi.baidu.com/god_sperm/blog/item/2aaac228e8a1ece8e7cd400a.html 电容触摸屏 2011-01-14 15:36 1.Kconfig文件    增加宏定义 2.Makefile文件 增加编译处理 3.添加程序源码 Touch screen remote control design document 2010…

10 款基于 jQuery 的切换效果插件推荐

本文整理了 10 款非常好用的jQuery切换效果插件,包括平滑切换和重叠动画等,这些插件可以实现不同元素之间的动态切换。 1. InnerFade 这是一个基于jQuery的小插件,可以实现页面内的元素淡入淡出效果。 源码/演示 2. HighlightFade 该插件可以…

r语言ggplot2一夜多图_ggplot2绘图:多张图合并为一张

以下内容来自教程 R语言中多张图画到同一个页面上常用的函数为par()和layout() par()函数详解 layout()函数的简单使用 但是这两个函数不适用于ggplot2;ggplot2作图如果希望把多张图放到同一个页面上基本的解决办法是使用(The basic solution is to use the gridExtra R packa…

电容屏原理

电容屏 电容技术的触摸屏是一块四层复合玻璃屏,如下图所示。玻璃屏的内表面和夹层各涂有一层ITO导电层,最外层是只有0.0015毫米厚的矽土玻璃保护层。内层ITO作为屏蔽层,以保证良好的工作环境,夹层ITO涂层作为检测定位的工作层&am…

js矢量图类库:Raphaël—JavaScript Library

官方网址:http://raphaeljs.com/ Raphal is a small JavaScript library that should simplify your work with vector graphics on the web. If you want to create your own specific chart or image crop and rotate widget, for example, you can achieve it si…

sklearn 绘制roc曲线_如何用Tensorflow和scikit-learn绘制ROC曲线?

我试图从tensorflow提供的CIFAR-10示例的修改版本绘制ROC曲线。它现在为2类,而不是10如何用Tensorflow和scikit-learn绘制ROC曲线?的网络的输出被称为logits并采取以下形式:[[-2.57313061 2.57966399] [0.04221377 -0.04033273] [-1.42880082…

Linux的I2C 设备驱动 -- mini2440 上i2c接口触摸屏驱动

本篇记录在友善之臂 mini2440 平台上挂载I2C接口触摸屏的驱动开发过程。内核版本linux-2.6.32.2, 平台是ARM9 S3C2440I2C接口的触摸屏如上篇 Linux的I2C驱动体系结构讲述http://www.lupaworld.com/273398/viewspace-204237.html要挂载新的I2C设备,需要实现3部分&…

十六进制字符串转整形

System.Convert.ToInt32( "字符串 ",16); 转载于:https://www.cnblogs.com/dashi/archive/2011/12/22/4034737.html

gridview databind 会导致页面刷新马_Innodb批量页面刷盘情况下的quot;两次写quot;

//Innodb批量页面刷盘情况下的"两次写"//之前的文章中,我们介绍过innodb的两次写特性,这里给出链接:InnoDB的两次写特性今天我们完善一下这部分的内容。我们知道innodb数据页的默认大小是16kb,磁盘和内存通过数据页进行…

linux内核I2C子系统学习(一)

这部分准备分几个部分进行分析总结 因为I2C的通信肯定至少要有2个芯片完成,所以它的驱动是由2大部分组成:主芯片的i2c的驱动从芯片的i2c的驱动 注:万一选的都不支持咋办???(惨了,只能…

【转】excel表格导出集锦repeater实用,和普通用法

【http://www.cnblogs.com/s-y-l/archive/2011/12/23/2299008.html】下面导出excel主要解决repeater产生乱码的问题publicvoid CreateExcel(DataSet ds,string typeid,string FileName) { HttpResponse resp; resp Page.Response; …

什么是流量攻击? 流量攻击怎么处理?

由于DDoS攻击往往采取合法的数据请求技术,再加上傀儡机器,造成DDoS攻击成为最难防御的网络攻击之一。据美国最新的安全损失调查报告,DDoS攻击所造成的经济损失已经跃居第一。 传统的网络设备和周边安全技术,例如防火墙和IDSs(Intr…