BeagleBone, i2c-2 and i2c-3 bus frequency

I've been playing around with I2C on my BeagleBone.
I am using Angstrom demo image Angstrom-Cloud9-IDE-eglibc-ipk-v2012.01-

First, I put pull-ups to SDA and SCL line of i2c-3 (I2C2 in SRM), and
probe the bus using i2cdetect. It looks normal:
root@beaglebone:~# i2cdetect -r -y 3
     0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- UU UU UU UU -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

From dmesg, I know that the bus frequency is 100kHz:
[ 0.884620] omap_i2c omap_i2c.3: bus 3 rev4.0 at 100 kHz

However when I check the SCL line with scope, I found that the bus
frequency is 25kHz instead of 100kHz.

I also try putting pull-ups to i2c-2 (I2C1 in SRM). The bus is enabled
by adding "i2c_bus=2,400" to boot arguments in uEnv.txt. Here I am
aiming for 400kHz bus frequency. The dmesg confirms that the bus has
been successfully configured:
[ 0.098696] omap_i2c omap_i2c.2: bus 2 rev4.0 at 400 kHz

When I check the SCL line, the bus frequency is measured to be 100kHz
instead of 400kHz. This is also /4 of the intended frequency like the
case of i2c-3.

Does anyone know how could I repair this? Do I need to set something
else to get the I2C working (something like clock divider, perhaps)?


Any updates on this? Does anyone also encounter the same issue?

Do you have any specific device the i2c bus could talk to? Why playing
with air? Connect something tangible and play with it.

I want to make sure that the configuration is OK before putting any device.
The frequency wouldn’t change if I connect some device to the bus, would it?

Highly unlikely.

Well it could be that it would change since devices are able slow down transmission

pure I2C does not have the minimum frequency, DC is possible. SMBus
has the minimum of 25 kHz (not sure about this value), but the timeout
between clocks must be less than 35ms

Actually, I’m curious why this inconsistency occurs (between dmesg reported i2c frequency and the actual bus frequency).
The other question is, is it possible to change the i2c bus frequency from userland? Or boot option?

Any pointers are welcomed…

from u-boot you set bootargs for the kernel. There you can use this
argument: i2c_bus=3,100
This means: i2c bus 3, freq=100kHz

I have beaglebone ubuntu from (nelson)
I tried to add:


to the end of:

but still in dmesh I have:

[ 0.112609] omap_i2c omap_i2c.1: bus 1 rev2.4.0 at 100 kHz
[ 1.501281] omap_i2c.3: alias fck already exists
[ 1.506439] omap_i2c omap_i2c.3: bus 3 rev2.4.0 at 100 kHz

I mean what’s the purpose having all this drystones on beagle if i2c is on 25kHz ???

Dne ponedeljek, 23. april 2012 07:47:33 UTC+2 je oseba lisarden napisala:

Have you been able to fix that? I have same problem - it looks like no matter what I put in uEnv.txt evrytime dmesg reports 100kHz…

Replies welcome!

Dne ponedeljek, 23. april 2012 02:39:04 UTC+2 je oseba Tuwuh S napisala:

The uEnv setting doesn’t work for me either. I’m hoping to look at this when I have some time, but it sure looks like a bug in the kernel i2c code though. A previous post indicated that if the bus was set to 400mhz it actually ran at 100; so both bus speeds are running at 1/4 the requested rate. Perhaps this indicates a problem with the value being set in the clock prescaler register I2C_PSC? Just a guess though, like I say, I haven’t had a chance to look yet.


Ok, there is a problem in drivers/i2c/busses/i2c-omap.c. internal_clk is getting incorrectly set to 4000. Based on the TRM the i2c internal clock for the 335x should be 12000. I’ve fixed this here by creating a new i2c flag OMAP_I2C_FLAG_FORCE_12000_INT_CLK and setting it in arch/arm/mach-omap2/omap_hwmod_33xx_data.c. Then, in omap_hwmod_33xx_data.c I check for the flag and set internal_clk appropriately if it’s set. With the new kernel in place I’ve measured the bus frequency at khz (100 was configured).


I’ve never been fiddling around with kernel compiling. So far I’m just using the prebuilt demo image. Maybe now’s the time for me to start learning. :wink:

