AnsweredAssumed Answered

Unrecoverable state following extra byte read on MKL27Z4

Question asked by Chris McHarg on Aug 25, 2016
Latest reply on Sep 5, 2016 by rasto

We were seeing instances of the I2C bus getting stuck in an unrecoverable state during I2C master reads on the MKL27Z4. The issue seemed to occur more often when the CPU was 'under pressure' - i.e I2C wasn't being serviced quickly. Looking at the I2C bus activity, it appeared the I2C controller would attempt to read one extra byte than expected after which the I2C lines would be left in their non-default (low) state.


We guessed that this could be occurring due to the I2C controller behavior not following the pattern expected by the CPU firmware - it becoming out of sync so that an extra byte read was created by the controller or a byte read was dropped by the CPU. Looking into it, that did seem to be occurring...


We were using I2C_MasterTransferBlocking() of KSDK 2.0. With this, multi-byte reads should have been triggered one byte at a time in the status polling read loop in I2C_MasterReadBlocking(). We tried disabling interrupts globally within the loop and the issue stopped occurring, which implies there's an unexpected timing dependency involved (between I2C state changes and CPU servicing). When we then added a 25usec delay within this loop, the issue would always occur. With just a 20usec delay (shorter than a 1byte transmission on the 400K I2C bus), the issue wouldn't occur. From the reference manual my impression was that byte reads or writes should only be triggered by accesses of the DATA register, but from the behavior mentioned above that didn't seem to be the case. It appeared that the controller would perform another read before the CPU was ready to trigger it (reading the value out of the data register). Possibly the controller was just continuing on the multibyte read or an extra byte read was being triggered unexpectedly early on in the sequence from a different register access maybe?


We've been able to work around this with either the global interrupt disable within the read loop or switching to I2C_MasterTransferNonBlocking() (which is interrupt instead of polling based). However it'd be good to get confirmation of this behavior and whether its a known issue or not.