(5)LinuxI2C驱动--浅谈LinuxI2C驱动架构
来源:互联网 发布:淘宝水果许可证怎么办 编辑:程序博客网 时间:2024/05/16 06:20
前面几个小结介绍了i2c总线的协议,又介绍了我们关注的eeprom的读写访问时序,还给出了两个访问eeprom的例子,我的目的是为了能更好的理解后面解析Linux下i2c驱动。
网上介绍Linux I2C驱动架构的文章非常的多,我把这些内容做了个归纳与简化,但是在搬出这些非常抽象的内容之前,我想先谈下我的理解。
如下图:
图中画了一个三星的s5pv210处理器,在处理器的里面集成了一个I2C适配器,外面有一个eeprom,通过SDA、SCL连接到cpu内集成的i2c适配器上。这样cpu就可以控制i2c适配器与外部的eeprom进行交互,也就是i2c适配器产生符合i2c协议的信号与eeprom进行通信。
所以对应到linux驱动下,控制i2c适配器有一套驱动代码,叫做i2c总线驱动,是用来产生i2c时序信号的,可以发送和接受数据;控制eeprom有一套驱动代码,叫做i2c设备驱动,这套驱动代码才是真正的对硬件eeprom控制。这也符合linux设备驱动分层的思想。而两套驱动代码之间有一个i2c核心,用来起到承上启下的作用。
以一个写eeprom为例,应用层发出写eeprom消息,i2c设备驱动接到消息,把消息封装成一个前文提到的i2c消息结构体,然后经i2c核心的调度把消息传给i2c适配器,i2c适配器就根据当前cpu的i2c总线协议把消息通过SDA和SCL发给了eeprom。
接下来开始搬运,,
1. I2C体系结构
linux的i2c体系结构分为三个组成部分。放张图加深理解。
(1)i2c核心
- 提供了I2C总线驱动的注册、注销方法
- 提供了I2C设备驱动的注册、注销方法
- 提供了I2C通信方法(algorithm)
对应代码:drivers/i2c/i2c-core.c
(2)i2c总线驱动
I2C总线驱动是对I2C硬件体系结构中适配器端的实现,适配器可由CPU控制,甚至集成在CPU内部(大多数微控制器都这么做)。适配器就是我们经常所说的控制器。
经由I2C总线驱动的代码,我们可以控制I2C适配器以主控方式产生开始位,停止位,读写周期,以及以从设备方式被读写,产生ACK等。
I2C总线驱动由i2c_adapter和i2c_algorithm来描述
对应代码:drivers/i2c/busses/i2c-s3c2410.c
(3)i2c设备驱动
I2C设备驱动是对I2C硬件体系结构中设备端的实现,设备一般挂接在收CPU控制的I2C适配器上,通过I2C适配器与CPU交换数据。
I2C设备驱动程序由i2c_driver来描述
对应代码:drivers/misc/eeprom/at24.c
2. I2C重要数据结构
在include/linux/i2c.h中定义四个I2C驱动中重要的数据结构:i2c_adapter,i2c_algorithm,i2c_driver,i2c_client.
i2c_adapter对应物理上的一个i2c适配器
struct i2c_adapter { struct module *owner;//所属模块 unsigned int id; unsigned int class; /* classes to allow probing for */ const struct i2c_algorithm *algo; /* 总线通讯方法指针,需要其产生特定的访问周期信号 */ void *algo_data; /* data fields that are valid for all devices */ struct rt_mutex bus_lock; int timeout; /* in jiffies */ int retries;/* 重复次数 */ struct device dev; /* the adapter device */ int nr; char name[48]; struct completion dev_released; struct list_head userspace_clients; };
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, u8 command, int size, union i2c_smbus_data *data); /* To determine what the adapter supports */ 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 *); 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); int (*command)(struct i2c_client *client, unsigned int cmd, void *arg); struct device_driver driver; const struct i2c_device_id *id_table;//该驱动所支持的i2c设备的ID表 int (*detect)(struct i2c_client *, struct i2c_board_info *); const unsigned short *address_list; struct list_head clients; };
i2c_client对应真实的物理设备,每个i2c设备都需要一个i2c_client来描述
struct i2c_client { unsigned short flags; /* div., see below */ unsigned short addr; /* chip address - NOTE: 7bit */ /* addresses are stored in the */ /* _LOWER_ 7 bits */ char name[I2C_NAME_SIZE]; struct i2c_adapter *adapter; /* the adapter we sit on */ struct i2c_driver *driver; /* and our access routines */ struct device dev; /* the device structure */ int irq; /* irq issued by device */ struct list_head detected; };
(1)i2c_adapter与i2c_algorithm
一个I2C适配器需要i2c_algorithm中提供的通信函数来控制适配器上产生特定的访问周期。i2c_algorithm中的关键函数master_xfer()用于产生I2C访问周期需要的信号,以i2c_msg为单位。
struct i2c_msg { __u16 addr; /* slave address */ __u16 flags; __u16 len; /* msg length */ __u8 *buf; /* pointer to msg data */ };
(2)i2c_adapter与i2c_client
i2c_driver与i2c_client是一对多的关系,一个i2c_driver上可以支持多个同等类型的i2c_client。
(3)i2c_adapter与i2c_client
i2c_adapter与i2c_client的关系与I2C硬件体系中适配器和从设备的关系一致,i2c_client依附在i2c_adapter上。
- (5)LinuxI2C驱动--浅谈LinuxI2C驱动架构
- (1)LinuxI2C驱动--概述
- (6)LinuxI2C驱动--I2C设备驱动
- (7)LinuxI2C驱动--I2C总线驱动
- (2)LinuxI2C驱动--I2C总线
- LinuxI2C总线驱动深入分析
- LinuxI2C总线驱动大致框架
- LinuxI2C总线驱动深入分析
- (3)LinuxI2C驱动--解析EEPROM的读写
- LinuxI2C子系统架构
- (4)LinuxI2C驱动--从两个访问eeprom的例子开始
- LinuxI2C驱动--从两个访问eeprom的例子开始
- LinuxI2C驱动--从两个访问eeprom的例子开始
- linuxi2c-core.c
- 新手写LinuxI2C驱动程序
- 浅谈USB驱动架构
- nginx 源码(5)事件驱动架构
- MDA(模型驱动架构)
- 数据结构与算法14: 利用Graphviz快速可视化树(visualizing Trees with Graphviz easily )
- j2se 随记
- 不要在大城市中迷失了自己
- IOS SDK详解之UIAlertController(IOS8之后替代AlertView和ActionSheet)
- 每个Javascript开发者都应当知道的那些事(转载)
- (5)LinuxI2C驱动--浅谈LinuxI2C驱动架构
- linux命令:cd命令
- 二叉树
- 报数问题
- java ee 基础常识
- perl 监控mysql数据库
- Algorithms—46.Permutations
- Error:duplicate files during packaging of APK Path in archive: META-INF/LICENSE.txt
- 获取和处理发送post request和head数据