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.

TM4C1292NCPDT: I2C transfer function

Part Number: TM4C1292NCPDT
Other Parts Discussed in Thread: TCA9555

Hi,

I've an issue in my code for I2C transfer.

In my reference running code, the function used for I2C transfer is following:

   I2C_Handle      i2c;
    I2C_Params      i2cParams;
    I2C_Transaction i2cTransaction;

    /* Create I2C for usage */
    I2C_Params_init(&i2cParams);
    i2cParams.bitRate = I2C_400kHz;
    i2c = I2C_open(stI2cConfig->vui8I2cBus, &i2cParams);
    /*if (i2c == NULL) {
        IOC_DRIVER_ERR("Error Initializing I2C\n");
    }
    else {
        IOC_DEBUG_DRIVER("I2C Initialized!\n");
    }*/

    i2cTransaction.slaveAddress = stI2cConfig->vui8slaveAddress;
    i2cTransaction.writeBuf = stI2cConfig->pui8txbuffer;
    i2cTransaction.writeCount = stI2cConfig->vui8writeCount;
    i2cTransaction.readBuf = stI2cConfig->pui8RxBuffer;
    i2cTransaction.readCount = stI2cConfig->vui8readCount;

    /* Print the Data send through the I2C */
    if(I2C_transfer(i2c, &i2cTransaction))  {
    }
    else {
        IOC_DRIVER_ERR("I2C Bus fault\n");
    }

    /* De-initialized I2C */
    I2C_close(i2c);
    /*IOC_DEBUG_DRIVER("I2C closed!\n");
    IOC_DEBUG_DRIVER_FLUSH();*/
    stI2cConfig->pui8RxBuffer = i2cTransaction.readBuf;
   
    

I2C_Handle, I2C_Params,I2C_Transaction are all defined in I2C.h file(in tirtos..\products\tidrivers..\packages\ti\drivers\i2c.h)

But when I try to run it from my microcontroller to TCA9555,I get the I2C signals(SCK and SDA) but not the output.

Whereas if I use the following function for my I2C transfer:

void i2cTivaLibTransfer(I2cStructType *pI2cData)
{
    uint32_t ui32Index, ui32Count;
    I2CMasterEnable(pI2cData->ui32I2cBus);

    /*if true - 400Khz, False - 100Khz */
    I2CMasterInitExpClk(pI2cData->ui32I2cBus, 120000000, true);

    I2CMasterSlaveAddrSet(pI2cData->ui32I2cBus, pI2cData->i2cSlaveAddress,
                                                        false);
    I2CMasterBurstLengthSet(pI2cData->ui32I2cBus, pI2cData->ui32TxCount);

    I2CMasterControl(pI2cData->ui32I2cBus,
                                I2C_MASTER_CMD_FIFO_BURST_SEND_START);
    for(ui32Index = 0; ui32Index < pI2cData->ui32TxCount; ui32Index++)
    {

        I2CFIFODataPut(pI2cData->ui32I2cBus,
                                       *(pI2cData->pui8DataTx+ui32Index));
    }

    while(I2CMasterBusy(pI2cData->ui32I2cBus))
    {

    }
    ui32Count = I2CMasterErr(pI2cData->ui32I2cBus);
    if(ui32Count != I2C_MASTER_ERR_NONE)
    {
    }
}

my output on TCA9555 is coming fine.

But the first code is working fine in the reference board.

Note that I'm running the above 2 code snippets in the debug mode, is it possible that the fist code snippet has anything to do with RTOS or it works only during free run/programming mode?

Best Regards,

