Unexpected I2C Bus speed


5 posts
by xian » Wed May 01, 2013 10:08 pm
I have been communicating with an AVR chip using I2C which seems to work fine up to around 250kHz. The problem is that the default speed the RPi uses seems to be around 500kHz (and when loading kernel module i2c_bcm2708 with baudrate=100000). Is this behavior to be expected?

I've been measuring the speed using a Bus Pirate in lodgic analyser mode and discovered that baudrate=21500 gives about 100kHz on the bus. Also having a /etc/modules file that reads:

Code: Select all
snd-bcm2835 baudrate=21500
i2c-bcm2708 baudrate=21500
i2c-dev
spi-bcm2708


doesn't seem to make it boot up to use 100kHz either. Please can you tell me how to make it use 100kHz from boot.
Posts: 51
Joined: Thu Nov 01, 2012 8:42 pm
by notro » Thu May 02, 2013 10:21 am
This is how the default baudrate is decided:

https://github.com/raspberrypi/linux/bl ... 2708.c#L73
Code: Select all
static unsigned int baudrate = CONFIG_I2C_BCM2708_BAUDRATE;
module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
MODULE_PARM_DESC(baudrate, "The I2C baudrate");
My running kernel has this value
Code: Select all
zcat /proc/config.gz | grep CONFIG_I2C_BCM2708_BAUDRATE
CONFIG_I2C_BCM2708_BAUDRATE=100000
If i2c_bcm2708 is loaded without specifying baudrate, 100k is the default.

In dmesg it looks like i2c_bcm2708 is loaded before /etc/modules is considered.

So the baudrate has to be given to the kernel before that.

I don't know if only one or both of these solutions will work:

Make a file /etc/modprobe.d/i2c.conf
Code: Select all
options i2c_bcm2708 baudrate=21500


Add to kernel command line, /boot/cmdline.txt
Code: Select all
i2c_bcm2708.baudrate=21500
Posts: 498
Joined: Tue Oct 16, 2012 6:21 pm
Location: Norway
by M33P » Thu May 02, 2013 10:29 am
The BSC (I2C controller) uses an even divisor from the core clock of 250MHz.

Baudrate is specified as Hz which then gets approximated as the next lowest even divisor from 250MHz which in some cases (at very low divisors - most of these unusable anyway) results in a deviation from the requested clock rate.

What should happen is that you get a baudrate close to (<1%), but not exactly, the one requested.

I would suspect that the bus pirate isn't exactly up to scratch in measuring high frequencies - it also probably doesn't take into account the fact that I2C will have long periods of idling between bytes, for example because the hardware is waiting for more data to transmit.

If /etc/modules isn't working (it should, by specifying the options bcm2708-i2c baudrate=xx line) then use the command line option.

Edit: ah. What is the name of the driver when lsmod is used? Your modules file is probably specifying it for a module that doesn't exist (DRV_NAME = bcm2708_i2c according to the source)
Posts: 199
Joined: Sun Sep 02, 2012 1:14 pm
by notro » Thu May 02, 2013 11:11 am
M33P wrote:Edit: ah. What is the name of the driver when lsmod is used? Your modules file is probably specifying it for a module that doesn't exist (DRV_NAME = bcm2708_i2c according to the source)
Good catch, I didn't see that. The name of the driver and the device is not the same.
Driver name: i2c_bcm2708
Device name: bcm2708_i2c (declared here: https://github.com/raspberrypi/linux/bl ... 708.c#L618)

Code: Select all
$ lsmod
Module                  Size  Used by
i2c_bcm2708             3727  0

Edit: I was wrong about the driver name, this is more correct
Driver name: bcm2708_i2c
Device name: bcm2708_i2c
Module name: i2c_bcm2708

A kernel module registers a driver which supports a device.
Posts: 498
Joined: Tue Oct 16, 2012 6:21 pm
Location: Norway
by xian » Thu May 02, 2013 10:09 pm
M33P wrote:I would suspect that the bus pirate isn't exactly up to scratch in measuring high frequencies - it also probably doesn't take into account the fact that I2C will have long periods of idling between bytes, for example because the hardware is waiting for more data to transmit.


Ok so on your suspicion of the Bus Pirate I added in another signal to calibrate it. On the same board as my AVR chip I have a DS1307 real time clock that I set to output a 32.768kHz signal that I could compare others too:
Image
The logic analyser is telling me that the DS1307 signal is running approximately 5 times faster than it is and so that is where my confusion is coming from.

Conclusion:
I was measuring the frequency correctly (reciprocal of time between to adjacent peeks) but the logic analyser's frequency measuring tool is out.
The RPi works as it's supposed to.
My AVR code is slow and need s improving to work at 100kHz.

notro wrote:In dmesg it looks like i2c_bcm2708 is loaded before /etc/modules is considered.
So the baudrate has to be given to the kernel before that.

I haven't had a chance to try your ideas yet but will let you know how it goes.
Posts: 51
Joined: Thu Nov 01, 2012 8:42 pm