cancel
Showing results for 
Search instead for 
Did you mean: 

BlueNRG-2 I2C not working at all

vrba.vojtech
Associate II

Hello, I am having some trouble with getting I2C to work.

My code:

void i2c_init(void) {
  /* Periph clock enable */
  SysCtrl_PeripheralClockCmd(CLOCK_PERIPH_GPIO | CLOCK_PERIPH_I2C2, ENABLE);
 
  // I2C2 pins
  GPIO_InitI2c2ClkPin4(); // SCL at DIO4
  GPIO_InitI2c2DataPin5(); // SDA at DIO5
 
  I2C_InitType i2c_settings;
  I2C_StructInit( & i2c_settings);
  i2c_settings.I2C_ClockSpeed = 100000;
  i2c_settings.I2C_OperatingMode = I2C_OperatingMode_Master;
 
  I2C_Init(I2C2, & i2c_settings);
 
  I2C_ClearITPendingBit(I2C2, I2C_IT_MSK);
 
  I2C_Cmd(I2C2, ENABLE);
}
 
int i2c_write(uint8_t addr, uint8_t reg, uint8_t * data, uint8_t len) {
  I2C_TransactionType t;
 
  // Write the slave address
  t.Operation = I2C_Operation_Write;
  t.Address = addr;
  t.StartByte = I2C_StartByte_Disable;
  t.AddressType = I2C_AddressType_7Bit;
  t.StopCondition = I2C_StopCondition_Enable;
  t.Length = 1 + len;
 
  // Flush the slave address
  I2C_FlushTx(I2C2);
  while (I2C_WaitFlushTx(I2C2) == I2C_OP_ONGOING);
 
  // Begin transaction
  I2C_BeginTransaction(I2C2, & t);
 
  // Fill TX FIFO with data to write
  I2C_FillTxFIFO(I2C2, reg);
 
  for (uint8_t i = 0; i < len; i++) {
    I2C_FillTxFIFO(I2C2, data[i]);
  }
 
  // Wait loop
  do {
    if (I2C_GetStatus(I2C2) == I2C_OP_ABORTED) {
      return ERROR;
    }
  } while (I2C_GetITStatus(I2C2, I2C_IT_MTD) == RESET);
 
  // Clear pending bits
  I2C_ClearITPendingBit(I2C2, I2C_IT_MTD | I2C_IT_MTDWS);
 
  return SUCCESS;
}
 
int i2c_read(uint8_t addr, uint8_t reg, uint8_t * data, uint8_t len) {
  I2C_TransactionType t;
 
  // Write the slave address
  t.Operation = I2C_Operation_Write;
  t.Address = addr;
  t.StartByte = I2C_StartByte_Disable;
  t.AddressType = I2C_AddressType_7Bit;
  t.StopCondition = I2C_StopCondition_Disable;
  t.Length = 1;
 
  // Flush the slave address
  I2C_FlushTx(I2C2);
  while (I2C_WaitFlushTx(I2C2) == I2C_OP_ONGOING);
 
  // Begin transaction
  I2C_BeginTransaction(I2C2, & t);
 
  // Fill TX FIFO with data to write
  I2C_FillTxFIFO(I2C2, reg);
 
  // Wait loop
  do {
    if (I2C_GetStatus(I2C2) == I2C_OP_ABORTED) {
      // Here it returns ERROR
      return ERROR;
    }
  } while (I2C_GetITStatus(I2C2, I2C_IT_MTDWS) == RESET);
 
  // Clear pending bits
  I2C_ClearITPendingBit(I2C2, I2C_IT_MTDWS);
 
  // read data
  t.Operation = I2C_Operation_Read;
  t.Address = addr;
  t.StartByte = I2C_StartByte_Disable;
  t.AddressType = I2C_AddressType_7Bit;
  t.StopCondition = I2C_StopCondition_Enable;
  t.Length = len;
  I2C_BeginTransaction(I2C2, & t);
 
  // Wait loop
  do {
    if (I2C_OP_ABORTED == I2C_GetStatus(I2C2)) {
      return ERROR;
    }
  } while (RESET == I2C_GetITStatus(I2C2, I2C_IT_MTD));
 
  // Clear pending bits
  I2C_ClearITPendingBit(I2C2, I2C_IT_MTD | I2C_IT_MTDWS);
 
  // Get data from RX FIFO
  while (len--) {
    * data = I2C_ReceiveData(I2C2);
    data++;
  }
 
  return SUCCESS;
}

For example, when I try to read a register using this i2c_read function, it returns ERROR when it checks status for I2C_OP_ABORTED in the write phase.r

I also tried the version with enabled interrupts and i2c_eot flag. The handler I2C2_Handler is never executed and it stucks when waiting in while(i2c_eot == RESET).

What am I doing wrong? I triple checked the wiring and it should be OK. Thanks.

1 ACCEPTED SOLUTION

Accepted Solutions
vrba.vojtech
Associate II

OK, I solved this problem with help of logic analyzer. I was putting in the device address in 8-bit format, but it seems the I2C peripheral shifts it 1 bit left (it assumes 7-bit address). So adding line

addr >>= 1;

at the beggining of read and write methods solved the problem.

The next problem was missing pull-up resistors. Under Table 129 "IO functional map" in the BlueNRG-2 datasheet, there is a note you can easily miss, saying: "All the I2C pins require external pull-up". I didn't know before so it could not work properly...

View solution in original post

1 REPLY 1
vrba.vojtech
Associate II

OK, I solved this problem with help of logic analyzer. I was putting in the device address in 8-bit format, but it seems the I2C peripheral shifts it 1 bit left (it assumes 7-bit address). So adding line

addr >>= 1;

at the beggining of read and write methods solved the problem.

The next problem was missing pull-up resistors. Under Table 129 "IO functional map" in the BlueNRG-2 datasheet, there is a note you can easily miss, saying: "All the I2C pins require external pull-up". I didn't know before so it could not work properly...