However I am wondering, why the internal clock must be set to 12000, not 16000 (which is 4 times the original 4000)?

I’m not really sure without doing more reading; just blindly trusting the TRM:

How to Program I2C

Module Configuration Before Enabling the Module

Program the prescaler to obtain an approximately 12-MHz I2C module clock (I2C_PSC = x; this value is to be calculated and is dependent on the System clock frequency).

I’ve got a tutorial for how to create OE patches, once I figure it out I’ll submit it, unless someone beats me to it.


I think I made it.

Change of uEnv.txt did the trick: lines that are important are (see attachment for full uEnv.txt):

mmcargs=setenv bootargs console=${console} i2c_bus=${i2cspeed} ${optargs} vram=${vram} omapfb.mode=${defaultdisplay}:${dvimode} omapdss.def_disp=${defaultdisplay} root=${mmcroot} rootfstype=${mmcrootfstype} ${device_args}

After reboot ob ubuntu on beagle it was easy to check i2c frequency in dmesg with:

ubuntu@omap:~/uav-helicoptor-ece4007/software/units$ dmesg | grep Kernel
[ 0.000000] Kernel command line: console=ttyO0,115200n8 i2c_bus=3,400 vram=12MB omapfb.mode=: omapdss.def_disp= root=/dev/mmcblk0p2 ro rootfstype=ext4 rootwait fixrtc ip=none


ubuntu@omap:~/uav-helicoptor-ece4007/software/units$ dmesg | grep i2c
[ 0.000000] Kernel command line: console=ttyO0,115200n8 i2c_bus=3,400 vram=12MB omapfb.mode=: omapdss.def_disp= root=/dev/mmcblk0p2 ro rootfstype=ext4 rootwait fixrtc ip=none
[ 0.100921] omap_i2c.1: alias fck already exists
[ 0.104095] omap_i2c.3: alias fck already exists
[ 0.112762] omap_i2c omap_i2c.1: bus 1 rev2.4.0 at 100 kHz
[ 0.128997] omap_i2c omap_i2c.3: bus 3 rev2.4.0 at 400 kHz

I made some screenshots from osciloscope where it can be seen that i2c clock on bus 3 is running on 400kHz.

But still it seems that reading data on i2c as file is quite a lot overhead - bug in i2c driver maybe?

Can yomebody hjelp in which direction to go to improve i2c driver? Should I reinvent it ? :wink:

Thanks for all comments.


Dne petek, 27. april 2012 08:27:36 UTC+2 je oseba Steve napisala:

uEnv.txt (834 Bytes)

Sory, link to picasa web images is as follows:
Hope it will help someone.

Dne petek, 27. april 2012 10:08:41 UTC+2 je oseba Zhivko napisala:

Are you using a in-kernel driver for your device, /dev/i2c-dev or i2c-get or something else?



Interesting; my uEnv.txt is completely different, literally the only thing it specifies is:

optargs=run_hardware_tests quiet

I added the i2c_bus=3,400 argument to optargs and it did in fact set the speed for the driver (not sure how I messed it up when I tried before). It still runs at about 1/4 speed without my patch though, which is strange as it doesn’t seem to match your experience. Which kernel are you running?


I made simple i2c bechmark using:

I am using i2c as channel like this:

if((fd = open("/dev/i2c-3",O_RDWR)) < 1) {
printf(“ERROR Opening File\n”);
return -1;

if(ioctl(fd,I2C_SLAVE,addr)) {
printf(“ERROR Opening Device\n”);
return -1;

and then issuing 1 write and 1 read.

And I am getting:

sudo ./i2c_bench 83 0 10
READ in 0s 733us
READ in 0s 488us
READ in 0s 397us
READ in 0s 397us
READ in 0s 366us
READ in 0s 367us
READ in 0s 366us
READ in 0s 488us
READ in 0s 397us
READ in 0s 366us
RAN 10 READS in 0s 4ms

So aproximately 1 read in 4ms. That’s after I enabled 400kH speed on bus.

I think 4ms for read from i2c is too little for our project - can you prupose different way of doing it?

Dne petek, 27. april 2012 13:28:15 UTC+2 je oseba Koen Kooi napisala: