I2C子系统详解1——I2C总线设备的驱动框架

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。

参考博客

I2C总线驱动框架详解

linux内核I2C子系统详解

一、I2C总线的物理特征

这部分内容的简介可见博客:SPI、I2C、UART(即串口)三种串行总线详解。

(1)通信线数目:两根,即SCL、SDA。

(2)通信的特点:同步、串行、电平、低速(几百k)、近距离。

(3)总线式结构:支持多个设备挂接在同一条总线上。

(4)主从式结构:通信双方必须一个为主设备,一个为从设备,主设备掌握通信的主动权,从设备按照主设备的节奏被动响应。每个从设备在总线中有唯一的地址,主设备通过从地址找到自己要通信的从设备(本质是广播)。

(5)I2C总线的用途:用于主SoC和外围设备之间的通信。常见的各种物联网传感器芯片(如gsensor、温度、湿度、光强度、酸碱度、烟雾浓度、压力等)均使用I2C接口和主SoC进行连接。

(6)I2C总线的最大优势:支持在总线上扩展多个外围设备。

(7)举例,电容触摸屏芯片的I2C接口:电容触摸屏芯片的多个引脚构成2个接口。其中一个接口是I2C接口,电容触摸屏芯片通过该接口与主SoC连接,此时触摸屏作为从设备。主SoC通过该接口初始化及控制电容触摸屏芯片,而芯片通过该接口向SoC汇报触摸事件的信息。我们使用电容触摸屏时重点关注的是这个接口。另一个接口是电容触摸屏的管理接口,电容触摸屏芯片通过该接口来控制触摸板硬件。该接口是电容触摸屏公司关心的,触摸屏芯片内部固件编程要处理这部分。我们使用电容触摸屏的人不需要关心这些内容。

二、I2C总线设备的驱动框架

I2C总线设备的驱动框架,或者说“I2C子系统”,其设计目的是让驱动开发者可以在内核中方便地添加自己的I2C设备的驱动程序,从而可以更容易地在linux下驱动I2C设备。

I2C总线设备的驱动框架内部关系如下:

1、驱动框架的组成部分

(1)I2C设备驱动层(I2C_client,I2C_driver)

和具体I2C接口的外设相关,每种外设都有自己的专属I2C驱动代码。

包括两部分:I2C从设备的注册、I2C设备驱动的注册。

(2)I2C核心层(I2C_core)

I2C核心提供了I2C总线驱动和I2C设备驱动的注册、匹配与注销方法,I2C通信方法,上层中与具体硬件无关的代码,以及探测设备检测设备地址的上层代码等。换言之,管理I2C驱动和I2C设备的注册、匹配,实现I2C的通信方法,是对I2C通信的抽象框架,与具体硬件无关。

(3)I2C总线驱动层(I2C_adapter、I2C_algorithm)

或者说I2C适配器层。这里说的I2C适配器,也就是I2C主设备,对应着Soc的I2C控制器,把I2C控制器看做一个设备,实现I2C控制器的驱动代码,和具体的Soc相关。

I2C总线驱动是I2C适配器的软件实现,或者说是SoC中内置的I2C控制器的软件抽象,可以将其理解为I2C主设备,它提供了I2C适配器与从设备间数据通信的功能。

I2C总线驱动用 I2C_adapter 和 I2C_algorithm 来描述I2C适配器。

2、I2C相关的驱动文件

源码中与I2C相关的驱动均位于drivers/i2c目录,包括的内容如下:

 (1)I2C设备驱动层相关的文件

x210开发板的电容触摸屏gslX680采用I2C接口,因此以这个I2C设备为例进行分析。其对应的驱动源代码文件是x210_kernel\drivers\input\touchscreen\gslX680.c文件。它由触摸屏IC原厂工程师提供,代码中涉及到很多触摸屏专业方面的知识,但无需理会。

gslX680.c文件进行了I2C设备驱动的注册,相应的I2C设备注册是在mach-x210.c文件中。

(2)I2C核心层相关的文件

I2C核心层相关的文件是i2c-core.c文件,它由内核开发者提供,和具体的硬件操作无关。

(3)I2C总线驱动层相关的文件

algos目录:存放的是I2C通信的算法(主要是时序等内容)。

busses目录:存放的是各种已经编写好的、将来要向i2c核心层注册的适配器文件。

我们主要分析drivers\i2c\busses\i2c-s3c2410.c文件

3、驱动实现的两种方式

I2C驱动有两种实现方法:

(1)第一种方式对应于drivers/i2c/i2c-dev.c文件

