最近工作中又使用到了I2C,所以借S3C2440开发板GT2440为硬件平台温习一遍I2C驱动体系。

linux内核中IIC驱动的体系框架

linux内核中IIC部分驱动代码位于:/drivers/i2c下,代码大致分为几个小目录及i2c目录下的的i2c核心代码:

核心代码:/drivers/i2c/i2c-core.c /drivers/i2c/i2c-core.h

busses目录:各种IIC控制器相关的驱动代码(也称为IIC总线驱动代码),如果S3C2440A内部集成了IIC控制器,它在busses目录下对应的控制器驱动代码为i2c-s3c2410.c

algos目录:定义的是一些通信方法,对于S3C2440A的IIC控制器的通信方法没在里面

muxes目录:各种外接在IIC控制器上的IIC从设备相关的驱动代码

从以上的目录我们可以看出,linux内IIC驱动体系分为3部分:IIC核心、IIC总线驱动、IIC设备驱动。

IIC核心:

IIC核心定义了各种数据结构及抽象出通用接口函数:

如注册(销)IIC适配器:

i2c_add_adapter(struct i2c_adapter *adapter);

i2c_del_adapter(struct i2c_adapter *adapter);

注册(销)IIC设备驱动:

i2c_register_drive(struct module *owner ,struct i2c_driver *driver);

i2c_del_driver(struct i2c_driver *driver);

IIC抽象的传输、发送和接收函数:

i2c_transfe(struct i2c_adapter *adapter,struct i2c_msg *msg,int num);

i2c_master_send(struct i2c_client *client,const char *buf,int count);

i2c_master_recv(struct i2c_client *client , char * buf , int count);

IIC总线驱动:

IIC总线驱动及IIC控制器驱动,为此linux内核中定义一个i2c_adapter数据结构来描述一个IIC适配器,而在不同架构上有不同实现方法:如S3C2440A上就使用i2c-s3c2410.c来实现了S3C2440A上的IIC控制器驱动

IIC设备驱动:

IIC设备在linux内核中用struct i2c_client结构来描述,而使用i2c_driver结构来描述挂载在IIC控制器上的IIC从设备如何与主机进行通信。

问:像IIC裸机驱动那样一个文件就能搞定的IIC驱动在linux中的结构却相当的复杂?

原因在于linux内核,IIC驱动是一类驱动,如果像裸机驱动那样,那么这个驱动只能用于特定的IIC控制器及IIC设备,这样一来如果有很多不同类型的IIC控制器或IIC设备,那么所有的代码都必须重写。这显然是不明智的,一个简单的方法是将不同类型的IIC控制器及IIC设备之间进行通信的共同点给抽象出来,而这部分的代码不管是任何IIC控制器或IIC设备都是一样的,这样移植不同的IIC总线驱动和IIC设备驱动时就能大大的减小代码量。就像内核中将IIC驱动分成了IIC总线驱动和IIC设备驱动一样,在裸机驱动中我们根本看不出那部分是总线驱动,哪部分是设备驱动?二者已经融为了一体。这样的缺陷也很明显,当我们的IIC总线上挂载了不同的IIC设备时,那么我们不得不重新写IIC控制器相关的驱动代码,而如果把它抽象出来,IIC总线驱动主要负责IIC总线的数据传输,如时钟控制、发出S/P信号、中断处理等等,而IIC设备驱动从负责解析出传输的这些数据的含义,因为对于不同的IIC设备,其总线上传输的这些数据的含义不同。个人认为linux的驱动的体系也是基于这种思想产生的。当我们明白了IIC驱动框架中如此负责的构造的良苦用心自然会更加深刻将整个驱动框架铭记于心。

Linux内核为IIC构造的几个重要的数据结构:

struct i2c_adapter {

struct module *owner;

unsigned int id __deprecated;

unsigned int

class; 适配器所属的类 const struct i2c_algorithm *algo;

该总线上的通信方法 void

*algo_data; 通信方法的附加数据

struct rt_mutex

bus_lock; 对所有设备的锁结构

int

timeout; 超时时间,在搞总线上发送信号多久没回的超时时间 int

retries; 重复的次数 struct device

dev; 适配器设备

int

nr; 总线的编号 char

name[48]; 名字 struct completion dev_released;

struct mutex

userspace_clients_lock;

struct list_head userspace_clients;

};

