CC2640R2F: I2C With CC2640R2

Part Number: CC2640R2F

Tool/software:

I am running the Simple_Central code on my CC2640R2 board and I am using the UART to relay data received over Bluetooth to a LaunchXL-F280025. So I want to use another board connected to a display along with some buttons to relay the message back and forth for searching for Bluetooth devices and then connecting. The information that was being shown through the usb serial.  I am trying to use the CC2640R2 as an I2C slave device.  From the I2C driver code there is some setup functions and then you call the I2CTransfer function.  I am trying to figure out how this function works in the I2C sequence.  Usually the slave will wait until the master sends the start bit along with the slave address, and once the slave has confirmed that the address is matching then the master will send the data.  It seems as though this sequence just starts the transaction.  Under the covers, is this function pending and waiting for the master to send the start bit if you configure it as a slave? 

  I have been learning bare metal code with an stm board and I have some basic I2C code that will configure a master and a slave with the multiple i2c pins on the board.  I am trying to just use the master code on this board and talk to the TI cc2640R2 board, but I'm not getting any response from the TI board.  The STM code uses interrupts for the slave.  And when I debug the code, the master sends a start bit along with the address and this triggers the slave interrupt due to the address interrupt being set.  I am wondering if the STM board is sending the address, but the TI board is not responding.  I set a transfer callback function, but I just keep getting a status of failure and nothing else.  Any ideas to point me in the right direction would be appreciated.  

This is some code I start on a separate thread in the simple_central program.  

void transferCallbackFxn(I2C_Handle handle, I2C_Transaction *msg, bool status)
{


     Display_print1(dispHandle, 7, 0, "Transaction Status %i\n", status);

//      // Check for a semaphore handle
//      if (msg->arg != NULL) {
//
//          // Perform a semaphore post
//          sem_post((sem_t *) (msg->arg));
//      }
}


static void SerialPeriph_Init()
{
          // initialize optional I2C bus parameters
          I2C_Params params;
          I2C_Params_init(&params);
          params.bitRate = I2C_400kHz;
          params.transferMode = I2C_MODE_CALLBACK;
          params.transferCallbackFxn = &transferCallbackFxn;

          // Open I2C bus for usage
          I2C_Handle i2cHandle = I2C_open(0, &params);
          if (i2cHandle == NULL) {
                  Display_print0(dispHandle, 6, 0, "Error Initializing I2C\n");
                  while (1);
              }
              else {
                  Display_print0(dispHandle, 6, 0, "I2C Initialized!\n");
              }

         // Initialize slave address of transaction
          I2C_Transaction transaction = {0};
          transaction.slaveAddress = SLAVE_ADDR;

          // Read from I2C slave device
          transaction.readBuf = readBuffer;
          transaction.readCount = sizeof(readBuffer);

          while(1) {
              I2C_transfer(i2cHandle, &transaction);
          }
    }


I call this code in the init function of the Simple_Central_taskFxn

I also made sure to enable the pins in the BoardGpioInitTable

onst PIN_Config BoardGpioInitTable[] = {

CC2640R2_LAUNCHXL_PIN_RLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* LED initially off */
CC2640R2_LAUNCHXL_PIN_GLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* LED initially off */
CC2640R2_LAUNCHXL_PIN_BTN1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS, /* Button is active low */
CC2640R2_LAUNCHXL_PIN_BTN2 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS, /* Button is active low */
CC2640R2_LAUNCHXL_SPI_FLASH_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MIN, /* External flash chip select */
CC2640R2_LAUNCHXL_UART_RX | PIN_INPUT_EN | PIN_PULLDOWN, /* UART RX via debugger back channel */
CC2640R2_LAUNCHXL_UART_TX | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL, /* UART TX via debugger back channel */
CC2640R2_LAUNCHXL_SPI0_MOSI | PIN_INPUT_EN | PIN_PULLDOWN, /* SPI master out - slave in */
CC2640R2_LAUNCHXL_SPI0_MISO | PIN_INPUT_EN | PIN_PULLDOWN, /* SPI master in - slave out */
CC2640R2_LAUNCHXL_SPI0_CLK | PIN_INPUT_EN | PIN_PULLDOWN, /* SPI clock */
CC2640R2_LAUNCHXL_I2C0_SCL0 | PIN_INPUT_EN | PIN_PULLUP, /* I2C clock */
CC2640R2_LAUNCHXL_I2C0_SDA0 | PIN_INPUT_EN | PIN_PULLUP, /* I2C clock */

PIN_TERMINATE
};

  • Hi !

    You are correct that usually the slave is waiting for the master to start a transaction. This is the case when the I2C driver is set as pending mode. However, in your code, you are setting the I2C driver in callback mode. This mode has a different behavior, according to the API :

    In I2C_MODE_CALLBACK, calls to I2C_transfer() return immediately. The application's callback function, I2C_Params.transferCallbackFxn, is called when the transaction is complete. Sequential calls to I2C_transfer() will place I2C_Transaction structures into an internal queue. Queued transactions are automatically started after the previous transaction has completed. This queuing occurs regardless of any error state from previous transactions. The transactions are always executed in chronological order. The I2C_Params.transferCallbackFxn function will be called asynchronously as each transaction is completed.

    By putting I2C in callback mode and by running it in a while(1) loop, you are continuously adding transaction queries into an internal queue, which will fill up the buffer quickly and use a lot of computing time and power for no reason.

    Since you are already doing the hard part of creating a new thread, the best solution for your use case in my opinion is to use I2C in blocking mode. You can see an example on how to use the blocking mode in the Synopsis of the API for I2C.

    Kind regards,
    Lea