I2C clock stretching


34 posts   Page 1 of 2   1, 2
by stefanBA » Mon Aug 06, 2012 9:44 pm
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
Posts: 4
Joined: Mon Aug 06, 2012 9:25 pm
by mahjongg » Mon Aug 06, 2012 10:08 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.
User avatar
Forum Moderator
Forum Moderator
Posts: 5865
Joined: Sun Mar 11, 2012 12:19 am
by jbeale » Mon Aug 06, 2012 10:23 pm
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.
User avatar
Posts: 2096
Joined: Tue Nov 22, 2011 11:51 pm
by stefanBA » Tue Aug 07, 2012 6:05 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.
Posts: 4
Joined: Mon Aug 06, 2012 9:25 pm
by jbeale » Tue Aug 07, 2012 6:22 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.
User avatar
Posts: 2096
Joined: Tue Nov 22, 2011 11:51 pm
by mahjongg » Tue Aug 07, 2012 6:58 pm
Gert, we need you here please! :(
User avatar
Forum Moderator
Forum Moderator
Posts: 5865
Joined: Sun Mar 11, 2012 12:19 am
by Gert van Loo » Tue Aug 07, 2012 7:41 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.
User avatar
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 2096
Joined: Tue Aug 02, 2011 7:27 am
by Gert van Loo » Thu Aug 09, 2012 4:42 pm
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.
User avatar
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 2096
Joined: Tue Aug 02, 2011 7:27 am
by jbeale » Thu Aug 09, 2012 5:08 pm
I added a note with this information on I2C clock stretching behavior to http://elinux.org/BCM2835_datasheet_err ... stretching
User avatar
Posts: 2096
Joined: Tue Nov 22, 2011 11:51 pm
by stefanBA » Thu Aug 09, 2012 5:26 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
Posts: 4
Joined: Mon Aug 06, 2012 9:25 pm
by stefanBA » Wed Sep 12, 2012 5:37 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
Code: Select all
bcm2708_wr(bi, BSC_DIV, cdiv);
to
Code: Select all
bcm2708_wr(bi, BSC_DIV, cdiv * 2);
This reduced the I2C speed from 100kHz to 50kHz.

Best regards,
Stefan
Posts: 4
Joined: Mon Aug 06, 2012 9:25 pm
by pico » Sun Sep 16, 2012 3:14 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!
Posts: 6
Joined: Sun Sep 16, 2012 2:49 pm
by Frank B » Thu Oct 04, 2012 6:15 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
by pico » Mon Oct 08, 2012 3:39 pm
What will be the minimum and maximum baud rates that can be selected by the new version of the driver?
Posts: 6
Joined: Sun Sep 16, 2012 2:49 pm
by Frank B » Mon Oct 08, 2012 6:16 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
by Frank B » Mon Oct 08, 2012 6:34 pm
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... :D

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
by Gert van Loo » Tue Oct 09, 2012 6:49 pm
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>
User avatar
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 2096
Joined: Tue Aug 02, 2011 7:27 am
by pepis » Wed Oct 24, 2012 5:43 am
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 :D
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
by upsala » Tue Dec 18, 2012 10:18 pm
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
Posts: 1
Joined: Tue Dec 18, 2012 10:09 pm
by s_wangnick » Mon Dec 24, 2012 11:53 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
by s_wangnick » Mon Dec 31, 2012 6:44 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
by rew » Wed Jan 09, 2013 1:08 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)
Check out our raspberry pi addons: http://www.bitwizard.nl/catalog/
User avatar
Posts: 396
Joined: Fri Aug 26, 2011 3:25 pm
by unclouded » Sat Jun 08, 2013 7:03 am
I think this is affecting me too. The slave is a half-software, half-hardware I2C implementation using the USI on an ATtiny861. The ATtiny861 is clocked using the internal RC oscillator at 8 MHz. It seems to make no difference whether it sleeps in IDLE mode or not in the main loop. A single-byte read is supposed to return 0xd8.

Code: Select all
$ sudo i2cget -y 1 0x4e
0x58  # 8 MHz, clock-stretching on -- MSB missing
0x6c  # 8 MHz, clock-stretching off -- AVR too slow?
0xd8  # 16 MHz, clock-stretching off -- correct


The trace below appears to show the clock being stretched after only 7 bits have been received:

Image

I wonder if rew's 1.5V spike is the Pi releasing SCL, the W/R bit being received by the AVR, which then pulls SCL low to stretch the clock too quickly to be captured in the trace above. The stretch after the ACK ( the thin SCL release in the trace above) is the AVR stretching the clock after the ACK, trying to load USIDR and not quite managing in time, hence the MSB being read by the Pi as zero even though the trace shows the MSB as a 1.
Posts: 3
Joined: Sat Jun 08, 2013 2:19 am
by Gert van Loo » Sun Jun 09, 2013 9:46 am
I am most curious about your comment which says "clock stretching off".
I was not aware that you can stop the AVR from stretching the clock.
I thought it ALWAYS stretches the clock. "While the TWINT Flag is set, the SCL low period is stretched."
I found two situations where the I2C of the AVR seems** to work with the Pi:
1/ Continous polling the I2C status and clear the TWINT ASAP.
2/ Use a very fast interrupt service routine also to clear the TWINT ASAP.

The latter is the preferred way but there is one nasty snag: The I2C interrupt is the lowest of all interrupts
so you have to make EVERY interrupt routine extremely fast.
Hence my timer IRQ is only this:
ISR(TIMER2_OVF_vect)
{ time++;
}

** I have not yet found time to do extensive bulk-data transfers to see how reliable it is.
User avatar
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 2096
Joined: Tue Aug 02, 2011 7:27 am
by unclouded » Wed Jun 12, 2013 10:40 am
I've been using an ATtiny85 and an ATtiny861, neither of which have real TWI support but instead they have a "USI" that provides some hardware support for what is a software I2C implementation. These devices can:

  • Disable clock stretching altogether by not driving SCL ( by leaving the appropriate bit in DDRx as 0)
  • Disable clock-stretching on USI counter overflow by using wire mode 2 rather than 3 in USICR.USIWM0..1, which disables stretching after 8 bits or after ACK/NAK and will therefore only stretch after START
  • Release SCL ASAP inside ISRs with "USISR |= ( 1 << USISIF)"
Posts: 3
Joined: Sat Jun 08, 2013 2:19 am