Hollenweger

iMX28 I2C CE 6.0 driver bug

Discussion created by Hollenweger on Aug 12, 2014

I think i have found a bug in the Windows CE 6.0 (and 7.0?) I2C driver (PLATFORM/COMMON/SOC/MX28_FSL_V2_PDK1_9/I2C/PDK/i2cClass.cpp). The Original code is not working if I try to simply read data:

 

    I2C_TRANSFER_BLOCK I2CXferBlock;

    I2C_PACKET I2CPacket[2];

    BYTE byOutValue;

    INT iResult[2];

 

    byOutValue = byAddr | 1; //READ

 

    I2CPacket[0].pbyBuf = (PBYTE) &byOutValue;

    I2CPacket[0].wLen = 1;

    I2CPacket[0].byRW = I2C_RW_WRITE;

    I2CPacket[0].lpiResult = &iResult[0];

 

    I2CPacket[1].pbyBuf = (PBYTE) lpbBuffer;

    I2CPacket[1].wLen = iBufferSize;

    I2CPacket[1].byRW = I2C_RW_READ;

    I2CPacket[1].lpiResult = &iResult[1];

 

    I2CXferBlock.pI2CPackets = I2CPacket;

    I2CXferBlock.iNumPackets = 2;

 

    if(I2CTransfer(hI2C, &I2CXferBlock))

    {

        *lpiResult = iResult[1];

    }

    else

    {

        *lpiResult = -1;

    }

 

The 1. Byte is send but the iMX28 do not continue sending clock's to read the Data bytes. This results in a locked up I2C Bus (Data line may stay low because the I2C slave has written the first bit but do not get any further Clocks).

 

I found that the problem is the RETAIN_CLOCK Bit in HW_I2C_CTRL0, unfortunately this bit is not very good documented, but to me it seems necessary to set this bit before changing in receive mode.

 

This is the pach I made to i2CClass.cpp:

 

Index: i2cClass.cpp

===================================================================

--- i2cClass.cpp (revision 2281)

+++ i2cClass.cpp (revision 2282)

@@ -552,9 +552,10 @@

             dwCtrl0 |= BM_I2C_CTRL0_PRE_SEND_START;

 

             // if there is more than 1 packet in the chain, set the RETAIN_LOCK bit on all buffers except first and last

-            if ( numPackets > 1 && i != 0)

+            // we have to set RETAIN_LOCK if the next packet is a a read!

+            if ( numPackets > 1 && packets[i+1].byRW == I2C_RW_READ)

                 dwCtrl0 |= BF_I2C_CTRL0_RETAIN_CLOCK(BV_I2C_CTRL0_RETAIN_CLOCK__HOLD_LOW);

             // WAIT4ENDCMD

             dwDMACmd |= BF_APBX_CHn_CMD_WAIT4ENDCMD(1);

         }

@@ -609,6 +610,7 @@

    }

 

Martin

Outcomes