AnsweredAssumed Answered

FLEXIO_I2C_MasterTransferBlocking returns before ACK/NAK and STOP

Question asked by Lucas Magasweran on Nov 19, 2018
Latest reply on Nov 26, 2018 by Lucas Magasweran

Disabling a level-shifter/signal redriver on the I2C bus using GPIO_WritePinOutput() immediately after a FlexIO I2C blocking read or write using FLEXIO_I2C_MasterTransferBlocking() break I2C communication. The level-shifter is disabled before shifting out/in the ACK/NAK and generating the STOP bit causing the transfer to fail.

 

I believe this is a bug in the FlexIO I2C state-machine, which currently requires using a delay as a work-around. My expectation is that the blocking API call should not return until all the data bits and the ACK/NAK and STOP bits are shifted out/in. Moreover, in the case of a write, if the device NAK's, the return status of FLEXIO_I2C_MasterTransferBlocking() will not be kStataus_I2C_Nak because the state machine returns too early.

 

The following is a simplified schematic. The I2C signal redriver is controlled by MCU0. MCU0 enables this redriver only when communicating with the EEPROM in order to isolate it the other I2C master, MCU1.

 

 

The following waveforms shows the same bus on either side of the buffer (MCU is on the top). Note, the buffer is required to isolate a KL27 from another master on this bus (multi-master is not supporting by the FlexIO 1.0 peripheral in this MCU).

 

Here is a write without a delay before disabling the buffer. Channel 1 is SDA from the MCU and shows that the two clock periods 400 us (running at 5 kHz) after shifting data out does not match. Therefore, the MCU does not see the ACK/NAK from the device and the device does not see the STOP bit from the MCU.

(write-0-us.png)

write-0-us.png

 

Here is a read without delay before disabling the buffer. Channel 1 is SDA from the MCU and and shows the host's NAK at the end of the read but the end of the NAK and the STOP bit are not seen by the device.

(read-0-us.png)

read-0-us.png

 

Adding a delay of two clock periods ~400 us between FLEXIO_I2C_MasterTransferBlocking() and GPIO_WritePinOutput() resolves the issue. As can be seen in the following two waveforms.

(write-400-us.png) Write:

write-400-us.png

(read-400-us.png) Read:

read-400-us.png

 

I believe the root cause is FLEXIO_I2C_MasterTransferBlocking() only checks the shifter status bits with  FLEXIO_I2C_MasterGetStatusFlags() and not the timer 0. From my understanding, Timer 0 needs two additional clock edges after the data bits have been shifted to either shift out or in the ACK/NAK and STOP bit.

 

To fix it I tried adding FlexIO Timer 0 status to the FLEXIO_I2C_MasterGetStatusFlags() but this did not work.

 

Have I correctly root caused the bug? If so, can you provide a hint about how to correct this without the work-around of a delay of two periods, which is baud rate specific?

 

Thank you.

 

Host: Linux Ubuntu 16.04 64-bit

IDE: kinetis-design-studio_3.2.0-1_amd64.deb

SDK: SDK_2.1_MKL27Z256xxx4

Target: MKL27Z256VMP4

Outcomes