I2C on KL17 not sending out 1st byte correctly after I2C START.

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

I2C on KL17 not sending out 1st byte correctly after I2C START.

1,258 Views
rickstuart
Contributor V

After sending out the I2C START I can not send out the 1st data byte 0xa0.  Instead, the KL17 I2C sends out 0x00.  If I insert a delay between sending out the I2C START and sending out the 1st I2C byte, the data byte is sent as expected (0xa0)!

As far as I know, there is no way to tell if the KL17 is finished sending out the I2C START.  In frustration, I have created code that waits for every bit in the I2C status register to clear to zero.  This might work well for sending data.  But no where does it say this is possible after sending I2C START.  A fact proven by my test code.

There must be a better way than to simply insert an arbitrary delay.  This sounds wrong and possibly dangerous in critical applications.

-thanks

Tags (3)
0 Kudos
3 Replies

955 Views
mjbcswitzerland
Specialist V

Hi

The double-buffered I2C has a few difficulties and the NXP example code generally works around these in a blocking manner, meaning that it is only really suitable when you are using it in a pre-emptive environment and less for bare-metal projects that require more than basic demonstrations.

There are other various discussions with a few examples of working around typical problems with delays, eg.

https://community.nxp.com/message/814032?commentID=814032#comment-814032

KL43 I2C problem

I have also attached a diagram showing the interrupts and states that can be used to solve this in a fully interrupt-driven manner in master and slave modes (showing required deviations from non-buffered I2C controller types). This implementation is included in the uTasker project in an industrially-proven form.

Regards

Mark

Kinetis for professionals: http://www.utasker.com/

0 Kudos

955 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi

The latest KSDK Version is V2 with below I2C_MasterStart() driver:

status_t I2C_MasterStart(I2C_Type *base, uint8_t address, i2c_direction_t direction)

{

    status_t result = kStatus_Success;

    uint32_t statusFlags = I2C_MasterGetStatusFlags(base);

    /* Return an error if the bus is already in use. */

    if (statusFlags & kI2C_BusBusyFlag)

    {

        result = kStatus_I2C_Busy;

    }

    else

    {

        /* Send the START signal. */

        base->C1 |= I2C_C1_MST_MASK | I2C_C1_TX_MASK;

#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING

        while (!(base->S2 & I2C_S2_EMPTY_MASK))

        {

        }

#endif /* FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING */

        base->D = (((uint32_t)address) << 1U | ((direction == kI2C_Read) ? 1U : 0U));

    }

    return result;

}

Customer could download the latest KSDK V2.0 software from here.


Wish it helps.

Have a great day,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

955 Views
rickstuart
Contributor V

I am experiencing the above problem in the I2C_HAL_MasterSendDataPolling() function which is part of the NXP Hardware Abstraction Layer (HAL) code.  This particular function can be found in NXP file fsl_i2c_hal.c.  I had to change the code so that it would properly send out the 1st byte over the I2C after a START.  I added a delay (the for loop) between the START and sending the 1st byte:

/* Need to generate a repeat start before changing to receive. */

I2C_HAL_SendStart(base);

for(volatile uint32_t i = 0; i < 75; i++)

{

}

/* Send slave address again */

if (!I2C_HAL_WriteByteBlocking(base, address | 1U))

{

    /* Send STOP if no ACK received */

    I2C_HAL_SendStop(base);

    return kStatus_I2C_ReceivedNak;

}

It is difficult to believe the HAL code is faulty or broken.  And it is difficult to believe there is no better way to fix this code than to insert an arbitrary delay.  Never the less, it is working now.  Why?

On the chance the real problem is in how the I2C1 registers are configured, here is what the debugger is reporting just before calling the NXP written I2C_HAL_MasterSendDataPolling() function:

I2C1:

A1 = 0x00

F = 0x1f

C1 = 0xb0

S = 0x20

D = 0x00

C2 = 0x00

FLT = 0x10

RA = 0x00

SMB = 0x00

A2 = 0xc2

SLTH = 0x00

SLTL = 0x00

S2 = 0x01

And just after:

I2C1:

A1 = 0x00

F = 0x1f

C1 = 0x80

S = 0x80

D = 0x7a

C2 = 0x00

FLT = 0x50

RA = 0x00

SMB = 0x00

A2 = 0xc2

SLTH = 0x00

SLTL = 0x00

S2 = 0x01

-thanks

0 Kudos