Dreaded I2C bus stuck LOW, even with basic Atmel example projects

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I've been dealing with lots of problems with the I2C communications bus in my application, where the Slave randomly gets stuck by indefinitely stretching the clock when in Transmitter mode (ie. when the Master wants to read from the Slave, the Slave pulls down the SCL line and stretches te clock forever after the Address ACK). All topics I could find about this problem seem to always point to a poor implementation on the hardware level, so I have made sure that all Resistor parameters are within the I2C Specification, and the oscilloscope shows a very healthy pulse for both SDA and SCL lines.

 

 

The I2C Master works at 3.3V and the Slave works at 5V, so a level shifter is in use between both PCBs. Currently we have 1k0 resistors fitted on Master PCB to 3V3 side of level shifter, 2k2 on 5V side, and 2k2 on Slave PCB. There are also other 2 slaves in the bus, with 4k7 resistors. During the LOW states, the Master sinks 3.3mA with 1k0 Rp resistors on 3v3 side of level shifter. With this setup, the tr (rise time) figure for the i2c was around 960ns, so it is within i2c specs for hardware, and have now ruled out rise time issues:

 

Tired of debugging almost every line of the software, I wanted to check if the "official" implementation is actually working well...

 

Turns out it's not!

 

I am using the TWIM Master and TWIS Slave examples for the UC3C-EK, from Atmel Studio (version 7.0.790) and ASF (version 3.30.1.368), with the minimal adaptations to work with my MCU, which is an AT32UC3C1512C; also the Slave example was modified to just echo whatever the Master sends. Tx, Rx and Stop interrupt handlers are thus kept to a bare minimum and they should be executing as fast as it gets. The result is that the Slave also gets stuck by stretching the I2C clock forever. Of course, with the default Atmel TWIMS driver, this means that the TWIM Master also gets stuck, as it waits unconditionally for the Slave to release the SCL line (which is a correct behavior per the I2C Specification, although quite undesirable to be honest. IMHO, a fail in the decisions taken for the official Specs).

 

What worries me the most is that I could alleviate the problem -but not solve it definitely- by just moving around sentences on the IRQ handler contained within the Atmel TWIS driver (!!!). What I mean is that, for example, if I just force to always call the Rx handler on the very first line of the IRQ handler (instead of doing some couple checks that are being done in the current implementation), seems like if the timings of the IRQ handler changed enough to make the Slave to get stuck less frequently. I2C bus speed is left as it comes with the example by default, at 50 Kbps (also tried 100 Kbps without better results). Also, the MCU is working with its internal RC8M clock (8MHz), and I have also tried with an external 8MHz crystal which should be more precise, but with same results.

 

Next thing I'm trying is to manage TWIS Slave I2C Rx and Tx operations solely through DMA (PDCA peripheral), to see if the supposedly faster reaction times will be enough to make the Slave more reliable. However it makes me feel uncomfortable to know that I don't even have a basic baseline from which to build up a more complex application :-/

 

Could anyone bring some suggestions?

Last Edited: Tue. Mar 15, 2016 - 02:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This looks like a HW issue, and since your dealing with level shifting, please show us a schematic of the I2C bus between master / slave.

 

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Of course,

 

Here is shown the state of the Master (3V3) and the Slave (5V) PCBs when the I2C bus gets stuck and both boards are connected:

 

 

 

Later, manually disconnecting/unplugging the I2C lines (with power still applied to 'keep' the stuck bus) (small image, only changes the red text):

 

Unplugged_small

 

 

The Master immediately pulls its lines up after disconnecting the boards, while the Slave maintains its lines driven LOW, which is what proves that the bus is being stuck LOW by the Slave (and not by the Master).

Also of interest is that the MOSFETs Q13 and Q14 contain an ‘anti-parallel’ diode within them, this is a diode which flows from S (anode) to D (cathode), due to internal structure of MOSFET; it's also known as a parasitic diode. This explains how the Slave MCU is able to pull down the pins in the MCU of the Master even through the level shifter (during fault, and during normal operation).

Last Edited: Tue. Mar 15, 2016 - 04:53 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you "choose" the 0x3f address for your slave address?  If I recall, one of the high addresses is reserved for signalling a 10 bit address, try choosing a lower address like 0x1f and see if your test works.   It could be your slave is waiting for more address bits, or some thing else. 

Also check the master status register to see what it is indicating.

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I use 0x3F because I was unlucky enough that my preferred address of choice (0x50) collided with some I2C sensors a while back. So started using this since then. 0x3F was chosen while reading the I2C Specification document to make sure that it would not collide with either the 10-bit addressing scheme or any of the reserved 7-bit addresses. 10-bit addresses should start always with "1111 0XX", so it won't collide. The other reserved addresses start all with "0000", so no problem there.

 

Good idea checking the TWIM Status Register, will do that.

 

Thanks,

Juan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Some devices behave in an unconventional way: they simply do not ack (for several reasons). If that's what you're confronting to, try releasing SDA (from the master) and see if the communication keeps going…

ɴᴇᴛɪᴢᴇᴎ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I suspect that when the Master (3.3v) asserts either SDA or SCL, the Slave (5v) is getting 1.7v (5v-3.3v) instead of zero volts.  There may be low-going spikes that cause the falling edges to go momentarily below 1.7 into the valid logic low range, and this might be causing intermittent valid logic levels for the Slave.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

"The result is that the Slave also gets stuck by stretching the I2C clock forever. Of course, with the default Atmel TWIMS driver, this means that the TWIM Master also gets stuck, as it waits unconditionally for the Slave to release the SCL line"

 

I suspect that you have something wrong in the slave software - if the data register is not written the TWI hardware will keep the clock stretched.  I would check your software.  Have you tried working with an off the shelf I2C slave - a serial memory chip for example. 

 

"(which is a correct behavior per the I2C Specification, although quite undesirable to be honest. IMHO, a fail in the decisions taken for the official Specs)."

 

The SMBus spec adds a 25ms timeout to the I2C spec.

 

kevin

 

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What happens if you cut the clock frequency in half? Or more?

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net