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.

CC2650 as I2C Slave

Other Parts Discussed in Thread: CC2650, CC2640

Hello,

I'm trying to make a simple application in which CC2650 works as an I2C slave.

 

[TI UPDATE 10/12/19: The use of I2CIntRegister below in a TI-RTOS based application can corrupt the vector table. Please see this FAQ for details why this can happen: https://e2e.ti.com/support/microcontrollers/other/f/908/t/849627]

Based on this figure, my app looks like this: 

void init_i2c()
{
	I2CSlaveInit(I2C0_BASE, 0x74);
	I2CIntRegister(I2C0_BASE, i2cCB);
	I2CSlaveIntEnable(I2C0_BASE, I2C_SLAVE_INT_START | I2C_SLAVE_INT_STOP | I2C_SLAVE_INT_DATA);
}


void i2cCB()
{
uint32_t val;
	    uint32_t status = I2CSlaveIntStatus(I2C0_BASE, true);
	    I2CSlaveIntClear(I2C0_BASE, status);

	    if(status & I2C_SLAVE_INT_DATA)
	    {
	        status = I2CSlaveStatus(I2C0_BASE);

	        if(status & I2C_SLAVE_ACT_RREQ)
	        {
	            val = I2CSlaveDataGet(I2C0_BASE);

	            if(val == 0x01)
	            {
					PIN_setOutputValue(ledPinHandle, Board_LED0, 1);
	            }
	            else if(val == 0x00)
	            {
	            	PIN_setOutputValue(ledPinHandle, Board_LED0, 0);
	            }

	        }
	    }
}

But after running the program it gets stuck in an infinite loop exception:

1001bbd8:   D0FD                beq        #0x1001bbd6
1001bbda:   4790                blx        r2

Thank you!

  • Hi,

    Did you enable the power domain before calling all the register writes?

    Power_setDependency(PowerCC26XX_PERIPH_I2C0)?

    Can you add exception handle to check out the PC location ...etc? You can find the implementation on our software developer's guide chapter 9.8
  • Hi Christin,

    Added Power_setDependency(PowerCC26XX_PERIPH_I2C0); and still the same.

    As for exception handle I'm not sure if this is what you're asking for.

    Thank you!

  • Hi,

    The exception handle indicates that the power domain for I2C is not on yet.

    Can you add the following code before doing any initialization? Also you need to pick 2 IOs for your SDA and SCL line.

        PRCMPowerDomainOn(PRCM_DOMAIN_PERIPH);
    
        Power_setDependency(PowerCC26XX_PERIPH_I2C0);
    
        /* Set constraints for Standby, powerdown and idle mode */
        Power_setConstraint(PowerCC26XX_SB_DISALLOW);
        Power_setConstraint(PowerCC26XX_IDLE_PD_DISALLOW);
    
        PRCMLoadSet();
        PRCMPeripheralRunEnable(PRCM_PERIPH_I2C0); // Enable I2C module
        PRCMLoadSet();
    

  • Hi,

    Are you able to get it running?

    Here is a simple example of I2C slave receiving 10 bytes data from master :

    PIN_Config ledPinTable[] = {
        Board_LED0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        Board_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        PIN_TERMINATE
    };
    
    
    PIN_Config i2cPinTable[] = {
    	Board_I2C0_SDA0 | PIN_INPUT_EN | PIN_PULLUP | PIN_OPENDRAIN,
    	Board_I2C0_SCL0 | PIN_INPUT_EN | PIN_PULLUP | PIN_OPENDRAIN,
        PIN_TERMINATE
    };
    
    void taskFxn(UArg a0, UArg a1) {
    
        PRCMPowerDomainOn(PRCM_DOMAIN_PERIPH);
    
        Power_setDependency(PowerCC26XX_PERIPH_I2C0);
        // Set Power dependecies & constraints
        Power_setDependency(PowerCC26XX_PERIPH_GPIO);
    
        /* Set constraints for Standby, powerdown and idle mode */
        Power_setConstraint(PowerCC26XX_SB_DISALLOW);
        Power_setConstraint(PowerCC26XX_IDLE_PD_DISALLOW);
    
        PRCMLoadSet();
        PRCMPeripheralRunEnable(PRCM_PERIPH_I2C0); // Enable I2C module
        PRCMPeripheralRunEnable(PRCM_PERIPH_GPIO);
        PRCMLoadSet();
    
        PINCC26XX_setMux(i2cPinHandle, Board_I2C0_SDA0, IOC_PORT_MCU_I2C_MSSDA);
        PINCC26XX_setMux(i2cPinHandle, Board_I2C0_SCL0, IOC_PORT_MCU_I2C_MSSCL);
    
        I2CSlaveInit(I2C0_BASE, 0x74);
    
        uint32_t i2cDataArray[10];
        uint8_t i;
        i = 0;
    
        while(1) {
        	while(I2CSlaveStatus(I2C0_BASE) != I2C_SLAVE_ACT_RREQ_FBR);
        	i2cDataArray[0] = I2CSlaveDataGet(I2C0_BASE);
        	PIN_setOutputValue(ledPinHandle, Board_LED0, 1);
        	{
        		for (i = 1; i < 10; i++)
        		{
        			while(I2CSlaveStatus(I2C0_BASE) != I2C_SLAVE_ACT_RREQ);
        			i2cDataArray[i] = I2CSlaveDataGet(I2C0_BASE);
        			PIN_setOutputValue(ledPinHandle, Board_LED0, !(PIN_getOutputValue(Board_LED0)));
        		}
        	}
        	PIN_setOutputValue(ledPinHandle, Board_LED0, 0);
        }
      }
    
    /*
     *  ======== main ========
     */
    int main(void)
     {
        Task_Params taskParams;
    
        /* Call board init functions */
        Board_initGeneral();
        // Board_initI2C();
        // Board_initSPI();
        // Board_initUART();
        // Board_initWatchdog();
    
        /* Construct heartBeat Task  thread */
        Task_Params_init(&taskParams);
        taskParams.arg0 = 1000000 / Clock_tickPeriod;
        taskParams.stackSize = TASKSTACKSIZE;
        taskParams.stack = &task0Stack;
        Task_construct(&task0Struct, (Task_FuncPtr)taskFxn, &taskParams, NULL);
    
        /* Open LED pins */
        ledPinHandle = PIN_open(&ledPinState, ledPinTable);
        if(!ledPinHandle) {
            System_abort("Error initializing board LED pins\n");
        }
    
        i2cPinHandle = PIN_open(&i2cPinState, i2cPinTable);
        if(!i2cPinHandle) {
            System_abort("Error initializing board LED pins\n");
        }
    
    //	PIN_setOutputValue(ledPinHandle, Board_LED0, 1);
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    }

  • Hello,

    Is there a similar implementation available for TI-RTOS 2.21 ?

    I'm trying to adapt this code for TI-RTOS 2.21 but facing issues.

    [Else is it possible to select both TI-RTOS 2.14 & TI-RTOS 2.21 in a ccs project? so that the drivers can be picked up from TI-RTOS 2.14 wherever required]

    Regards

    Anurag

  • What's the issue you are facing? Can you post the error msg you are seeing?
  • Hello Christin,

    I was able to write a code for TI-RTOS 2.21 by reffering I2CSlave.h

    The last error I'm not able to solve is :

    ".......................................

    .....................................

    undefined       first referenced                                                                                                                                

     symbol             in file                                                                                                                                    

    ---------       ----------------                                                                                                                                

    I2CSlave_config C:/ti/tirtos_cc13xx_cc26xx_2_21_00_06/products/tidrivers_cc13xx_cc26xx_2_21_00_04/packages/ti/drivers/lib/drivers_cc26xxware.aem3<I2CSlave.oem3>

    error #10234-D: unresolved symbols remain

    error #10010: errors encountered during linking; "i2cslave_trialv2.out" not built

    >> Compilation failure

    makefile:144: recipe for target 'i2cslave_trialv2.out' failed

    gmake[1]: *** [i2cslave_trialv2.out] Error 1

    makefile:140: recipe for target 'all' failed

    gmake: *** [all] Error 2

    **** Build Finished ****  "

    Can you suggest what am I missing. I figured that it's now an issue with I2CSlave_config.

    My code is as follows:

    Void taskFxn(UArg arg0, UArg arg1)
    {
    
        uint8_t ret;
    
        I2CSlave_Handle      i2c;
        I2CSlave_Params i2cParams;
    
        /* Create I2C for usage */
       
        I2CSlave_Params_init(&i2cParams);
        i2cParams.slaveAddress = 0x74;
        I2CSlave_init();
    
        i2c = I2CSlave_open(0, &i2cParams);
        if (!i2c)
        {
            System_printf("I2CSlave did not open");
         }
    
       
       I2CSlave_read(i2c, &ret, 10);
        if (!ret)
        {
            System_printf("Unsuccessful I2CSlave read");
        }
    
        System_printf("Debug %d t\n", ret);
    
    
        /* Deinitialized I2C */
        I2CSlave_close(i2c);
        //I2C_close(i2c);
        System_printf("I2C closed!\n");
    
        System_flush();
    }
    
    
    
    
    
    /*
     *  ======== main ========
     */
    int main(void)
    {
     //   Task_Params taskParams;
    
        /* Call board init functions */
        Board_initGeneral();
        Board_initI2C();
    
    
        /* Open LED pins */
        ledPinHandle = PIN_open(&ledPinState, ledPinTable);
        if(!ledPinHandle) {
            System_abort("Error initializing board LED pins\n");
        }
        PIN_setOutputValue(ledPinHandle, Board_LED1, 1);
    
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    }
    

  • Hi,

    The I2CSlave is actually not yet support on CC26XX. There is no lower level function mapped to those functions. If you want to use I2C as slave, you will have to directly use driverlib API(as what I posted above)
  • Hi Christin Lee,

    Can you also help me i am also facing similar issue. I want to use cc2640 as slave on i2c.
    Is this the driver API
    http://software-dl.ti.com/dsps/dsps_public_sw/sdo_sb/targetcontent/tirtos/2_14_01_20/exports/tirtos_full_2_14_01_20/products/cc26xxware_2_21_03_15980/doc/driverlib/group__i2c__api.html  

    you mentioned above? Can i utilize this API to use cc2640 as slave on I2C?

    Waiting for your kind help.

  • Hello Christin Lee,

    I have tried on cc2640 as you suggested above but application does not work properly.

    The code is following:

    Task_Struct taskStruct;
    Char task0Stack[SBP_TASK_STACK_SIZE];
    
    #define I2C0_SCL0          IOID_2
    #define I2C0_SDA0          IOID_3
    
    void i2C_createTask(void)
    {
      Task_Params task_i2cParams;
      Task_Params_init(&task_i2cParams);
      task_i2cParams.stack = task0Stack;
      task_i2cParams.arg0 = 1000000 / Clock_tickPeriod;
      task_i2cParams.stackSize = SBP_TASK_STACK_SIZE;
      task_i2cParams.priority = 4;
    
      Task_construct(&taskStruct, i2c_taskFxn, &task_i2cParams, NULL);
    }
    
    uint8_t status=1;
    uint32_t i2cDataArray[10]={0};
    static void i2c_taskFxn(UArg a0, UArg a1) {
    
        PRCMPowerDomainOn(PRCM_DOMAIN_PERIPH);
    
        Power_setDependency(PowerCC26XX_PERIPH_I2C0);
        // Set Power dependecies & constraints
        Power_setDependency(PowerCC26XX_PERIPH_GPIO);
    
        /* Set constraints for Standby, powerdown and idle mode */
        Power_setConstraint(PowerCC26XX_SB_DISALLOW);
        Power_setConstraint(PowerCC26XX_IDLE_PD_DISALLOW);
    
        PRCMLoadSet();
        PRCMPeripheralRunEnable(PRCM_PERIPH_I2C0); // Enable I2C module
        PRCMPeripheralRunEnable(PRCM_PERIPH_GPIO);
        PRCMLoadSet();
        PIN_State i2cPinState;
        PIN_Handle i2cPinHandle = PIN_open(&i2cPinState, i2cPinTable);
        status=PINCC26XX_setMux(i2cPinHandle, I2C0_SCL0, IOC_PORT_MCU_I2C_MSSCL);
         if(status==0)
        {
          status=1;
        }
        status=PINCC26XX_setMux(i2cPinHandle, I2C0_SDA0, IOC_PORT_MCU_I2C_MSSDA);
        if(status==0)
        {
          status=1;
        }
        I2CSlaveInit(I2C0_BASE, 0x53);
        uint8_t i=0;
    
        while(1) {
          // i2C read transaction
            while(I2CSlaveStatus(I2C0_BASE) != I2C_SLAVE_ACT_RREQ_FBR);
            i2cDataArray[0] = I2CSlaveDataGet(I2C0_BASE);
            {
                for (i = 1; i < 3; i++)
                {
                  while(I2CSlaveStatus(I2C0_BASE) != I2C_SLAVE_ACT_RREQ);
                  i2cDataArray[i] = I2CSlaveDataGet(I2C0_BASE);
                }
            }
            // i2C write transaction
            while(I2CSlaveStatus(I2C0_BASE) != I2C_SLAVE_ACT_TREQ);
             I2CSlaveDataPut(I2C0_BASE, 0x10);
        }
      }
    
    int main()
    {
      /* Register Application callback to trap asserts raised in the Stack */
      //RegisterAssertCback(AssertHandler);
    
     PIN_init(BoardGpioInitTable);
    // Board_initGeneral();
    
    #if defined( USE_FPGA )
      // set RFC mode to support BLE
      // Note: This must be done before the RF Core is released from reset!
      SET_RFC_BLE_MODE(RFC_MODE_BLE);
    #endif // USE_FPGA
      
      // Enable iCache prefetching
      VIMSConfigure(VIMS_BASE, TRUE, TRUE);
    
      // Enable cache
     VIMSModeSet(VIMS_BASE, VIMS_MODE_ENABLED);
    
    #if !defined( POWER_SAVING ) || defined( USE_FPGA )
      /* Set constraints for Standby, powerdown and idle mode */
      // PowerCC26XX_SB_DISALLOW may be redundant
      Power_setConstraint(PowerCC26XX_SB_DISALLOW);
      Power_setConstraint(PowerCC26XX_IDLE_PD_DISALLOW);
    #endif // POWER_SAVING | USE_FPGA
    
      /* Initialize ICall module */
      ICall_init();
    
      /* Start tasks of external images - Priority 5 */
      ICall_createRemoteTasks();
    
      /* Kick off profile - Priority 3 */
      GAPRole_createTask();
    
      SimpleBLEPeripheral_createTask();
      i2C_createTask();
    
      /* enable interrupts and start SYS/BIOS */
      BIOS_start();
    
      return 0;
    }
    
    

    Can you please help me? what can be the reason?

  • Hello ,

    Any help please?

  • Are you trying to use it together with BLE stack?
    If that's the case, you need to modify the task priority. (Please take a look at our software developer's guide)

    Or are you just checking out if the I2C slave code works or not?
    If that's what you want, please start with a empty TI-RTOS project and past the code there. In order to test the code, you need to have a master device running in order to get ACK.

    When you said it does not work properly, what do you mean?
  • Hello Christin,

    I am really thankful to you for your reply.
    By not working properly means, the software was getting stuck in the task. Now i have replaced the following:

    while(I2CSlaveStatus(I2C0_BASE) != I2C_SLAVE_ACT_RREQ_FBR);
    with
    if(I2CSlaveStatus(I2C0_BASE) == I2C_SLAVE_ACT_RREQ_FBR)

    and now the software is running properly.
    Actually at the moment i don,t have code for the Master device. I hope to get it at start of next week and i will test the i2c .
    if i got problem i will come back to you.

    One more question should i open the PINs again in main before starting the BIOS? as following:

    i2cPinHandle = PIN_open(&i2cPinState, i2cPinTable);
    if(!i2cPinHandle) {
    System_abort("Error initializing board LED pins\n");
    }

    I saw these are already opened in task.
    Thanks again for your help.

    Regards

    Mabbas
  • You don't have to open the pins in main function. Just need to make sure the handle(s) value is valid before you use any PIN_set commands.
  • Hello Christin & mabbas,

    I am using Ti-Rtos 2.21 and am facing the following issues:

    >> Compilation failure
    subdir_rules.mk:51: recipe for target 'main.obj' failed
    "../main.c", line 61: error #20: identifier "i2cPinTable" is undefined
    "../main.c", line 132: warning #225-D: function "ICall_init" declared implicitly
    "../main.c", line 135: warning #225-D: function "ICall_createRemoteTasks" declared implicitly
    "../main.c", line 138: warning #225-D: function "GAPRole_createTask" declared implicitly
    "../main.c", line 140: warning #225-D: function "SimpleBLEPeripheral_createTask" declared implicitly
    1 error detected in the compilation of "../main.c".
    gmake: *** [main.obj] Error 1
    gmake: Target 'all' not remade because of errors.
    
    **** Build Finished ****

    I'm not able to initialize i2cPinTable in Ti-Rtos 2.21. Can you tell me how to go about solving it or which files should I explore?

     I am trying to implement  I2C as a slave on CC2650, 

    Can you let me know your findings?

    Are you using Ti-Rtos 2.14 or 2.21?

    I do have a master module ready for testing but working on resolving the above issues.

  • Hi Anurag Meena,

    Actually i have not tested my code with master. But it is compiled without errors. I think the errors are occurring because you have not included the required header files properly.

    including correct headers will solve the issue. Let me know if still there is an issue.

    Thanks a lot.
  • Hello ,

    Did you got the solution of your problem??

  • Hello Christin,

    I am using it with BLE stack. What priority i should set? Should it higher then other tasks? I can test i2c slave while debugging or it does not work when the debugger is attached to cc2640?? I am trying to test it with debugger but i have not observed any thing.

    waiting for your kind reply.

    Regards

    MAbbas

  • It can be set to be the same as SBP task or even lower. You will have to handle this in your application layer.
  • Hello ,
    I was able to compile the code without any error.
    As you suggested it was a header file linking issue.

    I'm currently testing it.
    Did you get a chance to test it yet?

    Regards

    Anurag
  • Hi Christin Lee,

    Can you tell me how i can disable the I2C module and close the power constraints related to I2C.
    because once the cc2640 goes to sleep mode I2C still working that draws a current of approximately 2mA.

    Waiting for your help.
  • Hello Christin Lee,

    I want to put the cc2640 to standby . When i configure I2C as slave only one time before the 

    i2c_Configuration();

    // Application main loop
    for (;;)
    {

    }

    I have clock_event that puts cc2640 to standby.

    in event i release the power constraints and put the device to standby by using:

    Power_releaseDependency(PowerCC26XX_PERIPH_I2C0);
    Power_releaseDependency(PowerCC26XX_PERIPH_GPIO);
    Power_releaseConstraint(PowerCC26XX_SB_DISALLOW);
    Power_releaseConstraint(PowerCC26XX_IDLE_PD_DISALLOW);
    Task_sleep(NULL);
    Power_sleep(PowerCC26XX_STANDBY);

    1. But when i wakeup cc2640 using wake up line the I2C does not work again.

    2. If i configure the I2C every time when wakup occurs then the cc2640 does not goes to standby mode. As the current consumption is 2-3 mA.

    3. Can you tell me how i can use I2C properly? Should i initialize I2C each time when i want to use it ? or only once initialization would be enough?.

    4. About the constraints how i can handle them once the cc2640 is wakeup using wakeup line.

    Please help me its urgent.

    Regards

    MAbbas