This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

I2C read stops after 1 byte

Other Parts Discussed in Thread: CC2640

Hi,

I’m trying to read 5 bytes data from sensor NSE5310, and it works well with the first byte. Then the SCL signal seems stop and the program gets stuck there.

     I2C_Handle handle;

     I2C_Params params;

     I2C_Transaction i2cTrans;

     uint8_t rxBuf[32];     // Receive buffer

     uint8_t txBuf[32];     // Transmit buffer  


     // Configure I2C parameters

     I2C_Params_init(&params); // Use default parameter: Blocking mode, 100kHz

     // Initialize master I2C transaction structure

     i2cTrans.writeCount   = 0;

     i2cTrans.writeBuf     = txBuf;

     i2cTrans.readCount   = 5;

     i2cTrans.readBuf     = rxBuf;

     i2cTrans.slaveAddress = 0x40; 

   // Open I2C

     handle = I2C_open(Board_I2C, &params);

   // Do I2C transfer receive

     I2C_transfer(handle, &i2cTrans);

     I2C_close(handle);

It’s simple program and don’t know what’s the problem now. Please suggest how to solve this problem. Thank you very much!

BR Yueming

  • Hi,

    What's the setting for your I2C params? You can take a look at TI-RTOS driver documentation and see if it helps.
    C:/ti/tirtos_simplelink_2_13_00_06/docs/doxygen/html/_i2_c_8h.html
  • The I2C parameter is just the defualt parameters. It should work well with sequencialy reading:

    I2C_Params_init(&params); // Use default parameter: Blocking mode, 100kHz

    void I2C_Params_init(I2C_Params *params)
    {
    *params = I2C_defaultParams;
    }

    /* Default I2C parameters structure */
    const I2C_Params I2C_defaultParams = {
    I2C_MODE_BLOCKING, /* transferMode */
    NULL, /* transferCallbackFxn */
    I2C_100kHz, /* bitRate */
    NULL /* custom */
    };
  • The I2C driver interface produces log statements if instrumentation is enabled.

    Diagnostics Mask Log details

    Diags_USER1 basic operations performed
    Diags_USER2 detailed operations performed

    How to read thses logs?
  • Hi,

    You can refer to this example code, which contains how to enable log function for your own project

    github.com/.../uart_log
  • Does anyone have a clue why the reading stops after 1 byte (or why SCL stops)?

    This simple reading operation should be done quite easily with the funcation I2C_transfer ...
  • try to lower the speed and see if it fixed the problem

    www.i2c-bus.org/.../
  • There are only two choices: 100k or 400k Hz. The default baudrate is already the slowest speed, and at 100kHz everything should work properly.

    I suspect that after one byte is received, the master (CC2640) doesn't move this byte to the buffer or haven't clear the flag, therefore it goes to idle/standby state (so SCL signal discontines).

    This I2C_transfer function from TI lib should work well with the default settings. It would surprise me if I need to debug the TI lib function to the driver level for this simple operation... It's just read 5 byte data from a slave sensor...
  • Hi Yuemin Zhao,

    We do reads of more than 5 bytes every time we boot up the SensorTag. It is also part of self-tests we do in many other projects running with multiple sensors. We obviously also test for this as part of the RTOS release process.

    Are you confident your device is not clock stretching? If I compare to a read we do in the SensorTag it takes about 10us from the read of the first byte until the read of the second. In your log the clock is held low for much longer.

    Since you're starting the driver in blocking mode I2C_Transfer() will block until the transfer is complete, or any error was detected. Since you're stuck here it really points towards slave clock stretching.

    If you have difficulties debugging your device, you can follow the I2C transaction from the host by compiling the source for I2CCC26XX.c. Simply include the file from C:\ti\<your version>\products\<your version>\packages\ti\drivers\i2c\I2CCC26XX.c.

  • Hi Torbjorn

    Thanks your reply! Please help to rule out the software problem first, then I will check the details about the possible hardware issues.

    Should this test code below work well to read out 5 bytes from the I2C sensor (just assume the hardware has no problem at all)?
    Should I consider that after one byte is received, the master (CC2640) doesn't move this byte to the buffer or haven't clear some flag, therefore it goes to idle/standby state (SCL signal discontines) ?
    Is there any easy way to slow down the speed to 50k or 10k ? Thank you very much!

    I2C_Handle handle;
    I2C_Params params;
    I2C_Transaction i2cTrans;
    uint8_t rxBuf[32]; // Receive buffer
    uint8_t txBuf[32]; // Transmit buffer

    // Configure I2C parameters
    I2C_Params_init(&params); // Use default parameter: Blocking mode, 100kHz

    // Initialize master I2C transaction structure
    i2cTrans.writeCount = 0;
    i2cTrans.writeBuf = txBuf;
    i2cTrans.readCount = 5;
    i2cTrans.readBuf = rxBuf;
    i2cTrans.slaveAddress = 0x40;

    // Open I2C
    handle = I2C_open(Board_I2C, &params);

    // Do I2C transfer receive
    I2C_transfer(handle, &i2cTrans);

    I2C_close(handle);
  • Hi Yueming,

    Since you're in blocking mode I2CCC26XX_transfer() will not return until; 1. read complete or 2. an error occurs. Standby is prevented during the call, and after priming the initial address and first byte transfer it will wait for the interrupt before priming next byte, all while your call to I2CCC26XX_transfer() is pending on a semaphore. The semaphore is released in the interrupt either when read is completed or if there's an error.

    What we see in your trace is that the address and first byte are both ACKed. So, the interrupt has happened and the next byte should be setup. One of two things has happened:

    1. Global interrupts are disabled, or some other HW interrrupt is being processed indefinitely.
    2. Interrupt has been handled, and the second byte is primed, but we're is stuck because slave is clock stretching.
    3. An exception has happened. In register view check CFSR under System Control Block.

  • Thank you very much for the support, Torbjorn!

    The problem is sovled now. I rewrite the code in a task, then everything works fine now.
    It should be just a function call with blocking mode, since it will block the interrupt that is needed for the following bytes, as you suggested above.
  • Good to hear Yueming!

    Just for future reference; any RTOS driver should only be called from task context.