触摸屏I2C驱动移植
触摸屏简介
I2C 协议及 i2c 器件连接
每个连接到总线的器件都可使用软件根据它唯一的地址来识别,传输数据的设备之间是主从关系。
主机可做主机发送器或主机接收器;
多主机总线:两个或多个主机可同时发起数据传输,通过冲突检测及仲裁防止数据被破坏。
串行的 8 位双向数据传输。
主机:发起/停止数据传输,提供时钟信号的器件;
从机:被主机寻址的器件;
发送器:发送数据到总线的器件;
接收器:从总线接收数据的器件;
i2c 信号
S:SCL 高电平,SDA 由高到低跳变,开始传送数据;
P:SCL 高电平,SDA 由低到高跳变,结束传送数据;
transmitter 发送器 receiver 接收器;ACK:接收器在接收到 8 位数据后,在第 9 个时钟周期,拉低 SDA 电平;SDA 必须在 SCL 为高电平时有效,sda 数据必须在 SCL 为低电平下才可以发生变化;在第九个时钟是,主控会将 sda 拉高释放控制权,从设备收完数据后将 SDA 拉低,表示ack.
I2c 总线数据传输格式
发送到 SDA 总线上的每个字节必须是 8 位,每次传输可以发送的字节数量不受限制,每个字节后必须有一个响应位.先传输数据的高位(MSB).
GT9系列i2c接口有两个器件地址可用,我们用的是第一个0x5d:
配置触摸屏驱动
以友善电子的rk3399装的安卓系统为例;
打开系统配置菜单:
ron@ubuntu:~/work/rk3399-android-8.1$ cd kernel/
ron@ubuntu:~/work/rk3399-android-8.1/kernel$ make menuconfig
找到触摸屏Goodix GT9xx配置的Multi-touch Protocol A,取消选择、编译、重烧后,此屏幕触摸功能就会失效,原因是我们去掉了Goodix GT9xx的驱动程序。
linux i2c子系统(框架)
软件框架简图:
硬件框架简图:
查找匹配的设备树节点
kernel/arch/arm64/boot/dts/rockchip$ grep -nir "goodix_ts" rk3399*
rk3399-nanopi4-common.dtsi:851: gt9xx: goodix_ts@5d {
i2c4:i2c编号为4的控制器节点,包含了goodix,gt9xx的从设备信息。
所以,i2c4在驱动加载时,顺便生成了goodix,gt9xx的从设备信息,并放入从设备总线上,等着自己写的驱动程序匹配(通过competible属性);
i2c驱动框架用到5个核心对象
i2c驱动分层原理图:
i2c设备完成代码分析:
i2c子系统 工作原理分析
从两条主线入手
1.调用关系 如果贯穿?
应用
ret =read(fd, buf, sizeof(buf));//===========应用层
|
|
sys_read
|
|
gt9xx_read //===========从设备驱动层
|
|
ret = gtp_i2c_read(i2c_connect_client, buf, sizeof(buf));
|
|
struct i2c_msg msgs[2]; //创建2个数据包对象
msgs[0].flags = !I2C_M_RD; //写标志
msgs[0].addr = client->addr; //器件地址
msgs[0].len = GTP_ADDR_LENGTH;//16位地址
msgs[0].buf = &buf[0]; //存放寻址用地址的首地址
msgs[1].flags = I2C_M_RD; //读标志
msgs[1].addr = client->addr; //器件地址
msgs[1].len = len - GTP_ADDR_LENGTH; //设置要读的字节数
msgs[1].buf = &buf[GTP_ADDR_LENGTH];//存放读出来的内容的首地址
ret = i2c_transfer(client->adapter, msgs, 2);//将数据包交给底层函数进行收发数据包
|
| //===================== i2c核心层
ret = __i2c_transfer(adap, msgs, num);
|
|
for (ret = 0, try = 0; try <= adap->retries; try++) {
ret = adap->algo->master_xfer(adap, msgs, num);
| 函数指针找不到定义
| //======================???
}
2.分层 每层原理2.1 适配器层
入口和出口函数被封装
module_platform_driver(rk3x_i2c_driver);#define module_platform_driver(__platform_driver) \
module_driver(__platform_driver, platform_driver_register, \
platform_driver_unregister)#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);//创建平台驱动对象并初始化
static struct platform_driver rk3x_i2c_driver = {
.probe = rk3x_i2c_probe,
.remove = rk3x_i2c_remove,
.driver = {
.name = "rk3x-i2c",
.of_match_table = rk3x_i2c_match,//匹配条件
.pm = &rk3x_i2c_pm_ops,
},
};static const struct of_device_id rk3x_i2c_match[] = {
。。。
},
{
.compatible = "rockchip,rk3399-i2c",
.data = (void *)&rk3399_soc_data
},
{},
};struct rk3x_i2c {
struct i2c_adapter adap;
struct device *dev;
wait_queue_head_t wait;
。。。
};//设备树节点和平台驱动匹配成功
static int rk3x_i2c_probe(struct platform_device *pdev)
|
struct device_node *np = pdev->dev.of_node; //拿节点对象
struct rk3x_i2c *i2c;//本地结构体对象
i2c = devm_kzalloc(&pdev->dev, sizeof(struct rk3x_i2c), GFP_KERNEL);//创建本地对象
//初始化adapter对象
strlcpy(i2c->adap.name, "rk3x-i2c", sizeof(i2c->adap.name));//i2c-4 名字
i2c->adap.owner = THIS_MODULE;
i2c->adap.algo = &rk3x_i2c_algorithm; //注册算法对象 i2c通信就可以调下去了
i2c->adap.retries = 3;
i2c->adap.dev.of_node = np;
i2c->adap.algo_data = i2c;
i2c->adap.dev.parent = &pdev->dev;
//拿地址资源并IO映射
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
i2c->regs = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(i2c->regs))
return PTR_ERR(i2c->regs);
//拿中断资源申请中断
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "cannot find rk3x IRQ\n");
return irq;
}ret = devm_request_irq(&pdev->dev, irq, rk3x_i2c_irq,
0, dev_name(&pdev->dev), i2c);
//时钟初始化ret = i2c_add_adapter(&i2c->adap);//注册adapter对象
|
|
i2c_register_adapter(adapter);
|
dev_set_name(&adap->dev, "i2c-%d", adap->nr); // /dev/i2d-0,1,2,
adap->dev.bus = &i2c_bus_type; //adapter注册 到 i2c_bus_type
adap->dev.type = &i2c_adapter_type;
res = device_register(&adap->dev);
of_i2c_register_devices(adap);
|
|
for_each_available_child_of_node(adap->dev.of_node, node) {//遍历i2c4下的子节点
if (of_node_test_and_set_flag(node, OF_POPULATED))
continue;
of_i2c_register_device(adap, node);
|
|
struct i2c_board_info info = {};
addr_be = of_get_property(node, "reg", &len); //读i2c4下的子节点的reg属性
addr = be32_to_cpup(addr_be);
info.addr = addr;
result = i2c_new_device(adap, &info);
|
|
struct i2c_client *client;
client = kzalloc(sizeof *client, GFP_KERNEL);//创建client对象
client->adapter = adap;//绑定adapter
client->addr = info->addr;//设置client的器件地址
client->dev.bus = &i2c_bus_type;//client注册到i2c总线
}2.2从设备驱动层
#define i2c_add_driver(driver) \
i2c_register_driver(THIS_MODULE, driver)
|
driver->driver.owner = owner;
driver->driver.bus = &i2c_bus_type; //i2c_driver注册 到 i2c_bus_type
触摸屏I2C驱动移植相关推荐
- linux i2c 内核初始io,linux I2C驱动移植
linux I2C驱动移植 I²C总线仅使用SCL,SDA两根信号线实现设备间的数据交互,被广泛应用于微控制领域芯片与芯片之间的通信,如EEPROM,实时时钟,小型LCD等与CPU之间的通信. I2C ...
- Zynq-Linux移植学习笔记之46-光模块I2C驱动移植
1.背景介绍 近期板卡上开始使用中航光电的光模块,查阅资料发现这些光模块都可以通过I2C来获取状态信息并进行开关控制,描述如下,其中需要特别注意的是所有光模块的读写I2C地址都是一样的,不可以挂在一根 ...
- linux i2c触摸屏驱动程序,触摸屏i2c设备和驱动的创建流程及方法
添加i2c设备的流程: 1. 初始化 i2c_board_info 结构信息 和 i2c_driver 结构 //设备驱动结构体 static struct i2c_driver goodix_ts_ ...
- NUC972触摸屏驱动移植过程分析(二)
https://blog.csdn.net/b7376811/article/details/86607529 今天继续分析NUC972的触摸屏驱动移植过程,上一节主要分析了触摸屏需要数据,今天来分析 ...
- 2.6.36.2 s3c6410 触摸屏驱动移植。
CSDN_Acanoe 的博客:http://blog.csdn.net/ACanoe 硬件环境:OK6410 A板,4.3 寸TFT 屏. 移植内核:Linux2.6.36.2 . 参考内核: 飞 ...
- 正点原子Linux阿尔法开发板4.3 寸多点电容触摸屏测试问题和gt9xx系列linux驱动移植
正点原子Linux阿尔法开发板4.3 寸多点电容触摸屏测试问题和gt9xx系列linux驱动移植 正点原子官方CSDN 4.3 寸多点电容触摸屏测试问题 正点原子gt9xx系列linux驱动移植 1. ...
- 9.触摸屏驱动移植实战
转自 https://edu.csdn.net/lecturer/505 朱老师物联网大讲堂 <5.linux驱动开发-第9部分-5.9.触摸屏驱动移植实战> 第一部分.章节目录 5.9. ...
- NUC972触摸屏驱动移植过程分析(一)
https://blog.csdn.net/b7376811/article/details/86514683 因为下一个项目可能会用到触摸屏,所以这段时间对触摸屏的驱动的移植进行了研究,今天正好有机 ...
- 移植基于linux-2.6.26.5内核s3c2410触摸屏驱动移植
移植基于linux-2.6.26.5内核s3c2410触摸屏驱动移植的过程记录下来: (1)首先打一个补丁:s3c2410_touchscreen.patch, 在内核解压的根目录下 patch -N ...
最新文章
- Nature子刊:精胺介导稻瘟病菌侵染水稻叶片的新机制!
- OVH公司进军英国数据中心市场
- GoldenGate SQL error 1403 mapping 错误解决方案
- OAuth2认证有一定的了解
- Scrapy_XPath选择器
- java解析tcp报文_JAVA语言TCP通信和JDBC示例(AIS信息解析)
- 启动车子温车_什么是冷车启动
- golang 对象转json
- window下安装ruby与sass(附ruby)
- 服务器维护封号,LOL客服的关于他们自己服务器问题导致账号被封号的问题
- 基于PHP+MySQL动漫周边商城销售网站的开发与设计
- 基于AT89S52单片机的蘑菇大棚环境监测系统论文(附录代码)
- windows渗透利器——PentestBox的内功和攻击力
- Android10.0 os定制化系列讲解导读
- 被风吹过的冬天 ——2
- 2017年12月英语六级翻译洞庭湖
- DVWA 之 CSP Bypass
- 以太坊黄皮书(1~6章)
- 被面试官问到频繁跳槽,求职者应该怎么回
- DDD(领域驱动设计)系列主题:DDD兴起的原因以及与微服务的关系
热门文章
- Makefile文件是什么?(一)
- Makefile文件是什么
- 判断当前浏览器是否为IE11
- Mac 设置 xdebug + Sublime 方法整理
- css动画其他div,删除另一个div时的CSS3 Transition动画
- 计算机网络socket翻译成中文,Socket的错误码和描述(中英文翻译)
- Oracle EBS 12.2.7系统克隆教程
- 克隆linux系统之后如何配置网络ip
- 未来微型计算机发展趋势,简述什么是单片机(单片机未来发展趋势)
- 数字图像处理知识点梳理——第八章 图像压缩