【I2C】Linux使用GPIO模拟I2C

news2024/11/25 8:36:45

文章目录

  • 1. I2C GPIO系统架构简介
  • 2. 如何使能I2C GPIO驱动
    • 2.1 config配置
    • 2.2 dts配置
    • 2.3 测试验证
  • 3. 简单分析i2c-gpio.c驱动
    • 3.1 解析设备树
    • 3.2 配置SDA和SCL
    • 3.3 注册到i2c-algo-bit.c
  • 4. 简单分析i2c-algo-bit.c驱动
    • 4.1 提供I2C通信时的算法
    • 4.2 注册Adapter
  • 5. 参考资料

1. I2C GPIO系统架构简介

在Linux项目中,如果出现硬件硬件I2C不够用的情况下,我们就可以通过GPIO模拟I2C来解决。
Lnux内核的i2c-gpio是使用GPIO模拟I2C协议的驱动,在内核中已经实现了,我们要做的只需要配置2个GPIO(SDA和SCL)即可。

i2c-gpio的大致框架如下:
在这里插入图片描述
i2c-gpio.c

  • 解析设备树中的引脚配置信息
  • 提供GPIO SDA和SCL引脚配置接口。

i2c-algo-bit.c

  • 向I2C Core注册一个adapter
  • 提供I2C通信时的算法,然后通过i2c-gpio.c提供GPIO配置接口来收发数据。

注册成功后,"i2c-dev"驱动就会自动创建对应的"/dev/i2c-x"字符设备,然后我们就可以在应用层和驱动层操作该总线。

2. 如何使能I2C GPIO驱动

2.1 config配置

在对应的板级deconfig文件中,设置CONFIG_I2C_GPIO=y
对应的选项为:

Device Drivers->
    I2C support  --->
        I2C Hardware Bus support  --->
            <*> GPIO-based bitbanging I2C

确认配置后,i2c-gpio相关驱动就会被编译进内核。

2.2 dts配置

  • 修改一
    我这里是在IMX6ULL平台上测试的,修改文件:arch/arm/boot/dts/imx6ul.dtsi
    在这里插入图片描述
    !!!为什么需要修改aliases呢?!!!
    因为在添加添加adapter时,会通过aliases的别名编号配置adapter->nr总线编号。注册成功后,会创建/dev/i2c-4设备。
    在这里插入图片描述
  • 修改二
    添加需要模拟i2c的gpio,一定是先放sda再放scl,因为它是在i2c-gpio.c里面定义好的,必须这么写才可以。
    i2c5:i2c5_gpio {
    	#address-cells = <1>;
    	#size-cells = <0>;
    	compatible = "i2c-gpio";
    	gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>, 	/* sda */
    			<&gpio1 28 GPIO_ACTIVE_HIGH>; 	/* scl */
    	i2c-gpio,delay-us = <5>;		/* ~100 kHz */
    	status = "disabled";
    };
    
    图片效果如下:
    在这里插入图片描述
    !!!什么时候需要添加open drain属性?!!!
    使用GPIO模拟I2C模式时,一般GPIO需要工作在开漏模式。在of_i2c_gpio_get_props函数中,解析是否有定义open drain相关属性。如下:
    在这里插入图片描述
    当定义i2c-gpio,sda-open-draini2c-gpio,scl-open-drain属性后,说明是其它子系统已经将该GPIO配置成开漏输出了,这里不再进行开漏的配置。如果dts里面不定义,就启动GPIOD_OUT_HIGH_OPEN_DRAIN配置GPIO。所以,我这里并没有定义该属性,需要它在这里配置为开漏。
    在这里插入图片描述
  • 修改三
    使能模拟i2c5总线,并且在该总线下挂载ap3216c设备。
    &i2c5 {
    	status = "okay";
    	
    	ap3216c@1e {
    		compatible = "lite-on,ap3216c";
    		reg = <0x1e>;
    	};
    };
    

2.3 测试验证

重新编译烧录固件后,这里新增了/dev/i2c-4总线设备,它就是我们新增的GPIO模拟I2C总线设备。
在这里插入图片描述
使用i2c_tools测试该总线,可以正常的识别到设备,说明移植已经成功了。(备注:需要了解i2c_tools使用的,可以参考这篇博客《【I2C】基于Linux移植i2c-tool工具》)
在这里插入图片描述

