Skip to main content
vrba.vojtech
Associate II
February 5, 2020
Solved

BlueNRG-2 I2C not working at all

  • February 5, 2020
  • 1 reply
  • 1060 views

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.

This topic has been closed for replies.
Best answer by vrba.vojtech

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...

1 reply

vrba.vojtech
vrba.vojtechAuthorBest answer
Associate II
February 5, 2020

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...