这种方法只是对主设备(一般是SoC中内置的I2C控制器)的I2C基本操作进行封装,并且向应用层提供相应的操作接口,应用层需要编写代码来实现对从设备的控制和操作。

这种I2C驱动,只是给应用层提供了可以访问从设备的接口,本身没有对硬件做任何操作。应用需要实现对硬件的操作,因此写应用的人必须对硬件非常了解。其实实这就相当于在应用层完成传统的驱动的工作内容,所以这种I2C驱动又叫做“应用层驱动”。

它的优势是把差异化都放在应用中,这样在设备比较难缠(尤其是slave是非标准I2C时)时不用修改驱动,只需要修改应用就可以实现对各种设备的驱动。这种驱动在驱动层很简单,但并不主流这里不进行分析

(2)第二种方式将I2C驱动的所有代码都放在驱动层实现(直接向应用层提供最终结果)

这种实现方法中,应用层不需要知道这里面有I2C存在。比如电容式触摸屏驱动,直接向应用层提供了/dev/input/event1的操作接口,应用层编程的人根本不知道event1中涉及到I2C。这种实现方法是我们后续分析的重点。

4、相关的结构体

(1)struct i2c_adapter(I2C适配器)

struct i2c_adapter结构体用来描述一个 I2C适配器,在SoC中指的就是I2C控制器。

当向I2C核心层注册一个I2C适配器时,就需要提供这样的一个结构体变量,换另外一颗SoC则需要修改该结构体变量。

struct i2c_adapter {struct module *owner;             // 所有者unsigned int id;unsigned int class;               // 该适配器支持的从设备的类型const struct i2c_algorithm *algo; // 该适配器与从设备的通信算法void *algo_data;/* data fields that are valid for all devices    */struct rt_mutex bus_lock;int timeout;              // 超时时间int retries;struct device dev;        // 该适配器设备对应的deviceint nr;                   // 适配器的编号char name[48];            // 适配器的名字struct completion dev_released;//用来挂接(与适配器匹配成功的)从设备i2c_client的一个链表头struct list_head userspace_clients;  };

(2)struct i2c_algorithm结构体

struct i2c_algorithm结构体用来描述主设备和从设备通信的算法(主要是时序等内容),它与主设备、从设备都有关系。在构建i2c_adapter结构体变量的时候会去填充这个元素。

struct i2c_algorithm {/* If an adapter algorithm can't do I2C-level access, set master_xferto NULL. If an adapter algorithm can do SMBus access, setsmbus_xfer. If set to NULL, the SMBus protocol is simulatedusing common I2C messages *//* master_xfer should return the number of messages successfullyprocessed, or a negative value on error */int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,int num);int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,unsigned short flags, char read_write,u8 command, int size, union i2c_smbus_data *data);/* To determine what the adapter supports */u32 (*functionality) (struct i2c_adapter *);
};

注意,smbus协议是从I2C协议的基础上发展而来的,他们之间有很大的相似度,SMBus与I2C总线之间在时序特性上存在一些差别,应用于移动PC和桌面PC系统中的低速率通讯。

(3)struct i2c_client结构体

该结构体用来描述一个I2C从设备。

​struct i2c_client {    //  用来描述一个i2c从设备unsigned short flags;        //  描述i2c从设备特性的标志位unsigned short addr;         //  i2c 从设备的地址char name[I2C_NAME_SIZE];    //  i2c从设备的名字struct i2c_adapter *adapter; //  指向与从设备匹配成功的适配器struct i2c_driver *driver;   //  指向与从设备匹配成功的设备驱动struct device dev;           //  该从设备对应的deviceint irq;                     //  从设备的中断引脚struct list_head detected;   //  作为一个链表节点挂接到(与它匹配成功的)i2c_driver 相应的链表头上
};​

(4)struct i2c_driver结构体

该结构体代表一个I2C从设备的驱动。

