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)和休眠/供电域相关的联调成本。

相关推荐
GJGCY4 分钟前
财务智能体落地实践:RPA、大模型与规则引擎如何构建业财自动化闭环?
经验分享·ai·自动化·财务·智能体
尼喃2 小时前
662K和65Z5三脚稳压芯片PW6566,附引脚定义与典型电路图
嵌入式硬件
汇策研习社3 小时前
改良版ADX指标实战指南:告别传统ADX滞后、震荡误判难题
大数据·经验分享·金融·区块链·fastbull
tcpinchezhuwu3 小时前
教育行业AI落地实践:夜灯公考AI选岗与智能答疑系统架构解析
经验分享
cszn20264 小时前
AI如何自动识别PDF转换废标风险?智能评审项目实践
经验分享
卡梅德生物科技小能手5 小时前
卡美德生物科普MMP9(基质金属蛋白酶9):细胞外基质重塑的关键调节因子
经验分享·深度学习·生活
yyt3630458415 小时前
KlineChartQuant Tooltip 高频交互 200FPS 性能优化完整复盘
前端·经验分享·性能优化·typescript·vue·交互·chrome devtools
李永奉5 小时前
杰理可视化SDK开发-【BUG】配置“TWS两边同时按消息使能”功能后,按键单击功能无效失灵
开发语言·单片机·嵌入式硬件·物联网·bug
执迷不悟8236 小时前
51单片机--中断/定时/PWM
单片机·嵌入式硬件·51单片机
LuminousCPP7 小时前
C 语言集中实践全记录:顺序表 + 单链表原理实现与通讯录项目实战【附可运行源码】
c语言·开发语言·数据结构·经验分享·笔记