I’m using the iMX6Q in a bare metal application (proprietary OS). I’m having an odd issue with the I2C controller. Our board design uses I2C2 to talk to a serial memory chip. I2C2 is the only bus master, and the memory chip is the only slave on the bus. The problem occurs when trying to “take” the bus. This is the basic code:
// Make sure controller disabled
reg_ptr->I2CR = 0;
// Make sure interrupt flag is cleared
reg_ptr->I2SR = 0;
// Enable the I2C controller
reg_ptr->I2CR = I2C_I2CR_IENB;
// Make sure bus not busy
if(reg_ptr->I2SR & I2C_I2SR_IBB)
{
return(I2C_BUS_BUSY);
}
// Set transmit mode for sending the device address
// Note: setting the MSTA bit sends START condition on the bus
// setting MTX sets master transmit mode
reg_ptr->I2CR |= I2C_I2CR_MSTA | I2C_I2CR_MTX;
// Make sure bus now busy
while(!(reg_ptr->I2SR & I2C_I2SR_IBB))
{
// If arbitration lost, return
if(reg_ptr->I2SR & I2C_I2SR_IAL)
{
// Send stop
_i2c_stop(device_ptr);
return(I2C_ARBITRATION_LOST);
}
}
The problem is that the statement
reg_ptr->I2CR |= I2C_I2CR_MSTA | I2C_I2CR_MTX;
does not always set the IBB bit in the status register.
I can run the whole application (including the OS which contains the I2C driver) by loading it into memory using the (IAR) debugger – the I2C driver works fine (see I2C2 Succeed IBB.jpg attached). As soon as the code sets the MSTA and MTX bits in the CR reg, IBB gets set in the SR reg.
When the whole application gets loaded and run via our SPL, it fails at this statement because setting the MSTA and MTX bits in the CR reg does not generate IBB (see I2C2 Fail IBB.jpg). What does it take to make the IBB bit go high? It has to be more than just setting these bits. The I2C clock is of course running in both instances.
Hello,
Please use an oscilloscope to check the timing of the I2C signals to ensure that the start conditions and data transfers conform to the I2C protocol.
Best Regards,
Zhiming