我正在 Linux 上构建自定义游戏控制器,使用标准 PC 硬件(x86_64)上 HDMI、dvi 和 VGA 等视频端口中的 i2c 总线。
我想验证一下我当前的 i2c 总线速度设置,并尝试进行一些修改。我的理解是,这应该是一个 Linux 内核驱动程序的设置,不过我还没搞清楚,所以可能我的理解还不够准确。
所以我尝试的是:
lsmod | grep i2c
i2c_algo_bit 16384 1 i915
i2c_i801 36864 0
i2c_smbus 20480 1 i2c_i801
好的,i2c_algo_bit 是我正在使用的设备(我认为),也看了 i2c_smbus。
modinfo i915
modinfo i915 | grep -i "baud \| freq \| hz \| rate \| speed"
我尝试读取 i2c-i801 和 i915 的模块信息,但没有看到任何关于当前总线速度的信息。I2c (DDC) 有几种可能的设置,从 50kHz 到 400kHz。如果尚未设置为 400kHz,我想将其设置为 400kHz。
如何验证 i2c 总线的频率?以及如何更改它?
我研究了 6.8.0 系列内核,因为这是 Ubuntu 24.04.2 LTS 系统上目前所拥有的。
该系统使用了 Quadro K4200 显卡,该显卡公开了 I2C 总线,可以读取所连接显示器的身份:
Quadro K4200 使用该
nouveau
驱动程序,该驱动程序也依赖于该模块,问题中的驱动程序i2c-algo-bit
也是如此。i915
查看
/sys/class/i2c-adapter
Quadro K4200 提供的 I2C 总线,我看不到任何可用于定义 I2C 总线速度的用户空间文件。i2c-algo-bit.c源代码显示这是一个软件位驱动,其中软件控制I2C 总线上的单个
SCL
信号,并使用软件在 I2C 总线上信号的切换之间SDA
插入最小延迟。struct i2c_algo_bit_data具有以下字段,用于控制软件时序:
i2c-algo-bit.c 中的函数调用了
udelay()
,有时会延迟,adap->udelay
有时会延迟(adap->udelay + 1) / 2
。问题中使用的i915/display/intel_gmbus.c驱动程序使用以下宏对 I2C 总线速度进行硬编码:
在函数中使用它
intel_gpio_setup
来初始化i2c_algo_bit_data
udelay
:因此,i915 使用的 I2C 总线速度最高为 50 kHz(因为半时钟周期时间被硬编码为 10 微秒)。由于用于控制时序的软件延迟,实际总线速度可能会更低。
nouveau
Quadro K4200 使用的驱动程序也在 nouveau/nvkm/subdev/i2c/bus.c 中的函数中为 i2c-algo-bit 模块硬编码相同的udelay
值nvkm_i2c_bus_ctor
DDC标准规定硬件必须支持 100 kHz 的时钟频率,并且只有图形适配器才能作为 I²C 总线的(时钟)主控。因此,您的设备需要能够在 100 kHz 及以下的任何速度下工作,包括时钟拉伸等 I²C 相关的功能。(切勿自行在软件中实现 I²C 功能。如果您的微控制器没有 I²C 外设,请使用其他微控制器或使用其他总线。)
如果我可以给你一个建议的话:
不。
我曾经为一款嵌入式设备做过技术支持,该设备在同一个 I²C 总线上有自己的 EEPROM,并且还用于其前面的 mini-HDMI 接头。
有时(例如:我的多个独立客户端)在硬件后端从内部 EEPROM 查询硬件属性时使用图形用户界面,会导致 EEPROM 将来自包含 EDID 的屏幕内存的回复误解为写入命令,这是由于总线交互的时间冲突造成的。
以上提到的设备都是专用设备,这类总线事务每分钟可能不会超过一次。您可以推断一下您的控制器会引发多少次事务,以及与 DDC 的实际功能发生冲突并给用户带来严重困扰的可能性有多大。
显卡驱动程序通常只是对 I²C 总线进行位操作,并且它们无法意识到 I²C 总线上的多传输事务。
不要试图把游戏控制器挂在屏幕接口之外。那样只会适得其反,任何需要与控制器交互的软件都需要非常可疑的权限,而且即使在最昂贵但值得信赖的电子产品经销商那里,I²C 转 USB 适配器的价格也低于 2 欧元;你“买个显示器连接器,找个闲置的显卡接口,或者搭建一个能正常工作的直通设备(尽管视频信号是极高带宽且敏感的信号)”的成本绝对比这高。
如果您正在为 20 世纪 80 年代的游戏机构建游戏控制器,也许会考虑这些游戏机所具有的特定总线 - 无论如何您都会为它们编写非常定制的低级软件。
更实际的做法是,让你的自定义游戏控制器的微控制器直接支持 USB 接口。人机接口设备 (HID) 类几乎是你能用 USB 实现的最简单的东西。所有相关的微控制器系列,无论你用在什么场合,比如那些不需要百万量级生产或需要微瓦功耗的设备,都包含内置 USB 硬件的成员。实际上,任何微控制器都有一个 UART 接口,如果你需要,可以把它插到你原来的 IBM PC 背面。