usedbytes / neopixel_i2c

AVR-based i2c-slave Neopixel driver
GNU General Public License v2.0
31 stars 5 forks source link

SCL pin held LOW #4

Open chripink opened 6 years ago

chripink commented 6 years ago

Hi,

I'm using your library with a BeagleBone Black and I encounter an issue. When I communicate with the attiny85, at a certain moment on the i2c communication, the SCL pin it held LOW by the software. The problem is that the linux embedded on the beaglebone expect some CPU LOCKED because of that. The issue is appening some times at 100kHz but every times at 400kHz. Here is the scopes mesures to let you know what I mean : Here is the first frame of the i2c detect command

  1. The Attiny85 is erease, all other i2c devices are detected, i2c 100kHz sds00004
  2. he Attiny85 is erease, all other i2c devices are detected, i2c 400kHz sds00005
  3. The Attiny85 is programmed, you software is working and is detected at the 0x40 address but you can see something strange on the two last SCL pulses. Sometimes the linux expect a CPU LOCK, i2c 100kHz sds00003
  4. The Attiny85 is programmed, you software is running makes the linux expect a CPU LOCK at each i2cdetect command. You can see the SCL line held LOW for a while, i2c 400kHz sds00002

I see on you code that you activate the USIWM0 and USIWM1 from the USICR register to 1. We can read in the datasheet for USIWM0 and USIWM1 set to 1: "Two-wire mode. Uses SDA and SCL pins. Same operation as in two-wire mode above, except that the SCL line is also held low when a counter overflow occurs, and until the Counter Overflow Flag (USIOIF) is cleared"

Please can you help me for this issue ?

Thank you, Christophe

usedbytes commented 6 years ago

Hello Christophe,

This is called "clock stretching," and it's an integral part of the i2c specification: https://www.i2c-bus.org/i2c-primer/clock-generation-stretching-arbitration/

Clock Stretching

I2C devices can slow down communication by stretching SCL: During an SCL low phase, any I2C device on the bus may additionally hold down SCL to prevent it from rising again, enabling it to slow down the SCL clock rate or to stop I2C communication for a while. This is also referred to as clock synchronization.

Note: The I2C specification does not specify any timeout conditions for clock stretching, i.e. any device can hold down SCL as long as it likes.

This clock stretching is required to let the AVR stall the bus until it's finished doing the work that it needs to. Otherwise, the master might send a new request whilst the AVR is still busy processing the previous one.

I don't know why clock stretching is triggering your "CPU LOCK" (I also don't know what that is? Do you mean an RCU detected task stall?). In any case, if the master isn't correctly handling clock stretching, that's a problem with the master's i2c implementation rather than the AVR slave.

I can help you try and resolve it, but I don't have a Beaglebone to test. A quick Google indicates that the PRU's i2c hardware should handle i2c clock stretching. I don't know what i2c bus/driver you're using on the TI chip.

chripink commented 6 years ago

Hi, Thanks for your reply, I'm working with the guys makes the software to have more informations. I have done some test today and I see that with a standard debian image for the BBB (we are using a custom linux) the software don't crash. The only issue is that at 400kHz, the i2cdetect is really slow (like if there is some timout) and didn't detect anything. At 100kHz it's working without problem. I have do the same test with a Rpi (standard Raspbian image) and everything is working well... No matter the frequence used, it's working. Thanks for your reply, we are continuing to investigate and I let you know if we found something.

dioss-Machiel commented 6 years ago

In the last scope trace it seems that SDA is going high just before SCL goes high. Instead SCL should go high first (as can be seen in the other scope traces). Could this be causing the issue?

chripink commented 6 years ago

I see what you mean. Obviously a STOP condition is SCL should goes High before SDA. I don't know if this can make crash the CPU but you're right, this case is not a normal i2c stop. Normally, this is the master that generate the STOP condition. Does that mean that I have an issue with my master ? I suppose it's not a slave because a slave should not be able to generate a STOP consditon.