如何确定Linux中I2C适配器与总线的关联及固定总线编号
解决I2C适配器编号动态分配与可靠识别问题
一、显式静态分配I2C适配器编号
大部分Linux I2C控制器驱动支持通过Device Tree(DT)指定固定总线编号,避免动态分配带来的不确定性:
- 找到系统中所有I2C控制器节点(硬核IP对应节点通常是SoC厂商预定义的,如
&i2c0;软核IP是你在DT中自定义的节点) - 在每个控制器节点中添加
reg属性,第一个值设为你想要的固定总线编号(需确保编号不重复),后续值保留控制器的寄存器基地址与长度(依硬件架构而定) - 示例DT片段:
/* 硬核I2C控制器,指定为总线0 */ &i2c0 { reg = <0>; status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c0>; clock-frequency = <100000>; }; /* FPGA软核I2C控制器1,指定为总线1 */ fpga_i2c_1: i2c@0x40000000 { compatible = "xlnx,xps-i2c-1.00.a"; reg = <1 0x40000000 0x1000>; interrupts = <0 29 4>; clock-frequency = <100000>; #address-cells = <1>; #size-cells = <0>; status = "okay"; };
注意:不同驱动对reg属性的解析可能有差异,需对应驱动的文档确认格式。
二、可靠区分同名I2C总线
若静态编号分配不可行,可通过以下方式识别总线:
- 硬件路径匹配:每个I2C适配器的
/sys/class/i2c-dev/i2c-X/device链接指向其控制器的硬件节点,通过读取链接目标可区分硬核/软核总线:
# 查看i2c-0对应的控制器硬件路径 readlink /sys/class/i2c-dev/i2c-0/device
根据路径中的寄存器基地址(如软核IP通常对应FPGA映射的地址段,硬核IP对应SoC内置地址)即可判断总线归属。
- 自定义总线名称:在DT控制器节点中添加
name属性,覆盖默认名称:
fpga_i2c_1: i2c@0x40000000 { compatible = "xlnx,xps-i2c-1.00.a"; reg = <0x40000000 0x1000>; name = "fpga_i2c_1"; /* 自定义唯一名称 */ ... };
之后通过cat /sys/class/i2c-dev/i2c-*/name即可看到自定义名称,避免同名混淆。
三、静态声明I2C设备的操作方法
内核文档提到的静态声明,是指直接在DT的I2C控制器节点下挂载设备子节点,内核启动时会自动识别并加载驱动:
- 确保控制器节点已配置
#address-cells = <1>;和#size-cells = <0>;(表示子节点的reg是I2C设备地址) - 在控制器节点下添加设备子节点,指定
compatible(匹配驱动的字符串)和reg(设备的I2C地址) - 示例:
&i2c0 { status = "okay"; clock-frequency = <100000>; /* 静态声明AT24C02 EEPROM */ eeprom@50 { compatible = "atmel,24c02"; reg = <0x50>; pagesize = <16>; }; /* 静态声明BME280温湿度传感器 */ bme280@76 { compatible = "bosch,bme280"; reg = <0x76>; status = "okay"; }; };
系统启动后,可通过ls /sys/bus/i2c/devices/查看已识别的静态设备。
四、验证步骤
- 静态编号配置后,重启执行
i2cdetect -l,确认总线编号固定不变 - 自定义名称后,执行
cat /sys/class/i2c-dev/i2c-*/name,检查名称唯一 - 静态设备声明后,查看
dmesg输出,确认设备驱动已加载
内容的提问来源于stack exchange,提问作者Martin Vana
相关产品推荐
相关产品推荐