struct i2c_driver {    // 代表一个i2c设备驱动unsigned int class;      // i2c设备驱动所支持的i2c设备的类型/* Notifies the driver that a new bus has appeared or is about to be* removed. You should avoid using this if you can, it will probably* be removed in a near future.*/int (*attach_adapter)(struct i2c_adapter *);   // 用来匹配适配器的函数int (*detach_adapter)(struct i2c_adapter *);/* Standard driver model interfaces */
// 设备驱动层的probe函数int (*probe)(struct i2c_client *, const struct i2c_device_id *); int (*remove)(struct i2c_client *);       // 设备驱动层卸载函数/* driver model interfaces that don't relate to enumeration  */void (*shutdown)(struct i2c_client *);int (*suspend)(struct i2c_client *, pm_message_t mesg);int (*resume)(struct i2c_client *);/* Alert callback, for example for the SMBus alert protocol.* The format and meaning of the data value depends on the protocol.* For the SMBus alert protocol, there is a single bit of data passed* as the alert response's low bit ("event flag").*/void (*alert)(struct i2c_client *, unsigned int data);/* a ioctl like command that can be used to perform specific functions* with the device.*/int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);struct device_driver driver;      //  该i2c设备驱动所对应的device_driverconst struct i2c_device_id *id_table;  //设备驱动层用来匹配设备的id_table/* Device detection callback for automatic device creation */int (*detect)(struct i2c_client *, struct i2c_board_info *);const unsigned short *address_list;    //  该设备驱动支持的所有次设备的地址数组//  用来挂接与该i2c_driver匹配成功的i2c_client (次设备)的一个链表头struct list_head clients;                
};

(5)struct i2c_board_info结构体

这个结构体用来描述板子上的一个i2c设备的信息,一般用来对struct i2c_client结构体变量的成员进行赋值?

struct i2c_board_info {      //  这个结构体是用来描述板子上的一个i2c设备的信息char        type[I2C_NAME_SIZE];    //  i2c 设备的名字,用来初始化i2c_client.nameunsigned short    flags;            //  用来初始化i2c_client.flagsunsigned short    addr;             //  用来初始化 i2c_client.addrvoid        *platform_data;         //  用来初始化 i2c_client.dev.platform_datastruct dev_archdata    *archdata;   //  用来初始化i2c_client.dev.archdata
#ifdef CONFIG_OFstruct device_node *of_node;
#endifint        irq;                     //  用来初始化i2c_client.irq
};

(6)struct i2c_devinfo结构体

struct i2c_devinfo {struct list_head    list;   // 作为一个链表节点挂接到__i2c_board_list 链表上去int            busnum;       // 适配器的编号struct i2c_board_info    board_info; //  内置的i2c_board_info 结构体
};

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

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

相关文章

sqlite4java下载_使用sqlite4java的UnsatisfiedLinkError,没有sqlite4java-osx-amd64

我对这个问题有类似的问题:我正在运行一个使用sqlite的脚本,虽然我能够通过命令行成功运行sqlite3,但是当我尝试运行脚本时,我总是遇到这个错误:SEVERE: [sqlite] sqliteQueue[master.catalog]: error running job queuecom.almworks.sqlite4java.sqlite…

神经网络编程入门

本文主要内容包括: (1) 介绍神经网络基本原理, (2) AForge.NET实现前向神经网络的方法, (3) Matlab实现前向神经网络的方法 。 第0节、引例 本文以Fisher的Iris数据集作为神经网络程序的测试数据集。Iris数据集可以在http://en.wikipedia.or…

I2C子系统详解2——I2C核心层源码分析

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。 一、前言 由I2C总线设备的驱动框架可知,I2C总线设备驱动框架涉及的文件如下: (1)I2C设备驱动层相关的文件 x210开发板的电容触摸屏gslX680采用I2C接口…

软考复习之路—组成原理

计算机系统的基础知识应该是作为一个编程人员必备的一门课程,仅仅有了解了计算机的组成,程序在计算 机中的存储状态,运算等基本内容,我们才干继续对计算机有更深层次的认识,更easy学习与上手。比方说要 想学习操作系统…

python内存管理机制错误_Python内存管理机制和垃圾回收机制的简单理解

一、内存管理机制1.由c开发出来的cpython2.include / objests3.需要下载python源码包4.Pyobject:floatPyVarObject:5.在python中所有东西创建对象的时候,内部都会存储一个数据// 维护双向链表struct _object *_ob_next;struct _object *_ob_p…

C#中几种数据库的大数据批量插入

C#语言中对SqlServer、Oracle、SQLite和MySql中的数据批量插入是支持的&#xff0c;不过Oracle需要使用Orace.DataAccess驱动。 IProvider里有一个用于实现批量插入的插件服务接口IBatcherProvider。批量插入的实现可以通过实现该接口来实现。 /// <summary>/// 提供数据…

求背包问题所有解(C++实现)

这是我学习数据结构时的一道上机作业&#xff0c;那时还没养成写注释的习惯&#xff0c;所以各位得受点苦了。 只是简易背包问题。 代码&#xff1a; 展开 1 // 背包问题所有解2 // 作者:王锦 3 // 邮箱:jinkswvip.qq.com4 5 #include "stdafx.h"6 #include <iost…

