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.

I2C MasterBusy fails

Other Parts Discussed in Thread: TM4C129ENCPDT

Hello I am using tivaware 2.1.0.12573c with TM4C129ENCPDT and am finding the I2C module does not appear to be setting busy flag correctly.

If I use a 20ms delay with SysCtlDelay my code reads the FRAM fine, but if I wait for the busy flags to free it doesn't work.

Initialisation code:

// Enable and configure the peripherals used by I2C1

SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);

SysCtlPeripheralReset(SYSCTL_PERIPH_I2C1);

GPIOPinConfigure(GPIO_PG1_I2C1SDA);

GPIOPinConfigure(GPIO_PG0_I2C1SCL);

GPIOPinTypeI2CSCL(GPIO_PORTG_BASE, GPIO_PIN_0);

GPIOPinTypeI2C(GPIO_PORTG_BASE, GPIO_PIN_1);

GPIODirModeSet(GPIO_PORTG_BASE, GPIO_PIN_0, GPIO_DIR_MODE_HW);

GPIODirModeSet(GPIO_PORTG_BASE, GPIO_PIN_1, GPIO_DIR_MODE_HW);

I2CMasterInitExpClk(I2C1_BASE, ui32SysClock, true);

HWREG(I2C1_BASE + I2C_O_FIFOCTL) = 80008000;

Reading Code:

//read specified register on slave device
static uint32_t I2CReceive(uint32_t slave_addr, uint8_t reg, uint8_t * rxBuffer, uint16_t size)

{
	uint32_t 	resp;
	uint16_t 	x;

	while (I2CMasterBusy(I2C1_BASE));
//	SysCtlDelay(ui32SysClock/(20000));

  //specify that we are writing (a register address) to the slave device
  I2CMasterSlaveAddrSet(I2C1_BASE, slave_addr, false);
  I2CMasterDataPut(I2C1_BASE, (reg >> 8) & 0xFF);
  I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START);
	while (I2CMasterBusy(I2C1_BASE));
//	SysCtlDelay(ui32SysClock/(20000));

  I2CMasterDataPut(I2C1_BASE, reg & 0xFF);
  I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
	while (I2CMasterBusy(I2C1_BASE));
//	SysCtlDelay(ui32SysClock/(20000));

  x = 0;
  //specify that we are going to read from slave device
  I2CMasterSlaveAddrSet(I2C1_BASE, slave_addr, true);
  if (size == 1)
  	I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
  else
  	I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_START);
  while (x < size)
  {
  	while (I2CMasterBusy(I2C1_BASE));
// 	SysCtlDelay(ui32SysClock/(20000));
  	while (HWREG(I2C1_BASE + I2C_O_MCS) & I2C_MCS_BUSY);

  	resp = I2CMasterDataGet(I2C1_BASE);
    rxBuffer[x++] = resp;
    if (size > 1 && x < size)
    {
    	while (I2CMasterBusy(I2C1_BASE));
 //     	SysCtlDelay(ui32SysClock/(20000));
   	if (x < (size - 1))
    		I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_CONT);
    	else
    		I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH);
    }
  }
	SysCtlDelay(ui32SysClock/(20000));
 	return 0;
}

  • I hate having to answer my own question, but hopefully answers the issue for someone else.

    I found this question

    Which indicates the TM4C129 has an issue in that the busy flag is not set immediately.

    This means you need a short delay before doing the busy wait.

    I changed code to use

     SysCtlDelay(1000); // Allow Busy flag to set (TM4C129 issue)

     while (I2CMasterBusy(I2C1_BASE));

    This works reliably.

  • Hello Barry,

    Yes, that is correct. The Busy flag takes time after the command is sent. Using the delay loop or using interrupt are the suggested WA's.

    Regards
    Amit