Reply
Posts: 26
Registered: ‎12-06-2016
Accepted Solution

I2C - Basic Setup / Communication BGM113

Hello,

 

     I am in the process of converting my BGScript application into simplicity Studio / IAR.   The board is a a custom board with a BGM113 which connects to sensors over the I2C. 

 

     We are using PortB, Pin 11 / 12 for SDA/SCL respectively. 

 

      I have created a basic empty project via Simplicity Studio that includes the GATT profiles, etc, and in the init event I call my sensor I2C init function:

 

#define I2C_SCL_GPIO_PORT       	gpioPortB
#define I2C_SCL_GPIO_PIN        	12

#define I2C_SDA_GPIO_PORT       	gpioPortB
#define I2C_SDA_GPIO_PIN        	11

void setupI2C(void)
{

  // Using default settings
  I2C_Init_TypeDef i2cInit = I2C_INIT_DEFAULT;

  // Enable GPIO / I2C Clock
  CMU_ClockEnable(cmuClock_I2C0, true);
  CMU_ClockEnable(cmuClock_GPIO, true);

  /* Configure SDA/SCL */
  GPIO_PinModeSet(I2C_SCL_GPIO_PORT, I2C_SCL_GPIO_PIN, gpioModeWiredAndPullUp, 1);
  GPIO_PinModeSet(I2C_SDA_GPIO_PORT, I2C_SDA_GPIO_PIN, gpioModeWiredAndPullUp, 1);


  // Route Location was found on page 55 of the BGM113 Specification
  I2C0->ROUTEPEN = I2C0->ROUTEPEN | I2C_ROUTEPEN_SCLPEN;
  I2C0->ROUTELOC0 = (I2C0->ROUTELOC0 & (~_I2C_ROUTELOC0_SCLLOC_MASK))
			| I2C_ROUTELOC0_SCLLOC_LOC6;
	/* Set up SDA */
  I2C0->ROUTEPEN = I2C0->ROUTEPEN | I2C_ROUTEPEN_SDAPEN;
  I2C0->ROUTELOC0 = (I2C0->ROUTELOC0 & (~_I2C_ROUTELOC0_SDALOC_MASK))
			| I2C_ROUTELOC0_SDALOC_LOC6;

  /* Initializing the I2C */
  I2C_Init(I2C0, &i2cInit);

  /* Setting the status flags and index */
  i2c_rxInProgress = false;
  i2c_startTx = false;
}

 

I then call the following function

WriteI2CByte(DEVICE_ADDRESS, WHO_AM_I) which will generate a I2CResult of -5

 

void WriteI2CByte(int Address, uint8_t value)
{
  uint8 buffer[1];

  buffer[0] = value;

  /* Transfer structure */
  I2C_TransferSeq_TypeDef i2cTransferWriteRegister;

  /* Initializing I2C transfer */
  i2cTransferWriteRegister.addr          =  Address;
  i2cTransferWriteRegister.flags         = I2C_FLAG_WRITE;
  i2cTransferWriteRegister.buf[0].data   = buffer;
  i2cTransferWriteRegister.buf[0].len    = 1;
  I2C_TransferInit(I2C0, &i2cTransferWriteRegister);

  while (I2C_Transfer(I2C0) == i2cTransferInProgress);

  I2C_Result = I2C_Transfer(I2C0);
}

* I know the board works because the code works with BGScript; * I know the defines are correct.  Maybe the GPIO Settings (PullUp/PullUpFilter?)

 

Thoughts on how what is going wrong?   

 

Thanks,

-R

 

 

 

 

 

 

 

Highlighted
Posts: 185
Registered: ‎10-03-2015

Re: I2C - Basic Setup / Communication BGM113

I think you should take a look at one of the sample apps in Studio so you can get a better idea of how the I2C_Transfer function is supposed to work. 

 

To further simplify things you can look at the i2cspm kit library. 

 

...\SiliconLabs\SimplicityStudio\v4\developer\stacks\ble\v2.0.1.0\hardware\kit\common\drivers