Kiran

  • In my reference running code, the function used for I2C transfer is following:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    I2C_Handle i2c;
    I2C_Params i2cParams;
    I2C_Transaction i2cTransaction;
    /* Create I2C for usage */
    I2C_Params_init(&i2cParams);
    i2cParams.bitRate = I2C_400kHz;
    i2c = I2C_open(stI2cConfig->vui8I2cBus, &i2cParams);
    /*if (i2c == NULL) {
    IOC_DRIVER_ERR("Error Initializing I2C\n");
    }
    else {
    IOC_DEBUG_DRIVER("I2C Initialized!\n");
    }*/
    i2cTransaction.slaveAddress = stI2cConfig->vui8slaveAddress;
    i2cTransaction.writeBuf = stI2cConfig->pui8txbuffer;
    i2cTransaction.writeCount = stI2cConfig->vui8writeCount;
    i2cTransaction.readBuf = stI2cConfig->pui8RxBuffer;
    i2cTransaction.readCount = stI2cConfig->vui8readCount;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    I2C_Handle, I2C_Params,I2C_Transaction are all defined in I2C.h file(in tirtos..\products\tidrivers..\packages\ti\drivers\i2c.h)

    But when I try to run it from my microcontroller to TCA9555,I get the I2C signals(SCK and SDA) but not the output.

    - Please clarify if this is running on your custom board or the reference board. You later said  the first code is running fine on the reference board. I'm confused as to which one works and which one does not. 

    - Does your reference board connect to TCA9555?

    - What do you mean you get the I2C signals (SCK and SDA) but not the output. If you run your first code and you see SCK and SDA then the master is working. If the slave does not return data or acknowledge then you need to investigate the I2C device. 

    - Post your I2C bus waveform using logic analyzer. 

    Whereas if I use the following function for my I2C transfer:

    Fullscreen
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    I2CMasterBurstLengthSet(pI2cData->ui32I2cBus, pI2cData->ui32TxCount);
    I2CMasterControl(pI2cData->ui32I2cBus,
    I2C_MASTER_CMD_FIFO_BURST_SEND_START);
    for(ui32Index = 0; ui32Index < pI2cData->ui32TxCount; ui32Index++)
    {
    I2CFIFODataPut(pI2cData->ui32I2cBus,
    *(pI2cData->pui8DataTx+ui32Index));
    }
    while(I2CMasterBusy(pI2cData->ui32I2cBus))
    {
    }
    ui32Count = I2CMasterErr(pI2cData->ui32I2cBus);
    if(ui32Count != I2C_MASTER_ERR_NONE)
    {
    }
    }
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    my output on TCA9555 is coming fine.

    But the first code is working fine in the reference board.

    - Again, what is the difference between the waveforms generated by the first code vs the second code. Perhaps your first code has a different command sequence than the second code. 

    Note that I'm running the above 2 code snippets in the debug mode, is it possible that the fist code snippet has anything to do with RTOS or it works only during free run/programming mode?

    - Aren't you also running the second code in RTOS? It is  just that you use the TivaWare I2C driver rather than TI-RTOS I2C driver. 

  • Hi Charles,

    Please clarify if this is running on your custom board or the reference board. You later said  the first code is running fine on the reference board. I'm confused as to which one works and which one does not. 

    The TI-RTOS function (first code) is running on our reference board (which uses RTOS), but the second function (Tivaware I2C) works on our custom board.  

    - Does your reference board connect to TCA9555?

    Yes, the reference board as well as custom board both connect to TCA955.

    - What do you mean you get the I2C signals (SCK and SDA) but not the output. If you run your first code and you see SCK and SDA then the master is working. If the slave does not return data or acknowledge then you need to investigate the I2C device. 

    - Post your I2C bus waveform using logic analyzer. 

    - Again, what is the difference between the waveforms generated by the first code vs the second code. Perhaps your first code has a different command sequence than the second code.

    Please see the scope captures below for both TI-RTOS (1st code) and Tivaware functions(2nd code) on our custom board.

    TI-RTOS function(I2C)

    Tivaware function (I2C)

    While debugging step by step, I found that the code doesn't move ahead from the following line:


    /* Print the Data send through the I2C */
    if(I2C_transfer(i2c, &i2cTransaction)) 

    Similar problem comes in SPI transaction as well. One is TI-RTOS code for SPI transfer. See below

        uint32_t  i;
        SPI_Handle stSpiHandle;
        SPI_Params stSpiParams;
        SPI_Transaction stSpiTransaction;
    
        bool boTransferOK;
    
       // Semaphore_pend(Sem_spi_Handle, BIOS_WAIT_FOREVER);
        IOC_DEBUG_DRIVER("spi write\n");
        SPI_Params_init(&stSpiParams);
        stSpiParams.bitRate = 1500000;
        stSpiParams.frameFormat = SPI_POL0_PHA1;//SPI_POL0_PHA0;//
        stSpiParams.dataSize = 16;
    
        /* Initialize SPI handle as default master */
        stSpiHandle = SPI_open(stSpiConfig->vui8SpiBus, &stSpiParams);
        if (stSpiHandle == NULL) {
            IOC_DRIVER_ERR("Error initializing SPI\n");
            //Event_post(Event_Fault_Handler, Event_Id_00);
        }
        else {
            IOC_DEBUG_DRIVER("SPI initialized\n");
        }
    
        /* Initialize master SPI transaction structure */
        stSpiTransaction.count = stSpiConfig->vui8DataCount;
        stSpiTransaction.txBuf = stSpiConfig->pui8STxbuffer;
        stSpiTransaction.rxBuf = stSpiConfig->pui8SRxBuffer;
    
        if(stSpiConfig->vui8ChipSelect == 1)
        {
            GPIO_write(BOARD_PORTP_PIN1, LOW);
        }
        else
        {
            GPIO_write(BOARD_PORTF_PIN4, LOW);
        }
    
        /* Initiate SPI transfer */
        boTransferOK = SPI_transfer(stSpiHandle, &stSpiTransaction);
    
        if(boTransferOK) {
            if(stSpiConfig->vui8ChipSelect == 1)
            {
                GPIO_write(BOARD_PORTP_PIN1, HIGH);
            }
            else
            {
                GPIO_write(BOARD_PORTF_PIN4, HIGH);
            }
            for (i = 0; i < stSpiConfig->vui8DataCount; i++){
            /* Print contents of master transfer buffer */
    
                IOC_DEBUG_DRIVER("Send Data %d : %x\n", i+1,
                                         ((uint16_t *)stSpiTransaction.txBuf)[i]);
            }
        }
        else {
            IOC_DEBUG_DRIVER("Unsuccessful master SPI transfer");
          //  Event_post(Event_Fault_Handler, Event_Id_00);
    
        }
        IOC_DEBUG_DRIVER_FLUSH();
    
        for (i = 0; i < stSpiConfig->vui8DataCount; i++){
        /* Print contents of master transfer buffer */
    
            IOC_DEBUG_DRIVER("Received Data %d : %x\n", i+1,
                                     ((uint16_t *)stSpiTransaction.rxBuf)[i]);
        }
    
        /* Deinitialize SPI */
        SPI_close(stSpiHandle);

    Another one is Tivaware code for SPI transfer.

    See below.

    uint32_t ui32Index;
    
        SSIConfigSetExpClk(pspiData->ui32SpiBus, 120000000, SSI_FRF_MOTO_MODE_1,
                           SSI_MODE_MASTER, DO_SPI_PERIPHERAL_CLOCK, SPI_DATA_LENGTH);//
    
        /* Checks the SPI Rx FIFO is empty */
        while(SSIDataGetNonBlocking(pspiData->ui32SpiBus,pspiData->pui8DataRx+0))
        {
    
        }
    
       if(pspiData->ui8ChipSelect == 1)
         {
             GPIO_write(BOARD_PORTP_PIN1, LOW);
         }
         else
         {
             GPIO_write(BOARD_PORTF_PIN4, LOW);
         }
    
       for(ui32Index = 0; ui32Index < pspiData->ui32TransferCount; ui32Index++)
       {
    
           SSIDataPut(pspiData->ui32SpiBus, *(pspiData->pui8DataTx+ui32Index));
       }
    
       GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_2, 0x00);
       SSIEnable(pspiData->ui32SpiBus);
    
       while(SSIBusy(pspiData->ui32SpiBus))
       {
    
       }
       if(pspiData->ui8ChipSelect == 1)
       {
           GPIO_write(BOARD_PORTP_PIN1, HIGH);
       }
       else
       {
           GPIO_write(BOARD_PORTF_PIN4, HIGH);
       }
       GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_2, GPIO_PIN_2);
    
       for(ui32Index = 0; ui32Index < pspiData->ui32TransferCount; ui32Index++)
       {
    
           SSIDataGet(pspiData->ui32SpiBus, (pspiData->pui8DataRx+ui32Index));
    
           *(pspiData->pui8DataRx+ui32Index) &= 0x00FF;
    

    The first code snippet works on my reference board but not my custom board. But the second code snippet works fine on my custom board.

    The microcontroller connects to half bridge driver NCV7723 IC and gives output correctly with second code.

    Again,during debugging the issue comes in the following line in case of first code snippet

    /* Initiate SPI transfer */
    boTransferOK = SPI_transfer(stSpiHandle, &stSpiTransaction);

    - Aren't you also running the second code in RTOS? It is  just that you use the TivaWare I2C driver rather than TI-RTOS I2C driver. 

    The second code is being run in the debug mode and not in programming or free run mode so this is not real time.

    Best Regards,

    Kiran

  • The TI-RTOS function (first code) is running on our reference board (which uses RTOS), but the second function (Tivaware I2C) works on our custom board.  

    Is the below table the correct understanding? Can you fill out the question mark?

      Reference board Custom board
    TI-RTOS function (I2C) Working Not working
    TivaWare function (I2C) ? Working

    Please see the scope captures below for both TI-RTOS (1st code) and Tivaware functions(2nd code) on our custom board.

    Since TI-RTOS code works on the reference board, you should attach the scope capture for the reference board vs custom board with both running TI-RTOS. 

    I will also assume the TivaWare function will work on the reference board, correct?

    I see in your below code, you comment out lines 9-14. How can you guarantee you have acquired the handle when you call I2C_open(). If i2c is NULL then you haven't gotten the handle yet. Without the handle, how can you guarantee I2C_transfer() will work? 

    TI-RTOS function(I2C)

    Looking at your waveform, it looks like it is sending a address byte for write direction and a data byte and it then stops. If you want to write/read a register, you need to make sure your command adheres to the expected command sequence described in the slave device datasheet. 

    What is your vui8writeCount, vui8readCount? If you want to read one register then I think you need to set vui8writeCount to 1 and vui8readCount to 1. See the above i2c command sequence where it is slave_addr(W)->Register_addr->slave_addr(R)->Data.

    I will suggest you start with 100k speed rather than 400k. Once you get everything working, you can change back to 400k. 

    Refer to https://software-dl.ti.com/dsps/dsps_public_sw/sdo_sb/targetcontent/tirtos/2_14_04_31/exports/tirtos_full_2_14_04_31/docs/doxygen/html/_i2_c_8h.html for more details. 

    Honestly, I think TivaWare offers better flexibility in terms of I2C control. From my experience, each I2C device can be quite different from another I2C device. TivaWare will offer better custom control than TI-RTOS drivers. 

  • Hi Charles,

    I see in your below code, you comment out lines 9-14. How can you guarantee you have acquired the handle when you call I2C_open(). If i2c is NULL then you haven't gotten the handle yet. Without the handle, how can you guarantee I2C_transfer() will work? 

    --Even after uncommenting the above lines (of checking if I2C is NULL),the transfer isn't being carried out successfully. The code reaches the I2C_transfer() function but doesn't reach the next line.

    What is your vui8writeCount, vui8readCount? If you want to read one register then I think you need to set vui8writeCount to 1 and vui8readCount to 1.

    -- I'm writing the configuration register 0x06 of TCA9555 with 0xFF (for lower 8 bits) and 0x0F (for upper 8 bits) so write count is '3' (bytes) and read count is '0' in this case. See below

    i2cConfigbus stI2cConfig;
        uint8_t aui8txBuffer[DI_INPUTREG_WRITECOUNT];
        uint8_t aui8rxBuffer[DI_INPUTREG_READCOUNT];
    
        /* Configuring IO expander port as input for digital input and
        * output for Source sink selection
        */
        stI2cConfig.ui8regaddr = 0x06;
        stI2cConfig.vui8slaveAddress =  DI_SLAVEADDRESS;
        stI2cConfig.vui8I2cBus = Board_I2C9;
        aui8txBuffer[0] = 0x06;
        aui8txBuffer[1] = 0xFF;
        aui8txBuffer[2] = 0x0F;
        stI2cConfig.pui8txbuffer = aui8txBuffer;
        stI2cConfig.pui8RxBuffer = aui8rxBuffer;
        stI2cConfig.vui8writeCount = 3;
        stI2cConfig.vui8readCount = 0;
        ioc_DII2CTransfer(&stI2cConfig);

    This code is working in the reference board, Tivaware function is also working in the reference as well as custom board. But the RTOS function for I2C transfer doesn't work on custom board.

    Can you guide why it doesn't work?

    Best Regards,

    Kiran

  • This code is working in the reference board, Tivaware function is also working in the reference as well as custom board. But the RTOS function for I2C transfer doesn't work on custom board.

    So below is the result, right?

      Reference board Custom board
    TI-RTOS function (I2C) Working Not working
    TivaWare function (I2C) Working Working

    -- I'm writing the configuration register 0x06 of TCA9555 with 0xFF (for lower 8 bits) and 0x0F (for upper 8 bits) so write count is '3' (bytes) and read count is '0' in this case. See below

    I don't see an issue. 

    Can you guide why it doesn't work?

    If the same code works on your reference board, then I suppose it should work on the customer board as well.  Why don't you show the waveform for the reference board since it is working for you. How is the reference board waveform compared to your custom board? 

    I will strongly you start with 100k speed instead of 400k for debugging. Once you resolve 100k then you can change to 400k. 

    What is the pullup resistor value you use? In your custom board you have ACK bit (see below) that may be misinterpreted as NACK by the master. Can you look at the I2C registers and if you are getting any errors?

  • Hi Charles,

    Honestly, I think TivaWare offers better flexibility in terms of I2C control. From my experience, each I2C device can be quite different from another I2C device. TivaWare will offer better custom control than TI-RTOS drivers. 

    Just one query on above statement that is it possible to covert code written in TivaWare to TI-RTOS driver? Anything i need to take care before doing this.

    Please advice !!

    Thanks,

    Kiran

  • Refer to the below diagram. As you can see TI-RTOS has a Driver Interface that relies on the device specific driverlib. TI-RTOS for Tiva will use TivaWare driverlib . For other MCU such as MSP430 or C2000, their respective driverlib will be used. TI-RTOS driver provides a homogeneous interface across all TI products no matter which MCU/MPU you use. However, the implementation of the hardware modules will be different. For example, TM4C129 I2C module can be quite different from the C2000 in terms of features. In this case, TI-RTOS I2C driver may not be able to account for all the unique features each I2C module is capable of. TI-RTOS I2C driver will most likely provide a common feature sets for the all the MCU/MPU. Another thing is the possible errata. The TivaWare version used in TI-RTOS installation is older than the latest TivaWare version. There could be TivaWare driverlib issues that are already fixed in the latest version but not the older one. Finally, there could be errata that we have software workaround when TivaWare is used. However, implementing the same workaround in TI-RTOS driver will not be as straight forward. This is the reason I mentioned that TivaWare will be more flexible. Having said that, if you already have TI-RTOS driver implemented per your application requirements and if it is working then then there is no hard reason to move away from it. 

  • Hi Charles,

    Thanks for your reply.

    I will share the scope captures on reference board as well as 100k on custom board once I check them.

    Can you share an example code for I2C communication using TI-RTOS driver library?

    Thanks,

    Kiran