doublehp
Posts: 77
Joined: Wed May 02, 2012 1:11 am

Can not change I2C baud rate ?

Mon Jan 21, 2013 7:29 pm

I want to slow down my I2C bus. I have read in various places that it's ... hard, or impossible.

The default baudrate is 100kB; most devices accept up to 400kB, and some times more (up to 4MB). I want to slow down quiet much; down to 500Bauds.

I tried to do it the hard way: kernel hacking. After reading the driver source drivers/i2c/busses/i2c-bcm2708.c I have updated my kernel conf with
CONFIG_I2C_BCM2708_BAUDRATE=500
rebuild, and reboot.

Dmesg confirms that I have half a kilo:
[ 4.912334] bcm2708_i2c bcm2708_i2c.0: BSC0 Controller at 0x20205000 (irq 79) (baudrate 0k)
[ 5.280053] bcm2708_i2c bcm2708_i2c.1: BSC1 Controller at 0x20804000 (irq 79) (baudrate 0k)

0k is fine considering this:
dev_info(&pdev->dev, "BSC%d Controller at 0x%08lx (irq %d) (baudrate %dk)\n",
pdev->id, (unsigned long)regs->start, irq, baudrate/1000);
0.5 is rounded by %d to 0. Fine for me. zcat config.gz confirms 500.

To me, at 500B, i2cdetect -y 1 should take at least 2.3s.

The problem is that it takes only 0.270s aprox. What is to me ... way too fast.

With default kernel at 100k, the average execution time is 0.045s.

So, with lower value, the scan takes only 5 more times, when it should take 200 more time. Changing the value obviously has an impact, but not big enough to me.

I don't have scope to check, and I don't think any LED would let me see such a small difference.

Is there a bug in the kernel ? did I hit the highest limit of the divider ?
cdiv = bus_hz / baudrate;
I have no clue what the bus freq is, or the cdiv accepted values.

doublehp
Posts: 77
Joined: Wed May 02, 2012 1:11 am

Re: Can not change I2C baud rate ?

Mon Jan 21, 2013 8:02 pm

This is quiet strange to me ...

definitely a bug ... somewhere.

And definitely gonna do my own 500B manually: bitbanging :/ again :/ once more :'(

root@raspberrypi1:~# for i in 100000 50000 33000 10000 5000 3300 1000 500 333 100 50 33 ; do rmmod i2c_bcm2708 ; sleep 1 ; modprobe i2c_bcm2708 baudrate=$i ; sleep 1 ; echo "* $i" ; for j in `seq 5` ; do { time i2cdetect -y 1 ; } 2>&1 >/dev/null | grep real ; done ; done
* 100000
real 0m0.034s
real 0m0.032s
real 0m0.030s
real 0m0.028s
real 0m0.035s
* 50000
real 0m0.045s
real 0m0.047s
real 0m0.049s
real 0m0.043s
real 0m0.043s
* 33000
real 0m0.062s
real 0m0.059s
real 0m0.057s
real 0m0.063s
real 0m0.059s
* 10000
real 0m0.160s
real 0m0.155s
real 0m0.159s
real 0m0.155s
real 0m0.159s
* 5000
real 0m0.297s
real 0m0.301s
real 0m0.296s
real 0m0.305s
real 0m0.300s
* 3300
real 0m0.075s
real 0m0.077s
real 0m0.079s
real 0m0.071s
real 0m0.071s
* 1000
real 0m0.320s
real 0m0.315s
real 0m0.317s
real 0m0.321s
real 0m0.317s
* 500
real 0m0.251s
real 0m0.246s
real 0m0.252s
real 0m0.249s
real 0m0.247s
* 333
real 0m0.187s
real 0m0.188s
real 0m0.189s
real 0m0.187s
real 0m0.185s
* 100
real 0m0.074s
real 0m0.071s
real 0m0.068s
real 0m0.068s
real 0m0.076s
* 50
real 0m0.122s
real 0m0.124s
real 0m0.126s
real 0m0.129s
real 0m0.130s
* 33
real 0m0.242s
real 0m0.234s
real 0m0.237s
real 0m0.240s
real 0m0.236s
root@raspberrypi1:~#

doublehp
Posts: 77
Joined: Wed May 02, 2012 1:11 am

Re: Can not change I2C baud rate ?

Mon Jan 21, 2013 8:06 pm

* 3900
real 0m0.380s
real 0m0.377s
real 0m0.383s
real 0m0.377s
real 0m0.381s
* 3800
real 0m0.020s
real 0m0.016s
real 0m0.021s
real 0m0.015s
real 0m0.020s

* 3815
real 0m0.394s
real 0m0.385s
real 0m0.390s
real 0m0.385s
real 0m0.388s
* 3814
real 0m0.014s
real 0m0.018s
real 0m0.014s
real 0m0.018s
real 0m0.014s

doublehp
Posts: 77
Joined: Wed May 02, 2012 1:11 am

Re: Can not change I2C baud rate ?

Mon Jan 21, 2013 8:53 pm

I am now checking signal with a scope:

3815 produces a good signal around expected frequency.

1.5M produces a good signal (baud duration has the expected time length). But ... there is a but. The frame is sent at the requested rate, but words are not consecutive at all: words are seperated by a long lenght of silence. The duration of silence is about 7 times the word length. With my scope with basetime at 5us/d, a word is a bit more than 1 square, and the distance between two words is 7 squares. So this speed is technically ok, but not usefull, not efficient. Still, this test was required for a few things. I have tried with MCP23017 and MCP23018, and they stopped answering ack between 1.65M and 1.85M depending on bus length (less than 10cm, ~4").

Above 2MB, the signal is electrically correct, but slower than expected. 3MB is only 15% faster than 1.5M ... instead of 50%.

At 500k, the distance between words is the same duration than the word itself. Same at 300k.

Below 200k, the distance between words is shorter than the word duration.

So, 1.5M and 200k have roughly the same information efficiency. And 200k is the highest reasonable and efficient value.

3815 is the smallest one, for slow lines.

3814 does produce a fast signal, but my scope can not properly soom and sync on it.

It is now obvious to me that values below 3815 trigger a kernel bug. Either in kernel, or in hardware, but I rather think about kernel issue.

To reach baud rates below this magical limit, I will have to write again bit banging manually.

I2C now has no more secret for any one around here :)

Return to “Interfacing (DSI, CSI, I2C, etc.)”