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.

RTOS/TM4C123GH6PM: Not Able to Communicate With I2C

Part Number: TM4C123GH6PM


Tool/software: TI-RTOS

Hi,

I am using TM4C123GH6PM controller with TI-RTOS for Tiva C v: 2.16.00.08. I need to communicate with Pixy Cam5 which support I2C as slave (Addr :0x54).

I went through I2C example from the TI-RTOS sdk which downloaded through CCS.

Whenever I run the code it is going to IDLE mode. I checked with break points and used step in button to execute each step. In taskFxn fucntion it should execute inside while loop but before that it is going to IDLE mode.

I am not getting which I2C is enabled. So I iteratively connected to 0-3 I2C ports, none worked well.

I have attached my main function and extra header file that I have created for Camera.

/*
 * Copyright (c) 2015, 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.
 */

/*
 *    ======== i2ctmp006.c ========
 */

/* XDCtools Header files */
#include <xdc/std.h>
#include <xdc/runtime/System.h>

/* BIOS Header files */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>

/* TI-RTOS Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/I2C.h>

/* Example/Board Header files */
#include "Board.h"
#include "pixy_header.h"

#define TASKSTACKSIZE       640

Task_Struct task0Struct;
char task0Stack[TASKSTACKSIZE];
/*
int count = 0;
void gpioButtonFxn0(unsigned int index)
{
     Clear the GPIO interrupt and toggle an LED
   GPIO_toggle(Board_LED0);

    if (count++ == 100) {
        count = 0;
    }
}
*/

uint8_t getByte()
{

    uint8_t         txBuffer[1];
    uint8_t         rxBuffer[1];
    I2C_Handle      i2c;
    I2C_Params      i2cParams;
    I2C_Transaction i2cTransaction;

    /* Create I2C for usage */
    I2C_Params_init(&i2cParams);
    i2cParams.bitRate = I2C_400kHz;
    i2c = I2C_open(Board_I2C_TMP, &i2cParams);
    txBuffer[0] = 0x00;
    i2cTransaction.slaveAddress = Board_PIXY_ADDR;
    i2cTransaction.writeBuf = txBuffer;
    i2cTransaction.writeCount = 0;
    i2cTransaction.readBuf = rxBuffer;
    i2cTransaction.readCount = 1;

    I2C_transfer(i2c, &i2cTransaction);
     /* Deinitialized I2C */
     I2C_close(i2c);
     return rxBuffer[0];
}


/*
 *  ======== taskFxn ========
 *  Task for this function is created statically. See the project's .cfg file.
 */

void taskFxn(UArg arg0, UArg arg1)
{
        int i;
        uint8_t prev = 0;
        int maxblock = 100;
        /* Turn on user LED */
           GPIO_write(Board_LED1, Board_LED_ON);   //Green
           for(i=1000;i>0;i--);
           GPIO_write(Board_LED1, Board_LED_OFF);
           for(i=1000;i>0;i--);
        while(1)
        {
            getStart();
            int ret = getBlocks(maxblock);
            for(i=0;i<ret;i++)
            {
              int color = g_blocks[i].signature;
                if ( prev != color )
                {
                    switch(color)
                    {
                    case 1 : //printf("Green\n");
                             GPIO_write(Board_LED1, Board_LED_ON); //Green LED
                        break;
                    case 2 : // printf("Orange\n");
                             GPIO_write(Board_LED2, Board_LED_ON); //Red LED
                        break;
                    case 3 : //printf("Yellow\n");
                               GPIO_write(Board_LED0, Board_LED_ON); //Blue LED
                        break;
                    }
                }
                prev = color;
                //Task_sleep(100);
               }
          }

}

void taskFxn_1(UArg arg0, UArg arg1)
{
    int i;
    while(1){
    GPIO_write(Board_LED1, Board_LED_ON);   //Green
    for(i=1000000;i>0;i--);
    GPIO_write(Board_LED1, Board_LED_OFF);
    for(i=1000000;i>0;i--);
    }
}

/*
 *  ======== main ========
 */
