Hello!
I'm trying to use I2C to connect an ATmega8A microcontroller as an I2C slave to the RasPi. However, I'm experiencing problems with the clock stretching feature of I2C. Whenever the microcontroller is not able to execute the I2C interrupt fast enough, it holds the clock line low to make the I2C master (RasPi) wait. This feature is supported by RasPi according to the BCM2835 ARM Peripherals data sheet (section 3.1, page 28).
However, when the I2C slave actually stretches the clock (e.g. by 4 us), the RasPi seems to ignore it and generates the next falling clock edge without any further delay (e.g. 1 us after the slave released the clock line to high). The sampling of the data line also seems to happen at the time the regular (i.e. un-stretched) positive edge of the clock would have occured.
I'm using raspbian OS and bootc's kernel 3.2.23+. Although the I2C driver never detects a clock stretching timeout, I've tried to change the value of the clock stretch timeout register (CLKT) in the driver. I changed the default value of 0x40 to larger values (0x400, 0x4000) and also set it to zero to turn off clock stretch timeout detection. It did not change the behaviour.
Did anybody else experience a similar behaviour?
Does anybody know what I could be doing wrong?
Best regards,
Stefan
I2C clock stretching
22 posts
- Posts: 4
- Joined: Mon Aug 06, 2012 9:25 pm
Perhaps this feature is simply not implemented in the current I2C driver code.
That said, I have no idea how integrated into the actual I2C hardware clock stretching is.
That said, I have no idea how integrated into the actual I2C hardware clock stretching is.
I know a lot of I2C implementations don't support clock stretching, so my guess is the current I2C driver doesn't support that feature, even though the RPi hardware does. Given that you're in control of your software on the I2C master side, seems like you could work around it for now just by inserting your own delays into your code. Not pretty, but workable.
- Posts: 950
- Joined: Tue Nov 22, 2011 11:51 pm
Thanks for your replies, mahjongg and jbeale.
However, the ARM peripheral data sheet states that clock stretching is supported by the I2C peripheral hardware. The only thing that can be configured by the I2C driver is the clock stretching timeout value via the CLKT register. I tried different values (by modifying the driver), but it did not help. So my guess is now that the data sheet is missing some information regarding clock stretching.
jbeale, I do not understand how I could add the wait to my code, as the wait would have to happen between outputting the LSB of the data byte by the RasPi and reading in the ACK bit from the I2C slave. According to my understanding, this sequence is completely handled by the I2C peripheral. How can I introduce an additional delay into this sequence by software?
Thinking about your proposal, I tried lowering the clock speed of I2C, so that the amount of clock stretching needed is small compared to the clock period. This helps to make it work, but at rather slow speeds.
However, the ARM peripheral data sheet states that clock stretching is supported by the I2C peripheral hardware. The only thing that can be configured by the I2C driver is the clock stretching timeout value via the CLKT register. I tried different values (by modifying the driver), but it did not help. So my guess is now that the data sheet is missing some information regarding clock stretching.
jbeale, I do not understand how I could add the wait to my code, as the wait would have to happen between outputting the LSB of the data byte by the RasPi and reading in the ACK bit from the I2C slave. According to my understanding, this sequence is completely handled by the I2C peripheral. How can I introduce an additional delay into this sequence by software?
Thinking about your proposal, I tried lowering the clock speed of I2C, so that the amount of clock stretching needed is small compared to the clock period. This helps to make it work, but at rather slow speeds.
- Posts: 4
- Joined: Mon Aug 06, 2012 9:25 pm
Ah, good point, I wasn't really thinking about the protocol. I did a I2C driver a long time ago on a micro without I2C hardware, using bit-banging, so I had control over all timing in software. Not an attractive solution for the R-Pi, though.
- Posts: 950
- Joined: Tue Nov 22, 2011 11:51 pm
mahjongg wrote:Gert, we need you here please!
I know, I know. I already made a note to check tomorrow with the designer (who sits behind me).
I have to be careful but I remember there was something about I2C and clock stretching but
I thought that was the Alpha** silicon release and solved in all subsequent versions. I can't remember the details.
** No you don't have Alpha silicon. We never shipped Alpha silicon.
Ok, here I am, one day late but I have most of the answers from the developers mouth.
There is a bug in the I2C master that it does not support clock stretching at arbitrary points.
It does support clock stretching during the ACK phase.
I hope this clarifies it's behavior.
There is a bug in the I2C master that it does not support clock stretching at arbitrary points.
It does support clock stretching during the ACK phase.
I hope this clarifies it's behavior.
I added a note with this information on I2C clock stretching behavior to http://elinux.org/BCM2835_datasheet_err ... stretching
- Posts: 950
- Joined: Tue Nov 22, 2011 11:51 pm
Thank you a lot for clarifying this.
Although I thought it was the ACK phase, I can now confirm that the problem occurs in a non-ACK phase. The ATMEGA8A uses clock-stretching during the first bit following the ACK.
Best regards,
Stefan
Although I thought it was the ACK phase, I can now confirm that the problem occurs in a non-ACK phase. The ATMEGA8A uses clock-stretching during the first bit following the ACK.
Best regards,
Stefan
- Posts: 4
- Joined: Mon Aug 06, 2012 9:25 pm
I've been asked via private message, how I lowered the I2C clock speed. I'm giving the answere here, as it might be of interest of more people.
I'm using kenrel 2.2.23 from bootc. To lower the I2C clock speed, the clock divider (field CDIV in register DIV) has to be loaded with a higher value. I changed the initialization of this register in line 158 of "drivers/i2c/busses/i2c-bcm2708.c" (a file of the kernel source) from
Best regards,
Stefan
I'm using kenrel 2.2.23 from bootc. To lower the I2C clock speed, the clock divider (field CDIV in register DIV) has to be loaded with a higher value. I changed the initialization of this register in line 158 of "drivers/i2c/busses/i2c-bcm2708.c" (a file of the kernel source) from
- Code: Select all
bcm2708_wr(bi, BSC_DIV, cdiv);
- Code: Select all
bcm2708_wr(bi, BSC_DIV, cdiv * 2);
Best regards,
Stefan
- Posts: 4
- Joined: Mon Aug 06, 2012 9:25 pm
hi i2c fans,
I'm not sure if I'm experiencing a sypmtom of the above clock stretching problem, or if my problem relates to something different entirely.
I'm trying to comminucate with an atmega328p (Arduino clone) as an i2c slave. Everything is working using the latest i2c and i2c-dev drivers, except that when I read from the slave in anticipation of a response, if the slave hasn't actually send a response yest, I'm getting a byte return value of 0x55 (binary 01010101).
I've tried to implement clock stretching by getting the slave to pull the SCK line low, but this has no effect on what is happening on the Rpi side of things.
Basically, what I'm doing (and I'm new to i2c so this might be incorrect) is to have the slave, upon rx of a cmd string from the master (Rpi), change the SCK line (A5 or D19 in Arduino-speak) to an output and write LOW to it pull the line down, and hopefully let the master see the bus is locked and there's nothing to be read yet.
When the slave has completed its processing and is ready to respond, it converts SCK back to an input, and then send the response to the master.
The master, if left polling in a tight loop, will eventually read the response just fine -- the thing is is it has to wait in the polling loop until it reads a value that _isn't_ 0x55 before it knows it's got the response!
So I can work with this in a very hacky way for the time being by treating the 0x55 value as a special "busy" value, but if there is a way of doing this properly (so I can actually send the value 0x55 from the slave if I want to, for example
I'd appreciate any advice.
As I say, I'm new to i2c, and my problem may simply be I'm still misunderstanding something quite basic!
I'm not sure if I'm experiencing a sypmtom of the above clock stretching problem, or if my problem relates to something different entirely.
I'm trying to comminucate with an atmega328p (Arduino clone) as an i2c slave. Everything is working using the latest i2c and i2c-dev drivers, except that when I read from the slave in anticipation of a response, if the slave hasn't actually send a response yest, I'm getting a byte return value of 0x55 (binary 01010101).
I've tried to implement clock stretching by getting the slave to pull the SCK line low, but this has no effect on what is happening on the Rpi side of things.
Basically, what I'm doing (and I'm new to i2c so this might be incorrect) is to have the slave, upon rx of a cmd string from the master (Rpi), change the SCK line (A5 or D19 in Arduino-speak) to an output and write LOW to it pull the line down, and hopefully let the master see the bus is locked and there's nothing to be read yet.
When the slave has completed its processing and is ready to respond, it converts SCK back to an input, and then send the response to the master.
The master, if left polling in a tight loop, will eventually read the response just fine -- the thing is is it has to wait in the polling loop until it reads a value that _isn't_ 0x55 before it knows it's got the response!
So I can work with this in a very hacky way for the time being by treating the 0x55 value as a special "busy" value, but if there is a way of doing this properly (so I can actually send the value 0x55 from the slave if I want to, for example
As I say, I'm new to i2c, and my problem may simply be I'm still misunderstanding something quite basic!
- Posts: 2
- Joined: Sun Sep 16, 2012 2:49 pm
stefanBA wrote:I've been asked via private message, how I lowered the I2C clock speed.
With the next kernel release(i think), there will be an module parameter to set the speed:
- Code: Select all
modprobe i2c_bcm2708 baudrate=50000
(https://github.com/raspberrypi/linux/co ... 3aff524ca4)
Frank.
- Posts: 61
- Joined: Fri Sep 14, 2012 8:02 pm
- Location: Germany
What will be the minimum and maximum baud rates that can be selected by the new version of the driver?
- Posts: 2
- Joined: Sun Sep 16, 2012 2:49 pm
pico wrote:What will be the minimum and maximum baud rates that can be selected by the new version of the driver?
Hi,
theoretically, it should be somewhere between 1KHz...150MHz, if i read the datasheet correctly.
Try out,what you slaves can handle or look at the datasheets
Frank.
- Posts: 61
- Joined: Fri Sep 14, 2012 8:02 pm
- Location: Germany
pico wrote:I'm trying to comminucate with an atmega328p (Arduino clone) as an i2c slave.
Did you see the errata in the atmega328p-datasheet ? There's a silicon-bug in the mega328p too...(when acting as slave)
Two bugy i2c-silicons are talking to each other...
I would try with very low speeds to see if it works, and then slowly go higher.
Frank.
p.s. i would be interested in your results - i plan to use an arduino.
- Posts: 61
- Joined: Fri Sep 14, 2012 8:02 pm
- Location: Germany
I have had problems with I2C clock stretching and the BCM2835 I2C0 port.
Turns out that IF you stretch the clock in the ACK phase you HAVE to stretch it until after the first half a clock cycle.
The BCM2835 picks up on a stretched clock only during the second half of the clock cycle.
<Yes, this is a known bug>
Turns out that IF you stretch the clock in the ACK phase you HAVE to stretch it until after the first half a clock cycle.
The BCM2835 picks up on a stretched clock only during the second half of the clock cycle.
<Yes, this is a known bug>
I tried to connect my ATmega8 project as a I2C slave and I always got MSB missing (always zero). Firstly I changed oscillator from 8 to 16MHz on ATmega. It helped in some extend but I still sometimes got an error. But after firmware update ( to kernel 3.2.27) everything is fine, I've changed baudrate to 50kHz. Thanks Frank
For those who don't want to compile the kernel, you can use rpi-update script.http://www.raspberrypi.org/archives/1195
For those who don't want to compile the kernel, you can use rpi-update script.http://www.raspberrypi.org/archives/1195
- Posts: 4
- Joined: Mon Oct 22, 2012 9:26 am
- Location: Poland
I've an interesting problem, which can be related to this thread. If I set the i2c-clockrate to 100k, which is the default in raspbian, I have transfer-errors. But if I change the clockrate more than 5% away, the problems are gone.
I've tested clockrates from 50k to 550k but the problems where only at 100k.
Can somebody verify this?
Stefan
I've tested clockrates from 50k to 550k but the problems where only at 100k.
Can somebody verify this?
Stefan
- Posts: 1
- Joined: Tue Dec 18, 2012 10:09 pm
Gert van Loo wrote:I have had problems with I2C clock stretching and the BCM2835 I2C0 port.
Turns out that IF you stretch the clock in the ACK phase you HAVE to stretch it until after the first half a clock cycle.
The BCM2835 picks up on a stretched clock only during the second half of the clock cycle.
<Yes, this is a known bug>
This seems not sufficient. With RPi master and Attiny84 slave (with latest TinyWireS), I see in about 60 cases out of 20000 that the RPi, when writing, misses to generate a decent clock signal for the first bit of the next byte following a stretched ACK clock by the slave, even when the slave stretching proceeds into the second half of the ordinary RPi master clock cycle. This occurs when the next bytes first bit SDA signal is generated exactly 9.5 us after the master clock going low after the stretching. Since the RPi master clock toggles always with regular 5 us granularity, and since the RPi always gives minimum 0.5 us grace period for SDA to settle before letting the clock go high, in this case, the clock goes high and again low too fast to be picked up by at least by my 12MHz sampling.
This is an example of the phenomenon happening (there should be a 0xB7 being sent after the second 0x03):
http://sebastian.wangnick.de/rpi-i2c-bad.png
This is an example of how it looks when it works:
http://sebastian.wangnick.de/rpi-i2c-bad.png
This could explain why the approach of upsala (offsetting the RPi I2C frequency) might avoid the issue.
Note that even in the "good" case the RPi-generated SCL seems to me often quite tight on the first master bit after a slave clock-stretched ACK, many a time only 0.67 us +/- 7% high phase after a 9.33us low phase.
Now, it might be that this could be solved in the driver by delaying the sending of the next byte slightly after a slave clock stretch.
Kind regards,
Sebastian
- Posts: 2
- Joined: Mon Dec 24, 2012 11:00 pm
s_wangnick wrote:This is an example of how it looks when it works:
Sorry, wrong hyperlink. This is the example when it works:
http://sebastian.wangnick.de/rpi-i2c-good.png
Kind regards,
Sebastian
- Posts: 2
- Joined: Mon Dec 24, 2012 11:00 pm
Ok. I've been bitten by this too.
I've connected my 400MHz sampling scope, not my 12MHz digital logic tracer....
What happens is that the clock line goes "up" to about 1.5V and then low again.
Acording to my source code revision system the first time was april 5th. Grrr.
(Just spent a lot of time on this AGAIN)
I've connected my 400MHz sampling scope, not my 12MHz digital logic tracer....
What happens is that the clock line goes "up" to about 1.5V and then low again.
Acording to my source code revision system the first time was april 5th. Grrr.
(Just spent a lot of time on this AGAIN)
Check out our raspberry pi addons: http://www.bitwizard.nl/catalog/