I2C子系统详解3——I2C总线驱动层代码分析

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、前言 由I2C总线设备的驱动框架可知&#xff0c;I2C总线设备的驱动框架涉及的文件如下&#xff1a; &#xff08;1&#xff09;I2C设备驱动层相关的文件 x210开发板的电容触摸屏gslX680采用I2C接…

java join 异常_Java:守护进程:thread.join()没有完成,当在一个线程中抛出异常时...

我写了一个Java守护进程(一个实现守护进程和Runnable的类)&#xff0c;现在我遇到了以下问题&#xff1a;在init()中&#xff0c;我创建了一个新线程 . Thread thread new Thread(this); 在start()中我启动新线程 . thread.start() . 在运行中我做了很多不同的事情......然后发…

硬链接与符号链接的比较?

今天就说说硬链接&#xff08;实体链接&#xff09;与符号链接&#xff08;类似Windows的快捷方式&#xff09;的不同?首先我们应知道&#xff1a;每个档案都会占用一个inode ,档案内容由 inode记录来指向;想要读取该档案&#xff0c;必须要经过目录记录的文件名来指向正确的i…

JAVA--自制斐波那契数列输出

累了&#xff0c;写点简单的。 1 public class hello {2 3 /**4 * param args5 */6 public static void main(String[] args) {7 int Fabnum 10;8 int sum 0;9 System.out.print("Serial:\t"); 10 for(int i 1…

I2C子系统详解4——I2C设备驱动层代码分析

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 一、前言 由I2C总线设备的驱动框架可知&#xff0c;I2C总线设备的驱动框架涉及的文件如下&#xff1a; &#xff08;1&#xff09;I2C设备驱动层相关的文件 x210开发板的电容触摸屏gslX680采用I2C接…

golang java rpc_golang两种调用rpc的方法

本文实例讲述了golang两种调用rpc的方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;golang的rpc有两种方法进行调用&#xff0c;一种是rpc例子中给的&#xff1a;package mainimport ("net/rpc""net/http""log""net"&quo…

9、C语言 —— 指针的用处

为什么80%的码农都做不了架构师&#xff1f;>>> 1、用函数实现两个数的交换 ‍‍在没用函数之前&#xff0c;可以这样实现‍‍#include <stdio.h>int main() {int a 3;int b 7;int c;printf("交换前&#xff0c;a%d&#xff0c;b%d\n", a, b); …

内核中的竞争状态和互斥(简述)

以下内容源于朱有鹏《物联网大讲堂》课程的学习&#xff0c;如有侵权&#xff0c;请告知删除。 一、概念 &#xff08;1&#xff09;竞争状态&#xff08;简称竟态&#xff09;&#xff1b; &#xff08;2&#xff09;临界段&#xff08;某一段代码&#xff0c;该代码有可能…

MenuetOS

MenuetOS由芬兰人Ville Turjanmaa开发&#xff0c;是一个操作系统&#xff0c;用于和IBM PC兼容的电脑。 它由汇编语言写成&#xff0c;可以存入一只1.44MB的软盘中。 Menuet OS 的32位版本Menuet32使用GNU通用公共许可证发放&#xff0c;但64位版本Menuet64使用自己的协议发放…

php是一种,PHP是一种什么型的语言:()

案例分析一&#xff1a;假定CPU的主频是500MHz。硬盘采用DMA方式进行数据传送&#xff0c;其数据传输率为4MB/s, 每次DMA传输的数据量为8KB, 要求没有任何数据传输被错过。如果CPU在DMA初始化设置和启动硬盘操作等方面用了1000个时钟周期&#xff0c;并且在DMA传送完成后的中断…

java动态代理二cglib

2019独角兽企业重金招聘Python工程师标准>>> java动态代理 转载于:https://my.oschina.net/u/1430510/blog/290215

spring心得6--自动装配知识点讲解及案例分析

1.自动装配&#xff1a; spring3.2以上版本有四种自动装配类型&#xff1a; 1&#xff09;.byName:寻找和属性名相同的bean,若找不到&#xff0c;则装不上。 2&#xff09;.byType:寻找和属性类型相同的bean,找不到,装不上,找到多个抛异常。 3&#xff09;.constructor:按照参数…

中断的上下半部

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 前言 因为输入类设备的输入都是异步事件&#xff0c;因此一般使用中断来处理和响应。 中断处理程序处于中断上下文中&#xff0c;不能和用户空间数据交互&#xff08;不能使用copy_to(from)_usr函数…