(1)
IIC总线架构分析:
i2c设备驱动层组件(i2c-dev.c)
============================================================================
功能:
1.给用户提供调用接口
2.实现策略问题:它知道发什么数据,但是不知道怎么发数据
i2c核心层组件(i2c-core.c)
============================================================================
功能:
1.注册一根i2c总线
2.给驱动编程人员提供编程接口
i2c总线驱动层组件(i2c-s3c2410.c)
============================================================================
功能:
1.初始化硬件(初始化i2c控制器)
2.实现操作方法:(根据i2c操作时序进行控制i2c控制器实现数据接收/发送)它知道怎么去发送数据,但是不知道发什么数据。
I2C架构概述
Linux 的I2C体系架构分为3个组成部分:
(1)I2C核心:I2C核心提供了I2C总线驱动和总线设备注册,注销,通信方法。还提供了与适配器相关的代码以及探测代码等。
(2)I2C总线驱动:I2C总线驱动是对I2C硬件体系结构中适配器驱动的实现。(IIC使用的是平台设备驱动模型)
(3)I2C设备驱动:I2C设备驱动是对设备端的实现(客户驱动),比如EEPROM设备。
Hardware 是我们的硬件设备,调试设备的时候我们经常在这用示波器来跟踪I2C通讯波形。
根据I2C架构概述的介绍,可以知道:
I2C核心:I2C核心层
I2C总线驱动(platform bus):硬件实现控制层,访问抽象层
I2C设备驱动(device driver):driver层
注意:在我们linux I2C子系统中,有使用到平台设备驱动机制。使用平台设备驱动的主要目是:将硬件/平台相关的东西分离出来,以提高程序的可移植性。
(2)
i2c是很流行的串行半双工通信协议,主从架构。
linux 中有关于i2c子系统的实现支持,其和平台无关的,具体实现需要驱动工程师自己实现。
linux i2c中核心代码是i2c-core.c 其有i2c适配器、i2c算法、i2c驱动以及i2c设备注册、注销以及数据处理的实现。
i2c子系统各部分的关系:i2c适配器是设备,是i2c具体外设(外部或芯片内部)的抽象,i2c算法是i2c适配器的驱动,i2c设备是挂载到i2c外设的设备抽象,i2c驱动是i2c设备的驱动
(3)
主要数据结构
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.pm = &i2c_device_pm_ops,
};
struct i2c_adapter //i2c适配器抽象(其实算上相关操作函数才是真正的抽象),代表i2c外设设备,其需要由相关的algorithms才能工作。
{
struct module *owner; 内核模块指针。
unsigned int class; 代表哪类设备,不需要具体class指针,只是标记是哪类设备,用来匹配用的。
const struct i2c_algorithm *algo; 其用来操作设备的算法,是其驱动,没有算法适配器无法工作。
void *algo_data; 算法用到的数据。
struct rt_mutex bus_lock; 实时互斥锁,用来防止优先级翻转的,是实时进程需要的锁。
int timeout; 操作超时时间。
int retries;
struct device dev; 设备驱动模型的代表。
int nr; 适配器号,即总线号,linux idr模块使用的,用来所以适配器其指针的。
char name[48]; 名称
struct completion dev_released; linux完成量
struct mutex userspace_clients_lock; 互斥量
struct list_head userspace_clients; 设备链表
}
#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev) 通过设备地址找到相应的适配器地址。
struct i2c_algorithm //i2c算法即适配器驱动,是i2c通信协议的时序实现。
{
int (*master_xfer) 和外设的通信函数
int (*smbus_xfer) smbus协议通信函数
u32 (*functionality) (struct i2c_adapter *); 查询是否支持适配器
}
struct i2c_msg //i2c信息段:包含一包发送或接受数据的信息。
{
__u16 addr; i2c从设备地址,可以是7bit或10bit
__u16 flags i2c信息标志,代表地址长度 、读写数据等一些i2c协议标志
__u16 len; i2c消息长度*/
__u8 *buf; i2c消息指针
}
struct i2c_client //是挂载i2c外设上的设备抽象。
{
unsigned short flags i2c设备标志,用来表示设备的地址长度以及设备协议类型
unsigned short addr; 设备地址
char name[I2C_NAME_SIZE]; 名称
struct i2c_adapter *adapter; 所需适配器设备
struct i2c_driver *driver; 所匹配的设备驱动
struct device dev; 设备模型的设备代表
int irq; 设备所使用的中断后
struct list_head detected; i2c驱动中设备链表节点
}
struct i2c_driver //是i2c设备驱动的抽象
{
unsigned int class; 所属的类,和i2c适配器匹配
int (*attach_adapter) 以及废弃的函数,保持兼容
int (*probe)(struct i2c_client *, const struct i2c_device_id *); 驱动探测设备函数
int (*remove)(struct i2c_client *); 驱动移除设备函数
struct device_driver driver; 设备驱动模型中驱动代表
const struct i2c_device_id *id_table; i2c设备匹配表
int (*detect)(struct i2c_client *, struct i2c_board_info *); i2c设备检查函数,用来探测相关i2c设备
const unsigned short *address_list; i2c设备地址指针
struct list_head clients; i2c设备链表头,用来遍历驱动中设备
}
struct i2c_device_id //i2设备匹配表,i2c驱动用来匹配i2c设备的,
{
char name[I2C_NAME_SIZE]; i2c支持的设备名称
}
struct i2c_board_info //是静态创建i2c设备的模板,i2c设备分为静态创建和动态探测创建。
{
type: chip type, to initialize i2c_client.name 用来初始化设备名称
flags: to initialize i2c_client.flags 初始化设备标志
addr: stored in i2c_client.addr 初始化设备地址
platform_data: stored in i2c_client.dev.platform_data 初始化设备模型的平台相关数据
archdata: copied into i2c_client.dev.archdata 初始化设备模型子架构数据
of_node: pointer to OpenFirmware device node 用来构建设备树
irq: stored in i2c_client.irq
}