RK3576 android14 I2C总线,硬件I2C 与 GPIO模拟I2C 比对

在嵌入式 Linux 板级开发里,接一颗带 I2C 接口的外设时,常常会遇到两种做法:一是走 SoC 自带的 硬件 I2C 控制器,二是用两个 GPIO 软件模拟 成一条 I2C 总线。表面上看,二者在设备树里都能挂出同样的 i2c_client,驱动层也往往无感;但在 速率、波形质量、EMI、休眠与 IO 供电域、以及量产后的稳定性上有所差别。

一,两种方案参数对比

硬件i2c(soc外设控制器) gpio模拟i2c(i2c-gpio)
CRU 提供时钟,内核 i2c-designware 等驱动控制 SCL/SDA 时序 用两个 GPIO 在软件里 bit-bang,每比特多次 GPIO 翻转
易做 100k / 400k / 1M(受 clock-frequency 与从设备能力限制) 实际有效速率明显低于硬件 I2C,且与 delay-us、CPU 负载强相关
需占用 一组复用为 I2C 功能 的管脚(pinctrl 切到 i2cX xfer) 占用 任意 GPIO,功能保持为 GPIO 模式即可
硬件时序规整,上升沿/占空比由控制器与 IO 驱动能力保证 依赖 GPIO 驱动强度、走线、外部上拉;delay-us 过小易误码
控制器可随时钟门控;管脚电平与 IO 电压域(VCCIO)、休眠策略相关 同样受 VCCIO 保持 / 掉电 影响;无独立控制器时钟,但 GPIO 域掉电会直接"哑火"
标准 &i2cN { ... };,子节点 reg 为从机地址 compatible = "i2c-gpio",子设备写法与硬件 I2C 相同(对上层驱动透明)

总结:能走硬件 I2C、且管脚和复用都允许时,优先硬件 I2C;只有布线/复用冲突、或必须"任意脚"接从设备时,再用 GPIO 模拟,并接受速率、可靠性与休眠场景上的额外工程成本。


二,硬件 I2C

典型硬件 I2C:使能控制器、pinctrl 切到 I2C 复用、下面挂 reg = <0x**> 等子设备。

举个例子:

