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 18.104.22.1688), 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?