CC2642R: CC2642R I2C problem

Part Number: CC2642R

Hello,

I am working with a CC2642R1F as the I2C master and an ADC3140 as the I2C slave.

The I2C bus is configured at 100 kHz and uses 2.2 kOhm pull-up resistors on SDA and SCL.

I am experiencing an intermittent communication issue. Sometimes the I2C transaction is successful, but other times it fails.

When the transaction fails, the logic analyzer shows that the ADC3140 does not acknowledge the slave address (0x4C). The transaction stops with a NACK immediately after the address byte.

When the transaction succeeds, the ADC3140 acknowledges the address, register address, and data correctly.

For example:

Successful transaction:
Address 0x4C -> ACK
Register 0x02 -> ACK
Data 0x81 -> ACK

Failed transaction:
Address 0x4C -> NACK

To investigate the issue, I created a loop that continuously sends the same write command. In many cases, the ADC3140 only responds after the 6th, 8th, or 10th attempt.

The software sequence is:

  1. Initialize I2C.

  2. Set SHDNZ high.

  3. Wait using Task_sleep().

  4. Start writing ADC3140 registers.

Since the NACK occurs during the address phase, it appears that the ADC3140 is not responding on the bus at that moment.

Has anyone seen similar behavior with the ADC3140? Are there any startup timing requirements or special initialization steps before the first I2C access?

Thank you.

  • Hello Matheus Santos,

    Considering that you are seeing an intermittent issue this sounds something along the lines of an insufficient startup delay after SHDNZ:

    In TI-RTOS (SYS/BIOS), Task_sleep(N) sleeps for N system ticks. The default tick period is 1 ms. So:

    - Task_sleep(1) ≈ 1 ms - almost certainly shorter than the ADC3140's startup time
    - If your tick period is configured longer (e.g., 10 ms), the situation is worse

    For precise sub-tick delays, use ClockP_usleep() from the DPL layer:

    #include <ti/drivers/dpl/ClockP.h>

    GPIO_write(SHDNZ_PIN, 1); // assert SHDNZ high
    ClockP_usleep(10000); // 10 ms - check datasheet for minimum
    // begin I2C transactions

    If you want to stay with Task_sleep(), just ensure N ticks × tick_period ≥ the datasheet minimum plus margin.

    CC2642R I2C driver behavior on ADDR NACK

    There is a known hardware bug on the CC26XX I2C peripheral documented in I2CCC26XX.h (lines 73-75 in SDK 8.30): when
    the slave NACKs the address, the peripheral erroneously transmits one additional data byte before the driver can
    assert a STOP. The driver detects this condition and correctly returns I2C_STATUS_ADDR_NACK (-5), but those extra
    clock cycles are appearing on your bus during each failed attempt. This is benign for your use case but worth being
    aware of.

    Use I2C_transferTimeout() instead of I2C_transfer() to get this status code directly:

    int_fast16_t status = I2C_transferTimeout(i2c, &transaction, timeout_ticks);
    if (status == I2C_STATUS_ADDR_NACK) {
    // slave not ready - not a bus error, retry after additional delay
    }

    Recommended sequence

    // 1. Initialize I2C
    I2C_Params_init(&params);
    params.bitRate = I2C_100kHz;
    i2c = I2C_open(CONFIG_I2C_0, &params);

    // 2. Assert SHDNZ and wait for ADC3140 startup
    GPIO_write(CONFIG_GPIO_SHDNZ, 1);
    ClockP_usleep(10000); // 10 ms; replace with datasheet t_startup + margin

    // 3. Write registers (single attempt should now succeed)
    transaction.targetAddress = 0x4C;
    // ... fill write buffer ...
    int_fast16_t status = I2C_transferTimeout(i2c, &transaction, 1000);

    If you must poll (for example, because SHDNZ timing is outside your control), polling with a bounded retry count and a
    proper delay between attempts is fine - just verify the error code is I2C_STATUS_ADDR_NACK and not something else
    like I2C_STATUS_BUS_BUSY before retrying.

    Thanks,
    Alex F

  • Hello Alex,

    Thank you for the detailed explanation and for the information regarding the ADC3140 startup timing and the CC26xx I2C peripheral behavior.

    In my case, the main concern is not the startup delay itself. The workaround I am currently using consists of continuously attempting I2C communication in a loop until the ADC3140 responds correctly. Although this approach appears to work, it is not ideal for my application because I would prefer to have reliable communication established on the first attempt rather than relying on repeated retries until the device becomes responsive.

    Regarding the documented CC26xx I2C hardware issue, thank you for pointing me to that information. I would like to better understand whether this behavior is a permanent limitation of the hardware or if there are plans to address it in future device revisions.

    Do you know if TI plans to fix this issue in future CC26xx silicon revisions or SDK releases? Also, is this behavior present on all CC26xx devices and silicon revisions, or was it limited to specific manufacturing lots or hardware revisions?

    Any additional insight would be greatly appreciated.

    Thank you for your support.

    Best regards,

    Matheus Santos

  • Hello Matheus Santos,

    On the  topic of the I2C issue this is documented on the product Errata CC2642R SimpleLinkTm Wireless MCU Device Revision E Silicon Errata (Rev. D); on page 7 it details the following:

    The I2C.MSTAT[0] bit is not set immediately after writing to the I2C.MCTRL register. This can lead an I2C master to believe it is no longer busy and continuing to write data. Add four NOPs between writing to the MCTRL register and polling the MSTAT register.

    The workaround is implemented in the TI-provided I2C Master driver (I2CCC26XX.c) and in the I2C driver Library APIs (driverlib/i2c.c). The workaround is available in all Software Development Kit (SDK) versions.

    It looks like the workaround was added to the software but still noted the issue on lines 73-75 in I2CCC26XX file. 

    (This affects Revision F devices and earlier) 

    Although this approach appears to work, it is not ideal for my application because I would prefer to have reliable communication established on the first attempt rather than relying on repeated retries until the device becomes responsive.

    Is there other data that we could leverage here? As an example, does the ADC3140 always become available after x amount of time after resting/powering on the device. Or is the ADC3140 occasionally not available for access by the CC2642, and we cannot currently predict this? If we cannot predict this then the only solution would be to keep on requesting access till it works correctly. 

    Thanks,
    Alex F