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.

CC1312R: I2C 100KHz not working

Part Number: CC1312R

I have an issue with the I2C communication between a custom board and an external sensor (SHT21). Runnint TI-RTOS. The communication works flawless running on 400KHz. When lowered  to 100KHz TI-RTOS reports that the communication failed even tho I can see on a oscilloscope that the data was sent and the sensor responded with acks. The strange thing is that if I step through the code in I2CCC26XX_transfer() once, the communication starts working and continues to work, running free, until next reset.

Could it be some kind of timing issue in the driver? Didn't find any similar thread, so I still believe the problem is on "my" side. The pullups are totally 1.8 KOhm, which to me feels little low. I see that the microcontroller is unable to drive SDA and SCL to 0V, bottoms out at around 500mV but the SHT21 is able to get it down to zero volts so the CC1312 should see the ack (which it does on 400KHz).

I will try to change the pullups, in the meantime maybe someone has some insights?

Setup:

CCS  Version: 9.2.0.00013 

Simplelink CC13x2_CC26x2_sdk_3_10_00_53

GCC 7.2.1

TI-RTOS

ti/drivers/I2C.h

/Henrik

  • Hello Henrik,

    The LPSTK-CC1352R1 use pull-up resistor values of 3.3 K. That could be worth a try initially.

    Have you verified that the behavior is present in the latest SDK?

  • Hi Henrik,

    Could you elaborate a bit more on the exact test, do you jump between 400 and 100 kHz in run-time or is this two independent debug sessions? As for the pull-ups, could you verify if you got the external I2C pull-ups mounted on the LaunchPad, they should be right to the lower left of DIO5.

  • Eirik V said:
    The LPSTK-CC1352R1 use pull-up resistor values of 3.3 K. That could be worth a try initially.

    I removed the 2.2 kOhm resistors on our custom board, the SHT21 end has 10Kohm resistors leaving a total resistance of 10K. The signal now drops, but still only 400KHz working.

    Eirik V said:
    Have you verified that the behavior is present in the latest SDK?

    No I haven't, Ill test it.

    M-W said:
    Could you elaborate a bit more on the exact test, do you jump between 400 and 100 kHz in run-time or is this two independent debug sessions?

    Yes of course. They are two independent debug sessions. The speed is set on boot and kept on one setting throughout the whole debug session.

    M-W said:
    As for the pull-ups, could you verify if you got the external I2C pull-ups mounted on the LaunchPad, they should be right to the lower left of DIO5.

    I can take a look.

  • Just wanted to update on this issue.

    Tested the i2c sample code in SDK 3.10 with our board and it works fine with 100KHz, moved the main thread from the sample application into my application and it worked fine in that case also. So something in my code is messing up the i2c communication in some way. Need to look through the code.

    If no one has any idea for what the issue might be I think we can close this thread.

    A side note:

    I had some issues with CCS studio, doing a clean installation in a virtual machine running Ubuntu. Opening Resource explorer threw me an Exception. Some other people have had the same problem but didn't find anyone who was able to solve the problem in a "clear" way.

    java.lang.NullPointerException
        at com.teamdev.jxbrowser.chromium.swing.BrowserView.<init>(SourceFile:61)
        at com.ti.chromium.browser.JxBrowser.<init>(JxBrowser.java:274)
        ......

    I fixed this by installing some dependencies for JXBrowser. Maybe it can help someone else in the future.

    $ sudo apt install libgconf2-4 

  • Ok, did a quick glance through the code. What seems to be causing the problem are some attempts to communicate with sensors that are not present. If I remove these transfers 100KHz works or if I restart the I2C driver
    I2C_cancel(i2c);
    I2C_close(i2c);
    i2c = I2C_open(Board_I2C0, &i2cParams);

    after the transfer to the non existing devices 100KHz also works. So something breaks the driver when transferring data to devices that does not exist. As mentioned earlier, 400KHz works even after these transfers to the devices that are not present.

    This was done with SDK 3.10, do no idea if this is fixed in newer SDKs (if the problem is in the SDK and still not in my code).

    /Henrik

  • Hello Henrik,

    Thank you for the update.

    Can you share a code snippet for the failing case where the devices try to communicate with sensor that does not exist?

  • Yes of course. A small test application to test the behavior included below. One more interesting thing is that if the return statement in sht21_read_temperature from the first if statement is removed and the read of 3 bytes is done anyway a IBUSERR is raised when entering or leaving sleep in the main while loop.

    This code was tested with
    LAUNCHXL-CC1312R1 REV D
    CCS  Version: 9.2.0.00013 
    simplelink_cc13x2_26x2_sdk_3_10_00_53
    Example i2ctmp116_CC1312R1_LAUNCHXL_tirtos_ccs as base and tirtos_builds_CC1312R1_LAUNCHXL_debug_ccs

    Please let me know if you need more information.

    /*
     * Copyright (c) 2018-2019, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /*
     *  ======== i2ctmp116.c ========
     */
    #include <stdint.h>
    #include <stddef.h>
    #include <unistd.h>
    
    /* Driver Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/I2C.h>
    
    /* Example/Board Header files */
    #include "Board.h"
    
    #define TASKSTACKSIZE       640
    
    #include <stddef.h>
    #include <stdbool.h>
    #define SHT21_ADDR 0x40
    static I2C_Handle i2c;
    
    bool inited = 0;
    int
    cpu_i2c_init()
    {
    
        I2C_Params i2cParams;
        I2C_Params_init(&i2cParams);
        i2cParams.bitRate = I2C_100kHz;
    
        i2c = I2C_open(Board_I2C0, &i2cParams);
    
        if (i2c == NULL)
        {
            inited = false;
            return 0;
        }
        else
        {
            inited = true;
            return 1;
        }
    }
    
    static int
    cpu_i2c_trx(uint8_t addr, uint8_t* tx, int tx_len, uint8_t* rx, int rx_len)
    {
        I2C_Transaction i2cTransaction;
        i2cTransaction.slaveAddress = addr;
        i2cTransaction.writeBuf = tx;
        i2cTransaction.writeCount = tx_len;
        i2cTransaction.readBuf = rx;
        i2cTransaction.readCount = rx_len;
    
        if (inited && I2C_transfer(i2c, &i2cTransaction))
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
    
    enum
    {
        CMD_TRIGGER_TEMPERATURE = 0b11110011,
    };
    
    /******************************************************************************/
    int sht21_read_temperature(float* temperature)
    {
        uint8_t write[1] = {CMD_TRIGGER_TEMPERATURE};
        uint8_t read[3] = {0, 0, 0};
    
        if (cpu_i2c_trx(SHT21_ADDR, write, 1, NULL, 0) != 1) // <- Stepping through I2C_transfer() from here makes communication to sht21 successful
        {
            return 0;
        }
    
        sleep(1);
    
        if (cpu_i2c_trx(SHT21_ADDR, write, 0, read, 3) != 1)
        {
            return 0;
        }
    
        return 1;
    }
    
    /*
     *  ======== mainThread ========
     */
    void *mainThread(void *arg0)
    {
        uint8_t receive[1];
        uint8_t send[1] = {0x00};
        /* Call driver init functions */
        GPIO_init();
        I2C_init();
        cpu_i2c_init();
        
        cpu_i2c_trx(0x02, send, 1, receive, 1); // <- Makes communication to SHT21 stop working.
        
        while(1)
        {
            float t = 0;
            sht21_read_temperature(&t);
            sleep(1);
        }
    }
    

  • I also noticed that the low level on the LaunchXL evaluation board on the i2c bus is ~280 mV. Don't know if this is ok?

**Attention** This is a public forum