3. 简单分析i2c-gpio.c驱动

前面已经提到i2c-gpio.c驱动主要是3个功能:

3.1 解析设备树

在probe函数中会调用of_i2c_gpio_get_props函数来解析相关属性:

  • i2c-gpio,delay-us:配置每个bit的使用时间,也就是I2C通信时Clock的频率。
  • i2c-gpio,timeout-ms:配置i2c通信时的超时时间,如果超过这个时间没有收到ack,说明通信失败。
  • i2c-gpio,sda-open-drain:是否有在其它子系统里面定义了sda gpio为开漏模式,如果有就定义该属性。
  • i2c-gpio,scl-open-drain:是否有在其它子系统里面定义了scl gpio为开漏模式,如果有就定义该属性。
  • i2c-gpio,scl-output-only:配置scl gpio只支持输出模式,不支持输入模式。

具体代码如下:

static void of_i2c_gpio_get_props(struct device_node *np,
				  struct i2c_gpio_platform_data *pdata)
{
	u32 reg;

	of_property_read_u32(np, "i2c-gpio,delay-us", &pdata->udelay);

	if (!of_property_read_u32(np, "i2c-gpio,timeout-ms", &reg))
		pdata->timeout = msecs_to_jiffies(reg);

	pdata->sda_is_open_drain =
		of_property_read_bool(np, "i2c-gpio,sda-open-drain");
	pdata->scl_is_open_drain =
		of_property_read_bool(np, "i2c-gpio,scl-open-drain");
	pdata->scl_is_output_only =
		of_property_read_bool(np, "i2c-gpio,scl-output-only");
}

通过i2c_gpio_get_desc解析dts设备树文件里面定义gpios配置
gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>, <&gpio1 28 GPIO_ACTIVE_HIGH>;
具体代码如下:

	if (pdata->sda_is_open_drain)
		gflags = GPIOD_OUT_HIGH;
	else
		gflags = GPIOD_OUT_HIGH_OPEN_DRAIN;
	priv->sda = i2c_gpio_get_desc(dev, "sda", 0, gflags);
	if (IS_ERR(priv->sda))
		return PTR_ERR(priv->sda);

	if (pdata->scl_is_open_drain)
		gflags = GPIOD_OUT_HIGH;
	else
		gflags = GPIOD_OUT_HIGH_OPEN_DRAIN;
	priv->scl = i2c_gpio_get_desc(dev, "scl", 1, gflags);

3.2 配置SDA和SCL

配置操作SDA和SCL 2个GPIO的函数接口,后面可以通过它设置和获取GPIO的高低电平,具体代码如下:

bit_data->setsda = i2c_gpio_setsda_val;
bit_data->setscl = i2c_gpio_setscl_val;

if (!pdata->scl_is_output_only)
	bit_data->getscl = i2c_gpio_getscl;
bit_data->getsda = i2c_gpio_getsda;

3.3 注册到i2c-algo-bit.c

将配置好struct i2c_adapter的信息注册到i2c-algo-bit.c驱动中,具体代码如下:

adap->algo_data = bit_data;
adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adap->dev.parent = dev;
adap->dev.of_node = np;

adap->nr = pdev->id; // 其实这里adapter的编号是-1,真正的编号是后面注册时aliases获取的。前面已经有分析。
ret = i2c_bit_add_numbered_bus(adap);

4. 简单分析i2c-algo-bit.c驱动

前面已经提到i2c-algo-bit.c驱动主要是2个功能:

4.1 提供I2C通信时的算法

__i2c_bit_add_bus函数中会这一个i2c_bit_algo算法接口,我们使用i2c_transfer收发数据时,最终都会调用到i2c_bit_algo的bit_xfer函数收发数据。

const struct i2c_algorithm i2c_bit_algo = {
	.master_xfer = bit_xfer,
	.master_xfer_atomic = bit_xfer_atomic,
	.functionality = bit_func,
};

adap->algo = &i2c_bit_algo;

代码里面定义了很多模拟i2c时序的函数,就算我们自己写GPIO模拟I2C驱动,也都必须实现这些函数。
在这里插入图片描述

4.2 注册Adapter

