FLEXIO_I2C_MasterTransferBlocking returns before ACK/NAK and STOP

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

FLEXIO_I2C_MasterTransferBlocking returns before ACK/NAK and STOP

1,614 Views
lucasrangit
Contributor III

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.

pastedImage_1.png 

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

Labels (1)
Tags (3)
6 Replies

1,215 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi,

Could you provide more detailed info about test environment? Such as IDE software, MCUXpresso SDK version, hardware board and etc.

BTW: I could not open your attached pictures, could you edit this thread, please copy/paste those pictures at above thread. Thanks.


Have a great day,
Mike

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

1,215 Views
lucasrangit
Contributor III

I have updated the post with the details requested and attached the screenshots.

0 Kudos

1,215 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Lucas,

Thank you for the signal capture.

I could see the SDA signal difference with/without 400us delay at MCU(I2C master) and Device(I2C slave).

While, the signal difference is beyond my knowledge.

How do you connect the KL27 with your I2C slave device?

From my knowledge, the SDA signal line connects both KL27 and Device.

So the Channel 1 signal should be totally same with channel 3, even I2C bus communication exists issues.

pastedImage_1.png

Could you provide the I2C hardware schematics (KL27 with I2C device)?


Have a great day,
Mike

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

1,215 Views
lucasrangit
Contributor III

Hi Hui_Ma‌. I updated the post to include a simplified schematic (in this example, the device is an EEPROM).

In the waveforms, Channel 0 and 1 are on the MCU0 side of the buffer and Channel 2 and 3 are on the EEPROM side of the buffer. 

MCU0 enables the I2C redriver only during communication with the EEPROM. In other words, I use GPIO_WritePinOutput(GPIO0, 1) to enable the buffer before calling FLEXIO_I2C_MasterTransferBlocking() and GPIO_WritePinOutput(GPIO0, 0) to disable the buffer after.

I expect the host and device side signals to be identical. However, without the delay of two click periods (400 us when running at 5 kHz) the buffer is disabled too early and the waveforms don't match.

0 Kudos

1,215 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Lucas,

Thank you for the info.

I did a test and could regenerate your mentioned issue.

I would recommend to add below code to make sure I2C communication done before disable I2C buffer chip.

    FLEXIO_I2C_MasterTransferBlocking(&i2cDev,&masterXfer);

    while(!(FLEXIO->TIMSTAT & 0x01));

   GPIO_PortToggle(BOARD_LED_GPIO, 1u << BOARD_LED_GPIO_PIN);

After I add checking FlexIO timer0 status, I could find toggle GPIO pin after I2C stop flag.

pastedImage_1.png

I had reported this issue to SDK software team about FLEXIO_I2C_MasterTransferBlocking() function.

Sorry for that may bring any inconvenience to you.


Have a great day,
Mike

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

1,215 Views
lucasrangit
Contributor III

Thanks Hui_Ma‌ for reproducing the issue.

I will try your solution this week. It's better than mine because it's clock speed independent.

0 Kudos