Posts: 26
Registered: ‎12-06-2016

Re: I2C - Basic Setup / Communication BGM113

Hi Super Panda,

 

      Appreciate you responding.  I had taken a look at the samples before I coded that I2C driver.  That said, I took your advice and redid the code with the driver and still not getting the same result that I get with the BGScript version (<i2c scl_pin="PB12" sda_pin="PB11" />).

 

 

#define I2CSPM_INIT_DEFAULT_BGM113_REV5Board                                                    \
  { I2C0,                      /* Use I2C instance 0 */                        \
    gpioPortB,                 /* SCL port */                                  \
    12,                        /* SCL pin */                                   \
    gpioPortB,                 /* SDA port */                                  \
    11,                        /* SDA pin */                                   \
    6,                         /* Location of SCL */                           \
    6,                         /* Location of SDA */                           \
    0,                         /* Use currently configured reference clock */  \
    I2C_FREQ_STANDARD_MAX,     /* Set to standard rate  */                     \
    i2cClockHLRStandard,       /* Set to use 4:4 low/high duty cycle */        \
  }

#define I2CSPM_TRANSFER_TIMEOUT 300000

 

In main.c I allocate

 

I2CSPM_Init_TypeDef i2cInit = I2CSPM_INIT_DEFAULT_FOCAL;

 

and then after 

  /* Initialize stack */
  gecko_init(&config);

 /* Initialize I2C driver, using standard rate. Devices on DK itself */
  /* supports fast mode, but in case some slower devices are added on */
  /* prototype board, we use standard mode. */
  I2CSPM_Init(&i2cInit);

 

 

I then do a read

( Sequence for WHO AM I, is Write Address Stop, Read Buffer Stop)

 

ret = ReadI2C(i2c,I2C_Address,WHO_AM_I_XG,i2c_rxBuffer,1);

 

/**************************************************************************//**
 * @brief  Reading I2C data. Will busy-wait until the transfer is complete.
 *****************************************************************************/
int ReadI2C(I2C_TypeDef *i2c,uint8_t Address, uint8_t Register, uint8_t *Buffer, int BufferSize)
{
  int ret;

  ret = WriteI2CByte(i2c,Address,Register);
  if (ret != i2cTransferDone)
	  return (int)ret;

  I2C_TransferSeq_TypeDef    seq;
      seq.addr  = 0x00ff & Address;
      seq.flags = I2C_FLAG_READ;
      /* Select offset to start writing to */

      seq.buf[0].data = Buffer;
      seq.buf[0].len  = BufferSize;

      ret = I2CSPM_Transfer(i2c, &seq);
      if (ret != i2cTransferDone)
      {
        return((int) ret);
      }

      return 0;
}


/**************************************************************************//**
 * @brief  Transmitting I2C data. Will busy-wait until the transfer is complete.
 *****************************************************************************/
int WriteI2CByte(I2C_TypeDef *i2c,uint8_t Address, uint8_t value)
{
  uint8_t buffer[1];

  int ret;

  buffer[0] =  value;


  I2C_TransferSeq_TypeDef    seq;
      seq.addr  = 0x00ff & Address;
      seq.flags = I2C_FLAG_WRITE;
      /* Select offset to start writing to */

      seq.buf[0].data = buffer;
      seq.buf[0].len  = 1;

      ret = I2CSPM_Transfer(i2c, &seq);
      if (ret != i2cTransferDone)
      {
        return((int) ret);
      }

      return 0;
}
Posts: 185
Registered: ‎10-03-2015

Re: I2C - Basic Setup / Communication BGM113

Did you try doing this with a single READ/WRITE like below? BGScript I believe uses a fixed speed of ~250kHz and different from what you specified. Not sure what device you are trying to interface with, but perhaps bus speed is the issue? 

 