向I2C Core注册一个adapter,注册成功后,"i2c-dev"驱动就会自动创建对应的"/dev/i2c-x"字符设备,然后我们就可以在应用层和驱动层操作该总线。具体代码如下:

static int __i2c_bit_add_bus(struct i2c_adapter *adap,
			     int (*add_adapter)(struct i2c_adapter *))
{
	...
	
	ret = add_adapter(adap);
	if (ret < 0)
		return ret;

	return 0;
}

int i2c_bit_add_numbered_bus(struct i2c_adapter *adap)
{
	return __i2c_bit_add_bus(adap, i2c_add_numbered_adapter);
}

5. 参考资料

Linux内核驱动:gpio模拟i2c驱动:
https://blog.csdn.net/landishu/article/details/118441943

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/638776.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

翻车了,被读者找出 BUG

大家好呀&#xff0c;我是小楼。 本文是上篇文章《使用增强版 singleflight 合并事件推送&#xff0c;效果炸裂&#xff01;》的续集&#xff0c;没看过前文必须要先看完才能看本文&#xff0c;实在不想看&#xff0c;拉到文章末尾&#xff0c;给我点个赞再退出吧~Doge 上篇文…

如何进行App性能测试?SoloPi是最佳选择!

目录 引言 SoloPi简介 SoloPi特点 SoloPi的主要功能 下载SoloPi 安装SoloPi 使用SoloPi进行性能测试 性能数据查看与记录 环境加压 响应耗时计算工具 注意事项 Solopi提供的各项性能指标介绍 引言 大家好&#xff01;我是凡哥。 今天我想跟你们分享一下如何进行A…

Python的接口自动化-读写excel文件

目录 引言 一、xlrd、xlwt以及xlutils安装 二、xlrd操作excel文件的数据读取 三、xlwt向excel文件写入数据 四、xlutils操作excel文件 五、封装操作excel读和写的类 引言 使用python进行接口测试时常常需要接口用例测试数据、断言接口功能、验证接口响应状态等&#xff0…

Mysql升级8.0后日期类型兼容性问题

背景 最近对原有项目数据库进行升级&#xff0c;从MySQL 5.7 升级到8.0&#xff0c;因此项目种的驱动程序也要做相应升级。 问题 一、 升级后报&#xff1a;java.time.LocalDateTime cannot be cast to java.util.Date 该问题是因为代码中使用Map类型获取查询返回值&#xf…

lightdb检测不兼容工具CheckUnsupportOracle使用说明

oracle有很多特性在lightdb无法使用&#xff0c;使用该工具可以即时扫描某个在线数据库或本地文件夹中有哪些不兼容特性&#xff0c;-a -x对oracle不兼容特性有所区别&#xff0c;扫描范围可参考后续表格。 0、使用限制 默认扫描存储过程&#xff0c;函数及包默认仅支持oracl…

19JS10——预解析

文章目录 一、预解析二、变量预解析和函数预解析三、预解析案例1、案例1&#xff1a;结果是几&#xff1f;2、案例2&#xff1a;结果是几&#xff1f;3、案例3&#xff1a;结果是几&#xff1f;4、案例4&#xff1a;结果是几&#xff1f; 目标&#xff1a; 1、预解析 2、变量预…

电脑连上wifi但显示无网解决方案分享,轻松搞定电脑上网问题

有的时候我们会遇到这样的问题&#xff1a;电脑明明连接了网络但仍不能上网&#xff0c;并且出现错误提示“WiFi已连接但没有互联网”。遇到这种情况&#xff0c;我们可以先使用另一台设备访问网络&#xff0c;看看你能否正常上网。如果也不能上网&#xff0c;可以尝试重新启动…

七牛云存储开启referer防盗链后,微信小程序访问提示403

点击七牛云存储存储桶绑定的加速域名 配置站点域名和微信小程序域名 是否允许空Referer一定要打开&#xff0c;否则小程序上的视频或图片访问时将提示403

# 如何在Git上更改本地分支名称和远程分支名称

有时候我们需要修改git分支名称&#xff0c;例如不合理的分支名称。本篇文章分享了如何轻松地修改Git本地分支名称和修改远程分支名称。 在Git中&#xff0c;通常使用分支来使开发与您的主要工作流程分开。在软件工程团队中&#xff0c;通常要实施特定的工作流程。例如&#x…

