linux下s3c2440–i2c驱动学习之三"深入i2c,linux下S3C2440–I2C驱动学习之一“I2C核心数据结构” | 技术文章 | 狂......

最近学习

Linux的i2c 框架中各个部分的关系如下图所示:

31287714_1.gif

内核中 i2c 相关代码可以分为三个层次:

1. i2c 框架:i2c.h 和i2c-core.c 为i2c 框架的主体,提供了核心数据结构的定义、i2c 适配器驱动和设备驱动的注册、注销管理,i2c 通信方法上层的、与具体适配器无关的代码、检测设备地址的上层代码等;i2c-dev.c 用于创建i2c 适配器的/dev/i2c/%d 设备节点,提供i2c 设备访问方法等。

2. i2c 总线适配器驱动:定义描述具体i2c 总线适配器的i2c_adapter 数据结构、实现在具体i2c 适配器上的i2c 总线通信方法,并由i2c_algorithm 数据结构进行描述。

3. i2c 设备驱动:定义描述具体设备的i2c_client 和可能的私有数据结构、借助i2c 框架的i2c_probe 函数实现注册设备的attach_adapter 方法、提供设备可能使用的地址范围、以及设备地址检测成功后创建i2c_client 数据结构的回调函数。

I2C主要数据结构如下:

1. 一个 i2c 设备的驱动程序由i2c_driver 数据结构描述,定义于include/linux/i2c.h:

struct i2c_driver {

char name[32];          //最大32字节的字符串

int id;                       //id 可选0xf000 到0xffff 中的任一数值

unsigned int flags;     //一般直接设置为I2C_DF_NOTIFY

int (*attach_adapter)(struct i2c_adapter *);

int (*detach_client)(struct i2c_client *);

int (*command)(struct i2c_client *client,unsigned int cmd, void *arg);

void (*inc_use)(struct i2c_client *client);

void (*dec_use)(struct i2c_client *client);

};

现在讲解一下这个结构体:

(1).attach_adapter 回调函数在安装i2c 设备驱动程序模块时、或者在安装i2c 适配器驱动

程序模块时被调用,用于检测、认领设备并为设备分配i2c_client 数据结构.

(2).detach_client 方法在卸载适配器或设备驱动程序模块时被调用,用于从总线上注销设备、并释放i2c_client 及相应的私有数据结构。

(3).inc_use 和dec_use 所指向的函数用于改变i2c 设备驱动程序模块的引用计数。注意不要直接调用i2c_driver数据结构中的这两个方法,而要通过如下函数调用路径:

i2c_use_client > i2c_inc_use_client > inc_use

i2c_release_client > i2c_dec_use_client > dec_use

2. 一个 i2c 设备由i2c_client 数据结构进行描述:

struct i2c_client {

char name[32];

int id;

unsigned int flags; /* div., see below */

unsigned int addr; /* chip address - NOTE: 7bit addresses are stored in the */

/* _LOWER_ 7 bits of this char */

struct i2c_adapter *adapter; /* the adapter we sit on */

struct i2c_driver *driver; /* and our access routines */

void *data; /* for the clients */

int usage_count; /* How many accesses currently to the client */

};

现在讲解一下这个结构体:

在安装适配器或者设备的驱动程序时通过设备驱动程序 i2c_driver 中的attach_adapter 函数检测设备地址。如果检测成功则调用设备驱动程序提供的回调函数创建描述设备的i2c_client 数据结构,并将其中的driver指针指向设备驱动程序的i2c_driver 数据结构。这样将来就可以使用i2c_driver 中的注销设备和控制引用计数的方法了。

3. 一个 i2c 适配器由i2c_adapter 数据结构描述:

struct i2c_adapter {

char name[32];

unsigned int id; /* == is algo->id | hwdep.struct->id, for registered values see below */

struct i2c_algorithm *algo; /* the algorithm to access the bus */

void *algo_data;

void (*inc_use)(struct i2c_adapter *);

void (*dec_use)(struct i2c_adapter *);

int (*client_register)(struct i2c_client *);

int (*client_unregister)(struct i2c_client *);

void *data; /* private data for the adapter */

struct semaphore lock;

unsigned int flags; /* flags specifying div. data */

struct i2c_client *clients[I2C_CLIENT_MAX];

int client_count;

int timeout;

int retries;

#ifdef CONFIG_PROC_FS

/* No need to set this when you initialize the adapter */

int inode;

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)

struct proc_dir_entry *proc_entry;

#endif

#endif /* def CONFIG_PROC_FS */

};

现在讲解一下这个结构体:

在 i2c_adapter 数据结构中设计了clients 指针数组,指向该总线上每个设备的i2c_client 数据结构。由于一条i2c 总线上最多只有I2C_CLENT_MAX 个设备,所以可以使用静态数组(题外话,如果相关数据结构的个数是未知的,链表显然是更好的选择)。lock 信号量用于实现对i2c 总线的互斥访问:在访问i2c 总线上的任一设备期间当前进程必须首先获得该信号量,并且在阻塞等待i2c 操作完成期间不释放。

4.具体 i2c 适配器的通信方法由i2c_algorithm 数据结构进行描述:

struct i2c_algorithm {

char name[32]; /* textual description */

unsigned int id;

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

int (*slave_send)(struct i2c_adapter *,char*,int);

int (*slave_recv)(struct i2c_adapter *,char*,int);

int (*algo_control)(struct i2c_adapter *, unsigned int, unsigned long);

u32 (*functionality) (struct i2c_adapter *);

};

现在讲解一下这个结构体:

(1).master_xfer/smbus_xfer 指针指向i2c 适配器驱动程序模块实现的i2c 通信协议或者smbus 通信协议。由下文分析可见在用户进程通过i2c-dev 提供的/dev/i2c/%d 设备节点访问i2c 设备时,最终是通过调用master_xfer 或者smbus_xfer 指向的方法完成的。

(2).slave_send/recv 函数用于实现当i2c 适配器扮演slave 角色时的传输方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值