bool registerRead8(I2C_TypeDef *i2c, uint8_t addr, uint8_t reg, uint8_t *val)
{
  I2C_TransferSeq_TypeDef    seq;
  I2C_TransferReturn_TypeDef sta;
  uint8_t                    i2c_write_data[1];
  uint8_t                    i2c_read_data[1];

  seq.addr  = addr;
  seq.flags = I2C_FLAG_WRITE_READ;
  /* Select command to issue */
  i2c_write_data[0] = reg;
  seq.buf[0].data   = i2c_write_data;
  seq.buf[0].len    = 1;
  /* Select location/length of data to be read */
  seq.buf[1].data = i2c_read_data;
  seq.buf[1].len  = 1;

  sta = I2CSPM_Transfer(i2c, &seq);
  
  if (sta != i2cTransferDone)
  {
    return false;
  }
  
  if (NULL != val)
  {
    *val = i2c_read_data[0];
  }
  
  return true;
}
Posts: 26
Registered: ‎12-06-2016

Re: I2C - Basic Setup / Communication BGM113

Hi Super Ninja,

 

    I tried your code, and got the same result.   I hope to be in front of a OScope tomorrow so I can look a little more at the bus.   That said I think it would be a nice to know what the the BGScript I2C0 settings are from someone in the know. 

 

    Also, beyond the Frequency and Clock, what are the GPIO settings: pull down, pull up, pull up filter?  

 

Thanks again, 

-R

 

Posts: 185
Registered: ‎10-03-2015

Re: I2C - Basic Setup / Communication BGM113

Your settings were the same as mine...

gpioModeWiredAndPullUp

 

Posts: 26
Registered: ‎12-06-2016

Re: I2C - Basic Setup / Communication BGM113

Hi Super Ninja, 

 

     Just to put a bow on this thread, there were a few things going on in my case.   It seems that I had to move the the following code after what I thought was the initdevice call for the I2C in main.  

 

  CMU_ClockEnable(cmuClock_GPIO, true);
 /* Initialize I2C driver, using standard rate. Devices on DK itself */
  /* supports fast mode, but in case some slower devices are added on */
  /* prototype board, we use standard mode. */
  I2CSPM_Init(&i2cInit);

  /* Configure SDA/SCL */
  GPIO_PinModeSet(I2C_SCL_GPIO_PORT, I2C_SCL_GPIO_PIN, gpioModeWiredAndPullUp, 1);
  GPIO_PinModeSet(I2C_SDA_GPIO_PORT, I2C_SDA_GPIO_PIN, gpioModeWiredAndPullUp, 1);

This maybe due to the routes being to PB11/12.  

 

The second thing that messed me up was that I didn't properly set the address in the address field, or I should say, I did, and then didn't and then did again.   Either way, for a 7 bit addr, it is << 1 with the LSB being an X.   

 

Beyond that, appreciate the support.  I did end up moving the Register read to your code. 

 

Thanks,

-R

Posts: 185
Registered: ‎10-03-2015

Re: I2C - Basic Setup / Communication BGM113

And I was about to add another reply to ask if you had the address right! That has certainly tripped me up before. Glad you are up and running. 

Posts: 6
Registered: ‎01-31-2017

Re: I2C - Basic Setup / Communication BGM113

In my C project, I2C works in slave mode, using PC.10 and PC11 pin:

 

GPIO_PinModeSet(gpioPortC, 10, gpioModeWiredAndAlternate, 1);
GPIO_PinModeSet(gpioPortC, 11, gpioModeWiredAndAlternate, 1);

 

Try to configure like a "gpioModeWiredAndAlternate".

 

 

 

 

Posts: 1
Registered: ‎03-10-2017

Re: I2C - Basic Setup / Communication BGM113

I have an issue with I2C on PB11 and 12 pins. After calling gecko_init(&config) PB12  goes to 1 and stays it that state all time. GPIO_PinModeSet() and GPIO_PinOutClear don't change it's value. I don't know yet the reason it happens.

Posts: 3
Registered: ‎03-18-2017

Re: I2C - Basic Setup / Communication BGM113

sergey_belykh, I have seen the same issue;

 

if you call:

 

/* Initialize stack */
gecko_init(&config);

 

And then try to use PB12 - you cant control it (perhaps some control has been routed to it in the stack setup).