[C语言实现]数据结构之《关于我转生成队列这档事》

&#x1f970;作者: FlashRider &#x1f30f;专栏: 数据结构 &#x1f356;知识概要&#xff1a;详解队列的概念、顺序队列和链式队列的优点和缺点&#xff0c;以及代码实现。 目录 什么是队列&#xff1f; 选择什么结构来实现队列&#xff1f; 链式队列的实现 队列的结构…

在UE中使用Stencil功能

Stencil是指利用深度buffer的后8位数据进行bit mask信息的绘制&#xff0c;从而制作类似角色mask遮罩等效果&#xff0c;下面就在UE中进行制作。 1.首先在Project Settings项目设置中开启stencil&#xff0c;搜索stencil关键字在Custom Depth Stencil Pass选项中设置为Enabled…

PNAS:勘探地球物理学论文

阅读 《Sensing prior constraints in deep neural networks for solving exploration geophysical problems dendrimers》 题目译为《深度神经网络中用于解决勘探地球物理问题的感知先验约束》 研究意义 该研究提出三种可能的策略&#xff0c;以有效地讲地质和/或地球物理约…

面试官再问分布式事务,三天吃透这份至尊级学习笔记怼他

分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简单的说&#xff0c;就是一次大的操作由不同的小操作组成&#xff0c;这些小的操作分布在不同的服务器上&#xff0c;且属于不同的应用&#xff0c;分布式…

ABAP 新语法--Open SQL(草稿)

1. 常量 1.1 常量赋值 常量字段可以用来为内表中的部分字段赋初始值&#xff0c;字段类型和长度依据输入常量的值决定 SELECTmara~matnr, " 物料号mara~matkl, " 物料组mara~mtart, " 物料类型 AS lkenz, " 删除标识&#xff0c;常量空字符串123 AS fla…

QCon高分演讲:火山引擎容器技术在边缘计算场景下的应用实践与探索

近日&#xff0c;火山引擎边缘云原生团队的同学在QCon全球软件开发大会上分享了火山引擎容器技术在边缘计算场景下的应用实践与探索&#xff0c;并在一众AIGC、LLM等当下热门议题中脱颖而出&#xff0c;入选观众满意度投票中“叫好又叫座议题Top5”。 以下是演讲全文&#xff1…

论文阅读 Interpretable Unified Language Checking

本文提出了一种新的方法来解决多种自然语言处理任务中的问题&#xff0c;包括公平性检查、事实检查、虚假新闻检测和对抗攻击检测等。该方法基于大型语言模型和少量人类标注的提示信息&#xff0c;通过在模型中引入相应的提示&#xff0c;来提高模型的性能和可解释性。该论文的…

数据库索引及优化

索引 1.索引简介 1.1 概念 MySQL官方对索引的定义为&#xff1a;索引&#xff08;Index&#xff09;是帮助MySQL高效获取数据的数据结构。索引的本质&#xff1a;索引是数据结构。 注&#xff1a;在数据之外&#xff0c;数据库系统还维护着满足特定查找算法的数据结构&…

第二章---感知机

&#x1f31e;欢迎来到深度学习的世界 &#x1f308;博客主页&#xff1a;卿云阁 &#x1f48c;欢迎关注&#x1f389;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f31f;本文由卿云阁原创&#xff01; &#x1f64f;作者水平很有限&#xff0c;如果发现错误&#xff…

centos各个版本jenkins部署

目录 官网安装方法 安装java&#xff0c;**注意java版本&#xff0c;新版本jenkins只支持jdk11及以上 安装jenkins Jenkins启动失败的七个问题 jenkins 部署脚本 Nginx转发jenkins服务 官网安装方法 Redhat Jenkins Packages (jenkins-ci.org)https://mirrors.jenkins-c…

微信朋友圈怎么定时发送?微信朋友圈定时发送有什么优势?

刷朋友圈已经成为大部分人日常中不可缺少的一件事&#xff0c;同时也是企业用来触达客户的重要渠道。下面一起来了解一下微信朋友圈定时发送的优势有哪些&#xff0c;还有怎么定时发朋友圈吧。 定时发朋友圈的优势有哪些&#xff1f; 1、让企业能够更好地管理自己的宣传信息 …