int main(void)
{
   // int i;
    Task_Params taskParams;
    System_printf("Inside I2C Example\n");

    /* Call board init functions */
    Board_initGeneral();
    Board_initGPIO();
    Board_initI2C();
    init();

    /* Construct tmp006 Task thread */
    Task_Params_init(&taskParams);
    taskParams.stackSize = TASKSTACKSIZE;
    taskParams.stack = &task0Stack;
    Task_construct(&task0Struct, (Task_FuncPtr)taskFxn, &taskParams, NULL);


//    GPIO_write(Board_LED0, Board_LED_ON);   //blue

    System_printf("Starting the I2C example\nSystem provider is set to SysMin."
                  " Halt the target to view any SysMin contents in ROV.\n");
    /* SysMin will only print to the console when you call flush or exit */
    System_flush();
#if 0
    /* install Button callback */
       GPIO_setCallback(Board_BUTTON0, gpioButtonFxn0);

       /* Enable interrupts */
       GPIO_enableInt(Board_BUTTON0);
#endif


    /* Start BIOS */
    BIOS_start();

    return (0);
}


8662.pixy_header.h

About Camera:-

Pixy cam can identify up to 7 colors, that we can configure from PixyMon application. So using their API we can get which color is identified. When using I2C we do not have to read from particular register, On sending read command Pixy will write which all colors identified.

www.cmucam.org/.../Porting_Guide

