I2C "STOP signal" not send when receive a NAK

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

I2C "STOP signal" not send when receive a NAK

Jump to solution
1,969 Views
tapiepierre
Contributor III

Hello Freescale community,

 

I use Kinetis Design studio 2.0.0, MQX KSDK 1.0.0 with Processor expert, (uc MK64F),

 

I realized I2C communication using I2C0 as Master.

 

I talk with a eeprom in a Task every 50ms, when I want to talk with the Eeprom, if it is not present on the bus, I receive a NAK but the signal STOP is not send and the driver return :  I2C_Fail

 

You can see the behavior in the following screenshot :

 

41304_41304.pngI2C_not_good.png

 

I use the function :  i2c_status_t    I2C_DRV_MasterReceiveDataBlocking

 

To solve the problem I add this condition (indicate in RED) in the function I2C_DRV_MasterReceiveDataBlocking :

 

************************************************************************************************************************************************************************************************************

/*FUNCTION**********************************************************************

*

* Function Name : I2C_DRV_MasterReceiveDataBlocking

* Description   : Performs a blocking receive transaction on the I2C bus.

*

*END**************************************************************************/

i2c_status_t I2C_DRV_MasterReceiveDataBlocking(uint32_t instance,

                                       const i2c_device_t * device,

                                       uint8_t * cmdBuff,

                                       uint32_t cmdSize,

                                       uint8_t * rxBuff,

                                       uint32_t rxSize,

                                       uint32_t timeout_ms)

{

    assert(instance < HW_I2C_INSTANCE_COUNT);

 

    uint32_t baseAddr = g_i2cBaseAddr[instance];

    uint32_t i = 0;

    /* Get current runtime structure. */

    i2c_master_state_t * master = (i2c_master_state_t *)g_i2cStatePtr[instance];

 

    /* Return if there is already a trasction */

    if (!master->i2cIdle)

    {

        return master->status = kStatus_I2C_Busy;

    }

 

    master->rxBuff = rxBuff;

    master->rxSize = rxSize;

    master->txBuff = NULL;

    master->txSize = 0;

    master->status = kStatus_I2C_Success;

 

    I2C_DRV_MasterSetBaudRate(instance, device);

 

    /* Set direction to send for sending of address. */

    I2C_HAL_SetDirMode(baseAddr, kI2CSend);

 

    /* Enable i2c interrupt.*/

    I2C_HAL_ClearInt(baseAddr);

    I2C_HAL_SetIntCmd(baseAddr, true);

 

    /* Generate start signal. */

    I2C_HAL_SendStart(baseAddr);

 

    /* Send out slave address. */

    I2C_DRV_SendAddress(instance, device, cmdBuff, cmdSize, kI2CReceive, timeout_ms);

 

    /* Start to receive data. */

    if (master->status == kStatus_I2C_Success)

    {

        /* Change direction to receive. */

        I2C_HAL_SetDirMode(baseAddr, kI2CReceive);

 

        /* Send NAK if only one byte to read. */

        if (rxSize == 0x1U)

        {

            I2C_HAL_SendNak(baseAddr);

        }

        else

        {

            I2C_HAL_SendAck(baseAddr);

        }

 

        /* Dummy read to trigger receive of next byte in interrupt. */

        I2C_HAL_ReadByte(baseAddr);

 

        /* Wait for the transfer to finish.*/

        I2C_DRV_MasterWait(instance, timeout_ms);

    }

 

    if(master->status == kStatus_I2C_ReceivedNak)

          I2C_HAL_SendStop(baseAddr);

 

    /* The stop signal is send inside irq before reading the last byte. */

    /* Disable interrupt. */

    I2C_HAL_SetIntCmd(baseAddr, false);

 

    /* Indicate I2C bus is idle. */

    master->i2cIdle = true;

 

    /* Wait for the STOP signal finish. */

    while(I2C_HAL_GetStatusFlag(baseAddr, kI2CBusBusy))

    {

        if(++i == 2)

        {

            /* Something is wrong becuase the bus is still busy. */

            master->status = kStatus_I2C_Fail;

            break;

        }

        else

        {

            OSA_TimeDelay(1U);

        }

    }   

 

    return master->status;

}

 

************************************************************************************************************************************************************************

 

It is normal to have to add this condition  ?

Labels (1)
1 Solution
1,463 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello PE TAPIE:

That is a bug with KSDK v1.0.0, which is fixed in the latest versions. Attached you can find the relevant I2C driver and HAL from KSDK v1.2 so you can compare the differences, but I highly recommend you to migrate to KDS v3.0.0 and KSDK v1.2.0.


Regards!,
Jorge Gonzalez

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

View solution in original post

2 Replies
1,464 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello PE TAPIE:

That is a bug with KSDK v1.0.0, which is fixed in the latest versions. Attached you can find the relevant I2C driver and HAL from KSDK v1.2 so you can compare the differences, but I highly recommend you to migrate to KDS v3.0.0 and KSDK v1.2.0.


Regards!,
Jorge Gonzalez

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

1,463 Views
tapiepierre
Contributor III

Hello Jorge Gonzalez,

Thanks for you answer,

I looked at the differences beetween the two drivers and effectively the new works as expected

thanks,

0 Kudos
Reply