其中重要的成员有algo :该成员所指向的i2c_algorithm实际上就是具体的IIC控制器的通信方法,如发出S/P信号、传输数据等最底层的控制器操作。

struct i2c_algorithm {

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);

u32 (*functionality) (struct i2c_adapter

*); 适配器所支持的功能

};

由于每种适配器所支持的功能不同、传输数据的方法也不同,所以讲这个抽象出来,在不同的适配器中再去具体的实现它。

struct i2c_driver {

unsigned int class;

int (*attach_adapter)(struct i2c_adapter

*);

int (*detach_adapter)(struct i2c_adapter

*);

标准的驱动模型 int (*probe)(struct i2c_client *, const struct

i2c_device_id *);

int (*remove)(struct i2c_client *);

void (*shutdown)(struct i2c_client *);

int (*suspend)(struct i2c_client *, pm_message_t

mesg);

int (*resume)(struct i2c_client

*);

void (*alert)(struct i2c_client *, unsigned int

data);

类似ioctl int (*command)(struct i2c_client *client,

unsigned int cmd, void *arg);

用于设备驱动模型 struct device_driver driver;

列出该设备驱动所支持的设备 const struct i2c_device_id

*id_table;

设备探测的回调函数 int (*detect)(struct i2c_client *, struct

i2c_board_info *);

用于探测的i2c设备地址 const unsigned short *address_list;

链接所有探测出的i2c设备 struct list_head clients;

};

struct i2c_client

{ i2c_client 代表i2c从设备

unsigned short flags; I2C_CLIENT_TEN表示设备使用的是10位的地址,I2C_CLIENT_PEC表示使用SMBus包用在错误检查

unsigned short

addr; I2C设备在总线上的的地址 char name[I2C_NAME_SIZE]; 设备名

struct i2c_adapter

*adapter; 指向该I2C设备挂载的I2C适配器

struct i2c_driver

*driver; 指向支持该I2C设备的驱?

struct device

dev; 用于总线设备驱动模型

int

irq; 该设备能产生的中断号

struct list_head detected;

};

struct i2c_msg

{ I2C总线上传输信息的最小单位

__u16 addr; i2c设备地址,可以是10位的地址,如果是10位的地址flags标志中需设置I2C_M_TEN

__u16 flags; I2C_M_RD

读标志,所有的适配器都必须支持,其他的标志见I2C_FUNC_*

#define

I2C_M_TEN 0x0010 10位的从设备的地址

#define

I2C_M_RD 0x0001 从I2C设备中读数据

#define

I2C_M_NOSTART 0x4000 #define

I2C_M_REV_DIR_ADDR 0x2000 #define

I2C_M_IGNORE_NAK 0x1000 #define

I2C_M_NO_RD_ACK 0x0800 #define

I2C_M_RECV_LEN 0x0400 __u16

len; 消息的长度(字节数)

__u8

*buf; 指向消息数据的缓冲区

};

struct

i2c_board_info

{ 创建I2C设备的模版

char type[I2C_NAME_SIZE]; 设备类型,用于填充i2c_client.name

unsigned

short flags; 用于填充i2c_client.flags

unsigned

short addr; 用于填充i2c_client.addr

void *platform_data; 存储i2c_client.dev.platform_data

struct dev_archdata *archdata;

拷贝到i2c_client.dev.archdata

#ifdef

CONFIG_OF 指向打开固件的设备节点

struct device_node *of_node;

#endif

int irq; 存储到i2c_client.irq

};

i2c_board_info

被用来创建当前系统中I2C设备的列表,这些信息用来驱动模型树,对于主板会使用i2c_register_board_info来注册这些设备

接下来我们就着手分析linux提供的这些重要数据结构及IIC核心提供的这些核心函数是如何构造出整个IIC驱动框架的,耐心看下去你将对IIC体系驱动框架了如指掌!!!