Can you help me to solve this problem.

 

  • Hi Vishnu,
    Were you able to make some modification to the TI-RTOS example to interface with your I2C slave?

    Normally a task is used with semaphores. A task will have normally have three parts, a prologue code to setup the environment of the task before the while (1), a while(1) that includes a semaphore_pend() to block or wait for a signal (semaphore) to be posted signifying that data is available to process, and last the epilogue code that closes down the environment before the task exits. You are not using semaphore and you also comment out the Task_sleep. I'm not an expert in TI-RTOS but I think this may be a problem. I will also suggest you either start with the TI-RTOS example and try to adapt it to your slave device first before moving to something complicated as in your current code where you are calling complicated functions (i.e. getStart, getWord, getByte to read data from the file system). Try to send some simple data first.
  • Hi,

               Where are you constructing taskFxn_1(UArg arg0, UArg arg1) thread??  What are the priorities of the all the tasks you are using?? If you are using multiple tasks, keep the priority of  taskFxn highest and then try again. Check the received data on logic analyzer or something. Also add minimum required delay(depends on slave) in while loops.

    Regards,

    Digvijay

  • digvijay khambe said:
    Where are you constructing taskFxn_1( )  ...  What are the priorities of the all the tasks  ...  If using multiple tasks, keep the priority of  taskFxn highest  ...  Check the received data on logic analyzer ...  Add minimum required delay.

    Excellent advice!     And so nice to see you, 'Balance the Slate' - by assisting 'others' - as you continue to 'further grow/develop!'     Note too:  'Aiding others - so often builds (your) understanding & analysis - a very  fortunate ... AND most  'useful consequence.'

    And  Vendor/friend Charles wrote:  "Try to adapt it  first - before moving to something complicated  (i.e. 'calling  complicated functions.)  Try to send some simple data  first."    His too - proves very sound guidance - yet cannot that '30 or so, (always effort-laden) word description'  be replaced by ' just ONE WORD ... 'KISS!'    (which proves FAR more  memorable, directing & effective)

  • Hi Charles,

    I am able to make changes in existing program. But I do not know which I2C pin is initialized during Board_initI2C(); function call.

  • Hi,
    taskFxn_1() is a dummy function which is not involved in the program. I used that function before writing code for I2C, for checking task execution. There I wrote inside a while loop which was working fine. But I2C code is not going into the while loop in void taskFxn(UArg arg0, UArg arg1).

    As of now I am using only one task.
    void taskFxn(UArg arg0, UArg arg1)
    {
    System_printf("Inside Task\n");
    System_flush();
    int i;
    uint8_t prev = 0;
    int maxblock = 100;

    while(1)
    {
    System_printf("Entering into while\n");
    System_flush();
    getStart();
    int ret = getBlocks(maxblock);
    for(i=0;i<ret;i++)
    {
    int color = g_blocks[i].signature;
    if ( prev != color )
    {
    switch(color)
    {
    case 1 : //printf("Green\n");
    GPIO_write(Board_LED1, Board_LED_ON); //Green LED
    break;
    case 2 : // printf("Orange\n");
    GPIO_write(Board_LED2, Board_LED_ON); //Red LED
    break;
    case 3 : //printf("Yellow\n");
    GPIO_write(Board_LED0, Board_LED_ON); //Blue LED
    break;
    }
    }
    prev = color;
    //Task_sleep(100);
    }
    }

    }

    It is printing "Inside Task " in console but next printf statement is missing. Which means it is not entering into while loop.
  • Hi,
    Thank you for your support.
    Now I am getting output. Mistake was in Task_sleep().
    Can you explain what is the significance of Task_sleep() in TI-RTOS.

    Regards,
    Vishnu
  • Hi

    vishnu satheesh said:
    But I do not know which I2C pin is initialized during Board_initI2C(); function call.

    To understand PIN configuration you have to go through the following three files

    1.Board.h

    2.EK_TM4C1294XL.h

    3.EK_TM4C1294XL.c

    Below is the code related to PIN configuration of i2c in  EK_TM4C1294XL.c file which is related to my project.

    /*
     *  =============================== I2C ===============================
     */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(I2C_config, ".const:I2C_config")
    #pragma DATA_SECTION(i2cTivaHWAttrs, ".const:i2cTivaHWAttrs")
    #endif

    #include <ti/drivers/I2C.h>
    #include <ti/drivers/i2c/I2CTiva.h>

    I2CTiva_Object i2cTivaObjects[EK_TM4C1294XL_I2CCOUNT];

    const I2CTiva_HWAttrs i2cTivaHWAttrs[EK_TM4C1294XL_I2CCOUNT] = {
        {
            .baseAddr = I2C2_BASE,
            .intNum = INT_I2C2,
            .intPriority = (~0)
        },
        {
            .baseAddr = I2C8_BASE,
            .intNum = INT_I2C8,
            .intPriority = (~0)
        }
    };

    const I2C_Config I2C_config[] = {
        {
            .fxnTablePtr = &I2CTiva_fxnTable,
            .object = &i2cTivaObjects[0],
            .hwAttrs = &i2cTivaHWAttrs[0]
        },
        {
            .fxnTablePtr = &I2CTiva_fxnTable,
            .object = &i2cTivaObjects[1],
            .hwAttrs = &i2cTivaHWAttrs[1]
        },
        {NULL, NULL, NULL}
    };

    /*
     *  ======== EK_TM4C1294XL_initI2C ========
     */
    void EK_TM4C1294XL_initI2C(void)
    {
        /* I2C7 Init */
        /*
         * NOTE: TI-RTOS examples configure pins PD0 & PD1 for SSI2 or I2C7.  Thus,
         * a conflict occurs when the I2C & SPI drivers are used simultaneously in
         * an application.  Modify the pin mux settings in this file and resolve the
         * conflict before running your the application.
         */
        /* Enable the peripheral */
        SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C2);

        /* Configure the appropriate pins to be I2C instead of GPIO. */
        GPIOPinConfigure(GPIO_PN5_I2C2SCL);
        GPIOPinConfigure(GPIO_PL0_I2C2SDA);
        GPIOPinTypeI2CSCL(GPIO_PORTN_BASE, GPIO_PIN_5);
        GPIOPinTypeI2C(GPIO_PORTL_BASE, GPIO_PIN_0);

    //    /* I2C8 Init */
    //    /* Enable the peripheral */
    //    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C8);
    //
    //    /* Configure the appropriate pins to be I2C instead of GPIO. */
    //    GPIOPinConfigure(GPIO_PA2_I2C8SCL);
    //    GPIOPinConfigure(GPIO_PA3_I2C8SDA);
    //    GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_2);
    //    GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_3);

        I2C_init();
    }

    Regards,

    Digvijay

  • Hi,
    It is good that you are getting output but i still don't understand how Task_sleep() was creating problem??

    The Task_sleep(T) blocks the task for T clock ticks. You can set period equivalent to 1 clock tick.
    Regards,
    Digvijay
  • Thanks Digvijay for clarifying the doubts to the poster.