bash 复制代码
&i2c6 {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&i2c6m3_xfer>;

	sgm41542: sgm41542@3b {
		compatible = "sgm,sgm41542";
		status = "okay";
		reg = <0x3b>;
		extcon = <&u2phy0>, <&usbc0>;
		pinctrl-names = "default";
		pinctrl-0 = <&charger_ok>;
		interrupt-parent = <&gpio0>;
		interrupts = <RK_PD2 IRQ_TYPE_EDGE_FALLING>;
		otg-mode-en-gpios = <&gpio2 RK_PC7 GPIO_ACTIVE_HIGH>;
		input-voltage-limit-microvolt = <4500000>;
		input-current-limit-microamp = <3000000>;
		monitored-battery = <&bat>;
		regulators {
			vbus5v0_typec: vbus5v0-typec {
				regulator-compatible = "otg-vbus";
				regulator-name = "vbus5v0_typec";
			};
		};
	};

pinctrl-0 = <&i2c6m3_xfer> ; 表示 SCL/SDA 在 芯片复用功能 上,由 I2C 控制器驱动,而不是软件 toggling。
clock-frequency; 直接约束总线速率;与 i2c-gpio,delay-us 的调参逻辑完全不同。


三、GPIO 模拟 I2C

当硬件I2C控制器资源不足或需要特殊引脚配置时,GPIO模拟方案提供了灵活的替代选择。GPIO子系统支持开漏(OD)模式,可直接模拟I2C总线所需的线"与"特性。

举个例子:

bash 复制代码
/* GPIO 模拟 I2C 控制器节点:对内核表现为一个 i2c_adapter */
i2c_nfc: i2c-nfc {
	compatible = "i2c-gpio";

	/* SDA/SCL 必须为开漏语义:ACTIVE_HIGH | OPEN_DRAIN */
	sda-gpios = <&gpio2 RK_PD1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
	scl-gpios = <&gpio2 RK_PD0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;

	/*
	 * 每步 GPIO 操作之间的延时;过小易在长线/大电容总线上 NACK/丢包,
	 * 过大则降低有效速率。需结合示波器与 NFC 芯片手册在板级微调。
	 */
	i2c-gpio,delay-us = <20>;

	#address-cells = <1>;
	#size-cells = <0>;

	pinctrl-names = "default";
	/* 将相关脚固定为 GPIO 功能及 IRQ 脚上下拉 */
	pinctrl-0 = <&i2c_nfc_gpio &nfc_int_gpio>;
	status = "okay";

	/* 下游子设备写法与硬件 I2C 总线上一致 */
	nfc@38 {
		compatible = "nxp,nxpnfc";
		reg = <0x38>;
		interrupt-parent = <&gpio2>;
		interrupts = <RK_PC6 IRQ_TYPE_LEVEL_HIGH>;
		nxp,nxpnfc-irq = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
	};
};

aliases 里把 i2c10 指到 i2c_nfc,方便用户空间或文档用「逻辑编号」指代这条模拟总线:

bash 复制代码
		i2c8 = &i2c8;
		i2c9 = &i2c9;
		i2c10 = &i2c_nfc;
		i3c0 = &i3c0;

硬件 I2C 与 GPIO 模拟 I2C 都可能受 IO 电压域、休眠漏电策略影响;但 GPIO 模拟完全依赖 两根数据线处于合法空闲态(通常靠外部上拉 + 软件释放总线),一旦休眠路径上 IO 断电或态丢失,从设备可能锁死、需要掉电复位。


四,如何「抉择」?

  1. 优先选择硬件I2C控制器的场景:

高速数据传输(>100kHz)

多设备总线拓扑

实时性要求高的系统

需要DMA支持的批量传输

产品量产方案

  1. GPIO模拟I2C更合适的场景:

引脚资源紧张时的临时方案

特殊时序要求的设备

原型开发阶段的快速验证

低频(<10kHz)单设备通信

需要动态切换引脚的功能

实际项目里:只要原理图能把从设备的 SCL/SDA 接到 SoC 上可用的硬件 I2C 复用脚、且速率与可靠性有要求,就优先用硬件 I2C;只有在管脚/复用/布线已定型无法改线、或必须用普通 GPIO 才能接到从设备时,再接受 GPIO 模拟 I2C,并预留好上拉、位时序(如 delay-us)和休眠/供电域相关的联调成本。

相关推荐
不做无法实现的梦~1 小时前
常见工程分析软件
stm32·嵌入式硬件·算法
国产电子元器件2 小时前
电流检测信号漂移问题分析
单片机·嵌入式硬件
梁朝辉3 小时前
筛选运算放大器时对于开环增益这一项参数怎么看?
嵌入式硬件·硬件工程
轩Scott3 小时前
【无标题】
经验分享
中屹指纹浏览器3 小时前
2026指纹浏览器缓存机制深挖:HTTP强缓存与协商缓存隐性风控陷阱
经验分享·笔记
法雅特吉他3 小时前
入门吉他选购指南:桶型、材质、工艺对吉他性能的影响
经验分享·新媒体运营·学习方法·业界资讯·流量运营·材质·内容运营
zlinear数据采集卡3 小时前
单点接地设计电路深度解析:从理论原理到ZLinear采集卡的低噪声实战
c语言·单片机·嵌入式硬件·fpga开发
数据库小学妹3 小时前
数据库高可用架构实战:从主从复制到两地三中心的四层演进与避坑
数据库·经验分享·架构·dba
嵌入式小站3 小时前
STM32 零基础可移植教程 15:ADC 多通道扫描,读取三路 PWM 的平均电压
stm32·单片机·嵌入式硬件
Stick_ZYZ3 小时前
从项目启动到 Milvus 向量检索,我把 RAG 项目链路又打通了一层
java·人工智能·经验分享·ai·milvus