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.

CC2640 use I2C with BMA250 sensor problem

Other Parts Discussed in Thread: CC2640

Hi, All.

Currently, I'm working on a project with CC2640 and communicate with BMA250 by using I2C interface, and I found when transfer to BMA250 register, I2C will failed sometimes, but sometimes success.

So I let I2C transfer in 5 circle, letting transfer do until it success, but I found transfer always have 2 fail then in third time will success. Always be.

Why make this happen?

I use blocking mode of I2C.

  • Try to add some delay between I2C transfer.
  • Hi, YiKai.
    I had add delay between transfer, but still got this issue.
    I found out when I open I2C, in first 2 times transfer will fail, then after that all transfer will be success.
    If I close I2C and reopen again, the first 2 times transfer still fail.
    I can't figure it out why?
  • If you add delay after I2C open, do you still see the problem?
  • Yes, still have it.
  • Can you show me you I2C code?
  • static I2C_Handle i2c;
    static I2C_Transaction i2cTransaction;

    static void openI2C()
    {
    I2C_Params i2cParams;
    uint8_t peripheralNum = 0;

    I2C_Params_init(&i2cParams);
    i2cParams.transferMode = I2C_MODE_BLOCKING;
    i2cParams.bitRate = I2C_400kHz;

    i2c = I2C_open(peripheralNum, &i2cParams);
    if (i2c == NULL)
    {
    trace("error opening I2C\r\n", (data_t)NULL);
    }
    }

    static void transferI2C(uint8 addr, uint8 reg, uint8 value)
    {
    int i=0;

    uint8 readbuf[]={0};
    uint8 writebuf[2]={reg, value};

    openI2C();
    Task_sleep(1000/Clock_tickPeriod*1000);

    i2cTransaction.writeBuf = writebuf;
    i2cTransaction.writeCount = 2;
    i2cTransaction.readBuf = readbuf;
    i2cTransaction.readCount = 7;
    i2cTransaction.slaveAddress = addr;

    for(i=0; i<5; i++)
    {
    status = I2C_transfer(i2c, &i2cTransaction);
    Task_sleep(1000/Clock_tickPeriod*1000);

    if(status == TRUE)
    break;
    }
    I2C_close(i2c);
    }

    static void initiateGsensor(void (*gSensorCB)(PIN_Handle handle, PIN_Id pinId))
    {
    transferI2C(BMA250_I2CADDR, BMA250_SLEEP, BMA250_SLEEP_25MS);
    transferI2C(BMA250_I2CADDR, BMA250_BANDWIDTH, BMA250_BANDWIDTH_1MS);
    transferI2C(BMA250_I2CADDR, BMA250_RANGE, BMA250_RANGE_4G);
    transferI2C(BMA250_I2CADDR, BMA250_INT_SETTING_EN_X16, BMA250_INT_SETTING_EN_X16_SLOPE_ALL);
    transferI2C(BMA250_I2CADDR, BMA250_INT_SETTING_EN_X17, BMA250_INT_SETTING_EN_X17_HIGH_G_ALL);
    transferI2C(BMA250_I2CADDR, BMA250_SLOPE_THERSHOLD, BMA250_SLOPE_THERSHOLD_MEDIUM_LEVEL);
    transferI2C(BMA250_I2CADDR, BMA250_HIGH_G_THERSHOLD, BMA250_HIGH_G_THERSHOLD_MEDIUM_LEVEL);
    transferI2C(BMA250_I2CADDR, BMA250_INT_INT1_MAPPING, BMA250_INT_INT1_MAPPING_SLOPE_HIGH_G);
    transferI2C(BMA250_I2CADDR, BMA250_INT_LATCH_MODE, BMA250_INT_LATCH_MODE_TEMP_1S);
    }
  • When you say I2C transfer fail, do you mean status return of I2C_transfer is false?
  • Do you connect BMA250 to CC2640?
  • Yes, always. and I had successfully transfer register setting to BMA250, is no wrong in BMA250.
    cause after transfer 2 times, in third time the setting can set successful. and BMA250 can change setting also.
    Only this 2 times fail of I2C issue bother me.
  • When I2C transfer returns fail, do you see signal on SCL and SDA lines?
  • I saw the same type of thing with the BMA255, which seems to be very similar to the BMA250.  After checking that the defaults for the I2C lines in the BoardGpioInitTable were sensible and allowed the external pull-up resistors to work when the I2C bus was closed, and that I was complying with the timing requirements of the BMA255 (2us between writes in normal mode, and 450us between writes in suspend mode or low power mode 1), I noticed a very short glitch on each of the I2C lines as a transfer was started.  Although these were much shorter than the typical I2C cycles there was a possibility that the BMA255 might be interpreting them as a START condition.

    Stepping through the I2CCC26XX_open function in I2CCC26XX.c, the cause appeared to be that the I2C lines are muxed from GPIO to I2C before the I2C module is powered on.  I made the changes below and BMA255 access has been more reliable. (This is for tirtos_cc13xx_cc26xx_2_20_01_08 supplied with ble_sdk_2_02_01_18)

    The board this is running on has sensors on two separate I2C buses, so the I2C module will be switching between them, causing the driver to close and reopen on each bus switch.  This might not apply to your setup, so these glitches may not be the cause of your issues.

    --- a/products/tidrivers_cc13xx_cc26xx_2_20_01_10/packages/ti/drivers/i2c/I2CCC26XX.c
    +++ b/products/tidrivers_cc13xx_cc26xx_2_20_01_10/packages/ti/drivers/i2c/I2CCC26XX.c
    @@ -691,6 +691,16 @@ I2C_Handle I2CCC26XX_open(I2C_Handle handle, I2C_Params *params)
         /* Power on the I2C module */
         Power_setDependency(hwAttrs->powerMngrId);
     
    +    /* After enabling power, then we can mux the pins. */
    +    if (params->custom) {
    +       I2CCC26XX_I2CPinCfg* pinCfg_p = (I2CCC26XX_I2CPinCfg *)(params->custom);
    +        PINCC26XX_setMux(object->hPin, pinCfg_p->pinSDA, IOC_PORT_MCU_I2C_MSSDA);
    +        PINCC26XX_setMux(object->hPin, pinCfg_p->pinSCL, IOC_PORT_MCU_I2C_MSSCL);
    +    } else {
    +        PINCC26XX_setMux(object->hPin, hwAttrs->sdaPin, IOC_PORT_MCU_I2C_MSSDA);
    +        PINCC26XX_setMux(object->hPin, hwAttrs->sclPin, IOC_PORT_MCU_I2C_MSSCL);
    +    }
    +
         /* Initialize the I2C hardware module */
         I2CCC26XX_initHw(handle);
     
    @@ -1034,8 +1044,8 @@ static int I2CCC26XX_initIO(I2C_Handle handle, uintptr_t pinCfg) {
         }
     
         /* Set IO muxing for the UART pins */
    -    PINCC26XX_setMux(object->hPin, i2cPins.pinSDA, IOC_PORT_MCU_I2C_MSSDA);
    -    PINCC26XX_setMux(object->hPin, i2cPins.pinSCL, IOC_PORT_MCU_I2C_MSSCL);
    +    //PINCC26XX_setMux(object->hPin, i2cPins.pinSDA, IOC_PORT_MCU_I2C_MSSDA);
    +    //PINCC26XX_setMux(object->hPin, i2cPins.pinSCL, IOC_PORT_MCU_I2C_MSSCL);
         return I2C_STATUS_SUCCESS;
     }

  • Hi Norman,

    Thanks for pointing this out. I have forwarded your findings to our driver developers.

    Cheers,
    Fredrik
  • Hi, YiKai.
    There is no any signal return while transfer fails, only the signal that I write to a sensor.
  • Hi, Norman.
    Thanks to give us this information, I'll follow your suggestion and try again.