Why change clock speed
So why you would want to change speed of your I2C interface?
You might just need to probe your sensors more often.
You might also want to get around long standing I2C stretching bug, which caused that by default I2C stretching on rPi I2C controller is disabled.
What is I2C stretching? In short, it's a mechanism where slower device (in this case I2C slave), "stretches" the clock cycle by holding it down for longer (I2C is open-drain bus with pullups so any device can do that), and in that case other device is supposed to wait and probe data once the clock is back up. Some I2C devices rely on that behaviour if bus is too fast for them and not supporting it might cause those devices to read wrong. And slowing down clock is workaround for that
How to check clock speed?
Clock speed is read from /sys/class/i2c-adapter/i2c-*/of_node/clock-frequency
, where i2c-*
is one of the I2C buses device has.
You can get their names from (rPi3)
1# i2cdetect -l 2i2c-1 i2c bcm2835 I2C adapter I2C adapter 3i2c-2 i2c bcm2835 I2C adapter I2C adapter 4i2c-0 i2c bcm2835 I2C adapter I2C adapter
That is how it looks on rPi4:
1root@rpi4:~# i2cdetect -lrpi4:~# i2cdetect -l 2i2c-3 i2c bcm2835 (i2c@7e804000) I2C adapter 3i2c-1 i2c Broadcom STB : I2C adapter 4i2c-2 i2c bcm2835 (i2c@7e205000) I2C adapter 5i2c-0 i2c Broadcom STB : I2C adapter
SDA0/SCL0 appears to be bus i2c-3
so to check its current speed we run
1xxd /sys/class/i2c-adapter/i2c-3/of_node/clock-frequency 200000000: 0001 86a0 ....
which gives us 0x0186a0
or 100 000 Hz in dec
i2c-0/1 appears to be video chip busses, so I'd advice leaving those alone
How to change clock speed?
Previous iterations of Raspberry Pi used a i2c-bcm2708 driver that could accept the speed parameter either via module
parameters or dtparam
in config.txt
, like this:
1dtparam=i2c_arm=on 2dtparam=i2c1_baudrate=25000
This appears to not be the case on newer kernels on rPi4:
1root@rpi4:~# lsmod |grep i2c 2i2c_dev 24576 0 3i2c_bcm2835 20480 0 4root@rpi4:~# uname -a 5Linux rpi4 5.10.0-13-arm64 #1 SMP Debian 5.10.106-1 (2022-03-17) aarch64 GNU/Linux
Instead, you need to modify device tree. Device tree is configuration structure that tells Linux kernel what devices are present and how they should be set up.
First, we need to apt-get install device-tree-compiler
. Then we can look at the device tree via fdtdump /boot/firmware/bcm2711-rpi-4-b.dtb
.
To find entry that we're interested in, first we need to find right i2c interface. Let's say we're interested in changing i2c-3
Go into /sys/class/i2c-adapter/i2c-3
and look at symlinks:
1root@rpi4:~# ls -la /sys/class/i2c-adapter/i2c-3/of_node 2lrwxrwxrwx 1 root root 0 Apr 28 16:33 /sys/class/i2c-adapter/i2c-3/of_node -> ../../../../../firmware/devicetree/base/soc/i2c@7e804000
the /soc/i2c@7e804000
is the "magical" number we care about. We can then see whether we got the right guy:
1root@rpi4:~# fdtget /boot/firmware/bcm2711-rpi-4-b.dtb /soc/i2c@7e804000 clock-frequency 2100000
Then we change it
1root@rpi4:~# fdtput /boot/firmware/bcm2711-rpi-4-b.dtb /soc/i2c@7e804000 clock-frequency 10000 2root@rpi4:~# reboot
Changes will be applied after reboot
i2c-2
seems to be other bus, so try that one if your device doesn't see the change in speed. Historically that numbering has been
a bit of a mess (from Adafruit page: "The Raspberry Pi designers swapped over I2C ports between board releases. Just remember: 512M Pi's use i2c port 1, 256M ones use i2c port 0!" ).
So if something doesnt work try the other one
The busses that show up as "Broadcom STB" are between broadcom chips so I wouldn't touch settings on those.