linux i2c核心,总线与设备驱动,Linux2.6.37 I2C驱动框架分析(一)相关推荐

  1. 从需求的角度去理解Linux系列:总线、设备和驱动

    <从需求的角度去理解Linux系列:总线.设备和驱动>是一篇有关如何学习嵌入式Linux系统的方法论文章,也是从需求的角度去理解Linux系统软件的开篇.这是作者精心撰写的经验总结,希望嵌 ...

  2. 嵌入式Linux驱动笔记(二十七)------中断子系统框架分析

    你好!这里是风筝的博客, 欢迎和我一起交流. 中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行. 从硬 ...

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

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

  4. 设备树与驱动的关系_Linux I2C驱动竟然如此简单?手把手教你写i2c驱动

    Linux中I2C驱动框架分析 I2C核心(i2c_core) I2C核心维护了i2c_bus结构体,提供了I2C总线驱动和设备驱动的注册.注销方法,维护了I2C总线的驱动.设备链表,实现了设备.驱动 ...

  5. Linux的 i2c 驱动框架分析

    1.基本概念 总线设备驱动模型,是Linux 内核的一个基础,基本理论可以说按照大企业的分工原则,每个人只要负责自己的事情,向其他部门给出标准的接口调用,后勤部就负责后勤工作,厨房有可能跟后勤部产生工 ...

  6. 获取另一个驱动的设备结构体_《rt-thread驱动框架分析》-i2c驱动

    驱动分析 I2C设备驱动框架图: 我们先RT-Thread的I2C框架图(这是我自己理解的框架图,如果不对的地方,请指出): 上图是我分析的RTT的I2C框架图.主要分为三层,驱动层-核心层-设备层. ...

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

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

  8. Linux I2C核心、总线与设备驱动

    Linux I2C核心.总线与设备驱动 I2C总线仅仅使用SCL. SDA这两根信号线就实现了设备之间的数据交互,极大地简化了对硬件资源和PCB板布线空间的占用.因此, I2C总线非常广泛地应用在EE ...

  9. 《Linux总线、设备与驱动》USB设备发现机制

    http://blog.csdn.net/tankai19880619/article/details/11639185 说明:本分析基于mstar801平台Linux2.6.35.11内核,其他内核 ...

最新文章

  1. Ka的回溯编程练习 Part1|整划什么的。。
  2. React编写input组件传参共用onChange
  3. XPath-Helper 的安装和使用
  4. Retrofit 上传文件显示进度及踩坑记录
  5. 密码学赛后技术总结 小片段啦
  6. Vue项目怎样打包并部署在WindowsServer服务器通过IP访问
  7. PowerPC VxWorks BSP分析(1)--PowerPC体系结构
  8. HDU4911 Inversion 解题报告
  9. html如何让框架的边框消失,css如何让边框透明?
  10. Objective-C初学者指南(第2版)
  11. P1533 可怜的狗狗
  12. DisplayMetircs 类
  13. 动易自定义标签HTML输出,动易标签【ArticleList】
  14. 【Regular正则表达式】正则表达式学习
  15. 形式化方法 | Proof Engineering for Predicate Logic——Coq tatics 在谓词逻辑证明中的应用
  16. Spring注解之精进之路--超级详解
  17. MYSQL数据库版本更新
  18. ubuntu 右键选单没有创建文档
  19. 数学-排列组合的理解
  20. htc one x android5.0,HTC One X S720e 刷机包 FlymeOS4.5.4.2R For One X 安卓5.1.1 XTS高级设置 纯净无推广...

热门文章

  1. pytorch JIT浅解析
  2. Tengine Framework基础
  3. 动态表单工作量给后端
  4. GPU端到端目标检测YOLOV3全过程(上)
  5. Python爬虫实战糗事百科实例
  6. 零起点学算法22——华氏摄氏温度转换
  7. Windows 安装adb
  8. Android全屏,隐藏状态栏和标题栏
  9. android studio 开发环境搭建
  10. postgreSQL外键引用查询 查询外键被那些表占用