Linux内核i2c读写操作驱动架构
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
中断异常 处理程序
i2c_client{} 获取方式
条件: 2. 开发人员获取需要通信的 i2c 从设备:
i2c_client{}; 2. 分配读写操作 buf,进行读写操作
//xx_data.i2c_client 通过以上方法取得 struct xx_data {
struct i2c_client *i2c_client; } xx_data;
}; 成员变量解说: addr、flags 最初来源于 i2c_board_info{}结构成员,直接的来源是 i2c_client{}结构成员(如 上)。 关于 flags 的说明: 1) 由 i2c_board_info{}中传递的 flags,只起区分 addr 是 7 位还是 10 位的作用,默认为 7 位 地址,当使用 7 位 addr 时无需设置。(区分宏名:I2C_M_TEN) 2) flags 首先继承上面的来源于 i2c_board_info{}中的值,具备区分 addr 是 7 位还是 10 位的 功能 ,然后在 i2c_master_recv()、i2c_master_send()中再进一步依据是读写操作,来设置读 写操作标记以区分读写操作。(区分宏名:I2C_M_RD) 3) 由于 flags 读写位在 i2c_master_recv()、i2c_master_send() 中定义,所以如果要跨过此两 个函数,则需自行设置 flags 读写位。
硬件器 件中断
5
一、条件准备:
运用 i2c 子系统提供的驱动注 册机制,遍历匹配 i2c 总线的设 备链表,获取从设备;
手工编写代码,遍历匹配 i2c 总线的设备链表,获取从设备;
将 i2c_client{}从设备定义成全 局变量;
内核、其他驱动 的 i2c 读写事务
sys_write()、sys_read()、sys_ioctl() ... ...或新定义的系统调用
return -1; *val = u8RdVal; }
6
二、i2c 核心导出的接口层:
i2c_master_send()
i2c_master_recv()
循环调用
i2c_transfer() adap->algo->master_xfer()
循环次数内失败 -EAGAIN
-ETIMEDOUT 确定失败
};
成员变量解说: 1) addr, flags 分别表示从设备的地址和访问操作标志,最初源头为由开发人员构造和初始
化的 i2c_board_info{}结构 2) adapter 在从设备与适配器匹配后,在后端的 i2c_new_device()中被初始化
struct i2c_msg { __u16 addr; __u16 flags; __u16 len; __u8 *buf;
适配器平台驱动与平台资源匹配后
适配器驱动平台 probe(): i2c_imx->adapter.algo = &i2c_imx_algo; i2c_imx->adapter.retries = xx ; ... ... 再注册适配器设备,挂接到 i2c_client{};
i2c_imx_xfer()
sys_write()、sys_read()、sys_ioctl() ... ...或新定义的系统调用
中断异常 处理程序
i2c_client{} 获取方式
条件: 1. 开发人员获取需要通信的 i2c 从设备:
i2c_client{}; 2. 分配读写操作 buf,进行读写操作
i2c 核心导出的接口层:
};
成员变量解说: 1) addr 将初始化 i2c_client.addr 2) flags 将初始化 i2c_client.flags
struct i2c_client { unsigned short addr; unsigned short flags; struct i2c_adapter *adapter; ... ...;
{
struct i2c_adapter *adap = client->adapter;
struct i2c_msg msg;
msg.addr = client->addr; msg.flags = client->flags & I2C_M_TEN; msg.len = count; msg.buf = (char *)buf;
具体适配器驱动读写
#define I2C_M_TEN
0x0010
#define I2C_M_RD
0x0001
# define jiffies
raid6_jiffies()
int i2c_master_send(struct i2c_client *client, const char *buf, int count)
4
i2c 读写流程
运用 i2c 子系统提供的驱动注 册机制,遍历匹配 i2c 总线的设 备链表,获取从设备; 手工编写代码,遍历匹配 i2c 总线的设备链表,获取从设备; 将 i2c_client{}从设备定义成全 局变量;
应用层: write()、read()、ioctl()... ...
内核、其他驱动 的 i2c 读写事务
Байду номын сангаас
写操作
i2c_master_send()
读操作
i2c_master_recv()
循环次数:adapter.retries
i2c适配器驱动:(左为初始化) struct i2c_algorithm i2c_imx_algo = {
... ... .master_xfer = i2c_imx_xfer, }; 适配器平台驱动与平台资源匹配后 适配器驱动平台 probe(): i2c_imx->adapter.algo = &i2c_imx_algo; i2c_imx->adapter.retries = xx ; ... ... 再注册适配器设备,初始化 i2c_client{};
i2c_imx_write(): 寄存器操作
i2c_imx_read(): 寄存器操作
(这里以 i2c-imx.c 为例)
#define I2C_M_RD
0x0001
#define IMX_I2C_I2DR
0x10
struct imx_i2c_struct {
3
struct i2c_adapter { struct i2c_algorithm *algo; //见下 void *algo_data; int timeout; int retries; ... ...;
};
开发人员自己使用
成员变量解说: 1) timeout 可以由设计人员手工指定,不指定子系统将默认置 1HZ 2) retries 由设计人员手工指定 3) i2c_algorithm 对 i2c 适配器进行操作的接口
i2c_transfer(adap, &msg, 1); } EXPORT_SYMBOL(i2c_master_send);
int i2c_master_recv(struct i2c_client *client, char *buf, int count) {
struct i2c_adapter *adap = client->adapter; struct i2c_msg msg;
msg.addr = client->addr; msg.flags = client->flags & I2C_M_TEN; msg.flags |= I2C_M_RD; msg.len = count; msg.buf = buf;
i2c_transfer(adap, &msg, 1);
7
} EXPORT_SYMBOL(i2c_master_recv); int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) {
sda2
slave0-1
slave0-2
... ...
slave1-1
slave1-2
... ...
slave2-1
slave2-2
... ...
1
数据结构关系:
i2c_board_info{} .addr .flags ... ...
传递
由开发人员确定与哪 个 i2c 从设备进行通信
i2c_client{} .addr .flags *adapter ... ...
unsigned long orig_jiffies; int ret, try; ... ...; orig_jiffies = jiffies; if (adap->algo->master_xfer) {
... ...; for (ret = 0, try = 0; try <= adap->retries; try++) {
break; } return ret; } else{ return -EOPNOTSUPP; } } EXPORT_SYMBOL(i2c_transfer);
8
三、i2c 适配器驱动:(左为初始化)
struct i2c_algorithm i2c_imx_algo = { ... ...
.master_xfer = i2c_imx_xfer, };
ret = adap->algo->master_xfer(adap, msgs, num); //见下面 i2c-imx.c 的 i2c_imx_xfer() if (ret != -EAGAIN)
break; if (time_after(jiffies, orig_jiffies + adap->timeout))
i2c_algorithm{} *master_xfer *functionality ... ...
2
开发人员在调用 i2c_master_send() i2c_master_recv() 之前定义 长为 len 的 buf
i2c_imx_xfer() i2c_imx_func()
struct i2c_board_info { unsigned short addr; unsigned short flags; ... ...;
传递
在 i2c_master_send() i2c_master_recv() 中 定义
i2c_msg{} .addr .flags .len *buf
i2c_adapter{} *algo .timeout .retries *algo_data ... ...
开发人员自己使用
适配器驱动 probe 时挂接
struct i2c_algorithm { int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, int num); u32 (*functionality) (struct i2c_adapter *);
};
成员变量解说: 1) master_xfer 启动 i2c 适配器,分流读写操作的总接口 2) functionality 表示当前 i2c 适配器,支持和实现的操作功能
写操作示例: static xx_write(u8 val) {
u8 buf = val; i2c_master_send(xx_data.i2c_client, &buf, 1);//见下 }
读操作示例: static xx_read(u8 *val) {
u8 u8RdVal = 0; if (1 != i2c_master_recv(xx_data.i2c_client, &u8RdVal, 1 )) //见下
I2C 读写操作流程
目标:
分析整理 i2c 读写操作流程;
本文要点:
1、i2c 读写相关的数据结构及关系; 2、i2c 读写操作流程;
硬件框图:
2012 年 12 月 22 日
scl0 adapter i2c-0
sda0
scl1 adapter i2c-1
sda1
scl2 adapter i2c-2
循环调用
i2c_transfer() adap->algo->master_xfer()
循环次数内失败 -EAGAIN
-ETIMEDOUT 确定失败
写操作
成功
i2c_imx_xfer()
读操作
i2c_imx_write(): 寄存器操作
i2c_imx_read(): 寄存器操作
i2c 物理芯片电气操作